API reference

Transactions

A transaction is one request for payment. Create it with your key, send the buyer to its checkout, and it settles on its own. Webhooks tell you when.

Create a transaction

POST/api/transaction/create
API keyIdempotent201 Created

Creates a pending transaction and returns the id the checkout uses plus a private_key that is both the cancellation credential and the webhook signing secret. private_key is returned exactly once here — store it.

A transaction expires 24 hours after it is created; that is not configurable.

The amount is checked in USD: it must be worth at least 0.1 USD and at most 1,000,000 USD. If the rate that check needs is stale, the request fails with 503 rate_unavailable rather than pricing off an old number.

Parameters

amountdecimal string

Price, denominated in currency. Omit for an open-ended transaction. Must be greater than zero and must not exceed the currency's theoretical precision.

currencycurrency code

Denomination of amount — not what the buyer pays in. Required whenever amount is sent.

allowed_payment_methodscomma-separated

Comma-separated allowlist restricting what the buyer may choose. Every entry must exist in the seller's payment_methods. Maximum 25 entries.

webhookURL

Event destination. http/https only, no embedded credentials, and the host must resolve to a public address.

Up to 2,048 characters.
deposit0 or 1

1 creates a deposit transaction — amount and currency are forced to null and settled funds land as a deposit rather than revenue.

idempotency_keystring

Makes a retry safe. Scoped to (your key, method, path, sorted parameters, this value). Honoured on POST/PUT/PATCH/DELETE only; ignored on GET. Server errors and 429s are never cached.

Returns

201 Created. Transaction created.

3 attributes
transaction_iduid
private_keyuid

Returned exactly once. Cancellation credential and webhook signing secret.

expiresunix time

Errors

parameter_missing400

A required parameter is missing or empty. Also the answer when no API key is sent at all.

parameter_invalid400

A parameter is present but fails validation.

currency_not_found400

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

request_in_progress409

A request with the same idempotency_key is still running.

transaction_amount_must_be_over_{limit}_{currency}422

The transaction is worth less than the minimum. The slug names the limit, as in transaction_amount_must_be_over_0.1_usd; match on the prefix.

transaction_amount_must_be_under_{limit}_{currency}422

The transaction is worth more than the maximum. Match on the prefix.

invalid_payment_method422

That method is not allowed on this transaction, or is not on your account.

idempotency_key_reused_with_different_parameters422

That idempotency_key was already used for a request with different parameters.

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/transaction/create \
  -H "Authorization: Bearer $APA_KEY" \
  -d amount=20 \
  -d currency=usd \
  -d allowed_payment_methods=btc,xmr,usdt-erc20 \
  -d webhook=https://seller.example/hooks/apa \
  -d idempotency_key=2c9a4e7b-8d1f-4a6c
import os
import requests

KEY = os.environ["APA_KEY"]

response = requests.post(
    "https://anonpay.org/api/transaction/create",
    headers={"Authorization": f"Bearer {KEY}"},
    data={
        "amount": "20",
        "currency": "usd",
        "allowed_payment_methods": "btc,xmr,usdt-erc20",
        "webhook": "https://seller.example/hooks/apa",
        "idempotency_key": "2c9a4e7b-8d1f-4a6c",
    },
    timeout=30,
)
print(response.json())
const url = "https://anonpay.org/api/transaction/create";

const response = await fetch(url, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.APA_KEY}` },
  body: new URLSearchParams({
    amount: "20",
    currency: "usd",
    allowed_payment_methods: "btc,xmr,usdt-erc20",
    webhook: "https://seller.example/hooks/apa",
    idempotency_key: "2c9a4e7b-8d1f-4a6c",
  }),
});
console.log(await response.json());
$url = 'https://anonpay.org/api/transaction/create';
$key = getenv("APA_KEY");

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"],
    CURLOPT_POSTFIELDS => http_build_query([
        "amount" => '20',
        "currency" => 'usd',
        "allowed_payment_methods" => 'btc,xmr,usdt-erc20',
        "webhook" => 'https://seller.example/hooks/apa',
        "idempotency_key" => '2c9a4e7b-8d1f-4a6c',
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
Response201 Created
{
  "status": "success",
  "transaction_id": "9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c",
  "private_key": "a3f9d0e1c2b4a6f8e0d2c4b6a8f0e2d4",
  "expires": 1754006400
}

Choose how the buyer pays

POST/api/transaction/setpaymentmethod
No key200 OK

Called by the checkout once the buyer picks a payment method. Returns the payment instructions: a fresh receiving address for crypto, or one of the seller's enabled PayPal accounts. You only need it if you build your own checkout.

Works without a key, because the buyer holds none, and is limited to 60 requests per minute per IP.

A method can be chosen once per transaction: a second call is 409 payment_method_already_set. Calling it on an expired transaction marks the transaction expired.

Parameters

transaction_iduidRequired
payment_methodstringRequired

A currency code (btc, usdt-trc20, …) or ppl.

Returns

200 OK. Payment instructions for the buyer.

1 attributes
paymentobject
10 child attributes
addressstring

Receiving address, or PayPal email.

currencystring

What the buyer actually pays in.

topaydecimal string

Quoted at the currency's practical precision, rounded up so the seller is never short-changed.

paiddecimal string

Observed so far. Updated by the settlement job.

ratedecimal string

transaction-currency → payment-currency, locked in at mint time.

confirmationsinteger or null

Crypto only. -1 means nothing observed yet.

confirmations_neededinteger or null

Crypto only.

overpaiddecimal string

Present only when the buyer paid more than topay.

gsboolean

PayPal only — Goods & Services accepted.

ffboolean

PayPal only — Friends & Family accepted.

Errors

parameter_invalid400

A parameter is present but fails validation.

uid_not_found404

No transaction or withdrawal with that id.

payment_method_already_set409

A payment method was already chosen for this transaction.

transaction_inactive409

The transaction is no longer pending.

invalid_payment_method422

That method is not allowed on this transaction, or is not on your account.

disabled_payment_method422

The seller has switched that payment method off.

payment_method_unavailable422

The platform has paused or retired that payment method.

no_active_paypal_account422

No PayPal account is enabled to receive the payment.

transaction_amount_must_be_over_{limit}_{currency}422

The transaction is worth less than the minimum. The slug names the limit, as in transaction_amount_must_be_over_0.1_usd; match on the prefix.

rate_unavailable503

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

node_unavailable503

The node for that currency is unreachable. Retry shortly.

Request
curl https://anonpay.org/api/transaction/setpaymentmethod \
  -d transaction_id=9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c \
  -d payment_method=btc
import requests

response = requests.post(
    "https://anonpay.org/api/transaction/setpaymentmethod",
    data={
        "transaction_id": "9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c",
        "payment_method": "btc",
    },
    timeout=30,
)
print(response.json())
const url = "https://anonpay.org/api/transaction/setpaymentmethod";

const response = await fetch(url, {
  method: "POST",
  body: new URLSearchParams({
    transaction_id: "9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c",
    payment_method: "btc",
  }),
});
console.log(await response.json());
$url = 'https://anonpay.org/api/transaction/setpaymentmethod';

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_POSTFIELDS => http_build_query([
        "transaction_id" => '9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c',
        "payment_method" => 'btc',
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
Response, crypto200 OK
{
  "status": "success",
  "payment": {
    "address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
    "currency": "btc",
    "topay": "0.00021",
    "paid": "0",
    "rate": "0.0000105",
    "confirmations": -1,
    "confirmations_needed": 6
  }
}
Response, paypal200 OK
{
  "status": "success",
  "payment": {
    "address": "[email protected]",
    "currency": "usd",
    "topay": "20.00",
    "paid": "0",
    "rate": "1",
    "gs": true,
    "ff": false
  }
}

Cancel a pending transaction

POST/api/transaction/cancel
Key optional200 OK

Requires proof of ownership: your API key, or the transaction's private_key. Anything else is 403 not_permitted.

Cancelling is final — nothing revisits a cancelled transaction, so funds already sent to the minted address will not settle. Cancel only what is known to be unpaid.

Parameters

transaction_iduidRequired
private_keyuid

The transaction's private key. An alternative to authenticating with the seller's API key — this is the credential the buyer-facing checkout holds.

Returns

200 OK. Success.

Errors

not_permitted403

Authenticated, but the object belongs to someone else, or current_password was missing or wrong.

uid_not_found404

No transaction or withdrawal with that id.

transaction_inactive409

The transaction is no longer pending.

transaction_already_completed409

The transaction has already completed.

Request
curl https://anonpay.org/api/transaction/cancel \
  -H "Authorization: Bearer $APA_KEY" \
  -d transaction_id=9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c
import os
import requests

KEY = os.environ["APA_KEY"]

response = requests.post(
    "https://anonpay.org/api/transaction/cancel",
    headers={"Authorization": f"Bearer {KEY}"},
    data={
        "transaction_id": "9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c",
    },
    timeout=30,
)
print(response.json())
const url = "https://anonpay.org/api/transaction/cancel";

const response = await fetch(url, {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.APA_KEY}` },
  body: new URLSearchParams({
    transaction_id: "9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c",
  }),
});
console.log(await response.json());
$url = 'https://anonpay.org/api/transaction/cancel';
$key = getenv("APA_KEY");

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"],
    CURLOPT_POSTFIELDS => http_build_query([
        "transaction_id" => '9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c',
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
Response200 OK
{
  "status": "success"
}

Fetch a transaction

POST/api/transaction/info
Key optional200 OK

Without a key, or with a key belonging to a different seller, returns the public view. With the owning seller's key the response also carries private_key and webhook.

A valid but unrelated seller key is not an error — it simply yields the public view.

Parameters

transaction_iduidRequired

Returns

200 OK. The transaction. The public view without the owning seller's key; with it, the response adds private_key and webhook.

1 attributes
transactionobject
16 child attributes
uiduid

The transaction's id. Its checkout is at /checkout/{uid}.

seller_iduid

The seller it belongs to.

statusstring
pending
Waiting for payment. Every transaction starts here.
completed
Paid in full and confirmed. A completed webhook was sent.
cancelled
Cancelled with the seller's key or the transaction's private key. Final.
expired
24 hours passed without full payment.
amount_topaydecimal string or null

The price, in currency. Null for open-ended and deposit transactions.

amount_paiddecimal string or null

Received so far, expressed in currency.

currencystring or null

The unit of amount_topay.

allowed_payment_methodsarray of strings or null

The method codes the buyer may choose from. Null means every method you enabled.

payment_methodstring or null

Null until the buyer chooses.

createdunix time
expiresunix time

24 hours after created.

cancelledunix time or null
completedunix time or null
is_depositinteger

1 for a top-up of your own balance.

01
paymentobject or null

What the buyer pays, and where. Null until a method is chosen.

10 child attributes
addressstring

Receiving address, or PayPal email.

currencystring

What the buyer actually pays in.

topaydecimal string

Quoted at the currency's practical precision, rounded up so the seller is never short-changed.

paiddecimal string

Observed so far. Updated by the settlement job.

ratedecimal string

transaction-currency → payment-currency, locked in at mint time.

confirmationsinteger or null

Crypto only. -1 means nothing observed yet.

confirmations_neededinteger or null

Crypto only.

overpaiddecimal string

Present only when the buyer paid more than topay.

gsboolean

PayPal only — Goods & Services accepted.

ffboolean

PayPal only — Friends & Family accepted.

private_keyuidYour key only

Cancellation credential and webhook signing secret.

webhookstring or nullYour key only

Where this transaction's events are sent.

Errors

uid_not_found404

No transaction or withdrawal with that id.

Request
curl https://anonpay.org/api/transaction/info \
  -H "Authorization: Bearer $APA_KEY" \
  -d transaction_id=9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c
import os
import requests

KEY = os.environ["APA_KEY"]

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

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

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_HTTPHEADER => ["Authorization: Bearer $key"],
    CURLOPT_POSTFIELDS => http_build_query([
        "transaction_id" => '9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c',
    ]),
    CURLOPT_RETURNTRANSFER => true,
]);
$response = json_decode(curl_exec($ch), true);
Response200 OK
{
  "status": "success",
  "transaction": {
    "uid": "9c1f0b7a4e2d8f6a3b5c7d9e1f0a2b4c",
    "seller_id": "4b8e2d0f6a1c3e5b7d9f0a2c4e6b8d0f",
    "status": "completed",
    "amount_topay": "20",
    "amount_paid": "20",
    "currency": "usd",
    "allowed_payment_methods": [
      "btc",
      "xmr",
      "usdt-erc20"
    ],
    "payment_method": "btc",
    "created": 1753919400,
    "expires": 1754005800,
    "cancelled": null,
    "completed": 1753920000,
    "is_deposit": 0,
    "payment": {
      "address": "bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq",
      "currency": "btc",
      "topay": "0.00021",
      "paid": "0.00021",
      "rate": "0.0000105",
      "confirmations": 6,
      "confirmations_needed": 6
    },
    "private_key": "a3f9d0e1c2b4a6f8e0d2c4b6a8f0e2d4",
    "webhook": "https://seller.example/hooks/apa"
  }
}