# Meta (/reference/meta)

## Verify a key and see what it can do

`GET /v1/ping`

### Responses

- `200` — Key context.
  - `object` (optional, string)
  - `tenant_id` (optional, string (uuid))
  - `tenant_slug` (optional, string)
  - `key_id` (optional, string | null) — The key's PUBLIC display handle — its prefix plus the first 8 hex of its body (`mp3f9c1a77`). Safe to log. It is not the whole key and cannot be used to authenticate.
  - `env` (optional, string | null, one of: live, test, null)
  - `kind` (optional, string | null, one of: checkout, payout, wallet, null) — What this key may reach, before scopes narrow it further: `checkout` = invoices and hosted checkout, `payout` = money out, `wallet` = customers, deposit addresses, deposits, balances and sweeps. Fixed at creation; a route that refuses the kind answers `403 wrong_key_kind`.
  - `scopes` (optional, array, of string)
  - `signing_enabled` (optional, boolean) — false means this key cannot move funds, whatever its scopes say. True only when ALL THREE of the service, the project and the key have signing on — the same condition `POST /v1/payouts` enforces.
  - `signing_blocked_by` (optional, array, of string, one of: service, project, key) — Empty when `signing_enabled` is true. Otherwise names which level is off, so you know what to ask for: `service` = the operator's global kill switch, `project` = your tenant, `key` = this specific key.
  - `network` (optional, string, one of: mainnet, testnet)
  - `enabled_chains` (optional, array, of string, one of: ethereum, bsc, polygon, arbitrum, base, avalanche, tron, solana, ton, bitcoin, dogecoin, optimism, linea, zksync, scroll) — Every chain the platform serves your project — invoices, hosted checkout, your own wallet, payouts and conversions use all of these.
  - `wallet_chains` (optional, array, of string, one of: ethereum, bsc, polygon, arbitrum, base, avalanche, tron, solana, ton, bitcoin, dogecoin, optimism, linea, zksync, scroll) — The chains you have switched on for the wallet service (`PUT /v1/merchant/chains`): where `POST /v1/wallets` may issue a customer deposit address.
  - `payout_auto_approve_usd` (optional, string) — A payout worth this many USD or less is queued for signing straight away; above it, MolnPay reviews it first. Decimal string. Resolved from your plan unless an explicit ceiling is set on your account, where `0.00` means every payout is reviewed.
- `401` — Missing, malformed, expired or revoked API key.
- `403` — The key lacks the scope, its IP allowlist rejected the source, or signing is disabled.
- `429` — Rate limit or quota exceeded. Honour `Retry-After`.
- `500` — Unexpected error.
- `503` — A dependency is unavailable. Retryable with backoff.

## Supported chains, assets and their decimals

`GET /v1/chains`

Read `decimals` from here rather than hardcoding. `decimals_differ_from_default` flags the assets whose scale deviates (USDT/USDC on BSC are 18, not 6).

### Responses

- `200` — Chains.
  - `object` (required, string)
  - `data` (required, array)
  - `has_more` (required, boolean)
  - `next_cursor` (optional, string | null) — Opaque. Pass as `cursor` for the next page. Do not construct or parse it.
  - `data` (optional, array)
    - `chain` (optional, string, one of: ethereum, bsc, polygon, arbitrum, base, avalanche, tron, solana, ton, bitcoin, dogecoin, optimism, linea, zksync, scroll)
    - `name` (optional, string)
    - `network_type` (optional, string)
    - `chain_id` (optional, integer | null)
    - `native_currency` (optional, object)
      - `name` (optional, string)
      - `symbol` (optional, string)
      - `decimals` (optional, integer)
    - `required_confirmations` (optional, integer)
    - `explorer_url` (optional, string)
    - `enabled_for_tenant` (optional, boolean)
    - `account_kind` (optional, string, one of: contract, eoa) — What a NEW deposit address on this chain is. `contract` = a keyless smart account on the MolnPay factory (one address shared by every EVM chain listed with `contract`); `eoa` = a keypair held by the signer. Keypair chains are listed only when the operator has switched them on.
    - `status` (optional, string, one of: live, paused, coming_soon) — Platform-wide. `paused` is temporary (an incident); `coming_soon` is listed so you can see it is on the way. A hidden chain is simply absent from this list.
    - `status_note` (optional, string | null) — The operator's note on why the chain is not issuing, when it is not. Show it verbatim.
    - `deposits_enabled` (optional, boolean) — Chain-level: may `POST /v1/wallets` derive a NEW address here right now? The per-asset flag below is ANDed with this. An address you already hold is always returned, whatever this says.
    - `payouts_enabled` (optional, boolean) — Chain-level: may a NEW payout be requested on this chain right now?
    - `supports_memo` (optional, boolean) — When true, deposits without the memo cannot be attributed.
    - `assets` (optional, array)
      - `symbol` (optional, string)
      - `decimals` (optional, integer)
      - `contract` (optional, string | null)
      - `is_native` (optional, boolean)
      - `deposits_enabled` (optional, boolean) — May a NEW deposit address be issued, or a quote made, for this asset? Chain and asset switches combined.
      - `payouts_enabled` (optional, boolean) — May this asset be chosen for a NEW payout? Chain and asset switches combined.
      - `decimals_differ_from_default` (optional, boolean) — true where this asset's scale deviates from its usual one — currently USDT and USDC on BSC (18, not 6).
- `401` — Missing, malformed, expired or revoked API key.
- `403` — The key lacks the scope, its IP allowlist rejected the source, or signing is disabled.
- `429` — Rate limit or quota exceeded. Honour `Retry-After`.
- `500` — Unexpected error.
- `503` — A dependency is unavailable. Retryable with backoff.

## Every coin in the catalogue, including the ones not live yet

`GET /v1/coins`

The platform's BREADTH, for a page that wants to show it. Unlike `GET /v1/chains`, which lists only what you may act on now, this includes coins that are switched off — each one carries `live: false`. Do not build a payment picker on this endpoint; use `GET /v1/chains` for that, or you will offer a coin the next call refuses. The catalogue is read at MAINNET whichever mode your key is in, because "what do you carry" has one answer — a test key sees the whole list here and `GET /v1/chains` tells it what it can actually transact with. Ordered `live` first, then by market rank with natives ahead of tokens — so the first rows are coins you can use today AND the ones people recognise. `totals` is computed over the WHOLE catalogue, before `chain` and before `limit`.

### Parameters

- `limit` (query, optional, integer) — How many coins to return. The totals are unaffected.
- `filter` (query, optional, string, one of: all, live) — `live` returns only the coins the platform services today.
- `chain` (query, optional, string, one of: ethereum, bsc, polygon, arbitrum, base, avalanche, tron, solana, ton, bitcoin, dogecoin, optimism, linea, zksync, scroll) — One network's coins. `totals` still covers every network.
- `group` (query, optional, string, one of: symbol, contract) — `symbol` collapses a coin carried on several networks into one row with a `chains` count — right for a wall of logos. `contract` returns every deployment, which is what a per-network table wants.

### Responses

- `200` — The catalogue.
  - `object` (optional, string, one of: coin_list)
  - `totals` (optional, object)
    - `coins` (required, integer) — (chain, symbol) pairs — CONTRACTS. USDC on Ethereum and USDC on Base count twice.
    - `live` (required, integer) — How many of those are usable today.
    - `symbols` (required, integer) — Distinct tickers. The honest figure for `how many coins`.
    - `chains` (required, integer)
    - `chains_live` (required, integer)
    - `by_chain` (required, object) — Per network: `{ coins, live }`. So a networks table can print each row's count without pulling the whole catalogue to count it.
  - `returned` (optional, integer)
  - `data` (optional, array)
    - `chain` (required, string, one of: ethereum, bsc, polygon, arbitrum, base, avalanche, tron, solana, ton, bitcoin, dogecoin, optimism, linea, zksync, scroll) — With `group=symbol` (the default) this is the coin's BEST-RANKED deployment, not its only one — see `chains`. With `group=contract` it is the row's own network.
    - `chain_name` (required, string)
    - `chains` (required, integer) — How many networks carry this coin. Always 1 under `group=contract`. Greater than 1 means `chain`, `contract` and `decimals` describe ONE of several deployments — re-query with `group=contract` to get them all.
    - `symbol` (required, string)
    - `name` (optional, string | null) — The coin's full name where the catalogue has one, e.g. `PayPal USD`.
    - `contract` (optional, string | null) — null for a chain's native coin. Belongs to `chain` — under `group=symbol` that is one deployment of several when `chains` > 1.
    - `decimals` (required, integer) — This deployment's scale, which is NOT a property of the ticker: USDT is 6 on Ethereum and 18 on BSC. Under `group=symbol` it is the representative deployment's.
    - `is_native` (required, boolean)
    - `logo_url` (optional, string | null) — A logo you may render directly. Third-party art on a public CDN — treat it as decoration and fall back to your own placeholder if it fails to load.
    - `deposits_enabled` (optional, boolean) — The coin's own deposit switch, before the chain's is folded in.
    - `payouts_enabled` (optional, boolean) — The coin's own payout switch, before the chain's is folded in.
    - `decimals_differ_from_default` (optional, boolean) — This deployment's scale deviates from the symbol's usual one (USDT/USDC on BSC are 18, not 6).
    - `live` (required, boolean) — Is the PLATFORM servicing it today? The chain's switches and the coin's, combined. `false` means no new deposit address and no quote — NOT that a transfer to an address you already hold would be ignored; money sent to an address we issued is still credited. On a TEST key this still describes the platform: use `GET /v1/chains` for what a test project may act on.
- `401` — Missing, malformed, expired or revoked API key.
- `403` — The key lacks the scope, its IP allowlist rejected the source, or signing is disabled.
- `429` — Rate limit or quota exceeded. Honour `Retry-After`.
- `500` — Unexpected error.
- `503` — A dependency is unavailable. Retryable with backoff.

## Live USD prices for the assets we settle in

`GET /v1/market/prices`

Public and unauthenticated — exchange rates are not tenant data, and the hosted checkout needs them before any session exists. Prices are cached for `ttl_seconds`; respect it rather than polling. `usd` is a STRING, like every other amount in this API. `age_seconds` says how old the quote is: past `ttl_seconds` we serve the cached price immediately and refresh behind the response, so a value older than the TTL is expected and is not an error. When the upstream market source is not configured the response is a 503 with `configured: false` and an empty list — callers should render whatever they last had rather than treat it as an error.

### Parameters

- `symbols` (query, optional, string) — Comma-separated symbols, e.g. `USDT,ETH`. Omit for all priced assets.

### Responses

- `200` — Prices.
  - `object` (required, string, one of: price_list)
  - `configured` (required, boolean)
  - `ttl_seconds` (optional, integer)
  - `data` (required, array)
    - `symbol` (required, string)
    - `usd` (required, string) — Decimal string, never a number.
    - `age_seconds` (required, integer) — Seconds since this price was fetched upstream.
- `503` — The market source is not configured.

## Whether live pricing is available

`GET /v1/market/status`

Public. Lets a caller hide price-dependent UI rather than render an empty figure.

### Responses

- `200` — Status.
  - `object` (required, string, one of: market_status)
  - `configured` (required, boolean)
  - `base_url` (optional, string)