invoices

Pay invoice

Settles the given invoice. How it settles is chosen by the X-Adaptyv-Payment-Method request header:

Header valueBehaviour
(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-sptSettles from a Stripe shared payment token
x402-exactSettles 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.

post/api/v1/invoices/{invoice_id}/pay

Request

  • Base URL
    https://devs.adaptyvbio.com
  • URL
    https://devs.adaptyvbio.com/api/v1/invoices/{invoice_id}/pay
  • Auth
    HTTP bearer

Path parameters

invoice_idstring required

Foundry invoice UUID or Stripe invoice ID (in_xxx)

Headers

X-Adaptyv-Payment-Methodstring nullable

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.

Response

Invoice paid (or already paid)

already_paidboolean required

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.

hosted_invoice_urlstring nullable

Stripe-hosted invoice URL, when known.

idstring required

Stripe invoice ID (in_xxx) that was paid.

status'draft' | 'open' | 'paid' | 'void' | 'uncollectible' required

Invoice status from Stripe's API.

Example response

{
  "hosted_invoice_url": "https://invoice.stripe.com/i/acct_1234/test_5678",
  "id": "in_1OqLk2LkdIwHu7ix6OboRpXl",
  "settlement_reference": {
    "tx_hash": "0x9c2f1a7e5b0d4c3a8f6e2d1b0a9c8f7e6d5c4b3a29180f7e6d5c4b3a29180f7e"
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.