<aside>
:ambient-logo-original: Ambient Documentation
🌐 Homepage
</aside>
External clients can create and fund an API-only Ambient account without an email, browser login, wallet login, or the Ambient UI. The Ambient API key is the account credential. A wallet is used only to authorize the x402 payment.
Restart-safe TypeScript x402 subscription example
The integration has six steps:
POST /billing/x402/register-and-subscribe.payment_url with an x402 v2 client and select a live Solana or Base offer.POST /billing/x402/subscription-complete.The billing API origin is https://api.ambient.xyz. After provisioning, configure OpenAI-compatible clients with:
Base URL: <https://api.ambient.xyz/v1>
Authorization: Bearer <api_key>
Supported inference endpoints include POST /responses, POST /chat/completions, and GET /models relative to that base URL.
payTo): public Base or Solana address receiving USDC. Validate it against the trusted allowlist below.If you need one-off inference without creating an account or API key, use the separate account-free x402 client flow.
Supported plan_id values are:
starterbasicpowerproSee Ambient pricing for current monthly prices and plan allowances. The signed order and live 402 determine the exact amount for a purchase.
months is an integer from 1 through 12 and defaults to 1. A bulk purchase is charged at the monthly price multiplied by months; there is no bulk discount. Each month is provisioned as a consecutive monthly period so its allowance resets independently.
Renewals must use the plan at the account's farthest paid-through boundary. Ambient rejects a different plan before creating a payment order. When an order is created, all nonexpired current and future periods, unexpired pending orders, and the requested purchase may not exceed 12 months in total. A valid grant settled earlier can exceptionally take the account past that cap if it completes later; Ambient honors paid value instead of discarding the settlement.
Registration and renewal payment URLs expire after 24 hours. That is not the payment authorization lifetime: create the authorization immediately before transmission and obey the shorter live rail-specific validity window. Base challenges currently use a 300-second authorization window; Solana blockhash validity is shorter and dynamic. A grant created by a successful settlement expires after seven days. An expired pending order becomes eligible for cleanup eight days after its payment URL expired; cleanup is asynchronous, so do not use retention as a payment or completion deadline.
Persist the registration response and API key before paying. Serialize concurrent payment attempts and maintain at most one live or possibly transmitted authorization for an order. An expired authorization may be replaced only when durable state proves it was never marked attempted; never replace one after transmission was attempted or became ambiguous.
Jumpgate performs bounded, byte-identical retries for transient facilitator failures. Those internal retries do not make it safe for the client to send the paid request again. Do not run a paid request through generic 5xx or Retry-After retry middleware. After a paid request may have been transmitted, never automatically resend it, create a replacement authorization, or create a replacement order. Persist the raw response status and headers, including any receipt and grant, as soon as fetch resolves; read and store the body afterward as diagnostic data. Jumpgate is stateless, and Ambient does not expose a public settlement-status or grant-recovery endpoint.
For compile-tested TypeScript reference code with injected signer, durable storage, and locking boundaries, see Restart-safe TypeScript x402 subscription example.
Registration is public and does not use an Ambient credential:
POST <https://api.ambient.xyz/billing/x402/register-and-subscribe>
Content-Type: application/json
{
"plan_id": "basic",
"months": 3
}
A successful request returns 201 Created and Cache-Control: no-store:
{
"api_key": "<50-character Ambient API key>",
"order_id": "7592578c-37b3-441e-a97c-7d262ebc0a72",
"plan_id": "basic",
"months": 3,
"payment_url": "<https://jumpgate.ambient.xyz/paid/subscription/v2/basic/3/7592578c-37b3-441e-a97c-7d262ebc0a72?intent=><opaque>",
"expires_at": "<RFC 3339 timestamp about 24 hours after registration>",
"completion_url": "/billing/x402/subscription-complete"
}
Persist the complete response before paying, especially api_key and the opaque payment_url. Ambient displays the API key only once and stores only its prefix and SHA-256 hash. The key returns 401 Unauthorized until provisioning completes.
Registration creates a pending order containing the bootstrap key prefix and hash. It does not create the API-only team, activate the key, or add subscription periods until a valid paid grant completes atomically.
Registration is not idempotent: every successful call creates a distinct order and bootstrap key. A 429 Too Many Requests response includes Retry-After. Only create a replacement order before any payment authorization has been created for the previous order; unexpired pending renewal orders also reserve months against the 12-month cap.
When x402 sales are paused, registration and renewal intent creation return 403 Forbidden. Completion remains available so a valid saved grant for a payment already made can still provision idempotently; a sales pause is not a reason to abandon that grant.
Do not parse, reconstruct, shorten, or change payment_url. The signed intent binds the order, plan, duration, amount, and expiry.
Send an empty unsigned POST to the opaque payment_url with redirects disabled. A valid challenge returns 402 Payment Required with a base64-encoded x402 v2 object in Payment-Required.
Ambient supports these USDC rails when they appear in the live response:
| Network | CAIP-2 identifier | Canonical USDC asset | Accepted recipient |
|---|---|---|---|
| Solana mainnet | solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp |
EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v |
AYYo37bgztqAgP6wp2S9SiYWcijr8gz2o14c8RGWojJZ |
| Base mainnet | eip155:8453 |
0x833589fcd6edb6e08f4c7c32d4f71b54bda02913 |
0x6992c688c56BE442EfE1E1cE7D5c95212ED7d59B |
The live accepts array is authoritative for currently available rails and amounts, but it is not by itself a trusted recipient allowlist. A client must fail closed unless the selected offer satisfies all of these conditions:
x402Version is 2.scheme is exact.network, asset, and payTo match one allowed rail above. For Base, normalize both addresses to lowercase before comparison because a live challenge may use checksum casing. Compare Solana identifiers exactly because they are case-sensitive.amount is a canonical positive base-10 integer string. Parse it with BigInt or an equivalent checked integer type, require every offered rail to have the same value, and enforce the client's configured or user-approved maximum.Do not accept an arbitrary payTo from the live challenge. Configure or publish the trusted recipients above with the client, and update that allowlist before paying a rotated recipient. The challenge itself is not signed and does not let the client select Jumpgate's configured facilitator.
Choose one offered rail supported by the wallet. Do not create a payment payload merely to inspect the offer.
Use the linked TypeScript reference for the exact package pins and injected Base or Solana signer boundary. Do not use an automatic paid-fetch wrapper for a subscription payment_url.
npm install --save-exact @x402/[email protected] @x402/[email protected] @x402/[email protected] [email protected] @solana/[email protected]
For each order:
Payment-Signature before transmission when the client supports a pre-send hook.POST to the exact saved payment_url, with redirects disabled, the saved Payment-Signature, and a timeout of at least 125 seconds.fetch resolves, persist the raw status and all headers, including any Payment-Response and Ambient grants. Only then read and store the body as best-effort diagnostic data. Capture headers on non-2xx responses too.Subscription settlement happens before Jumpgate creates the grant and attempts Ambient's callback. The longer timeout covers facilitator discovery, settlement, confirmation, and the bounded synchronous callback attempts; a shorter client timeout can turn a successful on-chain payment into an ambiguous client result.
A successful Jumpgate response is 200 OK with this JSON shape:
{
"order_id": "7592578c-37b3-441e-a97c-7d262ebc0a72",
"plan_id": "basic",
"months": 3,
"amount_micro_usdc": 60000000
}
The numeric amount is illustrative; the validated live offer is authoritative. Save these response headers:
Payment-Response
X-Ambient-X402-Grant
X-Ambient-X402-Grant-Signature
X-Payment-Response may be accepted as a legacy fallback when Payment-Response is absent. New integrations should use the standard Payment-Response header.
Header names are case-insensitive. The selected network, payer, and transaction are in the payment response and the signed grant, not the JSON response body. Before treating the payment as successful, require:
200.success=true.