{
"error": "experiment not found",
"request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}
{
"error": "experiment not found",
"request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}
{
"error": "experiment not found",
"request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}
{
"error": "experiment not found",
"request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}
{
"error": "experiment not found",
"request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}
{
"error": "experiment not found",
"request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}
{
"error": "experiment not found",
"request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}
{
"error": "experiment not found",
"request_id": "req_019462a4-b1c2-7def-8901-23456789abcd"
}
invoices
Pay invoice
Settles the given invoice. How it settles is chosen by the
X-Adaptyv-Payment-Method request header:
Header value
Behaviour
(absent)
Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns 409 — retry with the X-Adaptyv-Payment-Method header used at creation.
mpp-spt
Settles from a Stripe shared payment token
x402-exact
Settles on-chain with an x402 exact USDC transfer
The payment rail is pinned when the experiment is created, and an explicitX-Adaptyv-Payment-Method cannot switch it: a header naming a rail other
than the pinned one is rejected with 409 — retry with the pinned rail.
Header-less discovery is the deliberate exception: a caller with a machine
payment policy is offered every machine rail this deployment serves and
commits by sending one rail’s credential, which may be a machine rail other
than the pinned one (they share a Stripe account, so the pin has already
decided everything it decides). Omitting the header is therefore not a way
to reach the pinned rail, and a caller with no machine policy falls through
to the hosted invoice — which on a crypto-pinned quote is the absent-header
409 in the table above.
This is the only endpoint that settles an invoice. The flow is two steps:
POST /quotes/{quote_id}/confirm issues the invoice and returns a payment
pointer to this route, then POST /invoices/{invoice_id}/pay settles it.
Send the first call with the method header and no credential. It answers
402, and the challenge is carried in the response headers, not the
body — PAYMENT-REQUIRED for x402-exact, WWW-Authenticate for
mpp-spt.
That challenge is the whole handshake: it carries every parameter needed to
produce the credential — for mpp-spt, the amount, currency, seller-network
id, expiry, and accepted payment-method types to mint the shared payment
token against. There is no separate endpoint to fetch them from, and there
cannot usefully be one: the credential must echo the challenge it answers,
so parameters obtained without taking a 402 cannot be settled here.
Both mpp-spt and x402-exact settle over the API directly with these
headers; the MCP server’s pay_invoice tool is one client of this route,
not the only way to reach the rail.
Repeat the call with the signed credential to settle — PAYMENT-SIGNATURE
for x402-exact, Authorization for mpp-spt — and the response is 200
with the paid invoice. Repeating it again is safe: an invoice that is
already paid answers 200 with already_paid: true and settles nothing.
When the settlement can be named, the response carries
settlement_reference. Treat it as optional even on a settling response.
The payment.methods array on the confirm response lists the methods this
environment accepts; a value outside that list is rejected with 400.
Biscuit-based bearer token. Obtain tokens from the Adaptyv Portal or via the /tokens endpoint. Tokens encode organization membership and role-based capabilities; the API verifies the token's cryptographic signature and authorization claims before processing requests. Use /tokens/attenuate to create restricted tokens for delegation.
Settlement method: mpp-spt or x402-exact. Must name the rail pinned at experiment creation; naming a different one is a 409. Omit to read the current invoice state and pay via the hosted URL instead — but a quote pinned to a crypto rail at experiment creation returns 409 when the header is absent, so retry with the value used at creation. The methods an environment accepts are listed in payment.methods on the confirm response.
Foundry invoice UUID or Stripe invoice ID (in_xxx)
Response
Invoice paid (or already paid)
Response returned by POST /invoices/{invoice_id}/pay.
Reports the invoice after the call, so no follow-up GET is needed. It is
returned for three outcomes, which status and already_paid tell apart:
a settlement this request performed, an invoice that was already paid, and
— when no payment-method header was sent — the current state of an invoice
that is still unpaid and that this call settled nothing on.
A 200 therefore does not by itself mean the invoice is paid. Read
status. The 402 challenge is not this body.
true when the call was a no-op because the invoice was already paid
before this request.
false otherwise — which covers two different outcomes: this request
settled the invoice, or no payment method was selected and the body
reports the invoice's current state without settling. Read status to
tell those apart; false alone does not mean the invoice is paid.
Names what settled this invoice — the on-chain transaction for
x402-exact, or the Stripe PaymentIntent for mpp-spt.
Only a response that performed the settlement can carry it, so it is
absent when already_paid is true and absent from the state read of
an unpaid invoice. Treat it as optional even on a settling response:
when the rail reports nothing this API can name honestly, the field is
omitted rather than guessed at.
Record it when you receive it. Repeating the call afterwards answers
already_paid without the reference, and it is not available from any
other endpoint.
Option 1
Option 2
Show child attributes
Was this page helpful?
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Adaptyv Bio Docs","colors":{"primary":"#5db0dd","light":"#5db0dd","dark":"#5db0dd"},"logo":{"light":"https://mintcdn.com/adaptyv-a4917ef6/3kX9xKvyzUlLV3Dj/logo/logo-light.svg?fit=max\u0026auto=format\u0026n=3kX9xKvyzUlLV3Dj\u0026q=85\u0026s=28a1e3df60674482d4bac1fc9d190568","dark":"https://mintcdn.com/adaptyv-a4917ef6/3kX9xKvyzUlLV3Dj/logo/logo-dark.svg?fit=max\u0026auto=format\u0026n=3kX9xKvyzUlLV3Dj\u0026q=85\u0026s=9af068e2ee0cfcd18651c6d5de78183b"},"favicon":"https://mintcdn.com/adaptyv-a4917ef6/3kX9xKvyzUlLV3Dj/favicon.svg?fit=max\u0026auto=format\u0026n=3kX9xKvyzUlLV3Dj\u0026q=85\u0026s=3c844e90e21e045d7ed937e532aa2bdf","background":{"decoration":"gradient"},"navbar":{"links":[{"href":"mailto:support@adaptyvbio.com","label":"Support"}],"primary":{"type":"button","label":"Test Your Proteins","href":"https://start.adaptyvbio.com"}},"footer":{"socials":{"x":"https://twitter.com/adaptyvbio","linkedin":"https://www.linkedin.com/company/adaptyvbio"}},"integrations":{"posthog":{"apiKey":"phc_BakxHKWkh2YgICIAQeQJuGpagepWpTNHGzWmf6dGAsU"}},"contextual":{"options":["copy","view","claude","chatgpt"],"display":"header"},"styling":{"latex":true},"navigation":{"global":{"anchors":[{"anchor":"Careers","icon":"users","href":"https://www.adaptyvbio.com/careers"},{"anchor":"Blog","icon":"newspaper","href":"https://www.adaptyvbio.com/blog"},{"anchor":"Experiment Configurator","icon":"flask","href":"https://start.adaptyvbio.com"},{"anchor":"Foundry Portal","icon":"desktop","href":"https://foundry.adaptyvbio.com"}]},"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"adaptyv-a4917ef6","hasAudioNarration":false,"actualSubdomain":"adaptyv-a4917ef6","customDomains":["docs.adaptyvbio.com"],"gitSource":{"type":"github","owner":"adaptyvbio","repo":"monorepo","deployBranch":"master","contentDirectory":"apps/docs-public","isPrivate":true,"mountPath":"","label":""},"chroma":{"liveDeploymentHistoryId":"6ac81a5673ce31311a1c600a","collectionId":"8d0ec86c-0af8-4714-8a77-5f724947b672","schemaVersion":"v3","latestBuiltDeploymentHistoryId":"6ac81a5673ce31311a1c600a"},"feedback":{"thumbs":true},"entitlements":{"AI_CHAT":{"status":"ENABLED"},"WEB_MCP":{"status":"ENABLED"},"NARRATION":{"status":"ENABLED"}},"buildId":"6adff8dc8f9b4f0222625cf9","clientVersion":"0.0.3971","searchFilterCounts":[{"language":"default","tag":"API","count":50},{"language":"default","tag":"API Endpoints","count":43},{"language":"default","tag":"Wiki","count":26},{"language":"default","tag":"Documentation","count":14},{"language":"default","tag":"experiments","count":13},{"language":"default","tag":"Technologies","count":10},{"language":"default","tag":"Proteins","count":9},{"language":"default","tag":"Getting Started","count":5},{"language":"default","tag":"Experiment Setup","count":5},{"language":"default","tag":"Experiment Types","count":5}]},"assistantConfig":{"enableAskAiButton":true,"enableStarterQuestions":false,"enableAskAiSearchBar":false,"deflection":{"enabled":true,"email":"support@adaptyvbio.com","showHelpButton":true}},"basePath":"","hasChatPermissions":true,"hasWebMcpPermissions":true,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-v7-file-tree","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"pause-universal-search-reconcile","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"per-site-search-delta","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-private-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-nav-generations","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"byok-sep-25","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"vite-origin","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-agent-model-picker","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-updated-9-15","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"isAtlas":false,"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":".shape-grid{margin:1rem 0 1.5rem}.sg-cards{display:grid;grid-template-columns:repeat(4,1fr);gap:10px}@media (max-width:640px){.sg-cards{grid-template-columns:repeat(2,1fr)}}.sg-card{position:relative;display:block;border:2px solid #e6e8ec;border-radius:10px;padding:7px 7px 5px;background:#fff;cursor:pointer;transition:border-color .12s,box-shadow .12s,background .12s,transform .12s}.sg-radio{position:absolute;width:1px;height:1px;opacity:0;pointer-events:none;margin:0}.sg-card img{width:100%;height:auto;display:block;margin:0}.sg-card span{display:block;font-size:11.5px;font-weight:600;text-align:center;margin-top:5px;line-height:1.25;color:#5b6472}.sg-card:hover,.shape-grid:not(:has(.sg-card:hover)) .sg-card:has(.sg-radio:checked){border-color:#3b6cf0;background:#eef3ff;box-shadow:0 0 0 3px #3b6cf0;transform:translateY(-2px)}.sg-card:hover span,.shape-grid:not(:has(.sg-card:hover)) .sg-card:has(.sg-radio:checked) span{color:#2b56c8}.sg-card:has(.sg-radio:focus-visible){outline:2px solid #3b6cf0;outline-offset:2px}.sg-caption{margin-top:16px;border:1px solid #e6e8ec;border-left:3px solid #3b6cf0;border-radius:8px;padding:14px 16px;min-height:72px}.sg-cap{display:none}.sg-sugg{display:block;margin-top:9px;padding-top:9px;border-top:1px solid #e6e8ec;font-size:.93em}.sg-sugg strong{color:#2b56c8}.shape-grid:not(:has(.sg-card:hover)):has(.sg-card[data-k=biphasic] .sg-radio:checked) .sg-cap[data-k=biphasic],.shape-grid:not(:has(.sg-card:hover)):has(.sg-card[data-k=drift] .sg-radio:checked) .sg-cap[data-k=drift],.shape-grid:not(:has(.sg-card:hover)):has(.sg-card[data-k=flat-dissoc] .sg-radio:checked) .sg-cap[data-k=flat-dissoc],.shape-grid:not(:has(.sg-card:hover)):has(.sg-card[data-k=ideal] .sg-radio:checked) .sg-cap[data-k=ideal],.shape-grid:not(:has(.sg-card:hover)):has(.sg-card[data-k=mass-transport] .sg-radio:checked) .sg-cap[data-k=mass-transport],.shape-grid:not(:has(.sg-card:hover)):has(.sg-card[data-k=no-plateau] .sg-radio:checked) .sg-cap[data-k=no-plateau],.shape-grid:not(:has(.sg-card:hover)):has(.sg-card[data-k=square-wave] .sg-radio:checked) .sg-cap[data-k=square-wave],.shape-grid:not(:has(.sg-card:hover)):has(.sg-card[data-k=super-stoich] .sg-radio:checked) .sg-cap[data-k=super-stoich]{display:block}.shape-grid:has(.sg-card[data-k=biphasic]:hover) .sg-cap[data-k=biphasic],.shape-grid:has(.sg-card[data-k=drift]:hover) .sg-cap[data-k=drift],.shape-grid:has(.sg-card[data-k=flat-dissoc]:hover) .sg-cap[data-k=flat-dissoc],.shape-grid:has(.sg-card[data-k=ideal]:hover) .sg-cap[data-k=ideal],.shape-grid:has(.sg-card[data-k=mass-transport]:hover) .sg-cap[data-k=mass-transport],.shape-grid:has(.sg-card[data-k=no-plateau]:hover) .sg-cap[data-k=no-plateau],.shape-grid:has(.sg-card[data-k=square-wave]:hover) .sg-cap[data-k=square-wave],.shape-grid:has(.sg-card[data-k=super-stoich]:hover) .sg-cap[data-k=super-stoich]{display:block}.dark .sg-card{background:#111827}.dark .sg-card span{color:#9aa4b2}.dark .sg-caption,.dark .sg-card{border-color:#243040}.dark .sg-sugg{border-top-color:#243040}.dark .sg-sugg strong{color:#9db8ff}.dark .sg-card:hover,.dark .shape-grid:not(:has(.sg-card:hover)) .sg-card:has(.sg-radio:checked){border-color:#6c95ff;background:#17233d;box-shadow:0 0 0 3px #6c95ff}.dark .sg-card:hover span,.dark .shape-grid:not(:has(.sg-card:hover)) .sg-card:has(.sg-radio:checked) span{color:#9db8ff}"}],"page":{"pagePath":"api-reference/invoices/pay-invoice","slug":"/api-reference/invoices/pay-invoice","pageMetadata":{"title":"Pay invoice","description":"Settles the given invoice. How it settles is chosen by the\n`X-Adaptyv-Payment-Method` request header:\n\n| Header value | Behaviour |\n|---|---|\n| _(absent)_ | Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns `409` — retry with the `X-Adaptyv-Payment-Method` header used at creation. |\n| `mpp-spt` | Settles from a Stripe shared payment token |\n| `x402-exact` | Settles on-chain with an x402 `exact` USDC transfer |\n\nThe payment rail is pinned when the experiment is created, and an *explicit*\n`X-Adaptyv-Payment-Method` cannot switch it: a header naming a rail other\nthan the pinned one is rejected with `409` — retry with the pinned rail.\nHeader-less discovery is the deliberate exception: a caller with a machine\npayment policy is offered every machine rail this deployment serves and\ncommits by sending one rail's credential, which may be a machine rail other\nthan the pinned one (they share a Stripe account, so the pin has already\ndecided everything it decides). Omitting the header is therefore not a way\nto reach the pinned rail, and a caller with no machine policy falls through\nto the hosted invoice — which on a crypto-pinned quote is the absent-header\n`409` in the table above.\n\nThis is the only endpoint that settles an invoice. The flow is two steps:\n`POST /quotes/{quote_id}/confirm` issues the invoice and returns a `payment`\npointer to this route, then `POST /invoices/{invoice_id}/pay` settles it.\n\nSend the first call with the method header and no credential. It answers\n`402`, and **the challenge is carried in the response headers, not the\nbody** — `PAYMENT-REQUIRED` for `x402-exact`, `WWW-Authenticate` for\n`mpp-spt`.\n\nThat challenge is the whole handshake: it carries every parameter needed to\nproduce the credential — for `mpp-spt`, the amount, currency, seller-network\nid, expiry, and accepted payment-method types to mint the shared payment\ntoken against. There is no separate endpoint to fetch them from, and there\ncannot usefully be one: the credential must echo the challenge it answers,\nso parameters obtained without taking a `402` cannot be settled here.\n\nBoth `mpp-spt` and `x402-exact` settle over the API directly with these\nheaders; the MCP server's `pay_invoice` tool is one client of this route,\nnot the only way to reach the rail.\n\nRepeat the call with the signed credential to settle — `PAYMENT-SIGNATURE`\nfor `x402-exact`, `Authorization` for `mpp-spt` — and the response is `200`\nwith the paid invoice. Repeating it again is safe: an invoice that is\nalready paid answers `200` with `already_paid: true` and settles nothing.\n\nWhen the settlement can be named, the response carries\n`settlement_reference`. Treat it as optional even on a settling response.\n\nThe `payment.methods` array on the confirm response lists the methods this\nenvironment accepts; a value outside that list is rejected with `400`.","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/invoices/{invoice_id}/pay","href":"/api-reference/invoices/pay-invoice","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {Fragment: _Fragment, jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n em: \"em\",\n p: \"p\",\n strong: \"strong\",\n table: \"table\",\n tbody: \"tbody\",\n td: \"td\",\n th: \"th\",\n thead: \"thead\",\n tr: \"tr\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_Fragment, {\n children: [_jsxs(_components.p, {\n children: [\"Settles the given invoice. How it settles is chosen by the\\n\", _jsx(_components.code, {\n children: \"X-Adaptyv-Payment-Method\"\n }), \" request header:\"]\n }), \"\\n\", _jsxs(_components.table, {\n children: [_jsx(_components.thead, {\n children: _jsxs(_components.tr, {\n children: [_jsx(_components.th, {\n children: \"Header value\"\n }), _jsx(_components.th, {\n children: \"Behaviour\"\n })]\n })\n }), _jsxs(_components.tbody, {\n children: [_jsxs(_components.tr, {\n children: [_jsx(_components.td, {\n children: _jsx(_components.em, {\n children: \"(absent)\"\n })\n }), _jsxs(_components.td, {\n children: [\"Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns \", _jsx(_components.code, {\n children: \"409\"\n }), \" — retry with the \", _jsx(_components.code, {\n children: \"X-Adaptyv-Payment-Method\"\n }), \" header used at creation.\"]\n })]\n }), _jsxs(_components.tr, {\n children: [_jsx(_components.td, {\n children: _jsx(_components.code, {\n children: \"mpp-spt\"\n })\n }), _jsx(_components.td, {\n children: \"Settles from a Stripe shared payment token\"\n })]\n }), _jsxs(_components.tr, {\n children: [_jsx(_components.td, {\n children: _jsx(_components.code, {\n children: \"x402-exact\"\n })\n }), _jsxs(_components.td, {\n children: [\"Settles on-chain with an x402 \", _jsx(_components.code, {\n children: \"exact\"\n }), \" USDC transfer\"]\n })]\n })]\n })]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"The payment rail is pinned when the experiment is created, and an \", _jsx(_components.em, {\n children: \"explicit\"\n }), \"\\n\", _jsx(_components.code, {\n children: \"X-Adaptyv-Payment-Method\"\n }), \" cannot switch it: a header naming a rail other\\nthan the pinned one is rejected with \", _jsx(_components.code, {\n children: \"409\"\n }), \" — retry with the pinned rail.\\nHeader-less discovery is the deliberate exception: a caller with a machine\\npayment policy is offered every machine rail this deployment serves and\\ncommits by sending one rail’s credential, which may be a machine rail other\\nthan the pinned one (they share a Stripe account, so the pin has already\\ndecided everything it decides). Omitting the header is therefore not a way\\nto reach the pinned rail, and a caller with no machine policy falls through\\nto the hosted invoice — which on a crypto-pinned quote is the absent-header\\n\", _jsx(_components.code, {\n children: \"409\"\n }), \" in the table above.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"This is the only endpoint that settles an invoice. The flow is two steps:\\n\", _jsx(_components.code, {\n children: \"POST /quotes/{quote_id}/confirm\"\n }), \" issues the invoice and returns a \", _jsx(_components.code, {\n children: \"payment\"\n }), \"\\npointer to this route, then \", _jsx(_components.code, {\n children: \"POST /invoices/{invoice_id}/pay\"\n }), \" settles it.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Send the first call with the method header and no credential. It answers\\n\", _jsx(_components.code, {\n children: \"402\"\n }), \", and \", _jsx(_components.strong, {\n children: \"the challenge is carried in the response headers, not the\\nbody\"\n }), \" — \", _jsx(_components.code, {\n children: \"PAYMENT-REQUIRED\"\n }), \" for \", _jsx(_components.code, {\n children: \"x402-exact\"\n }), \", \", _jsx(_components.code, {\n children: \"WWW-Authenticate\"\n }), \" for\\n\", _jsx(_components.code, {\n children: \"mpp-spt\"\n }), \".\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"That challenge is the whole handshake: it carries every parameter needed to\\nproduce the credential — for \", _jsx(_components.code, {\n children: \"mpp-spt\"\n }), \", the amount, currency, seller-network\\nid, expiry, and accepted payment-method types to mint the shared payment\\ntoken against. There is no separate endpoint to fetch them from, and there\\ncannot usefully be one: the credential must echo the challenge it answers,\\nso parameters obtained without taking a \", _jsx(_components.code, {\n children: \"402\"\n }), \" cannot be settled here.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Both \", _jsx(_components.code, {\n children: \"mpp-spt\"\n }), \" and \", _jsx(_components.code, {\n children: \"x402-exact\"\n }), \" settle over the API directly with these\\nheaders; the MCP server’s \", _jsx(_components.code, {\n children: \"pay_invoice\"\n }), \" tool is one client of this route,\\nnot the only way to reach the rail.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"Repeat the call with the signed credential to settle — \", _jsx(_components.code, {\n children: \"PAYMENT-SIGNATURE\"\n }), \"\\nfor \", _jsx(_components.code, {\n children: \"x402-exact\"\n }), \", \", _jsx(_components.code, {\n children: \"Authorization\"\n }), \" for \", _jsx(_components.code, {\n children: \"mpp-spt\"\n }), \" — and the response is \", _jsx(_components.code, {\n children: \"200\"\n }), \"\\nwith the paid invoice. Repeating it again is safe: an invoice that is\\nalready paid answers \", _jsx(_components.code, {\n children: \"200\"\n }), \" with \", _jsx(_components.code, {\n children: \"already_paid: true\"\n }), \" and settles nothing.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"When the settlement can be named, the response carries\\n\", _jsx(_components.code, {\n children: \"settlement_reference\"\n }), \". Treat it as optional even on a settling response.\"]\n }), \"\\n\", _jsxs(_components.p, {\n children: [\"The \", _jsx(_components.code, {\n children: \"payment.methods\"\n }), \" array on the confirm response lists the methods this\\nenvironment accepts; a value outside that list is rejected with \", _jsx(_components.code, {\n children: \"400\"\n }), \".\"]\n })]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Pay invoice","description":"Settles the given invoice. How it settles is chosen by the\n`X-Adaptyv-Payment-Method` request header:\n\n| Header value | Behaviour |\n|---|---|\n| _(absent)_ | Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns `409` — retry with the `X-Adaptyv-Payment-Method` header used at creation. |\n| `mpp-spt` | Settles from a Stripe shared payment token |\n| `x402-exact` | Settles on-chain with an x402 `exact` USDC transfer |\n\nThe payment rail is pinned when the experiment is created, and an *explicit*\n`X-Adaptyv-Payment-Method` cannot switch it: a header naming a rail other\nthan the pinned one is rejected with `409` — retry with the pinned rail.\nHeader-less discovery is the deliberate exception: a caller with a machine\npayment policy is offered every machine rail this deployment serves and\ncommits by sending one rail's credential, which may be a machine rail other\nthan the pinned one (they share a Stripe account, so the pin has already\ndecided everything it decides). Omitting the header is therefore not a way\nto reach the pinned rail, and a caller with no machine policy falls through\nto the hosted invoice — which on a crypto-pinned quote is the absent-header\n`409` in the table above.\n\nThis is the only endpoint that settles an invoice. The flow is two steps:\n`POST /quotes/{quote_id}/confirm` issues the invoice and returns a `payment`\npointer to this route, then `POST /invoices/{invoice_id}/pay` settles it.\n\nSend the first call with the method header and no credential. It answers\n`402`, and **the challenge is carried in the response headers, not the\nbody** — `PAYMENT-REQUIRED` for `x402-exact`, `WWW-Authenticate` for\n`mpp-spt`.\n\nThat challenge is the whole handshake: it carries every parameter needed to\nproduce the credential — for `mpp-spt`, the amount, currency, seller-network\nid, expiry, and accepted payment-method types to mint the shared payment\ntoken against. There is no separate endpoint to fetch them from, and there\ncannot usefully be one: the credential must echo the challenge it answers,\nso parameters obtained without taking a `402` cannot be settled here.\n\nBoth `mpp-spt` and `x402-exact` settle over the API directly with these\nheaders; the MCP server's `pay_invoice` tool is one client of this route,\nnot the only way to reach the rail.\n\nRepeat the call with the signed credential to settle — `PAYMENT-SIGNATURE`\nfor `x402-exact`, `Authorization` for `mpp-spt` — and the response is `200`\nwith the paid invoice. Repeating it again is safe: an invoice that is\nalready paid answers `200` with `already_paid: true` and settles nothing.\n\nWhen the settlement can be named, the response carries\n`settlement_reference`. Treat it as optional even on a settling response.\n\nThe `payment.methods` array on the confirm response lists the methods this\nenvironment accepts; a value outside that list is rejected with `400`.","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/invoices/{invoice_id}/pay","href":"/api-reference/invoices/pay-invoice","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"tags":["invoices"],"summary":"Pay invoice","description":"Settles the given invoice. How it settles is chosen by the\n`X-Adaptyv-Payment-Method` request header:\n\n| Header value | Behaviour |\n|---|---|\n| _(absent)_ | Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns `409` — retry with the `X-Adaptyv-Payment-Method` header used at creation. |\n| `mpp-spt` | Settles from a Stripe shared payment token |\n| `x402-exact` | Settles on-chain with an x402 `exact` USDC transfer |\n\nThe payment rail is pinned when the experiment is created, and an *explicit*\n`X-Adaptyv-Payment-Method` cannot switch it: a header naming a rail other\nthan the pinned one is rejected with `409` — retry with the pinned rail.\nHeader-less discovery is the deliberate exception: a caller with a machine\npayment policy is offered every machine rail this deployment serves and\ncommits by sending one rail's credential, which may be a machine rail other\nthan the pinned one (they share a Stripe account, so the pin has already\ndecided everything it decides). Omitting the header is therefore not a way\nto reach the pinned rail, and a caller with no machine policy falls through\nto the hosted invoice — which on a crypto-pinned quote is the absent-header\n`409` in the table above.\n\nThis is the only endpoint that settles an invoice. The flow is two steps:\n`POST /quotes/{quote_id}/confirm` issues the invoice and returns a `payment`\npointer to this route, then `POST /invoices/{invoice_id}/pay` settles it.\n\nSend the first call with the method header and no credential. It answers\n`402`, and **the challenge is carried in the response headers, not the\nbody** — `PAYMENT-REQUIRED` for `x402-exact`, `WWW-Authenticate` for\n`mpp-spt`.\n\nThat challenge is the whole handshake: it carries every parameter needed to\nproduce the credential — for `mpp-spt`, the amount, currency, seller-network\nid, expiry, and accepted payment-method types to mint the shared payment\ntoken against. There is no separate endpoint to fetch them from, and there\ncannot usefully be one: the credential must echo the challenge it answers,\nso parameters obtained without taking a `402` cannot be settled here.\n\nBoth `mpp-spt` and `x402-exact` settle over the API directly with these\nheaders; the MCP server's `pay_invoice` tool is one client of this route,\nnot the only way to reach the rail.\n\nRepeat the call with the signed credential to settle — `PAYMENT-SIGNATURE`\nfor `x402-exact`, `Authorization` for `mpp-spt` — and the response is `200`\nwith the paid invoice. Repeating it again is safe: an invoice that is\nalready paid answers `200` with `already_paid: true` and settles nothing.\n\nWhen the settlement can be named, the response carries\n`settlement_reference`. Treat it as optional even on a settling response.\n\nThe `payment.methods` array on the confirm response lists the methods this\nenvironment accepts; a value outside that list is rejected with `400`.","operationId":"pay_invoice","parameters":["4518675d-e1fb-4e00-b1a6-0f5f01e8fb68","f94ecb0e-0afe-40fb-814e-7cae7b4fb4b1"],"responses":{"200":"652964bb-916f-4e1f-bf83-d887837ef46e","400":"c184d1a8-f962-40e9-824a-92f784d5e9e2","401":"d0ee2b93-be3f-4a1d-b0e6-7202557b9eed","403":"7b6b0757-469f-4b9a-850e-23ed69dcb19c","404":"9e7cca1a-e3b3-4d60-b61a-5b1f1476b0a7","409":"5334b4ec-d705-46ae-af49-8c8901e346c6","422":"23c7c602-4a30-4934-a63d-0794147a19a5","500":"b0371302-c1b3-4228-ba19-7ede08af3d8c","501":"1a4efd5b-7f7a-40d1-88c7-9ab7c8b23253"},"x-required-action":"Pay","method":"post","type":"path","servers":["17169e3c-fb29-4b76-8040-3a4a0fa01432"],"security":["b792f57f-20a8-4bb6-b915-19cc094ad32d"],"path":"/api/v1/invoices/{invoice_id}/pay","baseUrlOptions":["https://devs.adaptyvbio.com/"],"title":"Pay invoice","codeSamples":[],"requiredOnlyExamples":false,"requestExampleType":"generated","responseExampleType":"generated"},"dependencies":{"parameters":{"4518675d-e1fb-4e00-b1a6-0f5f01e8fb68":{"name":"invoice_id","in":"path","description":"Foundry invoice UUID or Stripe invoice ID (`in_xxx`)","required":true,"schema":{"type":"string","isRequired":true,"description":"Foundry invoice UUID or Stripe invoice ID (`in_xxx`)","uniqueKey":"","typeLabel":"string"}},"f94ecb0e-0afe-40fb-814e-7cae7b4fb4b1":{"name":"X-Adaptyv-Payment-Method","in":"header","description":"Settlement method: `mpp-spt` or `x402-exact`. Must name the rail pinned at experiment creation; naming a different one is a `409`. Omit to read the current invoice state and pay via the hosted URL instead — but a quote pinned to a crypto rail at experiment creation returns `409` when the header is absent, so retry with the value used at creation. The methods an environment accepts are listed in `payment.methods` on the confirm response.","required":false,"schema":{"oneOf":[{"type":"string","description":"Settlement method: `mpp-spt` or `x402-exact`. Must name the rail pinned at experiment creation; naming a different one is a `409`. Omit to read the current invoice state and pay via the hosted URL instead — but a quote pinned to a crypto rail at experiment creation returns `409` when the header is absent, so retry with the value used at creation. The methods an environment accepts are listed in `payment.methods` on the confirm response.","uniqueKey":"oneOf.0","typeLabel":"string"},{"type":"null","description":"Settlement method: `mpp-spt` or `x402-exact`. Must name the rail pinned at experiment creation; naming a different one is a `409`. Omit to read the current invoice state and pay via the hosted URL instead — but a quote pinned to a crypto rail at experiment creation returns `409` when the header is absent, so retry with the value used at creation. The methods an environment accepts are listed in `payment.methods` on the confirm response.","uniqueKey":"oneOf.1","typeLabel":"null"}],"isRequired":false,"uniqueKey":"","typeLabel":"string | null"}}},"responses":{"652964bb-916f-4e1f-bf83-d887837ef46e":{"description":"Invoice paid (or already paid)","content":{"application/json":{"schema":{"type":"object","description":"Response returned by `POST /invoices/{invoice_id}/pay`.\n\nReports the invoice after the call, so no follow-up `GET` is needed. It is\nreturned for three outcomes, which `status` and `already_paid` tell apart:\na settlement this request performed, an invoice that was already paid, and\n— when no payment-method header was sent — the current state of an invoice\nthat is still unpaid and that this call settled nothing on.\n\nA `200` therefore does **not** by itself mean the invoice is paid. Read\n`status`. The `402` challenge is not this body.","required":["id","status","already_paid"],"properties":{"already_paid":{"type":"boolean","description":"`true` when the call was a no-op because the invoice was already paid\nbefore this request.\n\n`false` otherwise — which covers two different outcomes: this request\nsettled the invoice, or no payment method was selected and the body\nreports the invoice's current state without settling. Read `status` to\ntell those apart; `false` alone does not mean the invoice is paid.","isRequired":true,"uniqueKey":"already_paid","typeLabel":"boolean"},"id":{"type":"string","description":"Stripe invoice ID (`in_xxx`) that was paid.","example":"in_1OqLk2LkdIwHu7ix6OboRpXl","isRequired":true,"uniqueKey":"id","typeLabel":"string"},"status":{"type":"string","description":"Current invoice status after the call. `paid` on success.","enum":["draft","open","paid","void","uncollectible"],"isRequired":true,"uniqueKey":"status","typeLabel":"enum\u003cstring>"},"hosted_invoice_url":{"oneOf":[{"type":"string","description":"Stripe-hosted invoice URL, when known.","example":"https://invoice.stripe.com/i/acct_1234/test_5678","uniqueKey":"hosted_invoice_url.oneOf.0","typeLabel":"string"},{"type":"null","description":"Stripe-hosted invoice URL, when known.","example":"https://invoice.stripe.com/i/acct_1234/test_5678","uniqueKey":"hosted_invoice_url.oneOf.1","typeLabel":"null"}],"uniqueKey":"hosted_invoice_url","typeLabel":"string | null"},"settlement_reference":{"oneOf":[{"type":"null","uniqueKey":"settlement_reference.oneOf.0","typeLabel":"null"},{"type":"object","description":"Names what settled this invoice — the on-chain transaction for\n`x402-exact`, or the Stripe PaymentIntent for `mpp-spt`.\n\nOnly a response that performed the settlement can carry it, so it is\nabsent when `already_paid` is `true` and absent from the state read of\nan unpaid invoice. Treat it as optional even on a settling response:\nwhen the rail reports nothing this API can name honestly, the field is\nomitted rather than guessed at.\n\nRecord it when you receive it. Repeating the call afterwards answers\n`already_paid` without the reference, and it is not available from any\nother endpoint.","required":["tx_hash","type"],"properties":{"tx_hash":{"type":"string","description":"On-chain transaction hash of the settling transfer.","example":"0x9c2f1a7e5b0d4c3a8f6e2d1b0a9c8f7e6d5c4b3a29180f7e6d5c4b3a29180f7e","isRequired":true,"uniqueKey":"settlement_reference.oneOf.1.tx_hash","typeLabel":"string"},"type":{"type":"string","enum":["x402_transaction"],"isRequired":true,"uniqueKey":"settlement_reference.oneOf.1.type","typeLabel":"enum\u003cstring>"}},"uniqueKey":"settlement_reference.oneOf.1","typeLabel":"object"},{"type":"object","description":"Names what settled this invoice — the on-chain transaction for\n`x402-exact`, or the Stripe PaymentIntent for `mpp-spt`.\n\nOnly a response that performed the settlement can carry it, so it is\nabsent when `already_paid` is `true` and absent from the state read of\nan unpaid invoice. Treat it as optional even on a settling response:\nwhen the rail reports nothing this API can name honestly, the field is\nomitted rather than guessed at.\n\nRecord it when you receive it. Repeating the call afterwards answers\n`already_paid` without the reference, and it is not available from any\nother endpoint.","required":["payment_intent_id","type"],"properties":{"payment_intent_id":{"type":"string","description":"Stripe PaymentIntent ID (`pi_xxx`) credited to the invoice.","example":"pi_3OqLk2LkdIwHu7ix6OboRpXl","isRequired":true,"uniqueKey":"settlement_reference.oneOf.2.payment_intent_id","typeLabel":"string"},"type":{"type":"string","enum":["stripe_payment_intent"],"isRequired":true,"uniqueKey":"settlement_reference.oneOf.2.type","typeLabel":"enum\u003cstring>"}},"uniqueKey":"settlement_reference.oneOf.2","typeLabel":"object"}],"uniqueKey":"settlement_reference","typeLabel":"null · object · object"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"already_paid":true,"id":"in_1OqLk2LkdIwHu7ix6OboRpXl","status":"draft","hosted_invoice_url":"https://invoice.stripe.com/i/acct_1234/test_5678","settlement_reference":{"tx_hash":"0x9c2f1a7e5b0d4c3a8f6e2d1b0a9c8f7e6d5c4b3a29180f7e6d5c4b3a29180f7e","type":"x402_transaction"}}}},"exampleType":"generated"}},"exampleType":"generated"},"c184d1a8-f962-40e9-824a-92f784d5e9e2":{"description":"Unrecognised payment method, or a malformed credential","content":{"application/json":{"schema":{"type":"object","description":"Error response body returned by all endpoints on 4xx/5xx failures.\n\nEvery error response contains a human-readable message and the request ID\nfor support correlation. The `request_id` is also returned in the\n`x-request-id` response header.","required":["error","request_id"],"properties":{"error":{"type":"string","description":"Human-readable error description.","example":"experiment not found","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"request_id":{"type":"string","description":"Request identifier for support correlation (also in `x-request-id` header).","example":"req_019462a4-b1c2-7def-8901-23456789abcd","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"experiment not found","request_id":"req_019462a4-b1c2-7def-8901-23456789abcd"}}},"exampleType":"generated"}},"exampleType":"generated"},"d0ee2b93-be3f-4a1d-b0e6-7202557b9eed":{"description":"Invalid or missing authentication token","content":{"application/json":{"schema":{"type":"object","description":"Error response body returned by all endpoints on 4xx/5xx failures.\n\nEvery error response contains a human-readable message and the request ID\nfor support correlation. The `request_id` is also returned in the\n`x-request-id` response header.","required":["error","request_id"],"properties":{"error":{"type":"string","description":"Human-readable error description.","example":"experiment not found","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"request_id":{"type":"string","description":"Request identifier for support correlation (also in `x-request-id` header).","example":"req_019462a4-b1c2-7def-8901-23456789abcd","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"experiment not found","request_id":"req_019462a4-b1c2-7def-8901-23456789abcd"}}},"exampleType":"generated"}},"exampleType":"generated"},"7b6b0757-469f-4b9a-850e-23ed69dcb19c":{"description":"Insufficient permissions to pay invoices","content":{"application/json":{"schema":{"type":"object","description":"Error response body returned by all endpoints on 4xx/5xx failures.\n\nEvery error response contains a human-readable message and the request ID\nfor support correlation. The `request_id` is also returned in the\n`x-request-id` response header.","required":["error","request_id"],"properties":{"error":{"type":"string","description":"Human-readable error description.","example":"experiment not found","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"request_id":{"type":"string","description":"Request identifier for support correlation (also in `x-request-id` header).","example":"req_019462a4-b1c2-7def-8901-23456789abcd","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"experiment not found","request_id":"req_019462a4-b1c2-7def-8901-23456789abcd"}}},"exampleType":"generated"}},"exampleType":"generated"},"9e7cca1a-e3b3-4d60-b61a-5b1f1476b0a7":{"description":"Invoice not found or not accessible","content":{"application/json":{"schema":{"type":"object","description":"Error response body returned by all endpoints on 4xx/5xx failures.\n\nEvery error response contains a human-readable message and the request ID\nfor support correlation. The `request_id` is also returned in the\n`x-request-id` response header.","required":["error","request_id"],"properties":{"error":{"type":"string","description":"Human-readable error description.","example":"experiment not found","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"request_id":{"type":"string","description":"Request identifier for support correlation (also in `x-request-id` header).","example":"req_019462a4-b1c2-7def-8901-23456789abcd","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"experiment not found","request_id":"req_019462a4-b1c2-7def-8901-23456789abcd"}}},"exampleType":"generated"}},"exampleType":"generated"},"5334b4ec-d705-46ae-af49-8c8901e346c6":{"description":"The `X-Adaptyv-Payment-Method` header names a rail other than the one pinned at experiment creation (retry with the pinned rail — it is named in the error), a settlement for this invoice is already in flight, or the session is closed","content":{"application/json":{"schema":{"type":"object","description":"Error response body returned by all endpoints on 4xx/5xx failures.\n\nEvery error response contains a human-readable message and the request ID\nfor support correlation. The `request_id` is also returned in the\n`x-request-id` response header.","required":["error","request_id"],"properties":{"error":{"type":"string","description":"Human-readable error description.","example":"experiment not found","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"request_id":{"type":"string","description":"Request identifier for support correlation (also in `x-request-id` header).","example":"req_019462a4-b1c2-7def-8901-23456789abcd","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"experiment not found","request_id":"req_019462a4-b1c2-7def-8901-23456789abcd"}}},"exampleType":"generated"}},"exampleType":"generated"},"23c7c602-4a30-4934-a63d-0794147a19a5":{"description":"Invoice is not in a payable state","content":{"application/json":{"schema":{"type":"object","description":"Error response body returned by all endpoints on 4xx/5xx failures.\n\nEvery error response contains a human-readable message and the request ID\nfor support correlation. The `request_id` is also returned in the\n`x-request-id` response header.","required":["error","request_id"],"properties":{"error":{"type":"string","description":"Human-readable error description.","example":"experiment not found","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"request_id":{"type":"string","description":"Request identifier for support correlation (also in `x-request-id` header).","example":"req_019462a4-b1c2-7def-8901-23456789abcd","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"experiment not found","request_id":"req_019462a4-b1c2-7def-8901-23456789abcd"}}},"exampleType":"generated"}},"exampleType":"generated"},"b0371302-c1b3-4228-ba19-7ede08af3d8c":{"description":"Internal server error","content":{"application/json":{"schema":{"type":"object","description":"Error response body returned by all endpoints on 4xx/5xx failures.\n\nEvery error response contains a human-readable message and the request ID\nfor support correlation. The `request_id` is also returned in the\n`x-request-id` response header.","required":["error","request_id"],"properties":{"error":{"type":"string","description":"Human-readable error description.","example":"experiment not found","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"request_id":{"type":"string","description":"Request identifier for support correlation (also in `x-request-id` header).","example":"req_019462a4-b1c2-7def-8901-23456789abcd","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"experiment not found","request_id":"req_019462a4-b1c2-7def-8901-23456789abcd"}}},"exampleType":"generated"}},"exampleType":"generated"},"1a4efd5b-7f7a-40d1-88c7-9ab7c8b23253":{"description":"This environment does not provide the requested payment method","content":{"application/json":{"schema":{"type":"object","description":"Error response body returned by all endpoints on 4xx/5xx failures.\n\nEvery error response contains a human-readable message and the request ID\nfor support correlation. The `request_id` is also returned in the\n`x-request-id` response header.","required":["error","request_id"],"properties":{"error":{"type":"string","description":"Human-readable error description.","example":"experiment not found","isRequired":true,"uniqueKey":"error","typeLabel":"string"},"request_id":{"type":"string","description":"Request identifier for support correlation (also in `x-request-id` header).","example":"req_019462a4-b1c2-7def-8901-23456789abcd","isRequired":true,"uniqueKey":"request_id","typeLabel":"string"}},"uniqueKey":"","typeLabel":"object"},"examples":{"Example":{"title":"Example","value":{"error":"experiment not found","request_id":"req_019462a4-b1c2-7def-8901-23456789abcd"}}},"exampleType":"generated"}},"exampleType":"generated"}},"security":{"b792f57f-20a8-4bb6-b915-19cc094ad32d":{"adaptyv_biscuits_v0":{"type":"http","scheme":"bearer","bearerFormat":"Adaptyv Biscuits v0","description":"Biscuit-based bearer token. Obtain tokens from the Adaptyv Portal or via the `/tokens` endpoint. Tokens encode organization membership and role-based capabilities; the API verifies the token's cryptographic signature and authorization claims before processing requests. Use `/tokens/attenuate` to create restricted tokens for delegation.","scopes":[],"schemeName":"adaptyv_biscuits_v0"}}},"servers":{"17169e3c-fb29-4b76-8040-3a4a0fa01432":{"url":"https://devs.adaptyvbio.com/","description":"Production API (Public)"}},"processedSecurityOptions":[{"schemes":[{"scheme":{"type":"http","scheme":"bearer","bearerFormat":"Adaptyv Biscuits v0","description":"Biscuit-based bearer token. Obtain tokens from the Adaptyv Portal or via the `/tokens` endpoint. Tokens encode organization membership and role-based capabilities; the API verifies the token's cryptographic signature and authorization claims before processing requests. Use `/tokens/attenuate` to create restricted tokens for delegation.","scopes":[],"schemeName":"adaptyv_biscuits_v0"},"schema":{"title":"Bearer Auth","type":"string","isRequired":true,"description":"Biscuit-based bearer token. Obtain tokens from the Adaptyv Portal or via the `/tokens` endpoint. Tokens encode organization membership and role-based capabilities; the API verifies the token's cryptographic signature and authorization claims before processing requests. Use `/tokens/attenuate` to create restricted tokens for delegation.","format":"bearer","typeLabel":"string\u003cbearer>","deprecated":false},"schemeName":"adaptyv_biscuits_v0","name":"Authorization"}],"title":"adaptyv_biscuits_v0"}]},"originalFileLocation":"https://devs.adaptyvbio.com/api/v1/openapi.json"},"subdomain":"adaptyv-a4917ef6","siteName":"Adaptyv Bio Docs","title":"Pay invoice - Adaptyv Bio Docs","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-10-27T01:05:37.938Z","originalFileLocation":"api-reference/invoices/pay-invoice.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Settles the given invoice. How it settles is chosen by the X-Adaptyv-Payment-Method request header: | Header value | Behaviour | |---|---| | (absent) | Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns 409 — retry with the X-Adaptyv-Payment-Method header used at creation. | | mpp-spt | Settles from a Stripe shared payment token | | x402-exact | Settles on-chain with an x402 exact USDC transfer | The payment rail is pinned when the experiment is created, and an explicit X-Adaptyv-Payment-Method cannot switch it: a header naming a rail other than the pinned one is rejected with 409 — retry with the pinned rail. Header-less discovery is the deliberate exception: a caller with a machine payment policy is offered every machine rail this deployment serves and commits by sending one rail\u0026#x27;s credential, which may be a machine rail other than the pinned one (they share a Stripe account, so the pin has already decided everything it decides). Omitting the header is therefore not a way to reach the pinned rail, and a caller with no machine policy falls through to the hosted invoice — which on a crypto-pinned quote is the absent-header 409 in the table above. This is the only endpoint that settles an invoice. The flow is two steps: POST /quotes/{quote_id}/confirm issues the invoice and returns a payment pointer to this route, then POST /invoices/{invoice_id}/pay settles it. Send the first call with the method header and no credential. It answers 402, and the challenge is carried in the response headers, not the body — PAYMENT-REQUIRED for x402-exact, WWW-Authenticate for mpp-spt. That challenge is the whole handshake: it carries every parameter needed to produce the credential — for mpp-spt, the amount, currency, seller-network id, expiry, and accepted payment-method types to mint the shared payment token against. There is no separate endpoint to fetch them from, and there cannot usefully be one: the credential must echo the challenge it answers, so parameters obtained without taking a 402 cannot be settled here. Both mpp-spt and x402-exact settle over the API directly with these headers; the MCP server\u0026#x27;s pay_invoice tool is one client of this route, not the only way to reach the rail. Repeat the call with the signed credential to settle — PAYMENT-SIGNATURE for x402-exact, Authorization for mpp-spt — and the response is 200 with the paid invoice. Repeating it again is safe: an invoice that is already paid answers 200 with already_paid: true and settles nothing. When the settlement can be named, the response carries settlement_reference. Treat it as optional even on a settling response. The payment.methods array on the confirm response lists the methods this environment accepts; a value outside that list is rejected with 400.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Adaptyv Bio Docs\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Pay invoice - Adaptyv Bio Docs\">\u003cmeta data-mint-head property=\"og:description\" content=\"Settles the given invoice. How it settles is chosen by the X-Adaptyv-Payment-Method request header: | Header value | Behaviour | |---|---| | (absent) | Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns 409 — retry with the X-Adaptyv-Payment-Method header used at creation. | | mpp-spt | Settles from a Stripe shared payment token | | x402-exact | Settles on-chain with an x402 exact USDC transfer | The payment rail is pinned when the experiment is created, and an explicit X-Adaptyv-Payment-Method cannot switch it: a header naming a rail other than the pinned one is rejected with 409 — retry with the pinned rail. Header-less discovery is the deliberate exception: a caller with a machine payment policy is offered every machine rail this deployment serves and commits by sending one rail\u0026#x27;s credential, which may be a machine rail other than the pinned one (they share a Stripe account, so the pin has already decided everything it decides). Omitting the header is therefore not a way to reach the pinned rail, and a caller with no machine policy falls through to the hosted invoice — which on a crypto-pinned quote is the absent-header 409 in the table above. This is the only endpoint that settles an invoice. The flow is two steps: POST /quotes/{quote_id}/confirm issues the invoice and returns a payment pointer to this route, then POST /invoices/{invoice_id}/pay settles it. Send the first call with the method header and no credential. It answers 402, and the challenge is carried in the response headers, not the body — PAYMENT-REQUIRED for x402-exact, WWW-Authenticate for mpp-spt. That challenge is the whole handshake: it carries every parameter needed to produce the credential — for mpp-spt, the amount, currency, seller-network id, expiry, and accepted payment-method types to mint the shared payment token against. There is no separate endpoint to fetch them from, and there cannot usefully be one: the credential must echo the challenge it answers, so parameters obtained without taking a 402 cannot be settled here. Both mpp-spt and x402-exact settle over the API directly with these headers; the MCP server\u0026#x27;s pay_invoice tool is one client of this route, not the only way to reach the rail. Repeat the call with the signed credential to settle — PAYMENT-SIGNATURE for x402-exact, Authorization for mpp-spt — and the response is 200 with the paid invoice. Repeating it again is safe: an invoice that is already paid answers 200 with already_paid: true and settles nothing. When the settlement can be named, the response carries settlement_reference. Treat it as optional even on a settling response. The payment.methods array on the confirm response lists the methods this environment accepts; a value outside that list is rejected with 400.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Adaptyv Bio Docs\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://adaptyv-a4917ef6.mintlify.app/_mintlify/api/og/v2?division=invoices\u0026amp;title=Pay+invoice\u0026amp;description=Settles+the+given+invoice.+How+it+settles+is+chosen+by+the%0A%60X-Adaptyv-Payment-Method%60+request+header%3A%0A%0A%7C+Header+value+%7C+Behaviour+%7C%0A%7C---%7C---%7C%0A%7C+_%28absent%29_+%7C+Ret\u0026amp;theme=43e189271cead89711960f8b\u0026amp;signature=cb66bfa2bacd5117b96016e7bfbfb8a22d52e295a9ec3475c7143653b032d4be\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Pay invoice - Adaptyv Bio Docs\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Settles the given invoice. How it settles is chosen by the X-Adaptyv-Payment-Method request header: | Header value | Behaviour | |---|---| | (absent) | Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns 409 — retry with the X-Adaptyv-Payment-Method header used at creation. | | mpp-spt | Settles from a Stripe shared payment token | | x402-exact | Settles on-chain with an x402 exact USDC transfer | The payment rail is pinned when the experiment is created, and an explicit X-Adaptyv-Payment-Method cannot switch it: a header naming a rail other than the pinned one is rejected with 409 — retry with the pinned rail. Header-less discovery is the deliberate exception: a caller with a machine payment policy is offered every machine rail this deployment serves and commits by sending one rail\u0026#x27;s credential, which may be a machine rail other than the pinned one (they share a Stripe account, so the pin has already decided everything it decides). Omitting the header is therefore not a way to reach the pinned rail, and a caller with no machine policy falls through to the hosted invoice — which on a crypto-pinned quote is the absent-header 409 in the table above. This is the only endpoint that settles an invoice. The flow is two steps: POST /quotes/{quote_id}/confirm issues the invoice and returns a payment pointer to this route, then POST /invoices/{invoice_id}/pay settles it. Send the first call with the method header and no credential. It answers 402, and the challenge is carried in the response headers, not the body — PAYMENT-REQUIRED for x402-exact, WWW-Authenticate for mpp-spt. That challenge is the whole handshake: it carries every parameter needed to produce the credential — for mpp-spt, the amount, currency, seller-network id, expiry, and accepted payment-method types to mint the shared payment token against. There is no separate endpoint to fetch them from, and there cannot usefully be one: the credential must echo the challenge it answers, so parameters obtained without taking a 402 cannot be settled here. Both mpp-spt and x402-exact settle over the API directly with these headers; the MCP server\u0026#x27;s pay_invoice tool is one client of this route, not the only way to reach the rail. Repeat the call with the signed credential to settle — PAYMENT-SIGNATURE for x402-exact, Authorization for mpp-spt — and the response is 200 with the paid invoice. Repeating it again is safe: an invoice that is already paid answers 200 with already_paid: true and settles nothing. When the settlement can be named, the response carries settlement_reference. Treat it as optional even on a settling response. The payment.methods array on the confirm response lists the methods this environment accepts; a value outside that list is rejected with 400.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://adaptyv-a4917ef6.mintlify.app/_mintlify/api/og/v2?division=invoices\u0026amp;title=Pay+invoice\u0026amp;description=Settles+the+given+invoice.+How+it+settles+is+chosen+by+the%0A%60X-Adaptyv-Payment-Method%60+request+header%3A%0A%0A%7C+Header+value+%7C+Behaviour+%7C%0A%7C---%7C---%7C%0A%7C+_%28absent%29_+%7C+Ret\u0026amp;theme=43e189271cead89711960f8b\u0026amp;signature=cb66bfa2bacd5117b96016e7bfbfb8a22d52e295a9ec3475c7143653b032d4be\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/adaptyv-a4917ef6/zzyucPz0fZkqpoJX/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Adaptyv Bio Docs\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#5db0dd\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/invoices/pay-invoice.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.adaptyvbio.com/#organization\",\"name\":\"Adaptyv Bio Docs\",\"url\":\"https://docs.adaptyvbio.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/adaptyv-a4917ef6/3kX9xKvyzUlLV3Dj/logo/logo-light.svg?fit=max\u0026auto=format\u0026n=3kX9xKvyzUlLV3Dj\u0026q=85\u0026s=28a1e3df60674482d4bac1fc9d190568\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.adaptyvbio.com#website\",\"name\":\"Adaptyv Bio Docs\",\"url\":\"https://docs.adaptyvbio.com\",\"publisher\":{\"@id\":\"https://docs.adaptyvbio.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice#webpage\",\"url\":\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice\",\"name\":\"Pay invoice\",\"description\":\"Settles the given invoice. How it settles is chosen by the X-Adaptyv-Payment-Method request header: | Header value | Behaviour | |---|---| | (absent) | Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns 409 — retry with the X-Adaptyv-Payment-Method header used at creation. | | mpp-spt | Settles from a Stripe shared payment token | | x402-exact | Settles on-chain with an x402 exact USDC transfer | The payment rail is pinned when the experiment is created, and an explicit X-Adaptyv-Payment-Method cannot switch it: a header naming a rail other than the pinned one is rejected with 409 — retry with the pinned rail. Header-less discovery is the deliberate exception: a caller with a machine payment policy is offered every machine rail this deployment serves and commits by sending one rail's credential, which may be a machine rail other than the pinned one (they share a Stripe account, so the pin has already decided everything it decides). Omitting the header is therefore not a way to reach the pinned rail, and a caller with no machine policy falls through to the hosted invoice — which on a crypto-pinned quote is the absent-header 409 in the table above. This is the only endpoint that settles an invoice. The flow is two steps: POST /quotes/{quote_id}/confirm issues the invoice and returns a payment pointer to this route, then POST /invoices/{invoice_id}/pay settles it. Send the first call with the method header and no credential. It answers 402, and the challenge is carried in the response headers, not the body — PAYMENT-REQUIRED for x402-exact, WWW-Authenticate for mpp-spt. That challenge is the whole handshake: it carries every parameter needed to produce the credential — for mpp-spt, the amount, currency, seller-network id, expiry, and accepted payment-method types to mint the shared payment token against. There is no separate endpoint to fetch them from, and there cannot usefully be one: the credential must echo the challenge it answers, so parameters obtained without taking a 402 cannot be settled here. Both mpp-spt and x402-exact settle over the API directly with these headers; the MCP server's pay_invoice tool is one client of this route, not the only way to reach the rail. Repeat the call with the signed credential to settle — PAYMENT-SIGNATURE for x402-exact, Authorization for mpp-spt — and the response is 200 with the paid invoice. Repeating it again is safe: an invoice that is already paid answers 200 with already_paid: true and settles nothing. When the settlement can be named, the response carries settlement_reference. Treat it as optional even on a settling response. The payment.methods array on the confirm response lists the methods this environment accepts; a value outside that list is rejected with 400.\",\"dateModified\":\"2026-10-27T01:05:37.938Z\",\"isPartOf\":{\"@id\":\"https://docs.adaptyvbio.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"API Endpoints\",\"item\":\"https://docs.adaptyvbio.com/api-reference/experiments/list-experiments\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"invoices\",\"item\":\"https://docs.adaptyvbio.com/api-reference/invoices/list-invoices\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Pay invoice\",\"item\":\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice#apireference\",\"headline\":\"Pay invoice\",\"name\":\"Pay invoice\",\"description\":\"Settles the given invoice. How it settles is chosen by the X-Adaptyv-Payment-Method request header: | Header value | Behaviour | |---|---| | (absent) | Returns the current invoice state; pay via the hosted invoice URL. If the quote was pinned to a crypto rail at experiment creation, returns 409 — retry with the X-Adaptyv-Payment-Method header used at creation. | | mpp-spt | Settles from a Stripe shared payment token | | x402-exact | Settles on-chain with an x402 exact USDC transfer | The payment rail is pinned when the experiment is created, and an explicit X-Adaptyv-Payment-Method cannot switch it: a header naming a rail other than the pinned one is rejected with 409 — retry with the pinned rail. Header-less discovery is the deliberate exception: a caller with a machine payment policy is offered every machine rail this deployment serves and commits by sending one rail's credential, which may be a machine rail other than the pinned one (they share a Stripe account, so the pin has already decided everything it decides). Omitting the header is therefore not a way to reach the pinned rail, and a caller with no machine policy falls through to the hosted invoice — which on a crypto-pinned quote is the absent-header 409 in the table above. This is the only endpoint that settles an invoice. The flow is two steps: POST /quotes/{quote_id}/confirm issues the invoice and returns a payment pointer to this route, then POST /invoices/{invoice_id}/pay settles it. Send the first call with the method header and no credential. It answers 402, and the challenge is carried in the response headers, not the body — PAYMENT-REQUIRED for x402-exact, WWW-Authenticate for mpp-spt. That challenge is the whole handshake: it carries every parameter needed to produce the credential — for mpp-spt, the amount, currency, seller-network id, expiry, and accepted payment-method types to mint the shared payment token against. There is no separate endpoint to fetch them from, and there cannot usefully be one: the credential must echo the challenge it answers, so parameters obtained without taking a 402 cannot be settled here. Both mpp-spt and x402-exact settle over the API directly with these headers; the MCP server's pay_invoice tool is one client of this route, not the only way to reach the rail. Repeat the call with the signed credential to settle — PAYMENT-SIGNATURE for x402-exact, Authorization for mpp-spt — and the response is 200 with the paid invoice. Repeating it again is safe: an invoice that is already paid answers 200 with already_paid: true and settles nothing. When the settlement can be named, the response carries settlement_reference. Treat it as optional even on a settling response. The payment.methods array on the confirm response lists the methods this environment accepts; a value outside that list is rejected with 400.\",\"url\":\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice\",\"mainEntityOfPage\":{\"@id\":\"https://docs.adaptyvbio.com/api-reference/invoices/pay-invoice#webpage\"},\"dateModified\":\"2026-10-27T01:05:37.938Z\",\"publisher\":{\"@id\":\"https://docs.adaptyvbio.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.adaptyvbio.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Adaptyv Bio Docs\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Adaptyv Bio Docs","nav":{"global":{"anchors":[{"anchor":"Careers","icon":"users","href":"https://www.adaptyvbio.com/careers"},{"anchor":"Blog","icon":"newspaper","href":"https://www.adaptyvbio.com/blog"},{"anchor":"Experiment Configurator","icon":"flask","href":"https://start.adaptyvbio.com"},{"anchor":"Foundry Portal","icon":"desktop","href":"https://foundry.adaptyvbio.com"}]},"tabs":[{"tab":"Documentation","icon":"file-lines","pages":[{"title":"Documentation","href":"/docs/getting-started/introduction"}]},{"tab":"Wiki","icon":"book","pages":[{"title":"Wiki","href":"/wiki/technologies/cell-free-protein-expression"}]},{"tab":"Guides","icon":"lightbulb","pages":[{"title":"Guides","href":"/guides/improve-protein-expression"}]},{"tab":"API","icon":"code","groups":[{"group":"Getting Started","pages":[{"title":"Foundry API","href":"/api-reference/api-introduction"},{"title":"MCP Server","href":"/api-reference/mcp-server"},{"title":"Integrator \u0026 Partner Guide","href":"/api-reference/integrator-partner-guide"}]},{"group":"Payments","pages":[{"title":"Payments Overview","href":"/api-reference/payments/overview"},{"title":"Pay by hosted invoice","href":"/api-reference/payments/pay-hosted-invoice"},{"title":"Pay with x402 (exact)","href":"/api-reference/payments/pay-x402-exact"},{"title":"Pay with a Shared Payment Token (MPP-SPT)","href":"/api-reference/payments/pay-mpp-spt"}]},{"group":"API Endpoints","pages":[{"group":"experiments","pages":[{"title":"List experiments","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/experiments","href":"/api-reference/experiments/list-experiments"},{"title":"Create experiment","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/experiments","href":"/api-reference/experiments/create-experiment"},{"title":"Estimate experiment cost","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/experiments/cost-estimate","href":"/api-reference/experiments/estimate-experiment-cost"},{"title":"Get experiment","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/experiments/{experiment_id}","href":"/api-reference/experiments/get-experiment"},{"title":"Update experiment","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json patch /api/v1/experiments/{experiment_id}","href":"/api-reference/experiments/update-experiment"},{"title":"Get experiment invoice","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/experiments/{experiment_id}/invoice","href":"/api-reference/experiments/get-experiment-invoice"},{"title":"Get experiment quote","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/experiments/{experiment_id}/quote","href":"/api-reference/experiments/get-experiment-quote"},{"title":"Accept an experiment's quote and create an invoice","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/experiments/{experiment_id}/quote/confirm","href":"/api-reference/experiments/accept-an-experiments-quote-and-create-an-invoice"},{"title":"Get experiment quote PDF","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/experiments/{experiment_id}/quote/pdf","href":"/api-reference/experiments/get-experiment-quote-pdf"},{"title":"List results for an experiment","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/experiments/{experiment_id}/results","href":"/api-reference/experiments/list-results-for-an-experiment"},{"title":"List sequences for an experiment","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/experiments/{experiment_id}/sequences","href":"/api-reference/experiments/list-sequences-for-an-experiment"},{"title":"Submit experiment","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/experiments/{experiment_id}/submit","href":"/api-reference/experiments/submit-experiment"},{"title":"List experiment updates","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/experiments/{experiment_id}/updates","href":"/api-reference/experiments/list-experiment-updates"}]},{"group":"feedback","pages":[{"title":"Submit feedback, bug reports, or feature requests","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/feedback/submit","href":"/api-reference/feedback/submit-feedback-bug-reports-or-feature-requests"}]},{"group":"info","pages":[{"title":"Liveness probe","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/info/health","href":"/api-reference/info/liveness-probe"},{"title":"Database connectivity probe","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/info/health-db","href":"/api-reference/info/database-connectivity-probe"}]},{"group":"invoices","pages":[{"title":"List invoices","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/invoices","href":"/api-reference/invoices/list-invoices"},{"title":"Get invoice","description":"Fetches a single invoice by its Foundry UUID or Stripe invoice ID\n(`in_xxx`). The caller's org membership scopes visibility — an invoice\nbelonging to an org the caller cannot access returns 404.","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/invoices/{invoice_id}","href":"/api-reference/invoices/get-invoice"},{"title":"Pay invoice","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/invoices/{invoice_id}/pay","href":"/api-reference/invoices/pay-invoice"},{"title":"Get invoice PDF","description":"Redirects (307) to the Stripe-hosted PDF for the given invoice. The PDF is\nonly available after the invoice has been finalized (status `open` or\n`paid`). Requesting a PDF for a `draft` invoice returns 404 — finalize the\ninvoice first by submitting and confirming the associated quote.\n\nThe PDF URL is fetched live from Stripe on every request; clients should\nfollow the redirect immediately rather than caching it.","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/invoices/{invoice_id}/pdf","href":"/api-reference/invoices/get-invoice-pdf"}]},{"group":"quotes","pages":[{"title":"List quotes","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/quotes","href":"/api-reference/quotes/list-quotes"},{"title":"Get quote","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/quotes/{quote_id}","href":"/api-reference/quotes/get-quote"},{"title":"Accept quote","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/quotes/{quote_id}/confirm","href":"/api-reference/quotes/accept-quote"},{"title":"Reject quote","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/quotes/{quote_id}/reject","href":"/api-reference/quotes/reject-quote"}]},{"group":"results","pages":[{"title":"List results","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/results","href":"/api-reference/results/list-results"},{"title":"Get result","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/results/{result_id}","href":"/api-reference/results/get-result"}]},{"group":"sequences","pages":[{"title":"List sequences","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/sequences","href":"/api-reference/sequences/list-sequences"},{"title":"Add sequences to experiment","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/sequences","href":"/api-reference/sequences/add-sequences-to-experiment"},{"title":"Get sequence","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/sequences/{sequence_id}","href":"/api-reference/sequences/get-sequence"}]},{"group":"targets","pages":[{"title":"List targets","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/targets","href":"/api-reference/targets/list-targets"},{"title":"List custom target requests","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/targets/request-custom","href":"/api-reference/targets/list-custom-target-requests"},{"title":"Submit custom target request","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/targets/request-custom","href":"/api-reference/targets/submit-custom-target-request"},{"title":"Get custom target request","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/targets/request-custom/{request_id}","href":"/api-reference/targets/get-custom-target-request"},{"title":"Get target","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/targets/{target_id}","href":"/api-reference/targets/get-target"}]},{"group":"tokens","pages":[{"title":"List tokens","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/tokens","href":"/api-reference/tokens/list-tokens"},{"title":"Attenuate token","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/tokens/attenuate","href":"/api-reference/tokens/attenuate-token"},{"title":"Revoke the calling token and its entire lineage","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/tokens/revoke","href":"/api-reference/tokens/revoke-the-calling-token-and-its-entire-lineage"}]},{"group":"updates","pages":[{"title":"List updates","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/updates","href":"/api-reference/updates/list-updates"}]},{"group":"webhooks","pages":[{"title":"List the organization's webhook registrations.","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/webhooks","href":"/api-reference/webhooks/list-the-organizations-webhook-registrations"},{"title":"Register a webhook for the organization.","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json post /api/v1/webhooks","href":"/api-reference/webhooks/register-a-webhook-for-the-organization"},{"title":"Remove a webhook registration.","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json delete /api/v1/webhooks/{webhook_id}","href":"/api-reference/webhooks/remove-a-webhook-registration"},{"title":"Modify a webhook registration, including rotating or clearing its secret.","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json patch /api/v1/webhooks/{webhook_id}","href":"/api-reference/webhooks/modify-a-webhook-registration-including-rotating-or-clearing-its-secret"}]},{"group":"whoami","pages":[{"title":"Who am I","deprecated":null,"version":null,"openapi":"https://devs.adaptyvbio.com/api/v1/openapi.json get /api/v1/whoami","href":"/api-reference/whoami/who-am-i"}]}]}]},{"tab":"Changelog","icon":"newspaper","pages":[{"title":"Changelog","href":"/changelog/changelog"}]}]},"title":"Pay invoice - Adaptyv Bio Docs","buildId":"dpl_DFJrtvUi8HS5F9nkooKuDJsuD5BM","deploymentId":"dpl_DFJrtvUi8HS5F9nkooKuDJsuD5BM","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-rfhihCWU.js","utils-BmH1XFxk.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-BcNsxPKB.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-BAES3tkd.js","snippetPresets-DCMQBKLP.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","ApiExamples-D6l_bzE9.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-BOktbnNh.js","shallow-BCs8SgM7.js","getApiPlaygroundDisplay-DEmW5bJB.js","CodeSnippet-CpZOpB9C.js","CodeSnippets-BOBDqibl.js","Page-D5fEM6aW.js","getPastedJson-DH2JBvmr.js","icon-BBJH-kKh.js","MethodPill-D2Sd5NLC.js","DuplicateIcon-CGgfL2qN.js","createIcon-BKudBBzi.js","DynamicMarkdown-85clUA0i.js","SectionHeading-D0JiMgDx.js","axios-vUo_bRtp.js","Markdown-Cfiy0xZO.js","clsx-rL8ZCCw4.js","lib--scc4DXi.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-aeztFa9U.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-BywkCr5C.js"]}