CryptPays

Discovery

Unsupported or disabled currency

1101 · UNSUPPORTED_CURRENCY

CryptPays cannot resolve the ticker

Symptom
The request returns a standardized 4xx with code 1101.
Likely cause
The ticker or route format is unknown to the current catalog.
Resolution
Call /api/cryptocurrencies and use a canonical ticker returned there. Do not repeatedly retry an invalid ticker.

1102 · CURRENCY_DISABLED

The asset is known but unavailable

Symptom
The request returns a standardized 4xx with code 1102.
Likely cause
The chain or asset is currently disabled.
Resolution
Choose an enabled asset from the live catalog. Do not hardcode availability from an earlier response or static list.

Address identity

Callback address-family conflict

HTTP 409 with code 1202 CALLBACK_ADDRESS_FAMILY_CONFLICT means the exact callback URL already belongs to an incompatible address family.

Common examples
EVM → BTC, BTC → LTC, or SOL → EVM with the same callback URL.
Why it happens
Compatible repeated /create returns the existing immutable configuration; it is not an update endpoint.
Resolution
Use a new unique callback URL for the other family or configuration. Do not try to mutate the existing wallet with another /create call.

See Address Families.

Forwarding option

Unsupported priority

Code 1103 UNSUPPORTED_PRIORITY means the value is syntactically valid but the selected family does not offer that priority behavior.

EVMUse default.
ZECUse default; its ZIP-317 fee model does not expose slow/fast tiers.
TRONUse default.
BTC/LTC/BCH/DOGEslow, default, and fast are supported.
SOL/SPLslow, default, and fast are supported.

Deposit classification

Payment sent, but no callback

A deposit below the current minimum is recorded internally but is not forwarded and produces neither a pending nor confirmed callback.

What to check
Compare the independent deposit with the current decimal-string minimum from /api/{ticker}/info or /api/cryptocurrencies.
Important behavior
Below-minimum deposits are not aggregated. Sending another small amount does not complete the first deposit.
Resolution
Present the current minimum before payment and treat every later qualifying deposit as a separate payment lifecycle.

Delivery

No callback received

  1. Check the deposit.Confirm it meets the current minimum and has reached the required confirmations or finality.
  2. Inspect payment logs.Use the exact ticker and callback URL identity to find the lifecycle and delivery attempts.
  3. Check reachability.The production endpoint must be stable, public, HTTPS, publicly resolvable, and reachable through your firewall or WAF.
  4. Check acknowledgement.Only exact HTTP 200 succeeds; redirects and 201/202/204 responses trigger failure handling.
  5. Check request handling.Preserve raw bytes before body parsing and ensure your proxy does not rewrite the signed host or request target.

Idempotency

Duplicate callback or pending followed by confirmed

Repeated confirmed delivery

A previous request was not acknowledged with HTTP 200, so CryptPays retried the same confirmed snapshot. Fulfill the confirmed UUID only once.

Same UUID, new stage

Pending and confirmed intentionally share one UUID. Allow pending → sent; do not reject confirmed merely because its UUID appeared during pending.

Use persistent lifecycle-aware idempotency, such as the UUID plus stage or an allowed state transition. See UUID and idempotency.

Authentication

Signature mismatch

Compare each cryptographically bound component with the exact canonical request contract.

  • Both signature and timestamp headers are present.
  • The timestamp is numeric and within the absolute 300-second window.
  • The method is uppercase.
  • The hostname is lowercase, with scheme and port excluded.
  • The exact path and query are preserved without rebuilding or reordering.
  • The GET raw body is empty.
  • The POST raw body is captured before JSON or form parsing.
  • The signature is strict base64-decoded.
  • The current key from /api/pubkey is used.
  • Your proxy has not rewritten host, path, query, or percent escapes.

Lifecycle

Pending arrived, confirmed has not

Meaning
Pending is an informational deposit-detection event, not a forwarding guarantee.
What happens next
CryptPays waits for required confirmations/finality and successful payment processing and forwarding.
What to do
Do not fulfill from pending. Inspect /logs and accept confirmed even if the pending delivery previously failed.

Reconciliation

Logs lookup returns no payment

Request GET /api/{ticker}/logs?callback=... using the canonical ticker and the exact callback URL identity stored at creation.

  • Encode the complete callback URL as the callback query value.
  • Preserve its path, trailing slash, query ordering, literal plus signs, and percent escapes.
  • Use the same canonical asset ticker used for the payment lifecycle.
  • Read callbacks[*].uuid to correlate pending, confirmed, retry, and internal delivery state.

See the Payment Logs guide for the request example.

Chain fields

UTXO identity and Solana confirmations

UTXO: use hash plus output index

txid_in is the bare transaction hash and vout is a separate integer. Use (txid_in, vout); do not look for a colon inside txid_in.

Solana: finality is 0 or 1

confirmations=0 means pending/not final and confirmations=1 means confirmed/final. Do not expect 2, 5, 12, or slot distance. A numeric create override does not change this model.

HTTP response

Callback keeps retrying after processing

CryptPays recognizes only exact HTTP 200 as successful acknowledgement. The response body is ignored.

200 + empty bodySuccess
200 + JSONSuccess
200 + *ok*Success because status is 200
201, 202, or 204Failure
302 redirectFailure
500 + *ok*Failure

After a successful 200, /logs may show internal done. Your endpoint receives no separate result=done callback; fulfill on result=sent, pending=0.

Reconciliation

Fee or forwarded amount differs from expectation

/info fee_percent

Generic public tier

Informational default, not necessarily the transaction’s callback-domain or volume tier.

callback fee

Actual percentage

The contracted CryptPays percentage applied to this payment.

callback fee_coin

Total deduction

Commission plus applicable miner, network, gas, and rent-related recovery.

value_coin=value_forwarded_coin+fee_coin

Do not calculate fee_coin as percentage commission alone. Use the confirmed callback’s exact decimal strings for reconciliation.

Price metadata

Price or conversion field confusion

price is a USDT quote, not fiat. With convert=1, conversion fields are JSON-encoded strings whose only currency key is USDT.

JSON fragment
"value_coin_convert": "{\"USDT\":\"100.00\"}"

Decode the field value separately. Other currency keys and multi-fiat output are not currently supported; if no valid confirmed price exists, price and conversion fields are omitted.

Request target

Callback query conflict or proxy rewrite

Merchant query names

Use names such as order_id, invoice_id, or reference. Avoid CryptPays payload field names as custom query keys.

Reverse proxies

Nginx, Cloudflare, load balancers, and other proxies must preserve the original host and exact path/query used for signature verification.

If verification fails, do not decode, sort, normalize, or rebuild the query. Use the server/framework’s original request-target representation.

Escalation

Information to provide to support

Provide enough public transaction context to identify the payment without exposing wallet secrets.

Useful diagnostic context

  • Canonical ticker
  • Callback URL or merchant reference
  • Callback UUID, if available
  • txid_in and UTXO vout
  • Approximate timestamp
  • Observed callback HTTP response status

Never provide

  • Seed or recovery phrase
  • Private key or extended private key
  • Passwords or bearer credentials
  • Production signing secrets