# AgentPay API

AgentPay is a pay-per-call gateway: AI agents call third-party APIs through it from a prepaid wallet, without holding those APIs' keys. It shares API keys and the wallet with Freshness Validator (https://api.myuiaf.com).

- Base URL: `https://agentpay.myuiaf.com`
- HTML docs: https://myuiaf.com/agentpay/docs
- OpenAPI: https://myuiaf.com/agentpay/openapi.json
- Overview and pricing: https://myuiaf.com/agentpay

## MCP server

`https://agentpay.myuiaf.com/mcp` (Streamable HTTP). Same features as MCP tools; send `Authorization: Bearer fv1...`. Setup for Claude, OpenAI, Gemini, Grok and others: https://myuiaf.com/integrations

## Authentication

Send your key (`fv1.<agent_id>.<key_id>.<secret>`) in one of:

```
X-Agent-API-Key: fv1.acme-bot.k1.xxxxx
X-Api-Key: fv1.acme-bot.k1.xxxxx
Authorization: Bearer fv1.acme-bot.k1.xxxxx
```

Use `X-Agent-API-Key` when the destination API needs its own `Authorization` header from you. Your key is never forwarded. Get a key by buying credits: https://myuiaf.com/pricing#buy, or as an agent with `POST https://api.myuiaf.com/api/v1/credits`.

## List routes

`GET /v1/routes` returns the APIs you can call, each with `id`, `name`, `description`, `pricing_model`, `price_per_call_usd`, `sla_ms` and `proxy_url`.

## Call a route

`ANY /v1/proxy/{route_id}/{path}` (GET, POST, PUT, PATCH, DELETE, HEAD).

The path and query string are appended to the route's destination URL. Method, body (up to 1 MB) and headers are forwarded; AgentPay adds the destination key and removes your key, cookies and proxy headers. Redirects are returned, not followed.

```
curl -X POST "https://agentpay.myuiaf.com/v1/proxy/rt_weather/forecast" \
  -H "X-Agent-API-Key: fv1.acme-bot.k1.xxxxx" \
  -H "Idempotency-Key: 7f3c9a1e-forecast-honolulu" \
  -H "content-type: application/json" \
  -d '{"city":"Honolulu","days":3}'
```

## Idempotency (required)

Every call needs `Idempotency-Key` (1-255 printable characters, unique per logical call). Keys are remembered for 24 hours.

| Key state | Result |
|---|---|
| New | The call is made |
| Completed | Original response replayed with `Idempotent-Replayed: true`, no new charge (bodies over 64 KB: 409 `replay_body_unavailable`) |
| In progress | 409 `request_in_progress` |
| Used for a different request | 422 `idempotency_key_reused` |
| Failed earlier (not charged) | Tried again |

## When you are charged

The price is reserved before the call, then:

| Outcome | You get | Charged |
|---|---|---|
| 2xx within the SLA | The API's response | Route price |
| Any other status | The API's response | Nothing |
| No full answer within the SLA | 504 `sla_exceeded` | Nothing |
| API unreachable | 502 `destination_unreachable` | Nothing |
| Response over 10 MB | 502 `response_too_large` | Nothing |
| Not enough credit | 402 `insufficient_credits` (call not made; includes `price_usd` and `topup`) | Nothing |
| Wallet unavailable | 503 `ledger_unavailable` (call not made) | Nothing |

Pricing: flat routes $0.01 per successful call; pass-through routes cost the API's own price + 5%, rounded up to the cent.

## Response headers

`x-agentpay-call-id`, `x-agentpay-charged-usd`, `x-agentpay-available-usd`, `x-agentpay-ttfb-ms`, `x-agentpay-total-ms`, and `idempotent-replayed: true` on replays.

## Wallet and history

- `GET /v1/wallet/balance`: `balance_usd`, `held_usd` (reserved for calls in progress), `available_usd`, `topup_url`.
- `GET /v1/transactions?limit=50&before=<call_id>`: calls newest first (max 200 per page) with `status` (`completed`, `failed`, `pending`), `reason`, `destination_response_code`, `ttfb_ms`, `total_ms`. Pass `next_before` as `before` for the next page.

## Limits

- Requests per minute by tier: 60 / 120 / 300 / 1,000, separate from Freshness Validator.
- Request body 1 MB; response body 10 MB; replayed body 64 KB for 24 hours.
- Time limit per route: `sla_ms`.

## Errors

AgentPay's own errors are JSON: `{"error": "...", "code": "..."}`.

| Status | Code |
|---|---|
| 400 | `idempotency_key_required`, `invalid_path` |
| 401 | `missing_api_key`, `invalid_api_key` |
| 402 | `insufficient_credits` |
| 404 | `route_not_found` |
| 409 | `request_in_progress`, `replay_body_unavailable` |
| 413 | `body_too_large` |
| 422 | `idempotency_key_reused` |
| 429 | `rate_limited`, `temporarily_blocked` (see `Retry-After`) |
| 502 | `destination_unreachable`, `response_too_large` (not charged) |
| 503 | `ledger_unavailable`, `routes_unavailable`, `route_misconfigured` (not charged; retry with the same key) |
| 504 | `sla_exceeded` (not charged) |

## Health

`GET /v1/health` (no key): 200 with `"status": "ok"` when everything is reachable, otherwise 503. Both services at once: `GET https://myuiaf.com/api/status`.
