For the complete documentation index, see llms.txt. This page is also available as Markdown.

Payments

The Payments API is the public surface for the platform's payment session model. A payment session is a short-lived, tenant-scoped record that ties together an account, an amount, an optional invoice, and the payment page (CMS slug) that will collect the funds. The collection itself happens in the gateway (Stripe Elements, Zuora hosted page, etc.); this API is the orchestrator and the audit boundary, not the card-data path.

A typical flow:

  1. POST /api/v1/payments — create a session for (accountId, amountCents, currency), optionally bound to an invoiceId and a paymentPageSlug.

  2. The customer is redirected to the rendered payment page; the gateway widget completes the charge.

  3. POST /api/v1/payments/{id}/complete — the gateway callback (or a webhook handler) marks the session complete; the corresponding invoice (if any) is settled.

  4. GET /api/v1/payments/{id} — read the resolved session for receipts / reconciliation.

All endpoints require an API key. Writes use the commerce scope, reads use read. Card data is never accepted by this API; it always flows through the gateway directly.

paymentPageSlug is resolved within the tenant scope of the calling API key — page slugs are unique per tenant, not globally, so two tenants may safely reuse the same slug.

See also: Invoices (POST /invoices/{id}/pay is the invoice-driven entry point), PaymentMethods.

Endpoints

POST /api/v1/payment-links

Issue a signed payment link for an open invoice

post
/payment-links

Returns a link to a payment page that opens for one billing account and pays toward one open invoice. The link expires at the invoice due date (or today, if already past due) plus the tenant's grace window, never more than 30 days out. It stays usable until that invoice has no open balance, so a partial payment can be finished and a declined card retried from the same link; saving a payment method without paying uses it up. url is null when no active hostname serves the page yet; path is always returned. Typical use: a billing-system workflow issues the link when an invoice posts and writes it into the invoice field its email template includes.

Authorizations
X-API-KeystringRequired

Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.

Body
pageSlugstringRequired

Slug of the payment page the link opens

accountIdstringRequired

Billing-system account id

invoiceIdstringRequired

Open invoice the link is for (id or invoice number)

Responses
201

Link issued

application/json
post/payment-links
POST /api/v1/payment-links HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 57

{
  "pageSlug": "text",
  "accountId": "text",
  "invoiceId": "text"
}
{
  "data": {
    "url": "text",
    "path": "text",
    "expiresAt": "2026-01-01T00:00:00.000Z",
    "invoiceId": "text",
    "pageSlug": "text"
  }
}

Notes, examples, or caveats for POST /payment-links go here.

GET /api/v1/payments

List all payment sessions for the tenant

get
/payments
Authorizations
X-API-KeystringRequired

Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.

Query parameters
limitinteger · min: 1 · max: 100Optional

Max items to return (1–100, default 20)

Default: 20
offsetintegerOptional

Number of items to skip (default 0)

Default: 0
sortstringOptional

Field to sort by

sortDirstring · enumOptional

Sort direction

Default: ascPossible values:
statusstringOptional

Filter by status

Responses
200

Paginated list of payment sessions

get/payments
GET /api/v1/payments HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*

No content

Returns every payment session for the calling tenant in a single page (no cursor pagination yet). Useful for reconciliation and reporting; not intended as a customer-facing list. Filter / sort client-side by status, accountId, or createdAt.

Requires the read scope. Sessions stay in the response after completion; treat the row as immutable once status reaches a terminal state.

POST /api/v1/payments

Create a payment session

post
/payments
Authorizations
X-API-KeystringRequired

Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.

Header parameters
Idempotency-KeystringOptional

Idempotency key to safely retry without creating duplicates

Body
accountIdstringRequired
amountCentsintegerRequired
currencystringRequired
invoiceIdstringOptional
paymentPageSlugstringOptional
Responses
201

Payment session created

No content

post/payments
POST /api/v1/payments HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 98

{
  "accountId": "text",
  "amountCents": 1,
  "currency": "text",
  "invoiceId": "text",
  "paymentPageSlug": "text"
}

No content

Creates a new payment session. The session captures intent, not a charge — no funds move until the gateway widget confirms.

Provide paymentPageSlug to bind the session to a specific CMS-authored payment page (recommended; the rendered page knows which gateway widget to mount). Provide invoiceId to bind the session to an open invoice; on completion the invoice will be marked paid via the active billing adapter.

Requires the commerce scope. Returns 201 and a nextActions hint pointing to the rendered payment-page URL and POST /payments/{id}/complete.

GET /api/v1/payments/{id}

Get payment session details

get
/payments/{id}
Authorizations
X-API-KeystringRequired

Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.

Path parameters
idstringRequired
Responses
200

Payment session details

No content

get/payments/{id}
GET /api/v1/payments/{id} HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
200

Payment session details

No content

Returns the full payment-session record including its current status, the linked invoiceId (if any), the resolved gateway transaction id once the session has completed, and the audit metadata. Safe to poll while waiting for a webhook to mark the session complete.

Requires the read scope.

POST /api/v1/payments/{id}/complete

Mark a payment session as completed

post
/payments/{id}/complete
Authorizations
X-API-KeystringRequired

Scoped secret API key — send an sk_live_… value (keys issued before the typed format carry a bare pk_<hex> prefix and are also secret; they still work). A publishable pk_live_…/pk_test_… key is browser-safe, carries no scopes, and is refused by every endpoint in this spec with publishable_key_not_allowed. Coarse scopes: read, commerce, admin (admin covers everything below). Narrow per-resource scopes: journeys|pages :read|write|publish|delete, productsets :read|write|publish|delete, components|rules :read|write|delete, context :read (read-only context tier), catalog :read|write-native. publish is never implied by write.

Path parameters
idstringRequired
Responses
200

Payment session completed

No content

post/payments/{id}/complete
POST /api/v1/payments/{id}/complete HTTP/1.1
Host: api.peakcommerce.app
X-API-Key: YOUR_API_KEY
Accept: */*
200

Payment session completed

No content

Idempotent terminator for a session. Use this from the gateway success callback or from a webhook handler once the gateway confirms funds. Settles the linked invoice through the active billing adapter, writes payment.complete to the audit log, and emits the payment.succeeded event to subscribed webhooks.

Calling complete on a session that is already in a terminal state is a no-op (returns 200). Calling it on a session whose gateway transaction has not actually succeeded is a programming error — this endpoint trusts the caller and does not re-verify the gateway side.

Requires the commerce scope.

Last updated

Was this helpful?