Phoenix Pay
Getting Started

Quickstart

Create your first deposit with Phoenix Pay in 5 minutes.

This guide walks you through making your first payment with Phoenix Pay. By the end, you'll have created a deposit and set up webhook verification.

Prerequisites: You need an Ed25519 key pair and a registered public key in the Phoenix Pay admin dashboard. See Authentication if you haven't set this up yet.

Generate and Register Your Key

Generate an Ed25519 key pair locally (see Authentication for platform-specific instructions), then upload your public key in the admin dashboard. You'll receive a Key ID to include in every request.

Create Your First Deposit

Every request requires three auth headers: X-Key-Id, X-Timestamp, and X-Signature. The signature is computed over "{timestamp}.{request_body}".

Create a crypto deposit
TIMESTAMP=$(date +%s)
BODY='{"reference_id":"order-12345","amount":5000,"currency":"USDT","channel":"crypto_address"}'

curl -X POST https://pay.phoenixverse.io/api/deposits \
  -H "Content-Type: application/json" \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $TIMESTAMP" \
  -H "X-Signature: $(echo -n "${TIMESTAMP}.${BODY}" | openssl pkeyutl -sign -inkey private.pem | base64)" \
  -d "$BODY"
Response (201 Created)
{
  "intent_id": "01912e4a-7b3c-7def-8a90-1234567890ab",
  "action": "await",
  "message": "Send payment to TXrk4d5x7Bj3e6g7Y8Zw...",
  "pay_address": "TXrk4d5x7Bj3e6g7Y8Zw9AbCdEf1234567",
  "pay_currency": "usdttrc20",
  "pay_amount": 50.0,
  "expires_at": "2026-03-11T14:30:00Z"
}

The response tells you what to do via the action field:

ActionWhat to Do
await + pay_addressDisplay the crypto address and amount to your user
redirect + urlRedirect the user to the checkout URL
collect + collectShow a form (e.g., OTP input) and submit via the step endpoint
completedPayment already done — update your records

Amount format: 5000 means 5000 cents = 50.00 USDT. Amounts are always in the smallest currency unit.

Receive Webhooks

Phoenix Pay sends Ed25519-signed webhooks to your callback URL when payment status changes.

Webhook payload
{
  "event": "payment.status_changed",
  "intent_id": "01912e4a-7b3c-7def-8a90-1234567890ab",
  "reference_id": "order-12345",
  "type": "deposit",
  "status": "completed",
  "amount": 5000,
  "currency": "USDT",
  "channel": "crypto_address",
  "timestamp": "2026-03-11T12:45:00Z"
}

Verify the signature using Phoenix Pay's public key from GET /api/.well-known/signing-key. See Webhooks for full verification examples.

Your webhook endpoint must respond with a 2xx status within 10 seconds. Phoenix Pay retries up to 3 times with backoff (5s, 30s, 3min).

Poll for Status (Optional)

As a fallback to webhooks, poll the payment status at any time:

Get deposit by ID
curl https://pay.phoenixverse.io/api/deposits/01912e4a-7b3c-7def-8a90-1234567890ab \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $(date +%s)" \
  -H "X-Signature: <signature>"
Get deposit by reference ID
curl https://pay.phoenixverse.io/api/deposits/ref/order-12345 \
  -H "X-Key-Id: your-key-id" \
  -H "X-Timestamp: $(date +%s)" \
  -H "X-Signature: <signature>"

Phoenix Pay also runs background sync every 5 minutes, catching any missed PSP webhooks automatically.

Next Steps