Developer docs v0.1.0

Subscriptions

Recurring billing, billed in advance.

Concepts, behaviour and examples: Subscriptions guide.

GET /v1/subscriptions

List subscriptions

Cursor-paginated (limit, starting_after).

Authentication
Merchant API key
Effect
Read-only.

Query parameters

NameTypeRequiredDescription
limitintegernoPage size (1–100). · ≥ 1, ≤ 100, default 20
starting_afterstringnoObject ID; return objects after it (ascending ID order). · 26 chars
customerstringnoFilter by customer ID. · 26 chars
status"incomplete" | "incomplete_expired" | "trialing" | "active" | "past_due" | "unpaid" | "paused" | "canceled"noFilter by status.

Responses

StatusMeaningBody / error codes
200Success.object
400Invalid request.invalid_query_param
401Missing or invalid API key.authentication_error
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "list",
  "url": "string",
  "has_more": false,
  "data": [
    {
      "object": "subscription",
      "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "status": "incomplete",
      "default_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "collection_method": "charge_automatically",
      "billing_cycle_anchor": "2026-10-25T18:00:00.000Z",
      "current_period_start": "2026-10-25T18:00:00.000Z",
      "current_period_end": "2026-10-25T18:00:00.000Z",
      "trial_start": "2026-10-25T18:00:00.000Z",
      "trial_end": "2026-10-25T18:00:00.000Z",
      "cancel_at": "2026-10-25T18:00:00.000Z",
      "next_payment_attempt": "2026-10-25T18:00:00.000Z",
      "cancel_at_period_end": false,
      "canceled_at": "2026-10-25T18:00:00.000Z",
      "ended_at": "2026-10-25T18:00:00.000Z",
      "pause_collection": {
        "behavior": "void",
        "resumes_at": "2026-10-25T18:00:00.000Z"
      },
      "metadata": {},
      "description": "string",
      "items": [
        {
          "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
          "price_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
          "quantity": 1,
          "metadata": {}
        }
      ],
      "created_at": "2026-10-25T18:00:00.000Z",
      "updated_at": "2026-10-25T18:00:00.000Z"
    }
  ]
}

POST /v1/subscriptions

Create a subscription

Bills in advance. Without a trial a pending first charge is committed with the subscription. With an Idempotency-Key the response is incomplete and the charge is submitted after commit; without a key the synchronous response is active on success or incomplete on decline/pending. A 201 does not mean the customer has paid — read status and consume payment.succeeded/payment.failed.

Authentication
Merchant API key
Effect
Creates the subscription and its first-period charge (none during a trial); emits subscription.created.

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoMakes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars

Request body

FieldTypeRequiredDescription
customer_idstringyesULID · 26 chars
itemsobject[]yesAll prices must share currency and interval, be active, and belong to non-archived products. · ≥ 1 items, ≤ 100 items
items[].price_idstringyesULID · 26 chars
items[].quantityintegerno≥ 1, default 1
items[].metadataobjectnoFree-form key/value data. Each value ≤16 KiB of JSON, ≤8 nesting levels, ≤100 properties/elements.
default_instrument_idstring | nullnoDefaults to the customer's default instrument. Required unless a trial starts. · 26 chars
metadataobjectnoFree-form key/value data. Each value ≤16 KiB of JSON, ≤8 nesting levels, ≤100 properties/elements.
descriptionstringno≤ 500 chars
trial_period_daysintegernoMutually exclusive with trial_end. · > 0
trial_endstring (date-time)no
Example request
{
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "items": [
    {
      "price_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "quantity": 1,
      "metadata": {}
    }
  ],
  "default_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "metadata": {},
  "description": "string",
  "trial_period_days": 1,
  "trial_end": "2026-10-25T18:00:00.000Z"
}

Responses

StatusMeaningBody / error codes
201Created (not necessarily paid).Subscription
400Rule violation.instrument_required price_inactive product_inactive mixed_billing_dimensions instrument_enrollment_required
401Missing or invalid API key.authentication_error
404Not found, or not yours.resource_missing
409Another change holds the subscription lock; retry.subscription_locked
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "subscription",
  "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "status": "incomplete",
  "default_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "collection_method": "charge_automatically",
  "billing_cycle_anchor": "2026-10-25T18:00:00.000Z",
  "current_period_start": "2026-10-25T18:00:00.000Z",
  "current_period_end": "2026-10-25T18:00:00.000Z",
  "trial_start": "2026-10-25T18:00:00.000Z",
  "trial_end": "2026-10-25T18:00:00.000Z",
  "cancel_at": "2026-10-25T18:00:00.000Z",
  "next_payment_attempt": "2026-10-25T18:00:00.000Z",
  "cancel_at_period_end": false,
  "canceled_at": "2026-10-25T18:00:00.000Z",
  "ended_at": "2026-10-25T18:00:00.000Z",
  "pause_collection": {
    "behavior": "void",
    "resumes_at": "2026-10-25T18:00:00.000Z"
  },
  "metadata": {},
  "description": "string",
  "items": [
    {
      "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "price_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "quantity": 1,
      "metadata": {}
    }
  ],
  "created_at": "2026-10-25T18:00:00.000Z",
  "updated_at": "2026-10-25T18:00:00.000Z"
}

GET /v1/subscriptions/:id

Retrieve a subscription

Authentication
Merchant API key
Effect
Read-only.

Path parameters

NameTypeRequiredDescription
idstringyesObject ID (ULID). · 26 chars

Responses

StatusMeaningBody / error codes
200Success.Subscription
401Missing or invalid API key.authentication_error
404Not found, or not yours.resource_missing
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "subscription",
  "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "status": "incomplete",
  "default_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "collection_method": "charge_automatically",
  "billing_cycle_anchor": "2026-10-25T18:00:00.000Z",
  "current_period_start": "2026-10-25T18:00:00.000Z",
  "current_period_end": "2026-10-25T18:00:00.000Z",
  "trial_start": "2026-10-25T18:00:00.000Z",
  "trial_end": "2026-10-25T18:00:00.000Z",
  "cancel_at": "2026-10-25T18:00:00.000Z",
  "next_payment_attempt": "2026-10-25T18:00:00.000Z",
  "cancel_at_period_end": false,
  "canceled_at": "2026-10-25T18:00:00.000Z",
  "ended_at": "2026-10-25T18:00:00.000Z",
  "pause_collection": {
    "behavior": "void",
    "resumes_at": "2026-10-25T18:00:00.000Z"
  },
  "metadata": {},
  "description": "string",
  "items": [
    {
      "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "price_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "quantity": 1,
      "metadata": {}
    }
  ],
  "created_at": "2026-10-25T18:00:00.000Z",
  "updated_at": "2026-10-25T18:00:00.000Z"
}

POST /v1/subscriptions/:id

Update a subscription

Partial update. Changing items replaces all items; they must keep the subscription's currency and interval. On an active subscription the price difference for the rest of the period is charged first (proration_behavior: create_prorations, default); a declined unkeyed charge returns 402 and leaves items unchanged, a pending result holds the change until it settles. Mid-period downgrades return 409 proration_credit_unsupported — send proration_behavior: none to change items with no charge/credit (billed from the next period). trialing, paused and past_due change items without proration. Pausing: pause_collection: {behavior: "void", resumes_at}; null resumes.

Authentication
Merchant API key
Effect
Updates the subscription; may create a proration charge, pause or resume it; emits subscription.updated/paused/resumed.

Path parameters

NameTypeRequiredDescription
idstringyesObject ID (ULID). · 26 chars

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoMakes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars

Request body

FieldTypeRequiredDescription
default_instrument_idstring | nullnoULID · 26 chars
itemsobject[]no≥ 1 items
items[].price_idstringyesULID · 26 chars
items[].quantityintegerno≥ 1, default 1
items[].metadataobjectnoFree-form key/value data. Each value ≤16 KiB of JSON, ≤8 nesting levels, ≤100 properties/elements.
metadataobjectnoFree-form key/value data. Each value ≤16 KiB of JSON, ≤8 nesting levels, ≤100 properties/elements.
descriptionstringno≤ 500 chars
cancel_at_period_endbooleanno
pause_collectionobject | nullno
pause_collection.behavior"void"yes
pause_collection.resumes_atstring (date-time)noOptional; must be in the future.
proration_behavior"create_prorations" | "none"nodefault "create_prorations"
Example request
{
  "default_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "items": [
    {
      "price_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "quantity": 1,
      "metadata": {}
    }
  ],
  "metadata": {},
  "description": "string",
  "cancel_at_period_end": false,
  "pause_collection": {
    "behavior": "void",
    "resumes_at": "2026-10-25T18:00:00.000Z"
  },
  "proration_behavior": "create_prorations"
}

Responses

StatusMeaningBody / error codes
200Success.SubscriptionWithProration
400Rule violation.mixed_billing_dimensions instrument_required price_inactive product_inactive
401Missing or invalid API key.authentication_error
402Unkeyed proration charge declined; items unchanged.proration_payment_failed
404Not found, or not yours.resource_missing
409State conflict.subscription_not_updatable proration_in_progress proration_credit_unsupported invalid_status_transition subscription_locked
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "subscription",
  "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "status": "incomplete",
  "default_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "collection_method": "charge_automatically",
  "billing_cycle_anchor": "2026-10-25T18:00:00.000Z",
  "current_period_start": "2026-10-25T18:00:00.000Z",
  "current_period_end": "2026-10-25T18:00:00.000Z",
  "trial_start": "2026-10-25T18:00:00.000Z",
  "trial_end": "2026-10-25T18:00:00.000Z",
  "cancel_at": "2026-10-25T18:00:00.000Z",
  "next_payment_attempt": "2026-10-25T18:00:00.000Z",
  "cancel_at_period_end": false,
  "canceled_at": "2026-10-25T18:00:00.000Z",
  "ended_at": "2026-10-25T18:00:00.000Z",
  "pause_collection": {
    "behavior": "void",
    "resumes_at": "2026-10-25T18:00:00.000Z"
  },
  "metadata": {},
  "description": "string",
  "items": [
    {
      "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "price_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "quantity": 1,
      "metadata": {}
    }
  ],
  "created_at": "2026-10-25T18:00:00.000Z",
  "updated_at": "2026-10-25T18:00:00.000Z",
  "proration_transaction": {
    "object": "payment",
    "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
    "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
    "subscription_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
    "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
    "instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
    "amount": 1,
    "currency": "RON",
    "status": "pending",
    "netopia_ntp_id": "string",
    "netopia_status_code": 1,
    "error_message": "string",
    "period_start": "2026-10-25T18:00:00.000Z",
    "period_end": "2026-10-25T18:00:00.000Z",
    "description": "string",
    "metadata": {},
    "proration": false,
    "review": {
      "status": "open",
      "reason": "subscription_expired",
      "opened_at": "2026-10-25T18:00:00.000Z",
      "resolution": "refunded_externally",
      "note": "string",
      "resolved_at": "2026-10-25T18:00:00.000Z",
      "resolved_by_api_key_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C"
    },
    "created_at": "2026-10-25T18:00:00.000Z",
    "payment_link_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
    "payer_email": "string"
  }
}

DELETE /v1/subscriptions/:id

Cancel a subscription

Cancels immediately (no refund). With at_period_end=true the paid period is kept and a fixed cancel_at deadline is set; it cancels without a further charge once due.

Authentication
Merchant API key
Effect
Cancels now (subscription.canceled) or schedules cancellation (subscription.updated).

Path parameters

NameTypeRequiredDescription
idstringyesObject ID (ULID). · 26 chars

Query parameters

NameTypeRequiredDescription
at_period_endbooleannoCancel at period end instead of now. · default false

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoMakes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars

Responses

StatusMeaningBody / error codes
200The canceled or scheduled subscription.Subscription
401Missing or invalid API key.authentication_error
404Not found, or not yours.resource_missing
409State conflict.invalid_status_transition subscription_locked
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "subscription",
  "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "status": "incomplete",
  "default_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "collection_method": "charge_automatically",
  "billing_cycle_anchor": "2026-10-25T18:00:00.000Z",
  "current_period_start": "2026-10-25T18:00:00.000Z",
  "current_period_end": "2026-10-25T18:00:00.000Z",
  "trial_start": "2026-10-25T18:00:00.000Z",
  "trial_end": "2026-10-25T18:00:00.000Z",
  "cancel_at": "2026-10-25T18:00:00.000Z",
  "next_payment_attempt": "2026-10-25T18:00:00.000Z",
  "cancel_at_period_end": false,
  "canceled_at": "2026-10-25T18:00:00.000Z",
  "ended_at": "2026-10-25T18:00:00.000Z",
  "pause_collection": {
    "behavior": "void",
    "resumes_at": "2026-10-25T18:00:00.000Z"
  },
  "metadata": {},
  "description": "string",
  "items": [
    {
      "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "price_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "quantity": 1,
      "metadata": {}
    }
  ],
  "created_at": "2026-10-25T18:00:00.000Z",
  "updated_at": "2026-10-25T18:00:00.000Z"
}

POST /v1/subscriptions/:id/resume

Resume a paused subscription

If the paid period has already ended a new period starts immediately and is charged; otherwise the existing period is kept. A due scheduled cancellation cancels instead.

Authentication
Merchant API key
Effect
Clears the pause; may start and charge a new period; emits subscription.resumed.

Path parameters

NameTypeRequiredDescription
idstringyesObject ID (ULID). · 26 chars

Headers

NameTypeRequiredDescription
Idempotency-KeystringnoMakes retries safe: same key + body replays the stored response (idempotency-replayed: true); a different body returns 409 idempotency_key_in_use. · ≤ 96 chars

Responses

StatusMeaningBody / error codes
200Success.Subscription
401Missing or invalid API key.authentication_error
404Not found, or not yours.resource_missing
409State conflict.invalid_status_transition subscription_locked
429Rate limited; honor retry-after.rate_limit_exceeded too_many_auth_failures
500Server error.api_error
Example response
{
  "object": "subscription",
  "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "merchant_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "customer_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "status": "incomplete",
  "default_instrument_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
  "collection_method": "charge_automatically",
  "billing_cycle_anchor": "2026-10-25T18:00:00.000Z",
  "current_period_start": "2026-10-25T18:00:00.000Z",
  "current_period_end": "2026-10-25T18:00:00.000Z",
  "trial_start": "2026-10-25T18:00:00.000Z",
  "trial_end": "2026-10-25T18:00:00.000Z",
  "cancel_at": "2026-10-25T18:00:00.000Z",
  "next_payment_attempt": "2026-10-25T18:00:00.000Z",
  "cancel_at_period_end": false,
  "canceled_at": "2026-10-25T18:00:00.000Z",
  "ended_at": "2026-10-25T18:00:00.000Z",
  "pause_collection": {
    "behavior": "void",
    "resumes_at": "2026-10-25T18:00:00.000Z"
  },
  "metadata": {},
  "description": "string",
  "items": [
    {
      "id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "price_id": "01JB9XK3M2R7TQ8N4V6Y0ZPA1C",
      "quantity": 1,
      "metadata": {}
    }
  ],
  "created_at": "2026-10-25T18:00:00.000Z",
  "updated_at": "2026-10-25T18:00:00.000Z"
}