Conventions
A handful of conventions apply to every endpoint in the Seller API. Read this page once and you can stop thinking about formatting.
Money
All monetary amounts are integers expressed in the currency's minor units (cents for USD, pence for GBP, and so on). This matches the convention used by Stripe and most payment APIs.
| You see | It means |
|---|---|
999 + "USD" | $9.99 |
1250 + "EUR" | €12.50 |
0 | Zero |
null | Not applicable to this record |
To display an amount, divide by 100:
const display = (amount, currency) =>
new Intl.NumberFormat("en-US", { style: "currency", currency })
.format(amount / 100);
display(999, "USD"); // "$9.99"Fields that follow this convention include:
productOption.pricecustomer.totalPaidinvoice.amountdiscount.amountOffdiscount.minimumSpend,discount.maximumSpend
discount.percentOff is the exception — it's a whole-number percentage from 0 to 100.
Currency codes
All currency codes are uppercase ISO 4217 strings ("USD", "EUR", "GBP"). They appear next to the field they describe.
Timestamps
The API uses two timestamp formats depending on the resource. Both are unambiguous, but they're different — pay attention.
ISO 8601 strings
Most timestamps are returned as UTC ISO 8601 strings:
"createdAt": "2026-04-25T10:32:01.000Z"Used by: customer.memberSince, invoice.createdAt, discount.startsAt, discount.expiresAt.
Unix seconds
Subscription lifecycle timestamps are returned as Unix epoch seconds (integer):
"startedAt": 1745539921,
"expiresAt": 1748131921Used by: subscription.startedAt, subscription.expiresAt.
This matches the format used by webhook payloads. To convert in JavaScript:
new Date(unixSeconds * 1000);Inputs you provide
Date inputs you send (query parameters like createdAfter, request body fields like expiresAt) must be valid ISO 8601 strings. The API accepts standard formats such as:
2026-04-25T00:00:00Z
2026-04-25T10:32:01.000ZIdentifiers
- Discord IDs (server ID, customer / user ID, role ID) are strings of digits, e.g.
"123456789012345678". Always treat these as strings — they exceed JavaScript's safe integer range. - Subscord IDs (subscription, product, product option, discount) are returned as strings in responses, even though they are numeric in our database. Path parameters (e.g.
/v1/subscriptions/{id}) accept the integer form. - Invoice IDs are non-numeric strings (e.g.
"cs_test_..."or"inv_..."depending on the payment method). Always treat as opaque strings. - Idempotency keys are arbitrary client-generated strings. See Idempotency.
Response shapes
Single-resource responses
Single-resource endpoints return the resource directly:
{
"id": "42",
"name": "Premium",
"...": "..."
}List responses
List endpoints return an envelope with data and nextCursor:
{
"data": [
{ "id": "1", "...": "..." },
{ "id": "2", "...": "..." }
],
"nextCursor": "eyJpZCI6Mn0"
}nextCursor is null when there are no more pages. See Pagination for how to use it.
Error responses
All errors share a single envelope:
{
"error": {
"code": "not_found",
"message": "Subscription not found."
}
}See Errors for the full reference.
Booleans
Booleans are real JSON booleans (true / false), not 0 / 1 or "yes" / "no". Subscription status and freeTrial fields are exceptions — they are human-readable strings to match the dashboard's CSV export format.
Nullable fields
Optional fields are explicitly returned as null rather than omitted, so your client can rely on the shape being consistent.
Times of day
Anywhere the API filters by date (createdAfter, createdBefore, start, end) the comparison uses the exact instant you provide. There is no implicit "round to start of day" — if you want a full day, pass T00:00:00Z and T23:59:59Z.