API reference

Rates and currencies

Exchange rates, the currency registry, and the payment-method and reward catalogues.

Exchange rates

POST/api/info/rates
API key200 OK

A rate is how many units of currency_to one unit of currency_from buys.

currency_from in the response lists only the currencies actually returned. A currency whose rate is missing or stale is dropped from both the list and rates rather than failing the request. The exception is currency_to itself: if its rate is stale the whole call is 503 rate_unavailable.

Staleness limits are 900 s for crypto and 14400 s for fiat — fiat providers publish daily, so a single short limit would mark every fiat rate stale most of the time. Results are served from a 5-second process cache.

Parameters

currency_tocurrency codeRequired

Quote currency.

currency_fromcomma-separated

Comma-separated codes. Omitted returns every currency. Unrecognised entries are dropped silently here rather than rejected.

Returns

200 OK. Rates for the requested currencies.

3 attributes
currency_fromarray of strings

Only the currencies actually returned.

currency_tostring
ratesmap

Errors

parameter_invalid400

A parameter is present but fails validation.

currency_not_found400

The currency code does not exist, or has no usable rate.

rate_unavailable503

A price feed is stale, so the request is refused rather than priced off an old rate. Retry shortly.

Request
curl https://anonpay.org/api/info/rates \
  -H "Authorization: Bearer $APA_KEY" \
  -d currency_to=usd \
  -d currency_from=btc,xmr,usdt-erc20
import os
import requests

KEY = os.environ["APA_KEY"]

response = requests.post(
    "https://anonpay.org/api/info/rates",
    headers={"Authorization": f"Bearer {KEY}"},
    data={
        "currency_to": "usd",
        "currency_from": "btc,xmr,usdt-erc20",
    },
    timeout=30,
)
print(response.json())
const url = "https://anonpay.org/api/info/rates";

const response = await fetch(url, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.APA_KEY}` },
  body: new URLSearchParams({
    currency_to: "usd",
    currency_from: "btc,xmr,usdt-erc20",
  }),
});
console.log(await response.json());
$url = 'https://anonpay.org/api/info/rates';
$key = getenv("APA_KEY");

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"],
    CURLOPT_POSTFIELDS => http_build_query([
        "currency_to" => 'usd',
        "currency_from" => 'btc,xmr,usdt-erc20',
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
Response200 OK
{
  "status": "success",
  "currency_from": [
    "btc",
    "xmr",
    "usdt-erc20"
  ],
  "currency_to": "usd",
  "rates": {
    "btc": "95210.4",
    "xmr": "162.88",
    "usdt-erc20": "1"
  }
}

The currency registry

POST/api/info/currencies
API key200 OK

The only endpoint without a status envelope: it returns the currency map directly.

theoretical is the ledger precision and the cap on decimals accepted in an amount; practical is what buyers are quoted in payment.topay.

Readable with any valid seller key. The registry is the same for everyone, so cache it, and filter on selectable for anything a buyer sees.

Returns

200 OK. The currency registry. No status envelope — a bare map, as it has always been.

1 attributes
{key}object
9 child attributes
namestring

Human-readable name.

theoreticalinteger

Ledger precision, and the cap on decimals accepted in an amount.

practicalinteger

Decimals quoted to buyers in payment.topay.

kindstring

A coin on its own chain, a token on another chain, or a fiat currency.

nativetokenfiat
chainstring or null

The chain a token lives on. Null for native coins and fiat.

erc20splbep20trc20
confirmationsinteger or null

Confirmations required before a crypto payment counts. Null for fiat.

statusstring

A paused or retired currency is still returned — historical transactions name it and must keep resolving — but must not be offered for new payments. Filter on selectable, not on this, for anything buyer-facing.

enabledpausedretired
selectableboolean

Whether this currency may be offered for new payments: false for paused and retired. Branch on this rather than on status.

explorer_urlstring or null

Block-explorer template with a {txid} placeholder, or null.

Request
curl https://anonpay.org/api/info/currencies \
  -H "Authorization: Bearer $APA_KEY"
import os
import requests

KEY = os.environ["APA_KEY"]

response = requests.post(
    "https://anonpay.org/api/info/currencies",
    headers={"Authorization": f"Bearer {KEY}"},
    timeout=30,
)
print(response.json())
const url = "https://anonpay.org/api/info/currencies";

const response = await fetch(url, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.APA_KEY}` },
});
console.log(await response.json());
$url = 'https://anonpay.org/api/info/currencies';
$key = getenv("APA_KEY");

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"],
    CURLOPT_POSTFIELDS => http_build_query([
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
Response200 OK
{
  "btc": {
    "name": "Bitcoin",
    "theoretical": 8,
    "practical": 8,
    "kind": "native",
    "chain": null,
    "confirmations": 6,
    "status": "enabled",
    "selectable": true,
    "explorer_url": "https://mempool.space/tx/{txid}"
  },
  "usdt-erc20": {
    "name": "Tether",
    "theoretical": 6,
    "practical": 3,
    "kind": "token",
    "chain": "erc20",
    "confirmations": 20,
    "status": "enabled",
    "selectable": true,
    "explorer_url": "https://etherscan.io/tx/{txid}"
  },
  "usd": {
    "name": "US Dollar",
    "theoretical": 2,
    "practical": 2,
    "kind": "fiat",
    "chain": null,
    "confirmations": null,
    "status": "enabled",
    "selectable": true,
    "explorer_url": null
  }
}

Currencies and payment methods in one call

POST/api/info/catalogue
API key200 OK

Everything a storefront needs to render payment options: the whole currency registry plus the platform's payment-method catalogue, in one cacheable read. Readable with any valid key.

Retired methods and paused currencies are included, because historical transactions still name them and still have to render. Branch on selectable for anything a buyer will see.

payment_methods is the platform's view: selectable there means the platform offers the method, not that you enabled it. Your own effective statuses are in payment_method_info on /api/user/info.

Each method names a group, resolved through payment_method_groups on the same response: the chain for a token, native for a coin, external for a processor. Render a method whose group is missing from the map rather than dropping it; a new group can appear at any time.

Cache it against version, which every catalogue change bumps.

Returns

200 OK. The currency registry plus the platform's payment-method catalogue.

4 attributes
versioninteger

Catalogue version, bumped by every operator edit. Cache against it: an unchanged value means nothing in here has moved.

currenciesmap
9 child attributes
namestring

Human-readable name.

theoreticalinteger

Ledger precision, and the cap on decimals accepted in an amount.

practicalinteger

Decimals quoted to buyers in payment.topay.

kindstring

A coin on its own chain, a token on another chain, or a fiat currency.

nativetokenfiat
chainstring or null

The chain a token lives on. Null for native coins and fiat.

erc20splbep20trc20
confirmationsinteger or null

Confirmations required before a crypto payment counts. Null for fiat.

statusstring

A paused or retired currency is still returned — historical transactions name it and must keep resolving — but must not be offered for new payments. Filter on selectable, not on this, for anything buyer-facing.

enabledpausedretired
selectableboolean

Whether this currency may be offered for new payments: false for paused and retired. Branch on this rather than on status.

explorer_urlstring or null

Block-explorer template with a {txid} placeholder, or null.

payment_methodsmap
7 child attributes
namestring

Human-readable display name.

kindstring

How the method settles: crypto mints a receiving address, external is settled off-platform (PayPal). This is the METHOD's kind, which is not a currency's native/token/fiat.

cryptoexternal
currencystring or null

The currency this method settles in, or null when the seller's own configuration decides — a PayPal account names its own currency.

statusstring
enabledpausedretired
selectableboolean

Whether the PLATFORM currently offers it. A seller may still have switched it off; combine with payment_methods from /api/user/info, or read that endpoint's payment_method_info, which already has.

sort_orderinteger

The operator's display order. Render in it rather than alphabetically.

groupstring or null

The method group this belongs to, keyed into payment_method_groups on the same response — the chain for a token, native for a coin whose chain is its own, external for a processor. Lets a storefront section sixty-odd methods without keeping a chain table of its own. Null only if the operator has not grouped it.

payment_method_groupsmap

Every group payment_methods[].group can name. A method whose group is absent here should be rendered rather than dropped.

2 child attributes
namestring

Human-readable group name.

sort_orderinteger

The operator's display order for the groups themselves.

Request
curl https://anonpay.org/api/info/catalogue \
  -H "Authorization: Bearer $APA_KEY"
import os
import requests

KEY = os.environ["APA_KEY"]

response = requests.post(
    "https://anonpay.org/api/info/catalogue",
    headers={"Authorization": f"Bearer {KEY}"},
    timeout=30,
)
print(response.json())
const url = "https://anonpay.org/api/info/catalogue";

const response = await fetch(url, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.APA_KEY}` },
});
console.log(await response.json());
$url = 'https://anonpay.org/api/info/catalogue';
$key = getenv("APA_KEY");

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"],
    CURLOPT_POSTFIELDS => http_build_query([
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
Response200 OK
{
  "status": "success",
  "version": 7,
  "currencies": {
    "btc": {
      "name": "Bitcoin",
      "theoretical": 8,
      "practical": 8,
      "kind": "native",
      "chain": null,
      "confirmations": 6,
      "status": "enabled",
      "selectable": true,
      "explorer_url": "https://mempool.space/tx/{txid}"
    }
  },
  "payment_methods": {
    "btc": {
      "name": "Bitcoin",
      "kind": "crypto",
      "currency": "btc",
      "status": "enabled",
      "selectable": true,
      "sort_order": 10,
      "group": "native"
    },
    "ppl": {
      "name": "PayPal",
      "kind": "external",
      "currency": null,
      "status": "enabled",
      "selectable": true,
      "sort_order": 900,
      "group": "external"
    }
  },
  "payment_method_groups": {
    "native": {
      "name": "Native coins",
      "sort_order": 0
    },
    "erc20": {
      "name": "Ethereum (ERC-20)",
      "sort_order": 10
    },
    "external": {
      "name": "External processors",
      "sort_order": 50
    }
  }
}

The reward catalogue

POST/api/info/rewards
API key200 OK

What /api/user/rewards/claim pays and requires: the amount, the currency, the window in seconds from account creation, and the withdrawable-USD floor each reward checks. Readable with any valid key.

A disabled reward is listed with enabled: false rather than omitted, because claiming it is 400 parameter_invalid rather than 422 requirements_not_met.

Returns

200 OK. The reward catalogue, as the claim endpoint enforces it.

1 attributes
rewardsmap
5 child attributes
amountdecimal string
currencystring
expires_secondsinteger

Claimable until created + expires_seconds, where created is on the profile.

min_usddecimal string

Withdrawable-USD floor this reward checks, "0" when it has none. What requirements_not_met is measured against.

enabledboolean

False means claiming it answers 400 parameter_invalid, not requirements_not_met.

Request
curl https://anonpay.org/api/info/rewards \
  -H "Authorization: Bearer $APA_KEY"
import os
import requests

KEY = os.environ["APA_KEY"]

response = requests.post(
    "https://anonpay.org/api/info/rewards",
    headers={"Authorization": f"Bearer {KEY}"},
    timeout=30,
)
print(response.json())
const url = "https://anonpay.org/api/info/rewards";

const response = await fetch(url, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.APA_KEY}` },
});
console.log(await response.json());
$url = 'https://anonpay.org/api/info/rewards';
$key = getenv("APA_KEY");

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"],
    CURLOPT_POSTFIELDS => http_build_query([
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
Response200 OK
{
  "status": "success",
  "rewards": {
    "transactioncreate": {
      "amount": "1",
      "currency": "usdt-erc20",
      "expires_seconds": 432000,
      "min_usd": "0",
      "enabled": true
    },
    "exchange100": {
      "amount": "12",
      "currency": "usdt-erc20",
      "expires_seconds": 432000,
      "min_usd": "100",
      "enabled": false
    }
  }
}