Skip to content

API operations

Every operation below is rendered during the static build from the curated OpenAPI artifact. The JSON examples are the same generated files exercised by the contract validator.

GET/api/channel/api-keys

List the calling channel's API keys

List every API key issued to the calling channel, newest first, revoked ones included — which key was live when is part of the record. This listing never returns secrets; plaintext is available only from creation or the invitation flow's bounded response recovery. Authenticate with a channel API key (Authorization: Bearer sk_test_...). The key acts on the channel that issued it and no other, so no channel id is taken from the request.

Authentication

  • ChannelApiKey

Responses

200 response

Successful Response

Inline 200 response schema
{
"items": {
"$ref": "#/components/schemas/MerchantApiKeyResponse"
},
"title": "Response List Own Channel Api Keys Api Channel Api Keys Get",
"type": "array"
}
200 response example
list_own_channel_api_keys_api_channel_api_keys_get.response.200.json
[]
POST/api/channel/api-keys

Issue the calling channel another API key

Issue an additional key for the calling channel and return its plaintext **once** — it is stored only as a hash and cannot be read again. This is the first half of a rotation: mint, deploy, then revoke the old key. There is a cap on how many keys a channel may hold active at a time; revoke one you no longer deploy before minting past it. Authenticate with a channel API key (Authorization: Bearer sk_test_...). The key acts on the channel that issued it and no other, so no channel id is taken from the request.

Authentication

  • ChannelApiKey

Request

Schema: ChannelApiKeyCreateRequest

Request example

create_own_channel_api_key_api_channel_api_keys_post.request.json
{
"name": "example"
}

Responses

201 response

Successful Response

Schema: MerchantApiKeyCreateResponse

201 response example
create_own_channel_api_key_api_channel_api_keys_post.response.201.json
{
"created_at": "example",
"environment": "example",
"id": "example",
"key": "example",
"name": "example",
"prefix": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/channel/api-keys/{key_id}/revoke

Revoke one of the calling channel's API keys

Stop a key working, immediately and permanently. Revoking a key that is already revoked succeeds and changes nothing, so a retry after a lost response is safe. A channel may revoke the key it is calling with — including its last one. That is deliberate: a leaked credential is worth more urgency than a locked-out integration. Recovering from it is not instant, so know the cost before you spend it: an operator can no longer hand over a replacement key directly, only issue an invitation, which your registered owner has to receive and redeem before your integration can call again. Authenticate with a channel API key (Authorization: Bearer sk_test_...). The key acts on the channel that issued it and no other, so no channel id is taken from the request.

Authentication

  • ChannelApiKey

Parameters

  • key_idpathRequired
    key_id parameter schema
    {
    "title": "Key Id",
    "type": "string"
    }

Responses

200 response

Successful Response

Schema: MerchantApiKeyResponse

200 response example
revoke_own_channel_api_key_api_channel_api_keys__key_id__revoke_post.response.200.json
{
"created_at": "example",
"environment": "example",
"id": "example",
"name": "example",
"prefix": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/channel/merchants

List the calling channel's merchants

Every merchant owned by the calling channel, newest first, paged. Authenticate with a channel API key (Authorization: Bearer sk_test_...); the key names the channel, so no channel id is taken from the request and a merchant belonging to anyone else — or to no channel at all — is never returned. Each row carries onboarding_status and payments_enabled, the two fields that decide what you can do with a merchant today, alongside the business_name and email you supplied when you provisioned it. That makes this the way back to a merchant_id you no longer hold: email is unique across the platform and you chose it, so ?email= returns exactly the merchant you mean — an exact, case-insensitive equality match, never a substring. Narrow with onboarding_status, repeatable — ?onboarding_status=pending&onboarding_status=in_progress is every merchant not yet through PayPal, in one call instead of a scan. search matches a case-insensitive substring of business_name or email, for browsing. Page with limit (default 50, max 200) and offset; total is the count under the same filters, so it says when to stop. This read does not call PayPal. It reports what we last recorded, which is what a webhook or the onboarding sweep last told us. Use GET /api/channel/onboarding/status for the live, PayPal-refreshed state of one merchant and for the per-capability map this listing omits.

Authentication

  • ChannelApiKey

Parameters

  • onboarding_statusqueryOptional

    Keep only merchants in these onboarding states. Repeat the parameter for more than one. Filtering is on the stored state.

    onboarding_status parameter schema
    {
    "anyOf": [
    {
    "items": {
    "$ref": "#/components/schemas/OnboardingStatus"
    },
    "type": "array"
    },
    {
    "type": "null"
    }
    ],
    "description": "Keep only merchants in these onboarding states. Repeat the parameter for more than one. Filtering is on the stored state.",
    "title": "Onboarding Status"
    }
  • searchqueryOptional

    Case-insensitive substring of business_name or email, for browsing. Stripped before it is measured, so a value of only whitespace is a 422 rather than a filter that silently matches everything. For recovering a merchant_id, prefer email.

    search parameter schema
    {
    "anyOf": [
    {
    "maxLength": 255,
    "minLength": 1,
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "description": "Case-insensitive substring of `business_name` or `email`, for browsing. Stripped before it is measured, so a value of only whitespace is a `422` rather than a filter that silently matches everything. For recovering a `merchant_id`, prefer `email`.",
    "title": "Search"
    }
  • emailqueryOptional

    Exact, case-insensitive match on the address you supplied at provisioning — the lost-merchant_id recovery key. Returns at most one merchant, because emails are unique across the platform. A value that is not an email address is a 422.

    email parameter schema
    {
    "anyOf": [
    {
    "format": "email",
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "description": "Exact, case-insensitive match on the address you supplied at provisioning — the lost-`merchant_id` recovery key. Returns at most one merchant, because emails are unique across the platform. A value that is not an email address is a `422`.",
    "title": "Email"
    }
  • limitqueryOptional
    limit parameter schema
    {
    "default": 50,
    "maximum": 200,
    "minimum": 1,
    "title": "Limit",
    "type": "integer"
    }
  • offsetqueryOptional
    offset parameter schema
    {
    "default": 0,
    "minimum": 0,
    "title": "Offset",
    "type": "integer"
    }

Responses

200 response

Successful Response

Schema: ChannelMerchantListResponse

200 response example
list_channel_merchants_api_channel_merchants_get.response.200.json
{
"limit": 1,
"offset": 1,
"total": 1
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/channel/merchants

Create a merchant under the calling channel

Create a new merchant owned by the calling channel. Authenticate with a channel API key (Authorization: Bearer sk_test_...); ownership always comes from the credential, never from the request body — a channel_id field in the body is rejected as unknown input. country_code is required and must identify the merchant's real ISO country; omission is rejected rather than defaulted to US. The created merchant is an ordinary top-level merchant marked with this channel's id; see docs/CHANNELS.md.

Authentication

  • ChannelApiKey

Request

Schema: ChannelMerchantCreateRequest

Request example

create_channel_merchant_api_channel_merchants_post.request.json
{
"business_name": "example",
"country_code": "US",
"email": "developer@example.com"
}

Responses

201 response

Successful Response

Schema: ChannelMerchantCreateResponse

201 response example
create_channel_merchant_api_channel_merchants_post.response.201.json
{
"business_name": "example",
"channel_id": "example",
"country_code": "US",
"created_at": "2026-01-01T00:00:00Z",
"email": "example",
"merchant_id": "example",
"onboarding_status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/channel/onboarding/start

Start PayPal onboarding for a channel merchant

Start the PayPal Integrated Sign-Up flow for one of the caller's merchants and return action_url. Maxana renders no onboarding UI of its own: open action_url inside PayPal's own iframe or mini-browser. 409 means either that the merchant already completed onboarding, which retrying cannot change, or that its PayPal link state changed while the referral was being minted. In the latter case no action_url is returned; read current onboarding status and retry only after any conflict or hold is resolved. Retrying a call that failed is safe: each attempt carries an idempotency key of its own, so a retry after a 503 gets back the referral PayPal may already have minted rather than a second one — while a call made after a successful answer is a new attempt, and mints a new referral. To send a connected merchant back to PayPal on purpose — to grant scopes PayPal reports missing, or to move to another PayPal account — send {"reconnect": true}; the merchant stays connected and keeps taking payments until they finish at PayPal. A failure says whose it was: 503 if PayPal could not be reached, or answered 429/5xx meaning ask again later — carrying PayPal's own Retry-After when it sent one; 502 if PayPal refused the referral, which retrying unchanged will not fix; 500 only for a fault on Maxana's side. Authenticate with a merchant or channel API key (Authorization: Bearer sk_test_...). A channel-scoped key must also pass X-Merchant-Id naming which of its merchants the call is for; an ordinary merchant key does not need it.

Authentication

  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Inline request schema
{
"anyOf": [
{
"$ref": "#/components/schemas/OnboardingStartRequest"
},
{
"type": "null"
}
],
"title": "Body"
}

Request example

start_channel_merchant_onboarding_api_channel_onboarding_start_post.request.json
{}

Responses

200 response

Successful Response

Schema: OnboardingStartResponse

200 response example
start_channel_merchant_onboarding_api_channel_onboarding_start_post.response.200.json
{
"action_url": "https://example.com/return"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/channel/onboarding/status

Read onboarding and PayPal capability status for a channel merchant

Read one of the caller's merchants' onboarding progress and PayPal capability status — which payment features (Advanced Card Checkout, Venmo/Pay Later platform-fee checkout, ...) PayPal has granted so far — so the channel can show its merchant where things stand. A capability PayPal has not granted also says why: in_review means PayPal is still underwriting it and nobody needs to act, while need_more_data means PayPal has asked the merchant for supplementary information and will not move until it arrives. Authenticate with a merchant or channel API key (Authorization: Bearer sk_test_...). A channel-scoped key must also pass X-Merchant-Id naming which of its merchants the call is for; an ordinary merchant key does not need it.

Authentication

  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: ChannelMerchantStatusResponse

200 response example
get_channel_merchant_status_api_channel_onboarding_status_get.response.200.json
{
"checkout_enabled": false,
"merchant_id": "example",
"onboarding_status": "example",
"payments_enabled": false,
"paypal_connection_status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/channel/statements

List the calling channel's statements

Every statement issued to the calling channel, newest period first. A statement is a closed period's record of what Maxana owes the channel: it is stored as issued and never recomputed, so a merchant that later moves to another channel cannot change what a past period says. Amounts are counted at **capture**, not at settlement, and every statement says so in volume_basis. A statement covers exactly one currency and never mixes them. Statements that have been superseded by a correction are hidden unless include_superseded=true; the correction links back to the one it replaced. Authenticate with a channel API key (Authorization: Bearer sk_test_...). The key acts on the channel that issued it and no other, so no channel id is taken from the request.

Authentication

  • ChannelApiKey

Parameters

  • currencyqueryOptional
    currency parameter schema
    {
    "anyOf": [
    {
    "maxLength": 3,
    "minLength": 3,
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "Currency"
    }
  • include_supersededqueryOptional
    include_superseded parameter schema
    {
    "default": false,
    "title": "Include Superseded",
    "type": "boolean"
    }
  • limitqueryOptional
    limit parameter schema
    {
    "default": 50,
    "maximum": 200,
    "minimum": 1,
    "title": "Limit",
    "type": "integer"
    }
  • offsetqueryOptional
    offset parameter schema
    {
    "default": 0,
    "minimum": 0,
    "title": "Offset",
    "type": "integer"
    }

Responses

200 response

Successful Response

Inline 200 response schema
{
"items": {
"$ref": "#/components/schemas/ChannelStatementResponse"
},
"title": "Response List Own Channel Statements Api Channel Statements Get",
"type": "array"
}
200 response example
list_own_channel_statements_api_channel_statements_get.response.200.json
[]

422 response

Validation Error

Schema: HTTPValidationError

GET/api/channel/statements/{statement_id}

Read one of the calling channel's statements

One statement, exactly as it was issued. Alongside the totals it carries a per-rail breakdown covering **all** of the channel's volume in the period, including rails whose platform fee this platform does not record: those show platform_fee_accrued_cents: null — unknown, not zero — and are excluded from the amount owed, with the reason stated. Volume that is present in your webhook feed but absent from the settlement is therefore accounted for rather than missing. Amounts are counted at **capture**, not at settlement, and every statement says so in volume_basis. A statement covers exactly one currency and never mixes them. Authenticate with a channel API key (Authorization: Bearer sk_test_...). The key acts on the channel that issued it and no other, so no channel id is taken from the request.

Authentication

  • ChannelApiKey

Parameters

  • statement_idpathRequired
    statement_id parameter schema
    {
    "title": "Statement Id",
    "type": "string"
    }

Responses

200 response

Successful Response

Schema: ChannelStatementResponse

200 response example
get_own_channel_statement_api_channel_statements__statement_id__get.response.200.json
{
"accounted_captured_amount_cents": 1,
"accounted_captured_amount_display": "example",
"accounted_transaction_count": 1,
"channel_id": "example",
"channel_share_cents": 1,
"channel_share_display": "example",
"correction_reason": "example",
"currency": "USD",
"excluded_captured_amount_cents": 1,
"excluded_captured_amount_display": "example",
"excluded_transaction_count": 1,
"generated_at": "2026-01-01T00:00:00Z",
"id": "example",
"period_end": "2026-01-01",
"period_start": "2026-01-01",
"platform_fee_accrued_cents": 1,
"platform_fee_accrued_display": "example",
"platform_fee_accrued_net_cents": 1,
"platform_fee_accrued_net_display": "example",
"platform_fee_collected_cents": 1,
"platform_fee_collected_display": "example",
"platform_fee_refunded_cents": 1,
"platform_fee_refunded_display": "example",
"rail_summaries": [],
"share_basis": "example",
"status": "example",
"superseded_by_statement_id": "example",
"supersedes_statement_id": "example",
"terms_description": "example",
"terms_fee_share_basis_points": 1,
"terms_per_transaction_currency": "USD",
"terms_per_transaction_minor_units": 1,
"terms_type": "example",
"volume_basis": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/channel/statements/{statement_id}/lines

List the transactions behind one statement

The per-transaction detail of a statement, oldest capture first, so it can be reconciled line by line against your own webhook feed: each line carries the transaction id you were sent, the provider's capture id, the merchant, the platform fee and what that line owes you. Paging is by limit/offset and is stable — an issued statement's lines cannot change, so page two is still page two however long the walk takes; total says when to stop. Lines of type fee_refund_adjustment are platform fee given back on a capture an earlier statement already counted: they carry no volume and a negative amount. Authenticate with a channel API key (Authorization: Bearer sk_test_...). The key acts on the channel that issued it and no other, so no channel id is taken from the request.

Authentication

  • ChannelApiKey

Parameters

  • statement_idpathRequired
    statement_id parameter schema
    {
    "title": "Statement Id",
    "type": "string"
    }
  • limitqueryOptional
    limit parameter schema
    {
    "default": 200,
    "maximum": 500,
    "minimum": 1,
    "title": "Limit",
    "type": "integer"
    }
  • offsetqueryOptional
    offset parameter schema
    {
    "default": 0,
    "minimum": 0,
    "title": "Offset",
    "type": "integer"
    }

Responses

200 response

Successful Response

Schema: ChannelStatementLinesResponse

200 response example
list_own_channel_statement_lines_api_channel_statements__statement_id__lines_get.response.200.json
{
"currency": "USD",
"limit": 1,
"lines": [],
"offset": 1,
"statement_id": "example",
"total": 1
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/channel/webhook-endpoints

List the calling channel's webhook endpoints

Return every endpoint this channel owns, newest first. Secrets are never included — only the hint kept for recognising which secret a row holds. The plaintext exists once, in the create and rotate responses.

Authentication

  • ChannelApiKey

Responses

200 response

Successful Response

Inline 200 response schema
{
"items": {
"$ref": "#/components/schemas/WebhookEndpointResponse"
},
"title": "Response List Channel Webhook Endpoints Api Channel Webhook Endpoints Get",
"type": "array"
}
200 response example
list_channel_webhook_endpoints_api_channel_webhook_endpoints_get.response.200.json
[]
POST/api/channel/webhook-endpoints

Subscribe the calling channel to its merchants' events

Create an endpoint receiving events for every merchant in this channel. The response carries the signing secret in plaintext, and it is the only time it is readable — the row stores it encrypted alongside a hash and a hint. Store it on receipt; there is no endpoint that returns it again, only one that replaces it. A temporary DNS resolution failure returns 424 so the caller can retry without treating an otherwise valid URL as permanently bad.

Authentication

  • ChannelApiKey

Request

Schema: WebhookEndpointCreateRequest

Request example

create_channel_webhook_endpoint_api_channel_webhook_endpoints_post.request.json
{
"url": "https://example.com/return"
}

Responses

201 response

Successful Response

Schema: WebhookEndpointCreateResponse

201 response example
create_channel_webhook_endpoint_api_channel_webhook_endpoints_post.response.201.json
{
"created_at": "example",
"description": "example",
"enabled": false,
"event_types": [],
"id": "example",
"secret": "example",
"secret_hint": "example",
"status": "example",
"updated_at": "example",
"url": "https://example.com/return"
}

422 response

Validation Error

Schema: HTTPValidationError

DELETE/api/channel/webhook-endpoints/{endpoint_id}

Stop delivering to one of the channel's endpoints

Disable an endpoint. Its delivery history is kept, not deleted.

Authentication

  • ChannelApiKey

Parameters

  • endpoint_idpathRequired
    endpoint_id parameter schema
    {
    "title": "Endpoint Id",
    "type": "string"
    }

Responses

200 response

Successful Response

Schema: WebhookEndpointResponse

200 response example
disable_channel_webhook_endpoint_api_channel_webhook_endpoints__endpoint_id__delete.response.200.json
{
"created_at": "example",
"description": "example",
"enabled": false,
"event_types": [],
"id": "example",
"secret_hint": "example",
"status": "example",
"updated_at": "example",
"url": "https://example.com/return"
}

422 response

Validation Error

Schema: HTTPValidationError

PATCH/api/channel/webhook-endpoints/{endpoint_id}

Partially update one of the channel's reusable webhook endpoints

Update any non-empty subset of url, description, and event_types. event_types is a complete replacement list, never a merge. To replace a URL, first disable the endpoint; PATCH keeps the endpoint id and signing secret for same-host changes. A different host requires rotate_secret=true; the response returns the new secret once. Then POST .../enable resumes future delivery. A successful enable does not replay retained NO_SUBSCRIBER events; replay those explicitly if needed. If an echoed current URL becomes stale before serialization, PATCH returns 409 so the caller can read the latest state and retry. A temporary DNS resolution failure returns 424 and leaves the endpoint unchanged. For example, PATCH a disabled endpoint with {"url": "https://receiver.example/webhooks", "rotate_secret": true}, install the returned secret, and then enable it.

Authentication

  • ChannelApiKey

Parameters

  • endpoint_idpathRequired
    endpoint_id parameter schema
    {
    "title": "Endpoint Id",
    "type": "string"
    }

Request

Schema: ChannelWebhookEndpointUpdateRequest

Request example

update_channel_webhook_endpoint_api_channel_webhook_endpoints__endpoint_id__patch.request.json
{
"url": "https://example.com/return"
}

Responses

200 response

Successful Response

Schema: ChannelWebhookEndpointUpdateResponse

200 response example
update_channel_webhook_endpoint_api_channel_webhook_endpoints__endpoint_id__patch.response.200.json
{
"created_at": "example",
"description": "example",
"enabled": false,
"event_types": [],
"id": "example",
"secret_hint": "example",
"status": "example",
"updated_at": "example",
"url": "https://example.com/return"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/channel/webhook-endpoints/{endpoint_id}/enable

Resume delivering to one of the channel's disabled endpoints

Flip a DISABLED endpoint back to ACTIVE. It keeps the same id, URL, signing secret, and event_types; only delivery resumes. This does not retry events enqueued while the endpoint was disabled and already preserved in the no_subscriber state. Contact Maxana if those events need to be replayed explicitly.

Authentication

  • ChannelApiKey

Parameters

  • endpoint_idpathRequired
    endpoint_id parameter schema
    {
    "title": "Endpoint Id",
    "type": "string"
    }

Responses

200 response

Successful Response

Schema: WebhookEndpointResponse

200 response example
enable_channel_webhook_endpoint_api_channel_webhook_endpoints__endpoint_id__enable_post.response.200.json
{
"created_at": "2026-01-01T00:00:00+00:00",
"description": "Channel payments webhook",
"enabled": true,
"event_types": ["payment.captured"],
"id": "00000000-0000-4000-8000-000000000001",
"secret_hint": "whsec_...c3d4e5",
"status": "active",
"updated_at": "2026-01-01T00:05:00+00:00",
"url": "https://merchant.example/webhooks/maxana"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/channel/webhook-endpoints/{endpoint_id}/rotate-secret

Replace one endpoint's signing secret

Issue a new signing secret for an endpoint and return it once. Before this, replacing a secret meant deleting and recreating the endpoint, which for a channel means its entire book stops being delivered to while the endpoint does not exist, and the endpoint id changes. **This is a hard cutover.** The previous secret stops signing immediately, so accept the new one before calling this — signature verification against the old secret will fail on the very next delivery.

Authentication

  • ChannelApiKey

Parameters

  • endpoint_idpathRequired
    endpoint_id parameter schema
    {
    "title": "Endpoint Id",
    "type": "string"
    }

Responses

200 response

Successful Response

Schema: WebhookEndpointCreateResponse

200 response example
rotate_channel_webhook_endpoint_secret_api_channel_webhook_endpoints__endpoint_id__rotate_secret_post.response.200.json
{
"created_at": "example",
"description": "example",
"enabled": false,
"event_types": [],
"id": "example",
"secret": "example",
"secret_hint": "example",
"status": "example",
"updated_at": "example",
"url": "https://example.com/return"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/checkout-sessions

Create a checkout session

Create an immutable server-side checkout session and return the hosted checkout_url and embed_url. Authenticate with a merchant API key (Authorization: Bearer sk_test_…). Pass an optional Idempotency-Key header (<=128 chars) to make retries safe. A channel-scoped key (acting for several merchants) must also pass X-Merchant-Id naming which of its merchants the session is for; an ordinary merchant key does not need it.

Authentication

  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • Idempotency-KeyheaderOptional
    Idempotency-Key parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "Idempotency-Key"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: CheckoutSessionCreateRequest

Request example

create_checkout_session_api_checkout_sessions_post.request.json
{
"amount": 1.0
}

Responses

201 response

Successful Response

Schema: CheckoutSessionResponse

201 response example
create_checkout_session_api_checkout_sessions_post.response.201.json
{
"amount": "1.00",
"checkout_session_id": "example",
"checkout_url": "https://example.com/return",
"currency": "USD",
"embed_url": "https://example.com/return",
"environment": "example",
"expires_at": "example",
"id": "example",
"merchant_name": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/checkout-sessions/{checkout_session_id}

Retrieve a checkout session

Fetch the public, buyer-safe view of a checkout session by id (amount, currency, merchant branding, status). No secrets are returned.

Authentication

  • No authentication

Parameters

  • checkout_session_idpathRequired
    checkout_session_id parameter schema
    {
    "title": "Checkout Session Id",
    "type": "string"
    }

Responses

200 response

Successful Response

Schema: PublicCheckoutSessionResponse

200 response example
get_checkout_session_api_checkout_sessions__checkout_session_id__get.response.200.json
{
"amount": "1.00",
"checkout_session_id": "example",
"checkout_url": "https://example.com/return",
"currency": "USD",
"embed_url": "https://example.com/return",
"environment": "example",
"expires_at": "example",
"id": "example",
"merchant_name": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/checkout-sessions/{checkout_session_id}/client-token

Create a client token for card fields

Mint the short-lived PayPal client token a browser needs before it can render hosted card fields (Advanced Credit and Debit Card). Without it there is no card form, so any integration that takes cards on its own page calls this. Pass the returned client_token to the PayPal JS SDK as its data-client-token attribute. No credential is sent: the checkout session id is the capability, and the call is made from the buyer's page, cross-origin, with no Authorization header. Mint one token per page load rather than caching it — tokens are short-lived. Returns 409 while the session is capturing or after it has finished, and 422 if the merchant has no connected PayPal account.

Authentication

  • No authentication

Parameters

  • checkout_session_idpathRequired
    checkout_session_id parameter schema
    {
    "title": "Checkout Session Id",
    "type": "string"
    }

Responses

200 response

Successful Response

Schema: CheckoutSessionClientTokenResponse

200 response example
get_session_client_token_api_checkout_sessions__checkout_session_id__client_token_post.response.200.json
{
"client_token": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/merchants/disputes

List disputes

List the disputes and chargebacks raised against the authenticated merchant, newest first. Maxana mirrors them from the payment provider and keeps them in sync from provider webhooks, so there is nothing to poll upstream. Page with limit (1-100, default 20) and offset. Authenticate with a dashboard bearer token, a merchant API key, or a channel API key naming one of its own merchants in X-Merchant-Id.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • limitqueryOptional
    limit parameter schema
    {
    "default": 20,
    "maximum": 100,
    "minimum": 1,
    "title": "Limit",
    "type": "integer"
    }
  • offsetqueryOptional
    offset parameter schema
    {
    "default": 0,
    "minimum": 0,
    "title": "Offset",
    "type": "integer"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Inline 200 response schema
{
"items": {
"$ref": "#/components/schemas/MerchantDisputeSummary"
},
"title": "Response List Merchant Disputes Api Merchants Disputes Get",
"type": "array"
}
200 response example
list_merchant_disputes_api_merchants_disputes_get.response.200.json
[]

422 response

Validation Error

Schema: HTTPValidationError

GET/api/merchants/disputes/{dispute_id}

Retrieve a dispute

Fetch one dispute by its Maxana id. Returns everything the list returns, plus available_actions — the response endpoints this dispute currently accepts, which depend on its status and lifecycle stage — the sanitized provider_payload, and any notes the Maxana operations team has shared with the merchant. Check available_actions before calling a response endpoint: an action the dispute does not accept is rejected. Same authentication as the list. Returns 404 if the dispute does not belong to this merchant.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: MerchantDisputeDetail

200 response example
get_merchant_dispute_api_merchants_disputes__dispute_id__get.response.200.json
{
"id": "example",
"provider": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/merchants/disputes/{dispute_id}/accept-claim

Accept a PayPal dispute claim

Accept liability on a native PayPal dispute claim for the authenticated merchant. This action instructs PayPal to refund the buyer and close the claim.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: AcceptDisputeClaimRequest

Request example

accept_merchant_dispute_claim_api_merchants_disputes__dispute_id__accept_claim_post.request.json
{
"note": "example"
}

Responses

200 response

Successful Response

Schema: DisputeActionResponse

200 response example
accept_merchant_dispute_claim_api_merchants_disputes__dispute_id__accept_claim_post.response.200.json
{
"dispute_id": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/merchants/disputes/{dispute_id}/acknowledge-return-item

Acknowledge a PayPal dispute return item

Acknowledge the returned item state on a native PayPal dispute for the authenticated merchant. The merchant must be connected to PayPal.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: AcknowledgeReturnItemRequest

Request example

acknowledge_merchant_dispute_return_item_api_merchants_disputes__dispute_id__acknowledge_return_item_post.request.json
{
"acknowledgement_type": "DAMAGED"
}

Responses

200 response

Successful Response

Schema: DisputeActionResponse

200 response example
acknowledge_merchant_dispute_return_item_api_merchants_disputes__dispute_id__acknowledge_return_item_post.response.200.json
{
"dispute_id": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/merchants/disputes/{dispute_id}/appeal

Appeal a PayPal dispute decision

Appeal a resolved native PayPal dispute decision for the authenticated merchant. The merchant must be connected to PayPal.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: AppealDisputeRequest

Request example

appeal_merchant_dispute_api_merchants_disputes__dispute_id__appeal_post.request.json
{}

Responses

200 response

Successful Response

Schema: DisputeActionResponse

200 response example
appeal_merchant_dispute_api_merchants_disputes__dispute_id__appeal_post.response.200.json
{
"dispute_id": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/merchants/disputes/{dispute_id}/escalate

Escalate a PayPal dispute

Escalate a native PayPal dispute for the authenticated merchant. The merchant must be connected to PayPal.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: EscalateDisputeRequest

Request example

escalate_merchant_dispute_api_merchants_disputes__dispute_id__escalate_post.request.json
{
"note": "example"
}

Responses

200 response

Successful Response

Schema: DisputeActionResponse

200 response example
escalate_merchant_dispute_api_merchants_disputes__dispute_id__escalate_post.response.200.json
{
"dispute_id": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/merchants/disputes/{dispute_id}/make-offer

Make a PayPal dispute offer

Make a seller resolution offer on a native PayPal dispute for the authenticated merchant. The merchant must be connected to PayPal.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: MakeDisputeOfferRequest

Request example

make_merchant_dispute_offer_api_merchants_disputes__dispute_id__make_offer_post.request.json
{
"note": "example",
"offer_type": "REFUND"
}

Responses

200 response

Successful Response

Schema: DisputeActionResponse

200 response example
make_merchant_dispute_offer_api_merchants_disputes__dispute_id__make_offer_post.response.200.json
{
"dispute_id": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/merchants/disputes/{dispute_id}/provide-evidence

Provide PayPal dispute evidence

Submit seller evidence to a native PayPal dispute for the authenticated merchant. The merchant must be connected to PayPal.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: ProvideDisputeEvidenceRequest

Request example

provide_merchant_dispute_evidence_api_merchants_disputes__dispute_id__provide_evidence_post.request.json
{}

Responses

200 response

Successful Response

Schema: DisputeActionResponse

200 response example
provide_merchant_dispute_evidence_api_merchants_disputes__dispute_id__provide_evidence_post.response.200.json
{
"dispute_id": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/merchants/disputes/{dispute_id}/provide-supporting-info

Provide PayPal dispute supporting information

Provide seller supporting information on a native PayPal dispute for the authenticated merchant. The merchant must be connected to PayPal.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: ProvideSupportingInfoRequest

Request example

provide_merchant_dispute_supporting_info_api_merchants_disputes__dispute_id__provide_supporting_info_post.request.json
{
"notes": "example"
}

Responses

200 response

Successful Response

Schema: DisputeActionResponse

200 response example
provide_merchant_dispute_supporting_info_api_merchants_disputes__dispute_id__provide_supporting_info_post.response.200.json
{
"dispute_id": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/merchants/disputes/{dispute_id}/send-message

Send a PayPal dispute message

Post a seller message to a native PayPal dispute for the authenticated merchant. The merchant must be connected to PayPal.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • dispute_idpathRequired
    dispute_id parameter schema
    {
    "title": "Dispute Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: SendDisputeMessageRequest

Request example

send_merchant_dispute_message_api_merchants_disputes__dispute_id__send_message_post.request.json
{
"message": "example"
}

Responses

200 response

Successful Response

Schema: DisputeActionResponse

200 response example
send_merchant_dispute_message_api_merchants_disputes__dispute_id__send_message_post.response.200.json
{
"dispute_id": "example",
"provider_dispute_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/payments/captures/{capture_id}/refund

Refund a captured payment

Give a buyer their money back, in full or in part. Omit the body (or omit amount) to refund the whole capture; send {"amount": 10.00} to refund part of it. The capture must belong to the merchant the credential acts for. Authenticate with a dashboard session holding refunds.manage (Finance tier), a merchant API key, or a channel API key naming one of its merchants with X-Merchant-Id. A channel's merchants have no dashboard by design, so without the key paths nobody but a Maxana employee could refund their buyers. Send an Idempotency-Key header if you retry: a repeat of a key already used replays the original outcome instead of refunding twice.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • capture_idpathRequired
    capture_id parameter schema
    {
    "title": "Capture Id",
    "type": "string"
    }
  • Idempotency-KeyheaderOptional
    Idempotency-Key parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "Idempotency-Key"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Inline request schema
{
"anyOf": [
{
"$ref": "#/components/schemas/RefundRequest"
},
{
"type": "null"
}
],
"title": "Refund Data"
}

Request example

refund_capture_api_payments_captures__capture_id__refund_post.request.json
{}

Responses

200 response

Successful Response

Schema: RefundResponse

200 response example
refund_capture_api_payments_captures__capture_id__refund_post.response.200.json
{
"success": false
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/payments/gravy/embed-token

Mint a Gr4vy Embed token for a checkout session

Mint a Gr4vy Embed token for a buyer checkout session. Requires a session whose merchant is routed to Gr4vy **and** holds their own Gr4vy credential — minting is gated on the resolved provider so a PPCP-routed session can never obtain a Gr4vy token. Availability is a per-merchant question, so the session is loaded before it can be answered.

Authentication

  • No authentication

Request

Schema: GravyEmbedTokenRequest

Request example

create_gravy_embed_token_api_payments_gravy_embed_token_post.request.json
{
"checkout_session_id": "cs_00000000000000000000000000000000"
}

Responses

200 response

Successful Response

Schema: GravyEmbedTokenResponse

200 response example
create_gravy_embed_token_api_payments_gravy_embed_token_post.response.200.json
{
"amount": 1,
"checkout_session_id": "example",
"currency": "USD",
"environment": "example",
"gr4vy_id": "example",
"merchant_account_id": "example",
"token": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/payments/nmi/tokenization-key

Fetch the Collect.js tokenization key for a checkout session

Return the public tokenization key that Collect.js needs for a checkout session. Card entry stays on the Maxana checkout page: Collect.js renders NMI's own iframed fields inside our form and hands back a single-use payment_token. The key it needs is public by design — NMI restricts it to minting tokens — but it belongs to one merchant, so it is served per session rather than shipped in the checkout bundle. Requires a session whose merchant is routed to NMI, so a PayPal- or Gr4vy-routed session can never obtain an NMI key. A POST rather than a GET keeps the session id out of URLs, logs and referrers, matching the Gr4vy token endpoint beside it.

Authentication

  • No authentication

Request

Schema: NmiTokenizationKeyRequest

Request example

get_nmi_tokenization_key_api_payments_nmi_tokenization_key_post.request.json
{
"checkout_session_id": "cs_00000000000000000000000000000000"
}

Responses

200 response

Successful Response

Schema: NmiTokenizationKeyResponse

200 response example
get_nmi_tokenization_key_api_payments_nmi_tokenization_key_post.response.200.json
{
"checkout_session_id": "example",
"environment": "example",
"supports_apple_pay": false,
"supports_google_pay": false,
"tokenization_key": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/payments/orders

Create a payment order

Create a new provider order for payment. Public buyer checkout must pass checkout_session_id. The amount, currency, description, items, and merchant are loaded from the immutable merchant-created checkout session; browser-supplied financial fields are rejected/ignored. A merchant-hosted checkout (X-Maxana-Checkout-Mode: direct) must also pass checkout_page_url — the URL of the page the widgets are mounted on. It becomes PayPal's return_url/cancel_url, so a redirect-based approval (mobile web, Pay Later) brings the buyer back to the merchant's own page with ?paypal_return=1 or ?paypal_cancel=1 appended, instead of to Maxana's /pay page. It must be https and on the very origin the request came from — a session's allowed_origins may hold several, and a page on one of them must not be able to send the buyer back to a different merchant's page. Anything else is refused rather than quietly redirected to Maxana. Hosted and embedded checkouts must not send it.

Authentication

  • No authentication
  • HTTPBearer
  • MerchantApiKey

Parameters

  • X-Maxana-Checkout-OriginheaderOptional
    X-Maxana-Checkout-Origin parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Maxana-Checkout-Origin"
    }
  • X-Maxana-Checkout-ModeheaderOptional
    X-Maxana-Checkout-Mode parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Maxana-Checkout-Mode"
    }
  • OriginheaderOptional
    Origin parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "Origin"
    }

Request

Schema: CreateOrderRequest

Request example

create_order_api_payments_orders_post.request.json
{
"checkout_session_id": "cs_00000000000000000000000000000000"
}

Responses

200 response

Successful Response

Schema: CreateOrderResponse

200 response example
create_order_api_payments_orders_post.response.200.json
{
"provider_order_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/payments/orders/{order_id}/capture

Capture an approved payment order

Capture an approved payment order and return the resulting transaction. A buyer page calls this with no credentials: it identifies the checkout with the X-Maxana-Checkout-Session-Id header, declares which kind of page it is with X-Maxana-Checkout-Mode (hosted, embedded or direct) and repeats its own origin in X-Maxana-Checkout-Origin. The response is then the sanitized public view — internal ids and merchant account fields are not leaked to it. A merchant calling with their own API key gets the full transaction instead, and needs none of those headers: the merchant is taken from the key, and for a public call from the stored transaction. A channel calls it the same way with its channel API key, naming which of its merchants the order belongs to in X-Merchant-Id; it can capture for the merchants it carries and for no others. Calling it from a server is how an approved payment is recovered when the buyer's browser never came back to finish it. An approval is not a capture and nothing completes it on its own, and the approved order cannot be replaced by starting a new one — so until this call is made the money has not moved.

Authentication

  • No authentication
  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • order_idpathRequired
    order_id parameter schema
    {
    "title": "Order Id",
    "type": "string"
    }
  • X-Maxana-Checkout-OriginheaderOptional
    X-Maxana-Checkout-Origin parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Maxana-Checkout-Origin"
    }
  • X-Maxana-Checkout-ModeheaderOptional
    X-Maxana-Checkout-Mode parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Maxana-Checkout-Mode"
    }
  • X-Maxana-Checkout-Session-IdheaderOptional
    X-Maxana-Checkout-Session-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Maxana-Checkout-Session-Id"
    }
  • PayPal-Client-Metadata-IdheaderOptional
    PayPal-Client-Metadata-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "Paypal-Client-Metadata-Id"
    }
  • PayPal-Mock-ResponseheaderOptional
    PayPal-Mock-Response parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "Paypal-Mock-Response"
    }
  • OriginheaderOptional
    Origin parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "Origin"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Inline request schema
{
"anyOf": [
{
"$ref": "#/components/schemas/CaptureOrderRequest"
},
{
"type": "null"
}
],
"title": "Payload"
}

Request example

capture_order_api_payments_orders__order_id__capture_post.request.json
{}

Responses

200 response

Successful Response

Schema: PublicCaptureResponse

200 response example
capture_order_api_payments_orders__order_id__capture_post.response.200.json
{
"amount": 1,
"created_at": "example",
"currency": "USD",
"payment_method": "example",
"provider_order_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/text-to-pay/requests

List text-to-pay requests

List your payment requests, newest first. Authenticate with a dashboard session or merchant API key. A channel API key can act for one of its merchants by sending X-Merchant-Id; the named merchant must belong to that channel. Readable by any dashboard role: knowing that a customer was asked for money is part of reading the account, even for a role that cannot ask.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • limitqueryOptional
    limit parameter schema
    {
    "default": 50,
    "maximum": 200,
    "minimum": 1,
    "title": "Limit",
    "type": "integer"
    }
  • offsetqueryOptional
    offset parameter schema
    {
    "default": 0,
    "minimum": 0,
    "title": "Offset",
    "type": "integer"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Inline 200 response schema
{
"items": {
"$ref": "#/components/schemas/TextToPayRequestResponse"
},
"title": "Response List Text To Pay Requests Api Text To Pay Requests Get",
"type": "array"
}
200 response example
list_text_to_pay_requests_api_text_to_pay_requests_get.response.200.json
[]

422 response

Validation Error

Schema: HTTPValidationError

POST/api/text-to-pay/requests

Text a customer a request to pay

Send a customer a text message asking them to pay a given amount. Authenticate with a dashboard session or merchant API key. A channel API key can act for one of its merchants by sending X-Merchant-Id; the named merchant must belong to that channel. The customer receives a message composed by the payment provider, containing a link to a hosted wallet where they can pay by card. The message is sent from the provider's own number, not yours, and cannot be recalled once accepted — so a request is rate-limited, capped in amount, and refused if an identical one went out moments ago. Your account also has a **daily send allowance**, counted over a rolling 24 hours. Spending it answers 429 naming the allowance and the time it frees up — the same status as a duplicate, and lifted the same way, by waiting. Ask support if your volume needs a higher one. Requires a connected NMI gateway account. Pass external_order_id to tie the request to your own order; it is stored on our side and is the only field of yours that survives, since the provider carries none. The request comes back pending. It stays pending until the customer pays or their window closes — the provider offers no delivery receipt and no callback, so poll GET /api/text-to-pay/requests/{id} rather than waiting for a webhook. **Do not retry every 502.** Two of them mean opposite things, so they are told apart by detail.code rather than by their status: - text_to_pay_provider_refused (retryable: true) — the provider rejected the request and nothing was created. Retrying is safe. - text_to_pay_unconfirmed (retryable: false) — we could not confirm the request and the message may already be on your customer's phone. Retrying is what charges them twice. detail.request_id names the request; it shows as unconfirmed until support settles it, and a later identical send is refused with 409 text_to_pay_unsettled until then.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: SendTextToPayRequest

Request example

send_text_to_pay_request_api_text_to_pay_requests_post.request.json
{
"amount_cents": 1,
"first_name": "example",
"instructions": "example",
"last_name": "example",
"phone": "+12025550123",
"topic": "example"
}

Responses

201 response

Successful Response

Schema: TextToPayRequestResponse

201 response example
send_text_to_pay_request_api_text_to_pay_requests_post.response.201.json
{
"amount_cents": 1,
"created_at": "2026-01-01T00:00:00Z",
"currency": "USD",
"customer_first_name": "example",
"customer_last_name": "example",
"expires_at": "2026-01-01T00:00:00Z",
"external_order_id": "example",
"id": "00000000-0000-4000-8000-000000000001",
"instructions": "example",
"last_polled_at": "2026-01-01T00:00:00Z",
"phone": "+12025550123",
"provider_status": "example",
"resolved_at": "2026-01-01T00:00:00Z",
"status": "example",
"topic": "example",
"transaction_id": "00000000-0000-4000-8000-000000000001"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/text-to-pay/requests/{request_id}

Read one text-to-pay request

Read one payment request, to find out whether the customer has paid. Authenticate with a dashboard session or merchant API key. A channel API key can act for one of its merchants by sending X-Merchant-Id; the named merchant must belong to that channel. This is how you learn the outcome. The provider offers no webhook and no delivery receipt, so a request stays pending until our reconciliation reads the conversation back — poll this rather than waiting to be told.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • request_idpathRequired
    request_id parameter schema
    {
    "format": "uuid",
    "title": "Request Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: TextToPayRequestResponse

200 response example
get_text_to_pay_request_api_text_to_pay_requests__request_id__get.response.200.json
{
"amount_cents": 1,
"created_at": "2026-01-01T00:00:00Z",
"currency": "USD",
"customer_first_name": "example",
"customer_last_name": "example",
"expires_at": "2026-01-01T00:00:00Z",
"external_order_id": "example",
"id": "00000000-0000-4000-8000-000000000001",
"instructions": "example",
"last_polled_at": "2026-01-01T00:00:00Z",
"phone": "+12025550123",
"provider_status": "example",
"resolved_at": "2026-01-01T00:00:00Z",
"status": "example",
"topic": "example",
"transaction_id": "00000000-0000-4000-8000-000000000001"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/text-to-pay/requests/{request_id}/cancel

Cancel a text-to-pay request

Withdraw a request the customer has not paid, so its link stops working. Authenticate with a dashboard session or merchant API key. A channel API key can act for one of its merchants by sending X-Merchant-Id; the named merchant must belong to that channel. The cancellation happens at the provider first and is recorded here only if it succeeded — a request marked canceled on our side alone would leave your customer holding a link they can still pay. Only a pending request can be canceled, and every other answer means it was not: - 404 — no such request under your account. - 409 — it cannot be canceled. Either it has already been paid, expired or canceled, or it is still sending, meaning we never got confirmation from the provider. That last one does not clear on its own and retrying will not change it: the message may be live and only support can settle it. Do not resend the request. - 502 — we reached the provider and the cancellation did not take. **Treat the link as still payable**, and do not tell your customer it is dead. - 503 — the rail is not configured on this deployment.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • request_idpathRequired
    request_id parameter schema
    {
    "format": "uuid",
    "title": "Request Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: TextToPayRequestResponse

200 response example
cancel_text_to_pay_request_api_text_to_pay_requests__request_id__cancel_post.response.200.json
{
"amount_cents": 1,
"created_at": "2026-01-01T00:00:00Z",
"currency": "USD",
"customer_first_name": "example",
"customer_last_name": "example",
"expires_at": "2026-01-01T00:00:00Z",
"external_order_id": "example",
"id": "00000000-0000-4000-8000-000000000001",
"instructions": "example",
"last_polled_at": "2026-01-01T00:00:00Z",
"phone": "+12025550123",
"provider_status": "example",
"resolved_at": "2026-01-01T00:00:00Z",
"status": "example",
"topic": "example",
"transaction_id": "00000000-0000-4000-8000-000000000001"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/transactions

List transactions

List a merchant's transactions with optional filters and pagination. A channel-scoped key must also pass X-Merchant-Id naming which of its merchants the read is for; an ordinary merchant key does not need it.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • statusqueryOptional

    Filter by status

    status parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "description": "Filter by status",
    "title": "Status"
    }
  • payment_methodqueryOptional

    Filter by payment method

    payment_method parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "description": "Filter by payment method",
    "title": "Payment Method"
    }
  • processorqueryOptional

    Filter by processor (e.g. stripe)

    processor parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "description": "Filter by processor (e.g. stripe)",
    "title": "Processor"
    }
  • searchqueryOptional

    Search in email/description

    search parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "description": "Search in email/description",
    "title": "Search"
    }
  • from_datequeryOptional

    Filter from date (ISO)

    from_date parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "description": "Filter from date (ISO)",
    "title": "From Date"
    }
  • to_datequeryOptional

    Filter to date (ISO)

    to_date parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "description": "Filter to date (ISO)",
    "title": "To Date"
    }
  • limitqueryOptional

    Max results

    limit parameter schema
    {
    "default": 20,
    "description": "Max results",
    "maximum": 100,
    "title": "Limit",
    "type": "integer"
    }
  • offsetqueryOptional

    Skip results

    offset parameter schema
    {
    "default": 0,
    "description": "Skip results",
    "minimum": 0,
    "title": "Offset",
    "type": "integer"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: PaginatedTransactions

200 response example
list_transactions_api_transactions_get.response.200.json
{
"items": [],
"limit": 1,
"offset": 1,
"total": 1
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/transactions/daily-revenue

Get daily revenue

Daily revenue and transaction counts for a merchant, bucketed by UTC calendar day over a bounded window. A channel-scoped key must also pass X-Merchant-Id naming which of its merchants the read is for; an ordinary merchant key does not need it.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • daysqueryOptional

    Number of days

    days parameter schema
    {
    "default": 30,
    "description": "Number of days",
    "maximum": 90,
    "title": "Days",
    "type": "integer"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Inline 200 response schema
{
"items": {
"$ref": "#/components/schemas/DailyRevenue"
},
"title": "Response Get Daily Revenue Api Transactions Daily Revenue Get",
"type": "array"
}
200 response example
get_daily_revenue_api_transactions_daily_revenue_get.response.200.json
[]

422 response

Validation Error

Schema: HTTPValidationError

GET/api/transactions/filter-options

Get transaction filter options

List the payment methods and processors present in a merchant's transactions. A channel-scoped key must also pass X-Merchant-Id naming which of its merchants the read is for; an ordinary merchant key does not need it.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: TransactionFilterOptions

200 response example
get_filter_options_api_transactions_filter_options_get.response.200.json
{
"payment_methods": [],
"processors": []
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/transactions/stats

Get transaction statistics

Aggregated stats, the completed provider-history scope, and whether a widened scope still awaits backfill. A channel-scoped key must also pass X-Merchant-Id naming which of its merchants the read is for; an ordinary merchant key does not need it.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: TransactionStats

200 response example
get_stats_api_transactions_stats_get.response.200.json
{
"avg_order_value": 1,
"platform_fees": 1,
"total_revenue": 1,
"transaction_count": 1
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/transactions/{transaction_id}

Get a transaction

Get a single transaction by id, scoped to the authenticated merchant. A channel-scoped key must also pass X-Merchant-Id naming which of its merchants the read is for; an ordinary merchant key does not need it.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • transaction_idpathRequired
    transaction_id parameter schema
    {
    "title": "Transaction Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: TransactionResponse

200 response example
get_transaction_api_transactions__transaction_id__get.response.200.json
{
"amount": 1,
"created_at": "example",
"currency": "USD",
"id": "example",
"merchant_id": "example",
"payment_method": "example",
"platform_fee": 1,
"provider": "example",
"provider_order_id": "example",
"status": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/transactions/{transaction_id}/provider-detail

Get a transaction's provider detail

Everything the payment provider reports about a transaction (AVS/CVV, connector, etc.). A channel-scoped key must also pass X-Merchant-Id naming which of its merchants the read is for; an ordinary merchant key does not need it.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • transaction_idpathRequired
    transaction_id parameter schema
    {
    "title": "Transaction Id",
    "type": "string"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Schema: ProviderDetailResponse

200 response example
get_transaction_provider_detail_api_transactions__transaction_id__provider_detail_get.response.200.json
{
"available": false,
"provider": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

POST/api/vault/charge

Charge a saved payment instrument

Charge a customer's saved method with merchant-initiated semantics. Authenticate with a dashboard session holding finance.manage, a merchant API key, or a channel API key naming one of its merchants with X-Merchant-Id. Obtain customer_ref from GET /api/vault/tokens and provide a unique idempotency_key for each intended charge; retrying that key returns the original transaction instead of charging twice.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Request

Schema: VaultChargeRequest

Request example

charge_vault_adhoc_api_vault_charge_post.request.json
{
"amount": 1.0,
"customer_ref": "example",
"idempotency_key": "example"
}

Responses

200 response

Successful Response

Schema: VaultChargeResponse

200 response example
charge_vault_adhoc_api_vault_charge_post.response.200.json
{
"transaction_id": "example"
}

422 response

Validation Error

Schema: HTTPValidationError

GET/api/vault/tokens

List saved payment instruments

List each customer's selected instrument without provider vault secrets. Authenticate with a dashboard session holding finance.manage, a merchant API key, or a channel API key naming one of its merchants with X-Merchant-Id. The returned customer_ref is the value accepted by POST /api/vault/charge. Use limit and offset to page through a merchant with more than 100 customers holding active instruments. When a customer has multiple active tokens, only the newest selectable token is returned.

Authentication

  • HTTPBearer
  • MerchantApiKey
  • ChannelApiKey + ChannelMerchantId

Parameters

  • limitqueryOptional
    limit parameter schema
    {
    "default": 100,
    "maximum": 100,
    "minimum": 1,
    "title": "Limit",
    "type": "integer"
    }
  • offsetqueryOptional
    offset parameter schema
    {
    "default": 0,
    "minimum": 0,
    "title": "Offset",
    "type": "integer"
    }
  • X-Merchant-IdheaderOptional
    X-Merchant-Id parameter schema
    {
    "anyOf": [
    {
    "type": "string"
    },
    {
    "type": "null"
    }
    ],
    "title": "X-Merchant-Id"
    }

Responses

200 response

Successful Response

Inline 200 response schema
{
"items": {
"$ref": "#/components/schemas/VaultTokenResponse"
},
"title": "Response List Vault Tokens Api Vault Tokens Get",
"type": "array"
}
200 response example
list_vault_tokens_api_vault_tokens_get.response.200.json
[]

422 response

Validation Error

Schema: HTTPValidationError

Only operations in the curated Public API appear here. Generated operation cards do not show dashboard, admin, or internal routes and do not replace the audience-specific tutorial that explains when an operation belongs in a flow.