Developer Docs
Storefront API
API References
Subscriptions

Subscriptions (Read)

Read-only endpoints for the Joy Subscription Storefront API. Use these to list a customer's subscription contracts, fetch full contract detail, preview upcoming and historical orders, preview the next charge, and resolve available shipping options.

All paths are relative to the base URL:

https://<your-app-domain>/storefront-api/v1

Every endpoint on this page requires both auth layers on every request. The shopId is always derived from the session — it is never read from a header.

X-Joy-App-Id: <app-id>
X-Joy-Secret-Key: sk_live_xxx     # server-side only, never expose to the browser
X-Session-Id: <session-id>

Responses use a consistent envelope:

// Success
{ "success": true, "data": { /* … */ }, "meta": { /* optional */ } }
 
// Error
{ "success": false, "error": { "code": "NOT_FOUND", "message": "…" } }

{contractId} is the numeric subscriptionContractId. Accessing a contract that does not exist, or one not owned by the authenticated customer, returns 404 NOT_FOUND (existence is never leaked).


Endpoint index

MethodPathDescription
GET/upcoming-ordersAll upcoming orders across the customer's contracts.
GET/subscriptionsList the customer's subscription contracts.
GET/subscriptions/{contractId}Full detail of one contract.
GET/subscriptions/{contractId}/upcoming-ordersUpcoming orders of one contract.
GET/subscriptions/{contractId}/history-ordersPast (billed) orders of one contract.
GET/subscriptions/{contractId}/next-chargePreview the next charge.
GET/subscriptions/{contractId}/shipping-optionsAvailable shipping options.

GET /subscriptions

List all subscription contracts owned by the authenticated customer. Each contract is enriched with its current cycle's nextOrderDate.

  • Method: GET
  • Path: /subscriptions
  • Auth: X-Joy-App-Id, X-Joy-Secret-Key, X-Session-Id

Query parameters

NameTypeNotes
statusstring (CSV)Filter by status, e.g. active,paused.
directionasc | descOrder by createdAt.

Pagination: none — returns the full list. No meta.

Request

curl -G "https://<your-app-domain>/storefront-api/v1/subscriptions" \
  --data-urlencode "status=active,paused" \
  --data-urlencode "direction=desc" \
  -H "X-Joy-App-Id: <app-id>" \
  -H "X-Joy-Secret-Key: sk_live_xxx" \
  -H "X-Session-Id: <session-id>"

Response

{
  "success": true,
  "data": [
    {
      "subscriptionContractId": 123456789,
      "status": "ACTIVE",
      "currentBillingCycle": 4,
      "nextOrderDate": "2026-07-01T00:00:00.000Z",
      "lines": [ /* … */ ]
      /* …other contract fields… */
    }
  ]
}

GET /subscriptions/{contractId}

Full detail of a single contract, including the upcoming order (merged cycle line prices, discounts, shipping/delivery price, estimated tax) and the upcoming fulfillment order.

  • Method: GET
  • Path: /subscriptions/{contractId}
  • Auth: X-Joy-App-Id, X-Joy-Secret-Key, X-Session-Id

Path parameters

NameTypeNotes
contractIdintegerPositive integer subscriptionContractId.

Query parameters: none.

Request

curl "https://<your-app-domain>/storefront-api/v1/subscriptions/123456789" \
  -H "X-Joy-App-Id: <app-id>" \
  -H "X-Joy-Secret-Key: sk_live_xxx" \
  -H "X-Session-Id: <session-id>"

Response

{
  "success": true,
  "data": {
    "subscriptionContractId": 123456789,
    "status": "ACTIVE",
    "upcomingOrder": {
      "cycleIndex": 5,
      "lines": [ /* merged */ ],
      "discounts": [ /* … */ ],
      "shippingPrice": "5.00",
      "deliveryPrice": "5.00",
      "estimatedTax": "1.20",
      "billingAttemptExpectedDate": "2026-07-01T00:00:00.000Z"
    },
    "upcomingFulfillmentOrder": {
      "currentOrder": { /* … */ },
      "fulfillmentOrders": [ /* … */ ],
      "scheduledFulfill": { /* … */ }
    }
    /* …other contract fields… */
  }
}

GET /upcoming-orders

All upcoming orders across every contract of the authenticated customer (dashboard view). The customer id is taken from the session — it is never client-controlled.

  • Method: GET
  • Path: /upcoming-orders
  • Auth: X-Joy-App-Id, X-Joy-Secret-Key, X-Session-Id

Query parameters

NameTypeDefaultNotes
nextCycleOnlybooleanIf true, only the next (current) cycle per contract.
afterstringCursor for the next page.
limitPerPageinteger10Range 1–50. Out of range returns 400 VALIDATION_FAILED.

Pagination: cursor. This is the only Read endpoint that returns meta.nextCursor.

"meta": { "hasNext": true, "hasPre": false, "total": 8, "nextCursor": "…" }

Request

curl -G "https://<your-app-domain>/storefront-api/v1/upcoming-orders" \
  --data-urlencode "nextCycleOnly=true" \
  --data-urlencode "limitPerPage=10" \
  -H "X-Joy-App-Id: <app-id>" \
  -H "X-Joy-Secret-Key: sk_live_xxx" \
  -H "X-Session-Id: <session-id>"

Response

{
  "success": true,
  "data": [
    {
      "subscriptionContractId": 123456789,
      "cycleIndex": 5,
      "lines": [ /* … */ ],
      "estimatedTax": "1.20"
    }
  ],
  "meta": { "hasNext": true, "hasPre": false, "total": 8, "nextCursor": "…" }
}

GET /subscriptions/{contractId}/upcoming-orders

Upcoming orders / billing cycles for one contract, each with estimatedTax.

  • Method: GET
  • Path: /subscriptions/{contractId}/upcoming-orders
  • Auth: X-Joy-App-Id, X-Joy-Secret-Key, X-Session-Id

Path parameters

NameTypeNotes
contractIdintegerPositive integer subscriptionContractId.

Query parameters

NameTypeDefaultNotes
limitPerPageinteger10Range 1–50. Out of range returns 400 VALIDATION_FAILED.

Pagination: page-style. meta is { hasNext, hasPre, total } (no nextCursor).

Request

curl -G "https://<your-app-domain>/storefront-api/v1/subscriptions/123456789/upcoming-orders" \
  --data-urlencode "limitPerPage=10" \
  -H "X-Joy-App-Id: <app-id>" \
  -H "X-Joy-Secret-Key: sk_live_xxx" \
  -H "X-Session-Id: <session-id>"

Response

{
  "success": true,
  "data": [ { "cycleIndex": 5, "lines": [ /* … */ ], "estimatedTax": "1.20" } ],
  "meta": { "hasNext": true, "hasPre": false, "total": 12 }
}

GET /subscriptions/{contractId}/history-orders

Past (billed) orders for the contract, with Shopify order links (hashedOrderId, shopGraphqlId).

  • Method: GET
  • Path: /subscriptions/{contractId}/history-orders
  • Auth: X-Joy-App-Id, X-Joy-Secret-Key, X-Session-Id

Path parameters

NameTypeNotes
contractIdintegerPositive integer subscriptionContractId.

Query parameters

NameTypeNotes
afterstringCursor for the next page.

Pagination: cursor (via after). meta is { hasNext, hasPre, total }. This endpoint does not return a nextCursor field — use hasNext to decide whether to keep paging, and derive the cursor from your own bookkeeping. Only the all-contracts GET /upcoming-orders endpoint returns meta.nextCursor.

Request

curl -G "https://<your-app-domain>/storefront-api/v1/subscriptions/123456789/history-orders" \
  --data-urlencode "after=<cursor>" \
  -H "X-Joy-App-Id: <app-id>" \
  -H "X-Joy-Secret-Key: sk_live_xxx" \
  -H "X-Session-Id: <session-id>"

Response

{
  "success": true,
  "data": [
    {
      "orderId": 5544332211,
      "billingAttemptExpectedDate": "2026-06-01T00:00:00.000Z",
      "shopGraphqlId": "12345678",
      "hashedOrderId": "abc123…",
      "lines": [ /* … */ ]
    }
  ],
  "meta": { "hasNext": true, "hasPre": false, "total": 24 }
}

GET /subscriptions/{contractId}/next-charge

Preview the next charge of a contract at a point in time — merged cycle prices, discounts, shipping/delivery price, and estimatedTax.

  • Method: GET
  • Path: /subscriptions/{contractId}/next-charge
  • Auth: X-Joy-App-Id, X-Joy-Secret-Key, X-Session-Id

Path parameters

NameTypeNotes
contractIdintegerPositive integer subscriptionContractId.

Query parameters

NameTypeDefaultNotes
datestring (ISO 8601)nowPreview the cycle effective at this date.

Request

curl -G "https://<your-app-domain>/storefront-api/v1/subscriptions/123456789/next-charge" \
  --data-urlencode "date=2026-07-01T00:00:00.000Z" \
  -H "X-Joy-App-Id: <app-id>" \
  -H "X-Joy-Secret-Key: sk_live_xxx" \
  -H "X-Session-Id: <session-id>"

Response

{
  "success": true,
  "data": {
    "cycleIndex": 5,
    "lines": [ /* merged */ ],
    "discounts": [ /* … */ ],
    "shippingPrice": "5.00",
    "deliveryPrice": "5.00",
    "estimatedTax": "1.20"
  }
}

GET /subscriptions/{contractId}/shipping-options

Available shipping/delivery options for the contract, based on current lines plus the delivery address. contractId is taken only from the path param.

  • Method: GET
  • Path: /subscriptions/{contractId}/shipping-options
  • Auth: X-Joy-App-Id, X-Joy-Secret-Key, X-Session-Id

Path parameters

NameTypeNotes
contractIdintegerPositive integer subscriptionContractId.

Query parameters: none.

Request

curl "https://<your-app-domain>/storefront-api/v1/subscriptions/123456789/shipping-options" \
  -H "X-Joy-App-Id: <app-id>" \
  -H "X-Joy-Secret-Key: sk_live_xxx" \
  -H "X-Session-Id: <session-id>"

Response

{
  "success": true,
  "data": [
    { "handle": "…", "title": "Standard", "price": "5.00" }
  ]
}
Product
Install on ShopifyWebsitePricing
Resources
DocumentationGetting StartedFAQsIntegrations
Company
Avada GroupContact Support
© 2026 Avada Group. All rights reserved.