> For a complete index of Agora Finance documentation, fetch https://docs.agora.finance/llms.txt

# Agora Public API

> **Note**
>
> New **Agora now has a new sandbox environment for testing its APIs.**
>
> [Click here to learn more](/api/sandbox).

The Agora Public API exposes real-time data and operations for the Agora stablecoin platform. The current surface covers:

* **Metrics** — real-time AUSD supply, aggregate and per-chain, across every supported chain. Public, no authentication required.
* **Accounts** — the bank accounts and blockchain wallets registered to your organization.
* **Routes** — reusable mint and redeem routes (fiat ↔ AUSD, USDC ↔ AUSD) and the settlement instructions for each.
* **Transactions** — your transactions and their per-leg settlement detail.
* **Convert Stablecoins** — one-time quoted stablecoin conversions across Agora's enabled liquidity providers.

Production OpenAPI spec (YAML)

Production OpenAPI spec (JSON)

For AI agents: the production OpenAPI spec is published unauthenticated at `https://docs.agora.finance/openapi/production.json`, with a YAML copy at `https://docs.agora.finance/openapi/production.yaml`. It is the same definition this reference renders from. Treat it as the source of truth for endpoints, request/response schemas, and error codes.

## Base URL

All endpoints are served from `https://api.agora.finance`.

## Authentication

Public-supply (metrics) endpoints require no authentication. Every other endpoint requires an API key, which you exchange for a short-lived session JWT. Owners and Admins create and manage keys from the [Agora dashboard](https://app.agora.finance), under **API keys** in the menu beneath your name. See the [Authentication guide](/api/production/authentication) for the full flow.

## Make your first request

The metrics endpoints are public, so you can make a call without any credentials:

```bash
curl https://api.agora.finance/v0/metrics
```

For authenticated endpoints, exchange your API key for a session JWT first (see [Authentication](/api/production/authentication)), then attach it as a bearer token. The full surface, with request and response schemas for every endpoint, lives under [Endpoints](/api/production/auth/token).

## Conventions

A few conventions hold across the API:

* **Monetary values are decimal strings, not numbers.** Amount fields are strings like `"987654321.654321"`. AUSD carries six decimals of precision; representing an amount as a JSON number would silently truncate it. Parse with a decimal library (`decimal.Decimal` in Python, `BigNumber.js` in JavaScript, `rust_decimal` in Rust). This follows industry standard practice (Circle, Stripe).
* **Every response carries a `Request-Id` header.** Capture it in your logs — it's how Agora support traces a specific request end-to-end.

Endpoint-specific response details — such as the per-chain shape and partial-state behavior of `/v0/metrics` — are documented on each endpoint under [Endpoints](/api/production/auth/token).

## Filtering list endpoints

`GET /v0/accounts`, `GET /v0/routes`, and `GET /v0/transactions` accept filters alongside `cursor` and `limit`. The grammar is the same on all three:

* **Filters combine with AND.** Every filter you send must hold for a record to appear.
* **Multi-value filters take one comma-separated parameter**: `?network=base,arbitrum`, not a repeated `?network=base&network=arbitrum`, which is rejected.
* **Date ranges use dotted bounds**: `.gte` / `.gt` for the lower bound, `.lte` / `.lt` for the upper, as in `?createdAt.gte=2026-03-01T00:00:00Z&createdAt.lt=2026-04-01T00:00:00Z`. Timestamps are ISO-8601 and must carry a zone (`Z` or an offset). The exclusive bounds let you select a period without naming its last instant.
* **A filter is never silently dropped.** An unknown parameter, an unknown range operator, a value outside the accepted set, an empty value, two bounds on the same side, or a range nothing can satisfy all return `400 parameter_invalid` with the offending parameter named in `context.issues`.

A filter that is valid but matches nothing returns `200` with an empty `data` array.

## Errors

Errors share a common JSON shape with a stable `code`, a human-readable `message`, and a `docs_url`. Triggered rate limits return `429 rate_limit_exceeded` with a `Retry-After` header. See the [Error Reference](/api/production/errors) for the full code list, the `401` reason taxonomy, and handling guidance.