A clean REST API for crypto payment infrastructure.
Create invoices and payment links, accept crypto, reconcile via webhooks, and pay out — all through a small REST surface with scoped keys, IP allow-listing, idempotency and rate limits.
Create your first invoice in 60 seconds.
Generate a test key in Merchant → Developers → API Keys, then create an invoice. The response contains a hosted checkout URL you can redirect customers to.
curlcurl -X POST https://api.xynex.app/v1/invoices \ -H "Authorization: Bearer cp_test_xxxxxxxxxxxxxxxx" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: $(uuidgen)" \ -d '{ "reference": "order-1042", "amount": 49.00, "currency": "usd", "customer": { "email": "buyer@example.com" } }'
response{ "data": { "id": "inv_01HX…", "public_id": "in_01HX…", "reference": "order-1042", "amount": 49, "currency": "usd", "status": "pending", "checkout_url": "https://xynex.app/checkout/abc123", "expires_at": "2026-06-06T12:00:00Z", "created_at": "2026-06-06T11:00:00Z" } }
Authentication, scopes and limits.
Every request must include a Bearer token. Test keys are prefixed cp_test_ and live keys cp_live_. Keys never leave the browser on creation — the plaintext is shown once.
Scopes
Each key carries an explicit list of scopes — e.g. invoices.write, payouts.read. Requests outside a key's scopes return 403 insufficient_scope. Use * only for trusted server keys.
IP allow-list
Optionally restrict a key to specific IPs or CIDR ranges. Requests from outside the allow-list return 403 ip_not_whitelisted and are recorded in your access denial log.
Rate limits
Configurable per key (1–600 / min, default 60). Every response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. 429s include Retry-After.
Idempotency
Pass an Idempotency-Key header on POSTs. The first response is cached for 24h; replays return the original body with Idempotent-Replayed: true.
Endpoint reference.
All endpoints are JSON, all writes accept an optional idempotency key, all responses include X-Request-Id for support correlation.
Invoices
- POST/invoicesCreate an invoice + hosted checkout URL
- GET/invoices/{id}Retrieve an invoice and its payment state
Payments
- GET/paymentsList payments, filtered by status / date
- GET/payments/{id}Retrieve a single payment
Payment links
- POST/payment-linksCreate a shareable payment link
Payouts
- POST/payoutsCreate a single crypto payout
- POST/payouts/batchSubmit a mass payout batch
- GET/payouts/{id}Retrieve a payout
Refunds
- POST/refundsIssue a refund against a settled payment
Balances
- GET/balancesList available + held balances per coin
Beneficiaries
- GET/beneficiariesList saved payout beneficiaries
- POST/beneficiariesCreate a beneficiary
- DELETE/beneficiaries/{id}Delete a beneficiary
Subscriptions
- POST/subscription-plansCreate a plan
- POST/subscriptionsCreate a subscription
- GET/subscriptions/{id}Retrieve a subscription
Reference
- GET/coinsSupported coins / networks
- POST/fees/previewPreview fees for a payout or invoice
Error envelope and status codes.
Errors share a single envelope. request_id is also returned as the X-Request-Id header.
json{ "error": "validation_failed", "message": "amount must be greater than 0", "issues": [{ "path": ["amount"], "message": "Number must be > 0" }], "request_id": "f47ac10b-58cc-…" }
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | Malformed body or query parameters |
| 401 | unauthorized | Missing or invalid bearer token |
| 403 | insufficient_scope / ip_not_whitelisted / plan_feature_disabled | Key lacks scope, caller IP not in allow-list, or plan does not include this endpoint |
| 404 | not_found | Resource does not exist or is not visible to this merchant |
| 422 | validation_failed | Schema-level rejection (Zod issues array included) |
| 429 | rate_limited | Per-minute quota exhausted; see X-RateLimit-Reset / Retry-After |
| 500 | internal_error | Unexpected server error; include request_id in support tickets |
Webhooks and signature verification.
Configure HTTPS endpoints under Merchant → Developers → Webhooks. Every delivery is HMAC-SHA256 signed using your endpoint secret. Always verify the signature with a constant-time compare before trusting the payload.
nodeimport { createHmac, timingSafeEqual } from "node:crypto"; export function verifyXynexSignature(rawBody: string, header: string, secret: string) { const expected = createHmac("sha256", secret).update(rawBody).digest("hex"); const a = Buffer.from(header); const b = Buffer.from(expected); return a.length === b.length && timingSafeEqual(a, b); }
Common events: invoice.created, payment.confirming, payment.finished, payout.completed, refund.completed.
Copy-paste examples for your stack.
Lightweight single-file samples — no npm package required. Drop them into your codebase and replace the API key.
API changelog.
- 2026-06-06Per-key IP allow-listing and rate-limit headers.API keys can now be restricted to specific IPs / CIDRs. Every response carries
X-RateLimit-Limit / Remaining / ResetandX-Request-Id. - 2026-05-20v1 stable.Invoices, payments, payouts, refunds, balances, beneficiaries, subscriptions, payment-links.
Build with Xynex.
Spin up sandbox keys in a minute. Move to live when you're ready — same API, same payloads.
