> Part of the API Mercado docs, in beta. Markdown for every page: append `index.md` to its URL. Site map: /llms.txt

# Billing and keys

Everything a developer needs to call paid APIs on API Mercado: how to
authenticate, what each call costs, how balances, holds and spend caps work,
and how to read every error the gateway can return.

## Authenticating requests

Every request carries a Key in the `X-API-Key` header:

```
curl -H "X-API-Key: mk_live_…" "https://eu-north-1.apimercado.com/v1/@<provider-slug>/<api-slug>/<path>"
```

Get a Key from any API's page: enable the API, then press **Create key** in the
dialog that follows. The Keys page lists every Key and mints ones scoped to several
APIs or capped per Month.

Keys are shown once at creation. Keep them server-side; a leaked Key spends
your balance. Revoke and re-create from the Keys page. There is no rotation
window and no expiry.

### Keyless operations

A few operations need no Key: those an API's provider made keyless (marked
`security: []` in its published spec), and every API's health check path. They are free and not
metered, so a browser can call them directly, and the gateway allows 60 of
them per minute per IP address and API (`keyless_rate_limited` beyond that).
A Key sent to one is removed and ignored, and the provider does not see who
called.

### Test requests from an API page

An org admin can send a test request from any API page their organization has
enabled ("Try it"). The marketplace sends it through the gateway with your
organization's **Portal test key**, which it creates on the first test and
lists on the Keys page. A test request is billed exactly like any other call,
from the same balance, and shows up in your requests and spend. You can give
the Portal test key a Spend cap or revoke it; the next test creates a new one.
Test requests are limited to 10 per minute per organization.

### TypeScript client

`@apimercado/client` wraps [openapi-fetch](https://openapi-ts.dev/openapi-fetch/) with the
gateway URL, the Key header and the gateway error shape. Every API page shows the
one-liner that generates its types; it fetches the API's OpenAPI spec from the gateway and
writes a `.d.ts` file you commit:

```sh
npm install @apimercado/client
npx @apimercado/client generate @<provider-slug>/<api-slug> -o <api-slug>.d.ts
```

```ts
import { createApimercadoClient } from "@apimercado/client";
import type { paths } from "./<api-slug>";

const api = createApimercadoClient<paths>({
  provider: "@<provider-slug>",
  api: "<api-slug>",
  apiKey: "mk_live_...",
});
const { data, error } = await api.GET("/<path>", { params: { query: { ... } } });
```

Providers can publish new versions and the gateway always serves the current one. The
generated file records the spec hash it was built from, so `npx @apimercado/client check
<api-slug>.d.ts` exits 1 in CI when the spec changed; regenerate and let the compiler point
at the calls that no longer match.

The client also sets [Max cost](#max-cost) for you (`maxCostMicros`), reads every
[response header](#response-headers) (`readCost`), and types the
[balance endpoint](#the-balance-endpoint) and the [request lookup](#the-request-lookup)
(`createAccountClient`).

## Base URL shape

All API traffic goes through the marketplace gateway:

```
https://eu-north-1.apimercado.com/v1/@<provider-slug>/<api-slug>/…
```

`@<provider-slug>` is the provider organization's slug, the same name as in
the marketplace URL `https://apimercado.com/discover/<provider-slug>/<api-slug>`. The
provider's public id (shown in small print at the bottom of every API page)
works in its place, `/v1/<provider-public-id>/<api-slug>/…`, so URLs copied
before slugs existed keep working. Every API page also has a markdown twin at
`<page>/llms.txt` with this whole setup written for a coding agent.

The same gateway hosts two platform endpoints under the reserved public id
`account`:

```
GET https://eu-north-1.apimercado.com/v1/account/balance
GET https://eu-north-1.apimercado.com/v1/account/requests/{requestId}
```

They are authenticated with any of your org's Keys, exactly like an API call,
and are never charged.

## The balance endpoint

`GET /v1/account/balance` returns your organization's current billing state.
All money fields are integer micro-dollars (1,000,000 = $1.00) with the unit
in the field name:

```json
{
  "monthly_balance_micros": 412000,
  "topup_balance_micros": 12500000,
  "available_balance_micros": 12912000,
  "month_resets_at": "2026-10-01T00:00:00.000Z",
  "key_spend_micros": 750000,
  "key_spend_cap_micros": 5000000,
  "next_expiring_lot": {
    "amount_micros": 12500000,
    "expires_at": "2028-03-01T00:00:00.000Z"
  }
}
```

- `monthly_balance_micros`: what remains of this Month's Free buffer.
- `topup_balance_micros`: what remains of your purchased Top-up balance.
- `available_balance_micros`: the two combined; a request is denied when it
  would cost more than this.
- `month_resets_at`: when the Monthly balance resets (the 1st of next Month,
  UTC).
- `key_spend_micros`: what the calling Key has spent this Month.
- `key_spend_cap_micros`: the calling Key's Spend cap, or `null` when
  unlimited.
- `next_expiring_lot`: the soonest-expiring Top-up Lot with its remaining
  amount, or `null` when nothing is left to expire.

## Response headers

| Header                     | On                                                                                        | Value                                                                                                                    |
| -------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ |
| `X-Mercado-Request-Id`     | every response to an API call, including the gateway's 400, 402, 403, 429 and 503 denials | The request's id. Use it for the [request lookup](#the-request-lookup) and in support questions.                         |
| `X-Mercado-Cost-Micros`    | every served response                                                                     | The Cost of that request, so far. On a call to your own API it is the full Cost, though only the proxy fee was deducted. |
| `X-Mercado-Fee-Micros`     | every served response                                                                     | The proxy fee part of that Cost.                                                                                         |
| `X-Mercado-Charge`         | calls to an API your own organization publishes                                           | `internal`: the call is priced in full, but only the proxy fee is deducted.                                              |
| `X-Mercado-Balance-Micros` | every served response                                                                     | Your Available balance after what was deducted.                                                                          |
| `X-Mercado-Resets-At`      | every served response                                                                     | When the Monthly balance resets.                                                                                         |
| `X-Mercado-Settlement`     | operations settled later                                                                  | `pending`: the price comes later (see [Holds](#holds)). `instant`: charged in full now.                                  |
| `X-Mercado-Hold-Micros`    | with `X-Mercado-Settlement: pending`                                                      | What is held until the provider settles.                                                                                 |

The only response without `X-Mercado-Request-Id` is the gateway's static 403
for an unknown or revoked Key (see `api_not_enabled`). A rate-limited request
returns `429` with a `Retry-After` header. The [TypeScript client](#typescript-client)
reads all of them with `readCost(response)`.

## What is charged

You pay the request's **Cost**: the API's Price plus a fixed proxy fee per
request. Every price on the Marketplace is the provider's Price
alone, marked "+ proxy fee", so an API with a $0 Price shows as Free; the enable
dialog spells the fee out. Providers may vary the Price per request up to the
price cap shown on the API page, so check `X-Mercado-Cost-Micros` rather than
assuming a list Price. Calls to an API your own organization publishes are
priced like any other call, but only the proxy fee is deducted: their
response headers report the full Cost and carry `X-Mercado-Charge: internal`.
To bound what a single call may cost, see [Max cost](#max-cost). Topping up costs a separate
percentage fee, added on top of the amount you buy and shown on your Stripe
invoice.

The current figures (the proxy fee, the top-up fee, the Free buffer, the
smallest top-up and how long purchased dollars last) are on the
[fees overview](https://apimercado.com/distribute#fees). Signed in, your organization's
own figures are on its [Billing page](https://apimercado.com/dashboard/billing).

A request is charged when the upstream API answers with a 2xx or 4xx status,
except 401, 403, and 429: those mean the provider's upstream rejected or
throttled the gateway itself, so you are not charged for them. Upstream 5xx
responses, timeouts, and every gateway denial are never charged.

Your Key never leaves the gateway. The `X-API-Key` header is removed before
the request is forwarded, and the provider identifies you only by the
`X-Mercado-Consumer-Id` and `X-Mercado-Key-Id` headers.
APIs with a $0 Price still require a Key and Access, and are rate-limited and
logged. They earn the Provider nothing, and cost you only the per-request proxy
fee.

## Prices and price changes

An API page shows what its requests actually cost: the 5th to 95th percentile
of the charged Price over the last 30 days, refreshed every 5 minutes, for
example "$0.0004 to $0.0012 per request, up to $0.002". Until an API has 20
charged requests in that window it shows "Up to $0.002 per request". The cap,
the most one request can cost, is always shown. Operations with their own
pricing show their own range and cap in the endpoint list.

When a provider raises a price or a cap, every organization with the API
enabled gets an email, and the API page shows "Price raised on <date>" or
"Price cap raised on <date>" for 30 days. A provider turning off the Free
buffer for its API emails you too. Lowerings send nothing.

Some APIs need a Top-up balance: their page says so. Your Free buffer pays
only the proxy fee on them, so their free operations keep working without a
top-up (see `topup_required`).

An operation marked "Not available yet" is priced by a provider that cannot
charge for calls yet. Calls to it are refused with `paid_pricing_unavailable`
and cost nothing; the API's free operations work as usual.

## Max cost

To bound what one call may cost you, proxy fee included, send
`X-Mercado-Max-Cost-Micros` with the request:

```
curl -H "X-API-Key: mk_live_…" -H "X-Mercado-Max-Cost-Micros: 20000" "https://eu-north-1.apimercado.com/v1/@<provider-slug>/<api-slug>/<path>"
```

- The gateway compares it with the most the call can cost: the called
  operation's price cap plus the proxy fee. When that is above your value, the
  call is refused with `402 max_cost_exceeded` before the provider is called,
  and nothing is held or charged. Set it against the cap shown on the API
  page, not against what calls usually cost.
- An allowed call reaches the provider with the header unchanged, so it can
  scale the work to your Max cost. You are still charged at most the
  operation's cap plus the proxy fee.
- The value is a whole number of micro-dollars, digits only. Anything else (a
  sign, a decimal point, spaces, an empty value, a number too large for a
  64-bit integer) is ignored and not forwarded, as if you had sent none.
- It applies to calls to your own organization's APIs too, checked against
  the full Cost. Keyless operations ignore it and do not forward it.

The [TypeScript client](#typescript-client) sends it on every call when created with
`maxCostMicros`.

## Balances: Free buffer and Month reset

Spend draws from two pools, Monthly first:

1. **Monthly balance**: the Free buffer every organization gets each Month
   (see [What is charged](#what-is-charged) for the amount). It is a trial the Marketplace funds, so Spend from it
   earns the Provider nothing. What you do not spend does not carry over: the
   balance resets on the 1st of each Month at 00:00 UTC.
2. **Top-up balance**: prepaid dollars you purchase. It never resets, and is
   spent only after the Monthly balance is exhausted.

## Holds

Before a request reaches the provider, the gateway holds the most it can cost:
the called operation's price cap plus the proxy fee. Requests in flight at the
same time cannot spend the same dollars, and a request is never half-paid. The
hold ends when the response is charged, after at most 60 seconds.

Some operations are **settled later**: the provider only knows the price once
the work is done (a video render, a transcript). The API's spec declares them,
and they work differently:

1. The gateway holds the operation's cap from your Top-up balance, minus your
   other open holds. The Free buffer never funds this hold. Without enough
   Top-up the request is denied with `topup_required` before the provider is
   called.
2. The response carries `X-Mercado-Settlement: pending` and
   `X-Mercado-Hold-Micros`. You pay the proxy fee now
   (`X-Mercado-Cost-Micros`).
3. The provider settles the request once, for 0 up to the hold. You pay the
   settled amount from Top-up and the rest is released. A hold the provider
   never settles is released after 48 hours.

The proxy fee is not returned when a hold is released. Open holds count toward
the Key's Spend cap, and a settled amount counts toward the Month the request
was made in. A provider may answer such a request with
`X-Mercado-Settlement: instant` (a cached result, a rejected input): it is
then charged in full at once, like any other request.

Example: an operation with a $0.25 cap. The submit holds `250000`
micro-dollars and costs the proxy fee. The provider settles `182000`: you pay
$0.182 and the other $0.068 is released.

## The request lookup

`GET /v1/account/requests/{requestId}` returns one request of your
organization by its `X-Mercado-Request-Id`. It is free and authenticated with
any of your org's Keys:

```
curl -H "X-API-Key: mk_live_…" "https://eu-north-1.apimercado.com/v1/account/requests/4f1c2b9e-0d7a-4b8e-9a51-2f3c6d7e8a90"
```

```json
{
  "request_id": "4f1c2b9e-0d7a-4b8e-9a51-2f3c6d7e8a90",
  "status": "pending",
  "price_micros": 0,
  "fee_micros": 100,
  "cost_micros": 100,
  "raw_cost_micros": 100,
  "hold_micros": 250000,
  "internal": false
}
```

The amounts in this example are illustrative; `fee_micros` is the proxy fee in force
when the request was made.

| `status`      | Meaning                                                                                                      |
| ------------- | ------------------------------------------------------------------------------------------------------------ |
| `charged`     | Charged in full when the response came back.                                                                 |
| `pending`     | Settled later: the proxy fee is charged, `hold_micros` is held until the provider settles.                   |
| `settled`     | The provider settled: `price_micros` is the settled amount, `cost_micros` adds the proxy fee.                |
| `released`    | The hold was released without a price (a $0 settle or 48 hours without one). Only the proxy fee was charged. |
| `not_charged` | Denied by the gateway or not charged (upstream 5xx, 401, 403 or 429). All amounts are 0.                     |

- `price_micros`, `fee_micros`, `cost_micros`: what the request charged. On a
  call to an API your own organization publishes they are the full amounts,
  though only the proxy fee was deducted.
- `raw_cost_micros`: deprecated, always equal to `cost_micros`. Read
  `cost_micros` instead; this field will be removed.
- `hold_micros`: what is held now; 0 unless `pending`.
- `internal`: `true` on a call to an API your own organization publishes.

A request settled later is read from its hold record, and is final once
`settled` or `released`. Any other request is read from the request log: it
appears a few seconds after its response and is kept 90 days. A request id of
another organization answers like an unknown one (`request_not_found`).

## Spend caps

Each Key can carry an optional monthly Spend cap. When the Key's own Spend
this Month reaches its cap, only that Key is denied; your other Keys keep
working until the org balance runs out. An unset cap means unlimited (bounded
by the org balance).

## Expiry

Top-up dollars arrive in Lots, and each Lot expires a fixed number of months
after it lands (see [What is charged](#what-is-charged) for how many).
Spend consumes the soonest-expiring Lot first, so nothing goes stale while a
later Lot could be spent. The balance endpoint's `next_expiring_lot` shows
what expires next; expired amounts simply leave the Top-up balance.

## Error codes

Gateway-generated errors share one body shape:

```json
{
  "error": {
    "code": "balance_exhausted",
    "message": "The organization balance is exhausted.",
    "resets_at": "2026-10-01T00:00:00.000Z",
    "docs": "https://docs.apimercado.com/billing-and-keys/#balance_exhausted"
  }
}
```

`resets_at` is the next Month reset (the 1st of next Month, 00:00 UTC). Every
denial the billing gateway generates carries it, even `org_suspended`,
`api_not_enabled`, and `billing_state_unavailable`, which are not really about
the Month reset, so a client can always say when the error state may change.
It is `null` only on the gateway's static 403 from its own key authentication
(see `api_not_enabled`) and on the account endpoints' own `key_not_authorized`
and `request_not_found`. `docs` links to the anchor below.

### key_not_authorized

`401`: returned only by the account endpoints themselves, when the caller
identity the gateway forwarded does not check out: the request bypassed the
gateway, or the Key's platform metadata is stale. This is not what a revoked
Key sees in normal use: the gateway rejects a revoked or unknown Key first,
with `api_not_enabled` below.

### request_not_found

`404`: the request lookup found no request with this id in your organization.
The id may be mistyped, belong to another organization, or be older than 90
days. A request charged in full appears a few seconds after its response, so
retry a just-made one shortly.

### api_not_enabled

`403`: the Key has no Access to this API. Enable the API for your
organization, or widen the Key's Scope, and retry.

A revoked or unknown Key gets this same code: the gateway's own authentication
rejects it before any billing check runs, answering HTTP 403 with a static
body whose `resets_at` is `null`. Revoked Keys are gone for good: mint a new
Key on the Keys page.

### org_suspended

`403`: the organization is suspended. All Keys are denied until the
suspension is lifted; contact support.

### balance_exhausted

`402`: the Available balance (Monthly plus Top-up, minus your open holds)
cannot cover the most the request can cost, which is the called operation's
price cap plus the proxy fee. The check runs before the call reaches the
provider, so a request is never half-paid. Top up, or wait for the Month reset
in `resets_at`.

### topup_required

`402`: the Price of this request must be paid from purchased dollars, and your
Top-up balance (minus your open holds) cannot cover its price cap. This
happens on an API whose provider asks for it (its page says calls need a
topped-up balance) and on every operation settled later (see
[Holds](#holds)). Your Free buffer still pays the proxy fee, so an API's free
operations keep working. Top up and retry.

### key_spend_cap_reached

`402`: this Key reached its monthly Spend cap, or has too little room under it
for the hold an operation settled later needs. Raise the cap, use another
Key, or wait for the Month reset in `resets_at`.

### max_cost_exceeded

`402`: the most this call can cost, the called operation's price cap plus the
proxy fee, is above the `X-Mercado-Max-Cost-Micros` you sent (see
[Max cost](#max-cost)). The provider was not called, and nothing was held or
charged. Raise the header, or leave it out, and retry.

### paid_pricing_unavailable

`503`: the called operation is priced, and its provider cannot charge for
calls yet (the API page marks it "Not available yet"). The provider was not
called, and nothing was held or charged. The API's operations without a price
still work. Retrying the same operation gets the same answer until the
provider can charge.

### billing_state_unavailable

`503`: the billing system could not read your balance or the API's pricing,
so the gateway failed closed. Nothing was charged. Retry shortly.

### path_not_routable

`400`: the gateway cannot tell which operation this path calls, so it cannot
price it. This happens on APIs that price operations in their spec, when a
path segment holds an encoded slash (`%2F`) or a backslash, or when the path
is not under the API's base URL. Nothing was charged, and retrying the same
URL gets the same answer: fix the URL.

### keyless_rate_limited

`429`: too many calls to an API's keyless operations (see Keyless operations)
from one IP address within a minute. Wait for the next minute and retry.

## Disputes

Charged incorrectly? From your request log, an org admin can report any
charged or settled request within 30 days of the request, with a description
of what went wrong. A resolved refund returns the full Cost (for a settled
request, the settled amount plus the proxy fee) to your Top-up balance and
shows up in your balance history; the provider is deducted the Price portion
and the platform forgoes its fee.

### request_not_settled

A `pending` request cannot be disputed yet: it has no price. Report it once
the provider settles it, or wait for its release.

### request_released

A `released` request cannot be disputed: it charged only the proxy fee, which
a release never returns, so there is nothing to refund.
