API Reference (Max only)
Subscriptions

Subscriptions

A subscription is the binding between a customer, a product, and a product option for a defined period of time. Subscriptions can be active or expired, recurring or one-off, paid or free trials.

The Seller API supports listing, reading, granting, extending, and canceling subscriptions. Deletion is not supported.

GET /v1/subscriptions

List subscriptions, most recent first.

Tier: B  ·  Auth: required  ·  Idempotent: N/A

Query parameters

ParameterTypeDescription
activebooleanFilter by active state.
customerIdstringFilter by Discord user ID.
productIdintegerFilter by product.
paymentMethodstringOne of stripe, crypto, free.
limitintegerPage size (max 100, default 50).
cursorstringPagination cursor.

Request

curl "https://subscord.com/api/v1/subscriptions?active=true&productId=42&limit=25" \
  -H "Authorization: Bearer ssk_live_..."

Response — 200 OK

{
  "data": [
    {
      "id": "1532",
      "customerDiscordId": "987654321098765432",
      "username": "johndoe",
      "product": { "name": "Premium" },
      "productOption": { "name": "Monthly" },
      "startedAt": 1745539921,
      "expiresAt": 1748131921,
      "status": "Active",
      "type": "Recurring",
      "freeTrial": "No",
      "paymentMethod": "stripe"
    }
  ],
  "nextCursor": "eyJpZCI6MTUzMn0"
}

GET /v1/subscriptions/{id}

Returns a single subscription.

Tier: A  ·  Auth: required  ·  Idempotent: N/A

Path parameters

ParameterTypeDescription
idintegerThe subscription ID.

Request

curl https://subscord.com/api/v1/subscriptions/1532 \
  -H "Authorization: Bearer ssk_live_..."

Response — 200 OK

Same shape as a single entry in the list response above.

POST /v1/subscriptions

Manually grant a subscription to a customer. Useful for backfills, manual sales handled outside Subscord, or comp accounts.

Tier: D  ·  Auth: required  ·  Idempotent: required (Idempotency-Key header)

Note. This creates the Subscord subscription record and updates the customer's Discord roles. It does not charge the customer or open a Stripe subscription. The created subscription is recorded with paymentMethod: "free" until a real invoice is attached. If the customer is not yet a Subscord customer, they are created as part of this call.

Request body

FieldTypeDescription
customer.idstringThe Discord user ID.
customer.usernamestringThe Discord username (used to create or refresh the customer record).
customer.avatarstringOptional avatar URL or hash.
productIdintegerThe product to subscribe them to.
optionIdintegerThe product option that defines billing period. Must belong to productId.
expiresAtstringISO 8601 UTC timestamp when the subscription should expire. Must be in the future.

Request

curl https://subscord.com/api/v1/subscriptions \
  -X POST \
  -H "Authorization: Bearer ssk_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0e9f8c8b-c3f4-4e1d-9b9a-1a2b3c4d5e6f" \
  -d '{
    "customer": {
      "id": "987654321098765432",
      "username": "johndoe"
    },
    "productId": 42,
    "optionId": 101,
    "expiresAt": "2026-12-31T23:59:59Z"
  }'

Response — 201 Created

Returns the newly created subscription using the same shape as GET /v1/subscriptions/{id}.

Errors

StatusCodeWhen
400invalid_requestMissing or invalid fields. productId does not belong to this server. optionId does not belong to productId. expiresAt is in the past or invalid.
409conflictThe server's plan member limit has been reached and no more subscriptions can be granted.

POST /v1/subscriptions/{id}/extend

Extend a subscription by a number of days. For Stripe-backed subscriptions, this also pushes the next renewal date in Stripe.

Tier: D  ·  Auth: required  ·  Idempotent: required

Path parameters

ParameterTypeDescription
idintegerThe subscription ID.

Request body

FieldTypeDescription
daysintegerNumber of days to extend (1 to 365).

Request

curl https://subscord.com/api/v1/subscriptions/1532/extend \
  -X POST \
  -H "Authorization: Bearer ssk_live_..." \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: extend-1532-2026-04-25" \
  -d '{ "days": 30 }'

Response — 200 OK

Returns the updated subscription.

Errors

StatusCodeWhen
400invalid_requestid is not an integer or days is out of range.
404not_foundNo subscription with that ID exists for this server.

POST /v1/subscriptions/{id}/cancel

Cancel a subscription. Marks it inactive in Subscord, cancels the Stripe subscription if applicable, and refreshes the customer's Discord roles.

Tier: D  ·  Auth: required  ·  Idempotent: required

No-op when already inactive. Calling cancel on a subscription that is already inactive is safe — the API simply returns the current state without making any changes.

Path parameters

ParameterTypeDescription
idintegerThe subscription ID.

Request

curl https://subscord.com/api/v1/subscriptions/1532/cancel \
  -X POST \
  -H "Authorization: Bearer ssk_live_..." \
  -H "Idempotency-Key: cancel-1532-once" \
  -H "Content-Type: application/json"

Response — 200 OK

Returns the canceled subscription with status: "Expired".

Errors

StatusCodeWhen
400invalid_requestid is not an integer.
404not_foundNo subscription with that ID exists for this server.

Field reference

The response shape mirrors the CSV export in your dashboard, plus customerDiscordId for stable cross-system linking.

FieldTypeDescription
idstringSubscription ID.
customerDiscordIdstringThe customer's Discord user ID.
usernamestringThe customer's Discord username at the time of the response.
product.namestring | nullThe product name.
productOption.namestring | nullThe product option name.
startedAtintegerUnix timestamp (seconds) when the subscription started. See Conventions.
expiresAtintegerUnix timestamp (seconds) when the subscription expires.
statusstring"Active" or "Expired".
typestring"Recurring" or "One-off".
freeTrialstring"Yes" or "No".
paymentMethodstring | null"stripe", "crypto", "free", or null.