# Pay with USDC (x402): buy directly, or add credit

Everything you buy over the Porkbun API is paid from prepaid **account credit**.
When an order fails with `INSUFFICIENT_FUNDS` and the account has no saved card,
the API can open a USDC checkout that tops the account up, and an AI agent with
a crypto wallet can pay it itself over **x402**, with no page and no person in
the loop. A person can pay the same checkout on a Coinbase page instead.

This is the same "Use Crypto" option as on porkbun.com: USDC on the Base
network, through Coinbase Business.

An agent with a wallet can also skip the credit entirely and **pay for one
purchase directly**: see the next section.

## Pay for a purchase directly

Add `"payWith": "usdc"` to `/domain/create`, `/domain/renew`,
`/domain/transfer`, `/closeout/buy` or a paid `/hosting/create`. No account
credit is needed.

```
POST /api/json/v3/domain/create/example.com
{"apikey":"pk1_...","secretapikey":"sk1_...","cost":1108,"payWith":"usdc"}
```

1. Every normal check runs first (availability, price, eligibility, the
   monthly spend limit). Then the call answers **HTTP 402** with code
   `PAYMENT_REQUIRED`, Coinbase's x402 terms in the `PAYMENT-REQUIRED` header
   (USDC on Base, the exact price), and `checkoutId`, `x402Url` and `payUrl` in
   the body. Nothing is charged.
2. An x402 client pays those terms and **repeats the same request** with a
   `PAYMENT-SIGNATURE` header. Most x402 clients and agent wallets do this on
   their own when they see a 402. Keep the same `Idempotency-Key` if you send
   one: a 402 releases it.
3. The purchase completes in that call. The response is the normal result plus
   `payment` (`paidWith`, `amount_cents`, `checkoutId`) and Coinbase's receipt in
   the `PAYMENT-RESPONSE` header.

If the purchase fails after the payment (the domain was taken, the registry
refused it), **the payment is not sent back to the wallet: it stays on the
account as Porkbun account credit.** The error response says so in `payment`:
`keptAsCredit: true` and `balance_cents`, the account's credit afterwards. Retry
the same purchase without `payWith` to buy from that credit, or spend it on
anything else; it is ordinary account credit.

Other errors:

- `PAYMENT_FAILED` (402): Coinbase refused the payment, for example not enough
  USDC. Nothing was charged; fresh terms are in `PAYMENT-REQUIRED`.
- `PAYMENT_IN_PROGRESS` (409): another request is already processing this
  payment. Do not pay again; check whether the purchase completed.

### If your wallet pays the URL itself (pay, then confirm)

Wallet tools such as a wallet MCP or Coinbase's `awal` CLI pay an x402 URL
themselves rather than handing you a signature, and a person can pay the
Coinbase page in a browser. For those:

1. Send the purchase with `"payWith": "usdc"` and take `checkoutId`,
   `x402Url` and `payUrl` from the 402.
2. Pay the `x402Url` with the wallet (for example
   `awal x402 pay <x402Url> --scheme auth-capture`), or have the person pay
   the `payUrl` page.
3. Repeat the same request with `"usdcCheckoutId": "<checkoutId>"` added. The
   purchase completes once the checkout is paid.

The checkout must be this account's, opened for this exact purchase and price,
and not already used. Answers to the repeat:

- `PAYMENT_REQUIRED` (402): not paid yet; terms attached.
- `PAYMENT_PENDING` (409): paid and settling on chain; repeat after
  `retryAfter` seconds. Do not pay again.
- `PAYMENT_MISMATCH` (409), `PAYMENT_NOT_FOUND` (404), `PAYMENT_ALREADY_USED`
  (409), `PAYMENT_EXPIRED` (409): see each message.

A purchase checkout that is paid but never claimed is added to the account's
credit after an hour, so the payment is never lost.

The price is exactly the purchase price; Porkbun covers Coinbase's fee. Not
available on sandbox keys.

## How it works

1. You ask for a checkout for an amount of credit (`POST /account/topupCrypto`).
   Nothing is charged by this call.
2. The response has two ways to pay the same checkout:
   - **`x402Url`**: for an agent with a crypto wallet. x402 is an open payment
     standard built on HTTP status 402 ("Payment Required"): the wallet pays
     the URL with a gasless USDC transfer on Base.
   - **`payUrl`**: a Coinbase page where a person pays, from a Coinbase account
     or any wallet holding USDC on Base.
3. Coinbase confirms the payment (usually within a minute) and Porkbun adds the
   credit to the account, less Coinbase's fee of about 1%.
4. You check `GET /account/topupCryptoStatus/{checkoutId}` until `state` is
   `COMPLETED`, then retry the order that needed the credit.

## 1. Open a checkout

```
POST /api/json/v3/account/topupCrypto
{"apikey":"pk1_...","secretapikey":"sk1_...","amount":1500}
```

`amount` is integer US cents, from 100 ($1.00) to 50000 ($500.00). Coinbase keeps
about 1% of it, so the response shows `estimatedFee_cents` and
`estimatedCredit_cents`. To cover an `INSUFFICIENT_FUNDS` shortfall exactly, open
the checkout for that response's `usdcAmountToCover`: a $2.50 shortfall needs a
$2.53 checkout. Send
`"dryRun": true` to check the account is eligible without creating anything.

```json
{
  "status": "SUCCESS",
  "checkoutId": "6abeec97d979cfdc17c60dbe",
  "amount_cents": 1500,
  "estimatedFee_cents": 15,
  "estimatedCredit_cents": 1485,
  "currency": "USDC",
  "network": "base",
  "payUrl": "https://payments.coinbase.com/payment-sessions/paymentSession_...",
  "x402Url": "https://api.cdp.coinbase.com/platform/v2/payment-sessions/paymentSession_.../authorizations/x402",
  "expiresAt": "2026-10-02T23:28:00Z"
}
```

A checkout is single-use and expires after about 24 hours.

## 2. Pay it

**An agent with a wallet** pays `x402Url` with its x402 client. Coinbase's
Agentic Wallet and Wallet MCP ("make an x402 request") do this out of the box.
Tell the user the dollar amount and get their OK first: on-chain payments
cannot be reversed.

**A person** opens `payUrl` and pays from a Coinbase account or a wallet holding
USDC on Base.

## 3. Wait for the credit

```
GET /api/json/v3/account/topupCryptoStatus/6abeec97d979cfdc17c60dbe
```

| `state` | Meaning |
|---|---|
| `ACTIVE` | Not paid yet. |
| `PROCESSING` | Paid; the credit is being added. Check again in a few seconds. |
| `COMPLETED` | Credited (`credited: true`). `balance_cents` shows the new balance. |
| `EXPIRED` / `FAILED` | Not paid in time, or the payment failed. Open a new checkout. |

Then retry the original request unchanged.

## From the MCP server

On the full server (`https://mcp.porkbun.com/mcp`, or the npm package):

- **Pay for a purchase directly:** `register_domain`, `renew_domain`,
  `transfer_domain`, `buy_closeout` and `create_hosting` take
  `pay_with_usdc: true`.
  - **Local install with a wallet** (Claude Code, Cursor, Codex, Claude
    Desktop): set `PORKBUN_X402_PRIVATE_KEY` to the private key of a Base
    wallet holding USDC, and optionally `PORKBUN_X402_MAX_CENTS` (the largest
    single payment, default 5000 = $50). The server signs the payment and the
    purchase completes in one call. It only signs terms that are exactly the
    quoted price in USDC on Base, and never above the cap. Use a wallet that
    holds only what you are willing to spend.
  - **Without one** (including the hosted connector, which holds no one's key):
    the tool returns `status: PAYMENT_REQUIRED` with the checkout. Pay its
    `x402Url` with a wallet tool or its `payUrl` in a browser, then call the
    same tool again with `usdc_checkout_id`.
- **Add credit instead:** `top_up_with_usdc` and `get_usdc_topup_status`.

None of these are offered on the versions in the Claude and ChatGPT app
directories, which do not move money.

## Who can use it

- The account's email and phone are verified (`VERIFICATION_REQUIRED`
  otherwise; both can be verified from the agent with
  `POST /account/verifyEmail/send` and `POST /account/verifyPhone/send`, see
  https://porkbun.com/llms/guides/verify-the-account).
- Not limited to bank-transfer credit (`CRYPTO_NOT_AVAILABLE`, with the reason
  in the message).
- Up to 10 checkouts per account per day (`CRYPTO_TOPUP_LIMIT`).
- Credit added over the API is capped each month at the account's monthly
  spend limit, or $100 when none is set, and USDC counts toward it together
  with card and MPP top-ups. Unpaid checkouts from the last day count as if
  paid (`TOPUP_LIMIT_EXCEEDED`).
- Not on sandbox keys (`SANDBOX_UNSUPPORTED`): use `/sandbox/topup` for test
  credit.

Each error carries a `next_action` describing what to do. The monthly limit
also applies to what the credit is spent on.

## Other ways to add credit

- `POST /account/topup` charges a card already saved on the account (ask the
  user first).
- On porkbun.com, Account Credit: card, bank transfer or crypto.


---

## More

- Guides (how-tos): https://porkbun.com/llms/guides
- Topic index: https://porkbun.com/llms
- Full reference (one file): https://porkbun.com/llms-full.txt
- OpenAPI spec (full schemas): https://porkbun.com/api/json/v3/spec
- Short overview: https://porkbun.com/llms.txt
- Official MCP server: https://porkbun.com/mcp (`npx -y @porkbunllc/mcp-server`)
- Create API keys: https://porkbun.com/account/api
