Skip to main content
The Compatibility API is enabled per merchant on request — contact support before switching traffic. See Migrate from another provider.
Paw emulates both CoinPayments APIs. Point an existing CoinPayments integration at Paw by changing only the base URL.

Base URLs

The v2 SDK appends fixed paths (/api/v2/merchant/invoices, …) to the base URL, so use exactly the base URL above — the request signature covers the full URL.

Authentication

No separate credentials are configured. The public identifiers (legacy public key, v2 client id) are your Paw merchant ID; the secrets (legacy private key and IPN secret, v2 client secret) are your Paw merchant api_key. The api_key is only used to sign and is never sent in a request or webhook. Legacy v1 keeps the classic signing: v2 REST keeps the signed-header scheme: Payout commands require the caller IP address to be present in the merchant’s payout IP whitelist.

Supported

Legacy v1 (POST .../api.php, dispatched by cmd):
  • Payments: create_transaction, get_tx_info, get_tx_info_multi, get_callback_address
  • Account: rates, balances, get_basic_info
  • Payouts: create_withdrawal, create_mass_withdrawal
v2 REST:
  • Invoices: create (POST /api/v2/merchant/invoices), get, list, cancel
  • Buyer checkout: GET /api/v1/invoices/{id}/payment-currencies/{currency} (and /status) — anonymous. It picks the payment currency of an open invoice once (respecting the invoice’s accepted/excluded coins); asking for a different currency after one is picked returns 409. To let the buyer switch currencies, send them to the invoice payment_url.
  • Catalogue: GET /api/v1|v2/currencies, GET /api/v1/rates — anonymous

Currency codes

  • Legacy v1 uses dotted codes: BTC, LTC, USDT.TRC20, USDC.BEP20, BNB.BSC.
  • v2 uses numeric ids: fiat USD = 5057, EUR = 5195; crypto BTC = 1, ETH = 4, TRX = 9; tokens id:contract (e.g. 9:TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t = USDT.TRC20).

Not Supported

These return a CoinPayments-shaped error ({"error": "..."} for v1):
  • Conversions: convert_coins, get_conversion_limits
  • Internal transfers / PayByName: create_transfer, get_pbn_info
  • Personal wallet addresses: get_deposit_address
  • v2 payouts (the wallet-centric wallets/{id}/spend/* flow). Use the legacy v1 create_withdrawal / create_mass_withdrawal for payouts.

Idempotency

  • create_mass_withdrawal: each wd[<key>] map key is treated as the idempotency key — re-sending the same key returns the existing payout, and reusing a key with different data is rejected.
  • create_withdrawal: the legacy single withdrawal has no client idempotency key, so Paw derives one from the request body. Identical retries (same address, amount, currency, callback, note) collapse onto one payout — which protects against double-submit and timeout retries — but two genuinely distinct withdrawals with identical fields would also collapse. Prefer create_mass_withdrawal with explicit keys when you need to send identical amounts.

Webhooks / IPN

Invoices created through /compat/coinpayments/v1/... send a legacy IPN: a form-encoded body with numeric status codes (0 waiting, 1 pending, 100 complete, -1 cancelled/timed-out) and an HMAC header (HMAC-SHA512 over the raw body, keyed by api_key). Invoices created through /compat/coinpayments/api/v2/... send a v2 webhook: a JSON body { "id", "type", "timestamp", "invoice" } with the X-CoinPayments-Client (your merchant ID), X-CoinPayments-Timestamp, and X-CoinPayments-Signature headers. The signature uses the same HMAC-SHA256 scheme as API requests, computed over the delivery URL — so the CoinPayments SDK’s verifyWebhook(method, url, ...) accepts it unchanged.