---
updatedAt: 2026-09-10T10:18:14.000Z
agentTools:
  projectIndex: https://docs.bitrefill.com/llms.txt
---

# Partner Integration Guide

Build an agent or MCP client on Bitrefill's MCP server: authentication, guest checkout, affiliate attribution and how to test.

Bitrefill sells gift cards, phone top-ups and eSIMs for crypto, cards and account balance. Our MCP server lets an AI agent do the whole job: find a product, check the price, buy it and read the result. This guide explains how to connect your agent or MCP client, how guest checkout works when the buyer has no Bitrefill account, how affiliate attribution pays you, and how to test without spending real money.

It is written for developers at partner companies. You need to know what MCP (Model Context Protocol) is and how HTTP and OAuth work. Everything else is explained here. If you only want to connect a desktop client to your own account, the [eCommerce MCP Server](https://docs.bitrefill.com/docs/ecommerce-mcp) page and the [Setup Guides](https://docs.bitrefill.com/docs/setup-guides) are the shorter read.

## At a glance

| Topic                 | Value                                                               |
| --------------------- | ------------------------------------------------------------------- |
| Server URL            | `https://api.bitrefill.com/mcp`                                     |
| Protocol              | MCP over Streamable HTTP, stateless, JSON-RPC 2.0                   |
| Authentication        | OAuth 2.1 (user login or client credentials) or a Bitrefill API key |
| Guest checkout        | Yes. A client-credentials token can buy without a Bitrefill account |
| Affiliate attribution | Add `?ref=<your code>` to the server URL                            |
| Tools                 | 12 in total, 7 visible to guests                                    |
| Rate limit            | 30 requests per minute per token                                    |
| Response format       | TOON text for read tools, JSON for `buy-products`                   |

## Quick start

> 📘 In short
>
> Point an MCP client at `https://api.bitrefill.com/mcp`, log in when the client asks, and call `search-products`. Add `?ref=<code>` to the URL if you have an affiliate code.

### Connect a client

Most MCP clients only need the URL. Claude, ChatGPT, Cursor and Claude Code discover our OAuth server automatically and open the Bitrefill login and consent screen in a browser.

```bash Claude Code
claude mcp add --transport http bitrefill "https://api.bitrefill.com/mcp?ref=YOURCODE"
```

If your product has no browser, or your users have no Bitrefill account, use a client-credentials token instead. If your own company is the buyer, an API key is the simplest option. Both are described in [The three modes in detail](#the-three-modes-in-detail).

### First request with curl

```bash
curl -s https://api.bitrefill.com/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

The `Accept` header must contain both `application/json` and `text/event-stream`. Without both you get HTTP 400.

### The purchase flow

Every purchase follows the same four tool calls.

| Step | Tool                  | What you get                                                                                        |
| ---- | --------------------- | --------------------------------------------------------------------------------------------------- |
| 1    | `search-products`     | Product ids (slugs) such as `amazon_com-usa`                                                        |
| 2    | `get-product-details` | Denominations (`package_value`), prices, accepted payment methods and whether a recipient is needed |
| 3    | `buy-products`        | An invoice with payment instructions                                                                |
| 4    | `get-invoice-by-id`   | Payment and delivery status, then the codes                                                         |

A guest purchase of a 10 USD Amazon gift card paid in Bitcoin:

```json tools/call
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "buy-products",
    "arguments": {
      "cart_items": [{ "product_id": "amazon_com-usa", "package_value": "10" }],
      "payment_method": "bitcoin",
      "email": "buyer@example.com"
    }
  }
}
```

The `email` argument only exists for guests. Logged-in buyers get the receipt on their account email.

## How the server behaves

> 📘 In short
>
> One authenticated HTTP POST per JSON-RPC message, no sessions, compact text responses, 30 requests per minute.

**Stateless transport.** Each POST is handled on its own. There is no `Mcp-Session-Id` header. `GET /mcp` and `DELETE /mcp` answer HTTP 405, because there are no server-initiated streams and no sessions to close. JSON-RPC notifications receive HTTP 202 with an empty body.

**Every request is authenticated.** The bearer token decides who the buyer is and which tools appear in `tools/list`. Do not cache the tool list across different tokens.

**Response format.** Read tools return TOON (Token-Oriented Object Notation), a compact text format built for language models. It reads like indented key-value lines and uses about 40 percent fewer tokens than JSON. `buy-products` returns plain JSON so payment details can be parsed exactly. Errors are always JSON with `isError: true` (see [Errors](#errors)).

**Rate limit.** 30 requests per minute per bearer token, or per IP address when there is no token. Over the limit you get HTTP 429 with the body below. Back off for the rest of the minute.

```json 429 response
{ "status": "rate_limit_reached", "message": "You have reached your request quota, if you need a higher quota please contact us" }
```

**Country.** The server reads the country from the IP address of the caller. When an AI vendor proxies the traffic, that is the vendor's IP. The country is used for fiat payment rules on some product categories. Crypto payments are not affected.

**Attribution data.** Every invoice created through MCP records the channel, your OAuth client and, when present, your affiliate id. That is what Bitrefill uses to report on your integration.

## Authentication

> 📘 In short
>
> Three ways in. OAuth login gives you the user's own account. OAuth client credentials give you a guest. An API key gives you your own account.

<Cards columns={3}>
  <Card title="OAuth user login" icon="fa-user">
    The buyer is the person who logged in. All 12 tools. For consumer assistants where each user has, or creates, a Bitrefill account.
  </Card>

  <Card title="OAuth client credentials" icon="fa-user-secret">
    The buyer is a guest. 7 tools. For agents that buy for people without an account, or before they log in.
  </Card>

  <Card title="API key" icon="fa-key">
    The buyer is the account that owns the key. All 12 tools. For server-side agents buying on behalf of your company.
  </Card>
</Cards>

### OAuth discovery

Our authorization server follows the MCP authorization specification (OAuth 2.1). Start from the protected resource metadata and let it lead you to the rest:

```
GET https://api.bitrefill.com/.well-known/oauth-protected-resource
```

It names the authorization server, `https://api.bitrefill.com/oauth/mcp`. The authorization server metadata (RFC 8414) lists the endpoints. Today they are:

| Purpose                     | Endpoint                                        |
| --------------------------- | ----------------------------------------------- |
| Authorization               | `https://api.bitrefill.com/oauth/mcp/authorize` |
| Token                       | `https://api.bitrefill.com/oauth/mcp/token`     |
| Dynamic client registration | `https://api.bitrefill.com/oauth/mcp/register`  |
| Revocation                  | `https://api.bitrefill.com/oauth/mcp/revoke`    |

Read them from the metadata instead of hard-coding them.

Facts that matter when you build your own client:

* **Scope.** Request `mcp`.
* **Resource indicator.** Send `resource=https://api.bitrefill.com/mcp` (RFC 8707) on authorize and token requests.
* **PKCE** with `S256` is mandatory.
* **Client identity.** Two options. Client ID Metadata Documents (CIMD), where your `client_id` is an HTTPS URL to a JSON document you host, is the recommended one and the one Claude uses. Dynamic Client Registration (RFC 7591) at the register endpoint also works. A CIMD document must be public, served over HTTPS on a real hostname, and smaller than 10 KB. `token_endpoint_auth_method` is `none` for CIMD clients, and `none` or `client_secret_post` for registered clients.
* **Redirect URIs** must match exactly. Loopback URIs (`http://127.0.0.1:<any port>/callback`) are accepted for native apps.
* **Token lifetime.** Access tokens live 6 hours, refresh tokens 7 days. A refresh token is single use and the refresh response contains a new one. Revoking a refresh token also invalidates the access tokens from the same grant.
* **Rate limits.** The OAuth endpoints are rate limited per IP address. If many of your users share one egress IP, register your client once and reuse it, and spread token refreshes over time.

### The three modes in detail

<Tabs>
  <Tab title="OAuth user login">
    The browser flow (authorization code). Your client redirects the user to the authorize endpoint, Bitrefill shows a login screen followed by a consent screen that names your client, and the user comes back with a code that you exchange for tokens.

    The buyer is that Bitrefill account. All tools are available, including account balance, saved cards, invoice history and bill payments.
  </Tab>

  <Tab title="Guest access with client credentials">
    A client-credentials token has no user. Bitrefill treats every request made with it as a guest (see [Guest accounts](#guest-accounts)).

    Register your client with `client_credentials` in `grant_types` (through CIMD or dynamic registration), then request a token:

    ```bash
    curl -s https://api.bitrefill.com/oauth/mcp/token \
      -d grant_type=client_credentials \
      -d client_id="$CLIENT_ID" \
      -d scope=mcp \
      -d resource=https://api.bitrefill.com/mcp
    ```

    Add `client_secret` when your client was registered with a secret. The token lives 6 hours. Request a new one when it expires.
  </Tab>

  <Tab title="API key">
    Create keys at [bitrefill.com/account/developers](https://www.bitrefill.com/account/developers). Your email must be verified, you choose a name and an optional expiry, and an account can hold 10 active keys. The secret is shown once.

    Send it as a bearer token:

    ```
    Authorization: Bearer <api key>
    ```

    The buyer is the account that owns the key, with all tools available. Keys are for agents you run for your own company. Do not hand one API key to many end users: every purchase would land on your account and count against your purchase limits.

    Never put the key in the URL. Keys in URLs end up in proxy and access logs, so the server only accepts them in the `Authorization` header.
  </Tab>
</Tabs>

### Authentication failures

A missing, invalid, expired or revoked credential gets HTTP 401 with a `WWW-Authenticate: Bearer error="invalid_token"` header. So does a disabled account. Compliant clients start the OAuth flow again when they see 401.

## Guest accounts

> 📘 In short
>
> A guest is a client-credentials token. Guests see 7 tools, must pass `email` to `buy-products`, pay with crypto or a payment link, and read their invoice with the `invoice_access_token` they received when buying. Keep that token safe.

### What a guest is

A guest has no Bitrefill account. Bitrefill cannot tell one guest from another between requests. That has two consequences you must design for:

* A guest has **no stable identity**. The checkout email and the invoice access token are the only handles on a purchase. Store them on your side if you want to show the purchase again later.
* **Ownership of an invoice is proven by its access token**, not by who is calling. Anyone with `invoice_id` and `invoice_access_token` can read the invoice, including the codes. Store both like a password.

Build on email plus access token and do not assume anything about how guests are represented internally.

### What guests can and cannot do

| Available to guests                                              | Login required                                                                                           |
| ---------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `search-products`, `get-product-details`                         | `list-invoices` (history)                                                                                |
| `buy-products` with crypto, fiat and third-party payment links   | `buy-products` with `payment_method` `balance` or `cashback`                                             |
| `get-invoice-by-id` with `invoice_access_token`                  | `saved_fiat_card_id` and `list-saved-fiat-cards`                                                         |
| `search_help_articles`, `get_help_article`, `list_help_articles` | `submit-prepayment-step` and every product that needs a `bill_payment_id` (bill payments, prepaid cards) |
| Gift delivery by email (`cart_items[].gift`)                     | `update-order`, `get-balances`, balance top-ups (deposit products)                                       |

Login-only tools are not listed in `tools/list` for a guest token, so a well-behaved agent never sees them. Calling one anyway returns `PERMISSION_DENIED`. Asking for a balance payment as a guest returns `INVALID_INPUT` with the message "Paying with account balance requires you to be logged in".

### A guest purchase, step by step

1. **Search and check the product.** `get-product-details` returns the accepted `payment_methods` for that product in three groups: `address_based` (crypto with an on-chain address), `link_only` (cards, Apple Pay, Google Pay, iDEAL, EPS, Przelewy24, Bancontact, Binance Pay, Kraken Pay) and `balance`.
2. **Buy.** Call `buy-products` with `cart_items`, `payment_method` and `email`. Fiat methods also need `billing_address` with at least `country`. `fiat_card` also needs `city`, `postal_code` and `address_line1`.
3. **Store the response.** The result is a JSON object with two keys. `response` holds the invoice: `invoice_id`, `invoice_access_token`, `expiration_minutes`, `cart_items`, and for crypto a `payment_info` block (address and amount), a `payment_link` to the web checkout and an `x402_payment_url` (see [Paying an MCP invoice with x402](#paying-an-mcp-invoice-with-x402)). For link-only methods `payment_link` is the only way to pay. `agent_instructions` tells the agent what to do next in plain language.
4. **Let the user pay.** Crypto: send the exact amount to the address before the invoice expires. Cards and other links: open `payment_link` in a browser. The link contains the access token, so treat it as private.
5. **Poll.** Call `get-invoice-by-id` with `invoice_id` and `invoice_access_token` until `invoice_status` is `complete`. Poll every 10 to 30 seconds, not faster. Statuses move through `unpaid`, `payment_detected`, `payment_confirmed` and `complete`. `blocked` means a compliance review that the agent cannot resolve.
6. **Deliver.** Each order in the invoice reports `status: delivered` and `redemption_info` with the code, plus an `access_link` to its page on bitrefill.com. eSIM orders add `esim_install_link`. Do not rely on email for delivery. Read the codes from the tool response or send the user to the link.

To change the payment method, call `buy-products` again. The unpaid invoice simply expires.

### Limits and checks that apply to guests

* **Purchase limits** apply to guest purchases. Exceeding them returns `purchase_limit_reached`.
* **Fraud and compliance checks** run on every invoice. A blocked invoice reports `invoice_status: blocked`. The errors `verification_required` and `access_denied` mean the buyer has to continue on the website. Do not retry.
* **Product availability** can differ between guests and logged-in users. Balance top-up products refuse guests with `user_not_registered`.

### From guest to account

Guests often become customers. Two paths exist:

* **Log in later through OAuth.** New purchases land on the user's account. Guest invoices stay reachable with their id and access token, but they do not appear in `list-invoices`.
* **Create an account from the receipt.** The checkout and receipt pages on bitrefill.com (reached through `payment_link` and the order `access_link`) offer to create an account. Within 30 days of completion, the purchase and its cashback can be claimed by that account.

If your product cannot open a browser at all, talk to your Bitrefill contact about login options before you build a workaround.

## Affiliate attribution

> 📘 In short
>
> Get an affiliate code from Bitrefill, append `?ref=<code>` to the server URL, and every purchase made through that connection is attributed to you. Commission accrues in BTC per delivered order and is paid out from your Bitrefill account.

### Getting a code

Affiliate status is a Bitrefill account type. Apply at [bitrefill.com/integrate](https://www.bitrefill.com/integrate/) or ask your Bitrefill contact. After a short business verification, your account becomes an affiliate account and receives an affiliate code, shown in your account.

### Passing the code

**MCP.** Configure the server URL as:

```
https://api.bitrefill.com/mcp?ref=YOURCODE
```

The code is read from the URL on every request, with every authentication mode (OAuth login, client credentials, API key). It must therefore be part of the URL your client stores, not something you send once.

**x402 REST API.** Send the header `X-Bitrefill-Affiliate-Id: YOURCODE` on `POST /x402/invoice/create` (see [The x402 REST API](#the-x402-rest-api)).

Rules:

* Codes are 6 to 16 letters and digits. Anything else is ignored.
* Attribution **fails open**. An unknown or malformed code never fails the purchase. It is dropped silently and the purchase goes through without attribution. Test your attribution explicitly (see [Test plan](#test-plan)).
* A `coupon_code` is a different thing. Coupons change the price for the buyer. Affiliate codes change who receives commission. Both can be present on one purchase.

### What is recorded and how commission works

* The invoice and each of its orders store your affiliate id.
* Commission is calculated per order at the rate agreed with Bitrefill, which can differ per product. Some products are excluded from the program and earn no commission.
* Commission counts once the order is paid and delivered. Refunded or failed orders earn nothing.
* Attribution does not depend on who pays or how: guest or logged-in buyer, crypto, card or balance.
* The commission report and payouts (withdrawals) are available from your Bitrefill affiliate account.

## Testing

> 📘 In short
>
> Read tools need no setup. For purchases, ask us to enable test products on your account: their invoices confirm automatically and nothing is charged. Test guest flows on staging or with one small real purchase. Verify affiliate attribution with a separate, non-affiliate account.

### Environments

| Environment | MCP URL                            | Notes                                                          |
| ----------- | ---------------------------------- | -------------------------------------------------------------- |
| Production  | `https://api.bitrefill.com/mcp`    | Real products, real money, real delivery                       |
| Staging     | Provided by your Bitrefill contact | Test accounts included. x402 payments settle on a test network |

Discovery tools (`search-products`, `get-product-details`, help articles) are free to call on production with any token, including a guest token. Start there.

### Test products

Bitrefill has a family of test products from a test provider. Their slugs end in `-syldavia`. Examples:

| Slug                      | Behaviour                                                         |
| ------------------------- | ----------------------------------------------------------------- |
| `delos-syldavia`          | Delivers a test code                                              |
| `syl-tel-syldavia`        | Test phone refill, needs `refill_input`                           |
| `test-esim-data-syldavia` | Delivers a test eSIM with an install link                         |
| `simple-bill-syldavia`    | Bill payment. Exercises `submit-prepayment-step` (login required) |
| `slowcorp-syldavia`       | Slow delivery, for testing polling                                |
| `failcorp-syldavia`       | Delivery fails on purpose                                         |

All of them belong to the test country `KN`, so `search-products` with `country: "KN"` lists them.

Two rules make them useful:

1. **They are hidden until Bitrefill enables them for your account.** Ask your Bitrefill contact to enable test products on the account behind your API key or OAuth login. Until then, `get-product-details` and `buy-products` answer `product_not_found`, even if search listed the product.
2. **Invoices made only of test products confirm automatically** when paid with a crypto or link-only method. No payment is needed and nothing is charged. Delivery then runs normally, so you can test the loop all the way to `redemption_info`. Test products that exist to simulate failures, such as `failcorp-syldavia`, are never confirmed automatically. Your Bitrefill contact can tell you how to exercise them.

> 🚧 Do not pay test products from balance
>
> A `balance` payment debits your real balance, also for a test product. Use a crypto or link-only method, which is confirmed automatically for test products.

Test products are enabled per account, so a guest token cannot use them. To test a guest flow end to end, use staging, or make one small real purchase on production (for example the cheapest denomination of a gift card you can use yourself).

### Interactive testing

<Tabs>
  <Tab title="MCP Inspector">
    Run `npx @modelcontextprotocol/inspector`, choose the Streamable HTTP transport and enter `https://api.bitrefill.com/mcp`. The Inspector runs the OAuth flow in the browser and lets you call tools by hand.
  </Tab>

  <Tab title="Claude Code">
    ```bash
    claude mcp add --transport http bitrefill https://api.bitrefill.com/mcp
    ```

    Then run `/mcp` inside Claude Code to authenticate. The [Use with Claude Code](https://docs.bitrefill.com/docs/use-with-claude-code) guide has the details.
  </Tab>

  <Tab title="curl">
    Use a client-credentials token for guest scenarios (see [Authentication](#authentication)) and send JSON-RPC calls as shown in [First request with curl](#first-request-with-curl).
  </Tab>
</Tabs>

### Test plan

| Check                 | How                                                                                                                                                         | Expected                                                                                                     |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| Discovery             | `tools/list` with a guest token, then with a user token                                                                                                     | 7 tools, then 12                                                                                             |
| Accept header         | Call without `text/event-stream` in `Accept`                                                                                                                | HTTP 400                                                                                                     |
| Search and details    | `search-products` with `intent`, then `get-product-details`                                                                                                 | Slugs, then the `package_value` list and `payment_methods`                                                   |
| Guest purchase        | `buy-products` with `email` and a crypto method                                                                                                             | `invoice_id`, `invoice_access_token`, `payment_info`, `payment_link`                                         |
| Guest polling         | `get-invoice-by-id` without the token, then with it                                                                                                         | `RESOURCE_NOT_FOUND`, then the invoice                                                                       |
| Logged-in purchase    | The same purchase with an OAuth user token or API key                                                                                                       | No `email` field in the schema, receipt to the account                                                       |
| Balance payment       | `payment_method: balance` with a user token                                                                                                                 | `payment_info.status` and an invoice that confirms by itself                                                 |
| Missing recipient     | A refill product without `refill_input`                                                                                                                     | `INVALID_INPUT` with `details.status: number_missing`                                                        |
| Wrong denomination    | `package_value: "7"` for a product with fixed packages                                                                                                      | `invalid_package` and the list of valid values                                                               |
| Expired token         | Wait, or revoke, then call                                                                                                                                  | HTTP 401, the client re-authenticates                                                                        |
| Rate limit            | 31 requests in one minute                                                                                                                                   | HTTP 429 on the 31st                                                                                         |
| Affiliate attribution | Purchase through `?ref=` with a separate non-affiliate account or a guest token, then ask your Bitrefill contact to confirm the affiliate id on the invoice | Attributed. Do not use your own affiliate account as the buyer for this check, the result would be ambiguous |
| Payment uncertain     | A balance payment that times out (staging)                                                                                                                  | `PAYMENT_UNCERTAIN`, and the agent polls instead of retrying                                                 |

### When something fails

Send us the `invoice_id`, the tool name, the UTC timestamp, your OAuth `client_id` or API key name (never the key itself) and the full error object. That is enough to find the request in our logs.

## Errors

> 📘 In short
>
> Tool errors come back as `isError: true` with a JSON body `{ error, code, details }`. Retry only `SERVICE_UNAVAILABLE`. Never retry `PAYMENT_UNCERTAIN`.

```json Error shape
{
  "error": "Invalid denomination '7' for product 'amazon_com-usa'. Available denominations: 5, 10, 25, 50, 100",
  "code": "INVALID_INPUT",
  "details": { "status": "invalid_package" }
}
```

| `code`                | Meaning                                                                          | What to do                                                                    |
| --------------------- | -------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `VALIDATION_ERROR`    | Arguments do not match the tool schema. `details` lists the fields               | Fix the arguments                                                             |
| `INVALID_INPUT`       | Arguments are well formed but wrong for this purchase. `details.status` says why | Fix and retry once                                                            |
| `RESOURCE_NOT_FOUND`  | Unknown product, invoice or order, or a guest without the right access token     | Check the ids. `details.suggestions` may list similar slugs                   |
| `PERMISSION_DENIED`   | The tool needs a logged-in user                                                  | Log in, or hide the tool                                                      |
| `SERVICE_UNAVAILABLE` | Search, a quote or a payment session failed temporarily                          | Retry with back-off                                                           |
| `PAYMENT_UNCERTAIN`   | A balance payment may have started                                               | Do not retry. Poll `get-invoice-by-id`                                        |
| `INTERNAL_ERROR`      | Unexpected failure on our side                                                   | Report it with the details from [When something fails](#when-something-fails) |

> ❗️ Never retry PAYMENT\_UNCERTAIN
>
> A second `buy-products` call after `PAYMENT_UNCERTAIN` can charge the balance twice. Poll `get-invoice-by-id` instead and let the invoice settle.

The `details.status` values you will meet most often: `product_not_found`, `product_not_available`, `invalid_package`, `number_missing`, `payment_method_not_accepted`, `invalid_payment_method`, `purchase_limit_reached`, `balance_too_low`, `bill_payment_id_missing`, `coupon_invalid`, `verification_required`, `access_denied`, `user_not_registered`, `missing_fiat_payment_info`, `invalid_billing_country`.

HTTP-level errors are separate: 400 for a bad `Accept` header, 401 for authentication, 405 for GET or DELETE, 429 for the rate limit.

## Tool reference

| Tool                                                             | Login | Purpose                                                                             | Key arguments                                                                                                                                                                                                                         |
| ---------------------------------------------------------------- | ----- | ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `search-products`                                                | No    | Find products by brand, country, category or type                                   | `query`, `intent` (required, the user's goal), `country` (default US), `product_type`, `category`, `page`, `per_page` (max 250)                                                                                                       |
| `get-product-details`                                            | No    | Prices, denominations, payment methods, recipient type, prepayment form             | `product_id`, `currency` (default BTC), `language`                                                                                                                                                                                    |
| `buy-products`                                                   | No    | Create an invoice and, for balance, pay it                                          | `cart_items[]` (`product_id`, `package_value`, `refill_input`, `bill_payment_id`, `gift`), `payment_method`, `email` (guests only), `billing_address`, `saved_fiat_card_id`, `balance_currency`, `coupon_code`, `return_payment_link` |
| `get-invoice-by-id`                                              | No    | Status, payment info, orders and codes                                              | `invoice_id`, `invoice_access_token` (guests)                                                                                                                                                                                         |
| `search_help_articles`, `get_help_article`, `list_help_articles` | No    | Bitrefill help center content for support questions                                 | `query`, article id                                                                                                                                                                                                                   |
| `list-invoices`                                                  | Yes   | Paid invoices of the logged-in user                                                 | `limit` (max 50), `start`, `after`, `before`, `include_orders`                                                                                                                                                                        |
| `get-balances`                                                   | Yes   | Store credit per sub-account (EUR, USD, BTC, cashback) and top-up options           | `currency`                                                                                                                                                                                                                            |
| `list-saved-fiat-cards`                                          | Yes   | Cards saved on the account, for `saved_fiat_card_id`                                | none                                                                                                                                                                                                                                  |
| `submit-prepayment-step`                                         | Yes   | Multi-step forms for bill payments and prepaid cards, ending in a `bill_payment_id` | `product_id`, `step_number`, `form_data`, `bill_payment_id`                                                                                                                                                                           |
| `update-order`                                                   | Yes   | Track the remaining balance of a gift card, archive an order                        | `order_id`, `remaining_amount`, `is_archived`                                                                                                                                                                                         |

Payment methods accepted by `buy-products`:

| Group                  | Methods                                                                                                                           | What the response contains                                                 |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| Address based (crypto) | `bitcoin`, `lightning`, `ethereum`, `usdc_base`, `usdt_erc20`, `usdc_solana` and the other chains listed by `get-product-details` | `payment_info` with address and amount, `payment_link`, `x402_payment_url` |
| Link only              | `fiat_card`, `apple_pay`, `google_pay`, `ideal`, `eps`, `p24`, `bancontact`, `binance_pay`, `kraken_pay`                          | `payment_link` only. The buyer finishes on bitrefill.com                   |
| Balance                | `balance` (with `balance_currency` EUR, USD or BTC) and `cashback`                                                                | Paid at once. Poll for confirmation                                        |

Fiat methods are charged in the method's standard currency, for example USD for cards. The tool description lists the currency per method. A cart holds up to 15 items. Add the same product twice for two units. Any item can be sent as a gift by email with `cart_items[].gift` (`recipient_name`, `recipient_email`, `sender_name`, optional `message`, `send_date` between 12 hours and 6 months ahead, and `theme`).

## Paying an MCP invoice with x402

`buy-products` returns `x402_payment_url` (`https://api.bitrefill.com/x402/invoice/pay`) for crypto invoices. A wallet that speaks x402 can settle a USDC invoice with two HTTP calls instead of a manual transfer to the address:

1. `POST /x402/invoice/pay` with the body `{ "invoice_id": "<id>" }`. The answer is HTTP 402 with a `PAYMENT-REQUIRED` header (base64 JSON describing amount, asset and networks).
2. Sign the payment with your x402 client and repeat the POST with a `PAYMENT-SIGNATURE` header. HTTP 200 means the payment is accepted and being settled. Poll `get-invoice-by-id`, or `GET /x402/invoice/status?invoice_id=<id>`, for delivery.

Conditions: the invoice was created with a USDC method (`usdc_base`, `usdc_arbitrum`, `usdc_polygon` or `usdc_solana`) and is younger than 15 minutes, which is the price lock. The `@x402/core` and `@x402/mcp` npm packages implement the client side.

## The x402 REST API

For agents that hold a wallet but no Bitrefill account, Bitrefill also exposes a wallet-native REST API on `https://api.bitrefill.com`. Identity is the wallet. Calls are paid per request in USDC (0.001 to 0.002 USD), or made free by signing in with the wallet (Sign In With X). It covers the same catalog as MCP with fewer options: crypto only, no gifts, no coupons.

<Accordion title="x402 routes" icon="fa-list">
  | Method and path | Purpose |
  | --- | --- |
  | `GET /x402/gift-cards/search`, `/x402/esims/search`, `/x402/topups/search` | Discovery with `q` and `country` |
  | `GET /x402/products/detail` | Product details |
  | `GET /x402/checkout/info` | Storefront information and the list of routes |
  | `POST /x402/invoice/create` | Price-locked invoice for `items[]` (`product_id`, `package_value`, `refill_input`). The affiliate header goes here |
  | `POST /x402/invoice/pay` | Settle the invoice |
  | `GET /x402/invoice/status` | Status, plus codes when signed in with the paying wallet |
  | `POST /x402/connect` | Sign once and receive a session token to send as `X-Access-Token` |
  | `GET /x402/my/orders`, `/x402/my/esims` | Orders and eSIMs of the signed-in wallet |

  Rate limits: 30 requests per minute per IP and 10 invoice creations per minute per IP. The OpenAPI description is at `https://api.bitrefill.com/openapi.json`.
</Accordion>

## Glossary

<Accordion title="Terms used in this guide" icon="fa-book">
  | Term | Meaning |
  | --- | --- |
  | Invoice | One payment intent. It has a UUID with dashes, a status, an access token and one or more orders |
  | Order | One product unit inside an invoice. It has a 24-character hex id, a delivery status and, once delivered, the code |
  | Product id (slug) | The text id of a product, for example `amazon_com-usa` or `esim-france` |
  | `package_value` | The denomination, for example `"10"` or `"1GB, 7 Days"`. Ranged products accept any value between `range.min` and `range.max` |
  | `refill_input` | The recipient for refills: phone number, account id, email or username, as `recipient_type` says |
  | Guest | A buyer without a Bitrefill account, identified only by checkout email and invoice access token |
  | Affiliate code | 6 to 16 letters and digits identifying a partner for commission |
  | TOON | Token-Oriented Object Notation, the compact text format used by read tools |
  | x402 | An HTTP 402 based payment protocol for wallets, and the name of Bitrefill's wallet-native REST API |
</Accordion>