Skip to content

Kaching Subscriptions API Documentation

Create rich subscription flows and streamline store operations on Shopify using our full-featured, enterprise-ready REST APIs.

  • A Shopify store with the Kaching Subscriptions app installed
  • A Kaching Subscriptions API key (generated from the app admin)
https://subscriptions.kachingappz.app/shop-api

All responses are JSON.

Every request must include a Bearer token in the Authorization header:

Authorization: Bearer <your-api-token>

If the header is missing, malformed, or the token is unknown, the API responds with 401 Unauthorized:

{
"error": "Unauthorized",
"message": "Invalid token"
}

The API allows 60 requests per 60 seconds per shop. Requests over the limit receive 429 Too Many Requests:

{
"isError": true,
"message": "Too many requests, please try again later."
}

List responses also include a throttle field reflecting the remaining Shopify GraphQL budget. When that budget drops below 1000, the API automatically delays the response by ~3 seconds to avoid tripping Shopify-side limits — design your integration to tolerate that latency.

GET /shop-api/contracts

Returns a paginated list of subscription contracts for the authenticated shop.

Query parameters

NameTypeRequiredDefaultDescription
cursorstringNoOpaque pagination cursor from the previous response’s cursor field.
querystringNostatus:ACTIVE OR status:PAUSED OR status:FAILED OR status:CANCELLEDShopify GraphQL query syntax, e.g. status:ACTIVE, status:PAUSED.
emailstringNoCustomer email (case-insensitive exact match). Narrows the result to that customer’s contracts. Combines with query via AND. Unknown email returns an empty data array.
customerIdstringNoShopify customer ID — either a numeric ID (e.g. 258369147) or a full GID (gid://shopify/Customer/258369147). Narrows the result to that customer’s contracts. Combines with query via AND. Unknown customer returns an empty data array. Takes precedence over email if both are supplied.
orderIdstringNoShopify order ID — either a numeric ID (e.g. 369147258) or a full GID (gid://shopify/Order/369147258). Narrows the result to the contract(s) attached to that order. Combines with query via AND. Unknown or non-subscription orders return an empty data array. Takes precedence over customerId and email if multiple are supplied.

Each page returns up to 50 contracts.

Example — fetch all active contracts

Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "query=status:ACTIVE"

Example — paginate

Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "query=status:ACTIVE" \
--data-urlencode "cursor=eyJsYXN0X2lkIjoi..."

Loop until hasNextPage is false, passing the previous response’s cursor on each iteration.

Example — fetch a single contract by ID

Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "query=id:123456789"

Example — fetch a specific customer’s contracts by email

Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "email=sarah@example.com"

Combine with query to narrow further, e.g. only that customer’s cancelled contracts:

Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "email=sarah@example.com" \
--data-urlencode "query=status:CANCELLED"

Example — fetch a specific customer’s contracts by customer ID

Customer ID is preferred over email when available — it’s stable across email changes. Accepts either the numeric ID or the full Shopify GID.

Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "customerId=258369147"
Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "customerId=gid://shopify/Customer/258369147"

Example — fetch a contract by orderId

Use orderId when you have a Shopify order in hand and want to find the subscription contract(s) it was generated by. Accepts either the numeric ID or the full Shopify GID.

Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "orderId=369147258"
Terminal window
curl -G "https://subscriptions.kachingappz.app/shop-api/contracts" \
-H "Authorization: Bearer <your-api-token>" \
--data-urlencode "orderId=gid://shopify/Order/369147258"

If multiple of orderId, customerId, and email are provided, priority is orderId > customerId > email; the lower-priority parameters are ignored.

Response (200)

{
"data": [
{
"node": {
"id": "gid://shopify/SubscriptionContract/123456789",
"status": "ACTIVE",
"currencyCode": "USD",
"lastPaymentStatus": "SUCCEEDED",
"revisionId": "gid://shopify/SubscriptionContractRevision/987654321",
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-02-10T14:22:00Z",
"deliveryPolicy": { "interval": "MONTH", "intervalCount": 1 },
"billingPolicy": {
"interval": "MONTH",
"intervalCount": 1,
"maxCycles": null,
"minCycles": null
},
"deliveryPrice": { "amount": "5.99", "currencyCode": "USD" },
"deliveryMethod": {
"__typename": "SubscriptionDeliveryMethodShipping",
"address": { "countryCodeV2": "US", "city": "San Francisco" }
},
"linesCount": { "count": 2 },
"lines": {
"edges": [
{
"node": {
"id": "gid://shopify/SubscriptionLine/111222333",
"title": "Product Title",
"variantTitle": "Variant Title",
"productId": "gid://shopify/Product/444555666",
"variantId": "gid://shopify/ProductVariant/777888999",
"quantity": 2,
"lineDiscountedPrice": {
"amount": "47.98",
"currencyCode": "USD"
},
"pricingPolicy": {
"basePrice": { "amount": "25.99", "currencyCode": "USD" },
"cycleDiscounts": [
{
"adjustmentType": "PERCENTAGE",
"afterCycle": 0,
"computedPrice": {
"amount": "23.99",
"currencyCode": "USD"
},
"adjustmentValue": { "percentage": 8.0 }
}
]
},
"discountAllocations": []
}
}
],
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"endCursor": null,
"startCursor": null
}
},
"discounts": { "edges": [] },
"customer": {
"id": "gid://shopify/Customer/258369147",
"displayName": "Sarah Johnson",
"defaultEmailAddress": { "emailAddress": "sarah@example.com" }
},
"orders": {
"edges": [{ "node": { "id": "gid://shopify/Order/369147258" } }],
"pageInfo": {
"hasNextPage": false,
"hasPreviousPage": false,
"endCursor": null,
"startCursor": null
}
}
}
}
],
"hasNextPage": true,
"cursor": "eyJsYXN0X2lkIjoiZ2lkOi8vc2hvcGlmeS...",
"throttle": 1850
}

See the Contract object reference below for field details.


POST /shop-api/contracts/pause

Transitions an ACTIVE contract to PAUSED. No further billing cycles run until the contract is resumed.

Request body

FieldTypeRequiredDescription
contractIdstringYesEither a Shopify GID (gid://shopify/SubscriptionContract/123) or the bare numeric ID.

Example

Terminal window
curl -X POST "https://subscriptions.kachingappz.app/shop-api/contracts/pause" \
-H "Authorization: Bearer <your-api-token>" \
-H "Content-Type: application/json" \
-d '{"contractId":"gid://shopify/SubscriptionContract/123456789"}'

Response (200)

{ "success": true }

POST /shop-api/contracts/resume

Transitions a PAUSED contract back to ACTIVE. Billing resumes on the contract’s configured schedule.

Request body

FieldTypeRequiredDescription
contractIdstringYesShopify GID or numeric ID of the contract.

Example

Terminal window
curl -X POST "https://subscriptions.kachingappz.app/shop-api/contracts/resume" \
-H "Authorization: Bearer <your-api-token>" \
-H "Content-Type: application/json" \
-d '{"contractId":"gid://shopify/SubscriptionContract/123456789"}'

Response (200)

{ "success": true }

POST /shop-api/contracts/cancel

Transitions a contract to CANCELLED.

Request body

FieldTypeRequiredDescription
contractIdstringYesShopify GID or numeric ID of the contract.

Example

Terminal window
curl -X POST "https://subscriptions.kachingappz.app/shop-api/contracts/cancel" \
-H "Authorization: Bearer <your-api-token>" \
-H "Content-Type: application/json" \
-d '{"contractId":"gid://shopify/SubscriptionContract/123456789"}'

Response (200)

{ "success": true }
FieldTypeDescription
idstringShopify GID for the contract.
statusstringOne of ACTIVE, PAUSED, FAILED, EXPIRED, CANCELLED, STALE.
currencyCodestringISO currency code for the contract.
lastPaymentStatusstringSUCCEEDED or FAILED.
revisionIdstringOpaque identifier for the current revision. Use to detect contract changes.
createdAtstringISO-8601 timestamp.
updatedAtstringISO-8601 timestamp.
deliveryPolicyobject{ interval, intervalCount } — how often deliveries happen.
billingPolicyobject{ interval, intervalCount, maxCycles, minCycles } — billing cadence and limits.
deliveryPriceobject{ amount, currencyCode } — shipping/delivery charge per cycle.
deliveryMethodobjectDelivery method, e.g. SubscriptionDeliveryMethodShipping with an address.
linesCountobject{ count } — total number of line items on the contract.
linesobjectConnection of line items — see below.
discountsobjectConnection of contract-level discount allocations.
customerobject{ id, displayName, defaultEmailAddress.emailAddress }.
ordersobjectConnection of orders generated by this contract.

interval values: DAY, WEEK, MONTH, YEAR.

FieldTypeDescription
idstringShopify GID for the line.
titlestringProduct title.
variantTitlestringVariant title.
productIdstringShopify product GID.
variantIdstringShopify variant GID.
quantitynumberNumber of units per delivery.
lineDiscountedPriceobject{ amount, currencyCode } — final per-line price after discounts.
pricingPolicyobject{ basePrice, cycleDiscounts[] } — base price and per-cycle adjustments.
discountAllocationsarrayLine-level discount allocations.

Cycle discount fields (pricingPolicy.cycleDiscounts[])

Section titled “Cycle discount fields (pricingPolicy.cycleDiscounts[])”
FieldTypeDescription
adjustmentTypestringPERCENTAGE, FIXED_AMOUNT, or PRICE.
afterCyclenumberCycle index after which the discount applies (0 = starting with cycle 1).
computedPriceobject{ amount, currencyCode } — resolved price once the discount applies.
adjustmentValueobjectEither { percentage } or { amount, currencyCode }, depending on type.

Connections (lines, orders, top-level list) return pageInfo:

FieldTypeDescription
hasNextPagebooleantrue if more pages exist.
hasPreviousPagebooleantrue if previous pages exist.
endCursorstringCursor for the last item in the current page.
startCursorstringCursor for the first item in the current page.
StatusWhenExample body
400Missing or malformed request body (e.g. no contractId) or invalid query parameter (e.g. email is not a valid address){ "error": "Missing contractId" }
401Missing, malformed, or unknown Bearer token{ "error": "Unauthorized", "message": "Invalid token" }
429Rate limit exceeded (60 requests / 60 seconds per shop){ "isError": true, "message": "Too many requests, please try again later." }
500Upstream Shopify error or mutation failure{ "error": "Failed to pause subscription contract" }

Mutation endpoints (pause, resume, cancel) surface Shopify-side validation messages in the error field when Shopify returns userErrors, so prefer showing the raw message to operators rather than masking it.