Agent Funding & Credits
Agent credits are a prepaid spending budget an agent draws down as it uses Primitive. A human operator funds the budget once on a hosted funding page; from then on the agent can read its remaining balance and top itself up against that budget without a human in the loop. Credits are denominated in your account currency (USD), so a balance of 5_000_000 micros is $5.00.
This is the fiat funding path. It is entirely separate from the on-chain x402 flow, where agents settle stablecoin (USDC) payments between each other non-custodially. If you are looking to collect or pay USDC on-chain, see Collecting Payments and x402 over Email instead. Use credits when you want a simple prepaid balance that funds your own agent's usage; use x402 when one agent is paying another.
There are two ways to add credits to a budget:
- Direct top-up — the agent calls
POST /v1/credits/topupto charge the funded budget and grant itself credits. - ACP checkout — the agent buys a fixed credit pack through an Agentic Commerce Protocol (ACP) checkout session, the open standard for agent purchases. This is a thin standards-compliant wrapper over the same budget machinery.
Both draw down the same delegated budget the operator funded. Balance reads never touch payment processing.
Amounts on the credits API are in micros: 1 USD = 1_000_000 micros. The ACP surface follows the ACP convention of the minor currency unit (cents), so a $20 pack is 2000.
Prerequisites
- An API key. See Quickstart. All credit and checkout requests authenticate with the agent's API key (
Authorization: Bearer prim_...). - A funded spending budget for your organization. An operator sets this up on the hosted funding page (below) before the agent can top up or check out. Without an active budget,
GET /v1/credits/balancereturnsnulland top-ups have nothing to charge.
You do not need to look up your organization id: it is resolved from your API key.
Prerequisite: a funded budget
The credit, funding, and checkout endpoints are available to any organization with an API key — there is no separate access grant to request. What gates them is a funded budget: until an operator funds one (next step), GET /v1/credits/balance returns null and top-ups and checkouts have nothing to charge.
Agent funding is in beta, so the flow may change. Questions? Contact support or email the Primitive help agent at dev@agent.primitive.dev.
Step 1: Fund a budget (operator)
Funding is a one-time human step. An operator opens a hosted funding page at /fund/<token>, where <token> is a single-use link you generate for them, and sets a spending allowance:
- Budget (max amount) — the ceiling the agent can spend in total.
- Per-top-up cap (optional) — the largest single top-up the agent may make.
- Expiry (optional) — when the allowance stops being usable.
The operator saves a payment method on that page. Card details never touch your agent or Primitive's API; the funding page handles them on a hosted, vaulted surface. Once funding completes, the organization has an active budget with a delegated allowance, and the agent can draw it down on its own.
The allowance caps you set here are enforced on every later charge: a top-up or checkout that would exceed the budget, breach the per-top-up cap, or run past the expiry is refused server-side.
Step 2: Check the balance
Read the current budget with GET /v1/credits/balance. There is no human in this loop — the agent calls it directly.
curl https://api.primitive.dev/v1/credits/balance \ -H "Authorization: Bearer $PRIMITIVE_API_KEY"
If the organization has an active budget, the response carries it; if not, budget is null.
{ "success": true, "data": { "budget": { "currency": "usd", "max_amount_micros": "20000000", "spent_micros": "4500000", "remaining_micros": "15500000", "per_topup_cap_micros": "5000000", "expires_at": "2026-12-31T00:00:00.000Z", "status": "active" } } }
| Field | Meaning |
|---|---|
currency | The budget's currency (e.g. usd). |
max_amount_micros | Total allowance the operator funded, in micros. |
spent_micros | How much of the allowance has been drawn down. |
remaining_micros | max_amount_micros - spent_micros, floored at zero. |
per_topup_cap_micros | Largest single top-up allowed, or null for no per-top-up cap. |
expires_at | When the allowance expires, or null for no expiry. |
status | Budget status; an active budget reads active. |
A null budget means no operator has funded one yet (or it is no longer active). Surface the funding page to your operator to create one.
The response also carries prepaid_credit: the usage credit your organization has bought with top-ups (together with any promotional or granted credit) that can still pay for usage from now on.
{ "success": true, "data": { "budget": { "...": "..." }, "prepaid_credit": { "currency": "usd", "remaining_micros": "4200000", "next_expires_at": null } } }
| Field | Meaning |
|---|---|
prepaid_credit.currency | The credit's currency, which is your organization's billing currency (e.g. usd). |
prepaid_credit.remaining_micros | What the credit can still pay for, in micros. It goes down as usage beyond your plan's monthly credit is paid from it. |
prepaid_credit.next_expires_at | The earliest expiry among credits with a balance, or null when none of them has an expiry date. Top-up credit has no expiry date. |
prepaid_credit is null when there is no such credit. It is left out of the response when an exact figure cannot be given right now, for example in the first few minutes after a top-up while the new credit is being activated; the budget is still returned.
Step 3: Top up directly
To charge the budget and grant credits in one call, POST /v1/credits/topup with the amount in micros. An Idempotency-Key header is required so a retried request never double-charges.
curl -X POST https://api.primitive.dev/v1/credits/topup \ -H "Authorization: Bearer $PRIMITIVE_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: topup-2026-06-26-001" \ -d '{"amount_micros": "5000000"}'
amount_micros is a positive integer number of micros (accepted as a number or a string). The response confirms the grant:
{ "data": { "topup_id": "...", "amount_micros": "5000000", "payment_intent_id": "...", "already_applied": false } }
already_applied is true when a retry with the same Idempotency-Key matched an earlier top-up, so you can tell a fresh charge from a replayed one.
The credit a top-up buys is added to your organization's prepaid credit (see prepaid_credit in Step 2). It pays for usage from the moment of the top-up onward and is used after your plan's monthly credit. Top-up credit has no expiry date and carries over between billing periods until it is used. If your usage was paused because the monthly credit ran out, it usually resumes as soon as the top-up succeeds; in rare cases, such as a top-up made right at the start of a new billing period, it can take a few minutes.
A top-up is charged and credited in your organization's billing currency. A spending budget in a different currency is refused with currency_mismatch before any charge.
A top-up that would exceed the funded budget, breach the per-top-up cap, or run past the allowance expiry is refused. See Errors.
Step 4: Buy a credit pack over ACP
The Agentic Commerce Protocol (ACP) surface lets an agent buy credits through the open ACP checkout standard rather than the proprietary top-up. It is the right path when your agent already speaks ACP, or when you want the standard create → complete lifecycle. These routes live at the API root (not under /v1), carry CORS and OPTIONS preflight, and advertise the ACP version they serve in the API-Version response header (currently 2025-09-29; 2025-09-12 is also accepted).
ACP responses use the ACP envelope ({ "type", "code", "message", "param" } on errors), which differs from the REST { "data" | "error" } shape used everywhere else in the API.
Credit packs
Checkout sells fixed packs. The pack id goes in the items array; the credits granted equal the dollars paid.
| Pack id | Price | Credits granted |
|---|---|---|
credits_5 | $5 | $5 in credits |
credits_20 | $20 | $20 in credits |
credits_50 | $50 | $50 in credits |
Delegate a payment token
Before a session can be completed, the agent vaults a scoped payment token against the funded budget with POST /agentic_commerce/delegate_payment. This is what authorizes settlement: completing a checkout requires a token that matches the organization's delegated budget, so a bare API key alone can never settle a cart. The allowance you pass bounds what the token may spend.
curl -X POST https://api.primitive.dev/agentic_commerce/delegate_payment \ -H "Authorization: Bearer $PRIMITIVE_API_KEY" \ -H "Content-Type: application/json" \ -H "API-Version: 2025-09-29" \ -d '{ "allowance": { "reason": "agent_credit_purchase", "max_amount": 2000, "currency": "usd" } }'
The response carries the vaulted token id as id; hold it for the complete step.
{ "id": "...", "created": "2026-06-26T12:00:00.000Z", "metadata": { "source": "primitive", "idempotency_key": "..." } }
The token is a conceptual reference to the vaulted, allowance-scoped payment authorization — there is no raw card data in it, and the actual charge is settled server-side against the funded budget.
Create a checkout session
POST /checkout_sessions builds a cart from one or more packs. The session comes back ready_for_payment with its line items and totals.
curl -X POST https://api.primitive.dev/checkout_sessions \ -H "Authorization: Bearer $PRIMITIVE_API_KEY" \ -H "Content-Type: application/json" \ -H "API-Version: 2025-09-29" \ -d '{ "items": [ { "id": "credits_20", "quantity": 1 } ] }'
The 201 response is an ACP session object: an id (prefixed cs_), status, currency, line_items, and totals. Read it again any time with GET /checkout_sessions/{id}, or change the cart or buyer with POST /checkout_sessions/{id} while the session is still ready_for_payment.
Complete the session
POST /checkout_sessions/{id}/complete settles the cart: it charges the delegated budget and grants the credits, exactly like a direct top-up. Pass the vaulted token in payment_data.token.
curl -X POST https://api.primitive.dev/checkout_sessions/cs_123/complete \ -H "Authorization: Bearer $PRIMITIVE_API_KEY" \ -H "Content-Type: application/json" \ -H "API-Version: 2025-09-29" \ -d '{ "payment_data": { "token": "..." } }'
On success the session moves to completed and carries an order. Completion is idempotent — the idempotency key is derived from the session id, so completing the same session twice never double-charges; a second call just returns the already-settled session. If payment_data.token does not match a delegated budget, completion fails with invalid_payment_token; call delegate_payment first.
Cancel a session
POST /checkout_sessions/{id}/cancel cancels an unpaid session. A session that is already completed cannot be canceled.
curl -X POST https://api.primitive.dev/checkout_sessions/cs_123/cancel \ -H "Authorization: Bearer $PRIMITIVE_API_KEY" \ -H "API-Version: 2025-09-29"
Redeem a credit code
A credit code adds prepaid usage credit to your organization. It needs no funded budget: the credit shows up in prepaid_credit on the balance (Step 2) and pays for usage from the moment it is redeemed.
Only an organization owner or admin can redeem a code. An API key redeems with the authority of the user who created it, based on that user's current role, so use a key created by an owner or admin.
primitive credits redeem LAUNCH50 primitive credits balance
The CLI generates the Idempotency-Key for you. Over the API the header is required: 1 to 200 printable ASCII characters, without spaces. Retrying with the same key and code returns the original grant with replayed: true and adds no second credit; the same key with a different code is refused with idempotency_key_reused, so use a new key for each code.
{ "success": true, "data": { "redemption_id": "...", "amount_micros": "50000000", "currency": "usd", "granted_at": "2026-09-23T17:00:00.000Z", "expires_at": "2026-12-31T00:00:00.000Z", "label": null, "replayed": false, "message": "$50.00 in credits added. Expires Dec 31, 2026. Applies to usage from now on." } }
expires_at is null when the credit does not expire. message is a ready-to-show summary of the grant.
A refused redemption uses the standard error envelope, and its error.message is written to be shown to the user as is:
| Status | error.code | Meaning |
|---|---|---|
| 400 | idempotency_key_required | The Idempotency-Key header is missing. |
| 400 | validation_error | The Idempotency-Key is empty, longer than 200 characters, or contains anything other than printable ASCII without spaces, or the body is invalid. |
| 409 | credit_code_already_redeemed | Your organization or user already redeemed this code, or another code in the same exclusive group (a set of codes of which each organization or user may redeem only one). |
| 422 | credit_code_invalid | The code is unknown, expired or used up, or the caller cannot redeem codes for the organization. |
| 422 | credit_code_not_eligible | The organization does not meet the terms of the promotion. |
| 422 | credit_code_balance_cap | The organization already holds the most promotional credit it can. Use some before redeeming another code. |
| 422 | idempotency_key_reused | This Idempotency-Key already redeemed a different code. |
| 429 | rate_limited | Too many requests or attempts. Wait for Retry-After and try again. |
| 503 | service_unavailable | The code could not be redeemed right now. Retry later with the same Idempotency-Key. |
The CLI prints the grant (amount and expiry) on success. On a refusal it prints the error.message and exits non-zero.
Credits vs on-chain x402
Credits and x402 are different payment rails — pick by who is paying whom:
| Agent credits (this page) | x402 (Collecting Payments) | |
|---|---|---|
| Money | Fiat (your account currency, e.g. USD) | Stablecoin (USDC), on-chain |
| Who funds | A human operator funds a prepaid budget | An organization or agent pays from its own wallet |
| Settlement | Charged against the funded budget | Non-custodial, on-chain via a signed authorization |
| Typical use | Funding your own agent's Primitive usage | One agent paying another for a resource |
| Standard | ACP checkout, or the direct top-up API | x402, synthetic or over email |
The two are independent. Funding a credit budget has no bearing on x402 wallets or spend policy, and vice versa.
Endpoint reference
Credit endpoints are under /v1; ACP endpoints are at the API root.
| Operation | Method and path |
|---|---|
| Get credit balance | GET /v1/credits/balance |
| Redeem a credit code | POST /v1/credits/redeem |
| Top up credits | POST /v1/credits/topup |
| Delegate a payment token | POST /agentic_commerce/delegate_payment |
| Create checkout session | POST /checkout_sessions |
| Get checkout session | GET /checkout_sessions/{id} |
| Update checkout session | POST /checkout_sessions/{id} |
| Complete checkout session | POST /checkout_sessions/{id}/complete |
| Cancel checkout session | POST /checkout_sessions/{id}/cancel |
See the API reference for full request and response schemas, Limits for budget and rate constraints, Errors for failure codes, and the CLI page for command-line usage. Pricing for usage that credits pay for is on the pricing page.