# Meirra API: authentication for AI agents

> The Meirra API authenticates every call with an API key. A person with a Meirra account creates the key and gives it to the agent. There is no OAuth flow and no agent self-registration.

## Base URL

All endpoints are under `https://api.meirra.com/v1`. For example, the balance endpoint is `GET https://api.meirra.com/v1/account/balance`. Use HTTPS only. `https://api.meirra.com/api/v1` is the same API under a second prefix and answers identically.

API catalog: https://api.meirra.com/.well-known/api-catalog

OpenAPI 3.1: https://api.meirra.com/openapi.json

## Get a key

An agent cannot create a key itself. Ask the account owner to:

1. Sign up or sign in. Developers can sign up at https://auth.meirra.com/developers/signup.
2. Open the developer dashboard at https://account.meirra.com/developers and create a key with a name, such as the agent's name.
3. Copy the full key when it is shown. It is shown only once; after that the dashboard shows only its first characters.
4. Add prepaid credit on the same dashboard. Paid calls are deducted from it.
5. Pass the key to the agent through a secret store or environment variable, never in a prompt, URL or log.

A key looks like `mk_live_` followed by 32 URL-safe characters (40 characters in total).

## Send the key

Send the key in one of these two headers. Both work the same way.

```
Authorization: Bearer mk_live_...
x-api-key: mk_live_...
```

`Authorization: Bearer` is recommended. If you send both headers they must hold the same key, or the call is refused with `CONFLICTING_API_KEYS` (400). An `Authorization` header that is not a single Bearer token, such as Basic, is refused with `INVALID_AUTHORIZATION_HEADER` (401).

```bash
curl https://api.meirra.com/v1/account/balance \
  -H "Authorization: Bearer $MEIRRA_API_KEY"
```

## Scope and limits

- There are no scopes. A key can call every endpoint for its account and spends that account's prepaid balance. Give each agent its own named key so it can be revoked on its own from the dashboard. A revoked key gets `INVALID_API_KEY` (401).
- A key may carry an IP allowlist. Calls from other addresses get `IP_NOT_ALLOWED` (403).
- Rate limit: 1000 requests per key per endpoint per hour. Responses carry `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset`. Over the limit you get `RATE_LIMIT_EXCEEDED` (429) with a `Retry-After` header in seconds; wait that long before retrying.
- Cost: paid calls are charged only when they succeed. A call that finds nothing is not charged. A successful paid call carries `X-Cost-Pence`, the pence debited; a call that ran but was not charged carries `X-Cost-Pence: 0`. Error responses are never charged. If the balance is too low the call is refused before it runs with `INSUFFICIENT_BALANCE` (402). `GET https://api.meirra.com/v1/pricing` returns current prices; it needs a key and is free.
- Retries: on POST, PUT, PATCH and DELETE you can send an `Idempotency-Key` header (at most 128 characters). Repeating it with the same body within 24 hours replays the first response, marked `X-Idempotent-Replayed: true`, without a second charge. Reusing it with a different body gets `IDEMPOTENCY_KEY_CONFLICT` (409).

## Errors

Errors are JSON: `{"success": false, "error": {"code": "...", "message": "..."}}`.

| Code | Status | Meaning |
|---|---|---|
| `MISSING_API_KEY` | 401 | No key was sent |
| `INVALID_AUTHORIZATION_HEADER` | 401 | `Authorization` is not a single Bearer token |
| `CONFLICTING_API_KEYS` | 400 | The two headers hold different keys |
| `INVALID_API_KEY` | 401 | The key is malformed, unknown or revoked |
| `IP_NOT_ALLOWED` | 403 | The caller's IP is outside the key's allowlist |
| `RATE_LIMIT_EXCEEDED` | 429 | Too many requests; wait for `Retry-After` |
| `INSUFFICIENT_BALANCE` | 402 | Add credit, then retry |
| `PAYMENT_FAILED` | 402 | The account has a failed payment; the owner must pay it before credit can be used |
| `BALANCE_UNAVAILABLE` | 503 | The balance could not be checked; nothing was charged; retry after `Retry-After` |

Do not retry a 401, 403 or 402 without a change: fix the key, the address or the balance first.
