Payments Overview
Every order is paid the same way in outline. You confirm a quote, which finalizes an invoice, and then you settle that invoice. What differs is how the money moves: a person clicking a link on a Stripe-hosted page, an on-chain USDC transfer, or a card charge your agent authorizes in advance.Hosted invoice
The default. A person pays a Stripe-hosted invoice page.
x402 (exact)
Your agent signs a USDC transfer; a facilitator settles it on-chain.
MPP-SPT
Your agent mints a bounded Stripe token; Stripe charges the card.
Base URLs
The sandbox is a separate environment with its own accounts, tokens, and Stripe
objects. Every example in this section uses
$FOUNDRY_API_URL, so either works:
Quote:Update and Invoice:Pay
actions: Member, Billing, or Admin. Member is the usual role for an
agent, since it also creates experiments; Billing suits someone who only handles
quotes and invoices. Viewer has no access to quotes or invoices at all.
The two steps
Confirming a quote never moves money. It finalizes the invoice and hands back apayment block telling you where to pay:
kind is hosted_invoice for the default rail, carrying hosted_invoice_url
instead. kind is machine when the invoice settles programmatically, and
methods lists the rails this environment accepts.
POST /invoices/{invoice_id}/pay is the only endpoint that settles an invoice.
Call it twice: once without a credential to receive the 402 challenge, once
with the credential to settle. Repeating the settling call is safe — an invoice
that is already paid answers 200 with already_paid: true and charges
nothing.
Choosing a rail
One header selects the rail on every call:
Any other value is rejected with
400. Note the spelling: x402-exact, never
x402.
Both machine rails are server-side only. A browser cannot send the method or
credential headers, or read the challenge headers, so drive these flows from a
backend or an agent runtime.
At experiment creation you can select the rail in the request body instead:
400 (payment_method_selector_conflict).
A token issued with a machine payment policy is challenged without the
header:
POST /invoices/{id}/pay answers 402 offering every rail the
environment serves, and whichever credential you send back decides the rail.
A stock x402 client can then pay without knowing the method header
exists. A stock MPP client also needs the header fallback described in
MPP-SPT. Ask
support@adaptyvbio.com for such a token.What the rail pins
The rail you choose when you create the experiment binds the experiment’s quote and invoice for its whole lifetime. Two consequences:- Switching between machine rails later is fine. An experiment created as
x402-exactcan be settled withmpp-spt, and the reverse. That applies between payments, not during one: once you have taken a402, that session owns the rail until it settles, and the header is ignored for the rest of it. - Crossing between the hosted-invoice rail and a machine rail is not. A quote
created without a machine rail cannot be settled with one, and a machine-rail
experiment cannot fall back to the hosted invoice. Both return
409. Create a fresh experiment instead.
Naming what settled
A settling200 carries settlement_reference when the payment can be named:
Status codes
POST /invoices/{invoice_id}/pay answers: