MagenPay Developer Docs

Build crypto checkout in minutes. Start with a single POST or drop in our pre-built UI.

⌘K
Get started

Introduction

The MagenPay API is built on REST. It uses standard HTTP verbs, returns JSON, and authenticates via bearer tokens. There is no SDK lock-in — anything that can speak HTTP can integrate with MagenPay.

API base URL
All endpoints are served from https://api.magenpay.com. Use https://api.sandbox.magenpay.com for the sandbox environment.

Quickstart

Three steps and you're charging customers in crypto.

  1. 1

    Get a merchant token

    Sign up at magenpay.com, complete onboarding, then generate a token from Dashboard → Developers → API Keys.

  2. 2

    Create a payment

    POST a payment request — receive a checkout URL.

  3. 3

    Listen for webhooks

    When payment confirms on-chain, we POST to your webhook endpoint with a signed payload.

Authentication

All requests authenticate with a bearer token in the Authorization header.

request.sh
BASH
Authorization: Bearer YOUR_MERCHANT_TOKEN
Keep your token secret
Never commit a merchant token to source control or expose it client-side. Use server-to-server requests only — and rotate immediately if you suspect a leak.

Test vs live tokens

Sandbox tokens are prefixed with test_ — production tokens with live_. Both look like UUIDs.

API reference

Create order

Create a new payment order. The response contains a checkout URL you can redirect the customer to, plus an on-chain address they can pay directly.

POST /v1/create-order

Body parameters

FieldTypeDescription
amount* numberAmount to charge in the chosen currency.
currency* stringUSDT · BNB · ETH · TRX
network* stringBEP20 · TRC20 · ERC20
redirect stringURL to redirect the customer to after payment.
reference1 stringYour internal order ID (max 80 chars).
expires_in integerSeconds until expiration (default 1800).

* required

Request

create-order
curl "text-amber-300">-X POST https://api.magenpay.com/v1/create-order \
  "text-amber-300">-H "Authorization: Bearer $MERCHANT_TOKEN" \
  "text-amber-300">-H "Content-Type: application/json" \
  "text-amber-300">-d '{
    "amount":     100,
    "currency":   "USDT",
    "network":    "BEP20",
    "redirect":   "https://shop.example/return",
    "reference1": "order-1234"
  }'

Response

200 OK
JSON
{
  300">"id":          12345,
  300">"payment_id": 300">"pay_abc123xyz",
  300">"status": 300">"NEW",
  300">"amount":      100,
  300">"currency": 300">"USDT",
  300">"network": 300">"BEP20",
  300">"address": 300">"0x1234567890abcdef1234567890abcdef12345678",
  300">"expires_at": 300">"2025-04-22T15:30:00Z",
  300">"checkout_url": 300">"https://pay.magenpay.com/c/pay_abc123xyz",
  300">"created_at": 300">"2025-04-22T15:00:00Z"
}

Retrieve order

GET /v1/get-order?payment_id={'{'}id{'}'}
get-order
BASH
curl https://api.magenpay.com/v1/get-order?payment_id=pay_abc123xyz \
  "text-amber-300">-H 'Authorization: Bearer $MERCHANT_TOKEN'

List orders

Returns up to 100 orders per page, sorted by created_at descending.

GET /v1/get-order-transaction

Cancel order

POST /v1/cancel-order
One-way operation
A cancelled order cannot be reactivated. The customer will see an "Order cancelled" message at the checkout URL.
Webhooks

Webhooks

When a payment confirms on-chain we send a JSON payload to your merchant_webhook URL. Webhooks are signed, retried, and idempotent.

Event payload

POST /your-webhook
JSON
{
  300">"event": 300">"order.paid",
  300">"id":          12345,
  300">"payment_id": 300">"pay_abc123xyz",
  300">"status": 300">"PAID",
  300">"amount":      100,
  300">"currency": 300">"USDT",
  300">"network": 300">"BEP20",
  300">"txid": 300">"0xabcdef...",
  300">"block_number":42_000_000,
  300">"confirmed_at": 300">"2025-04-22T15:02:18Z"
}

Signature verification

Every request includes an X-MagenPay-Signature header with the HMAC-SHA256 of the raw body. Always compare in constant time.

verify.{js|py}
"text-fuchsia-300">import crypto "text-fuchsia-300">from 'node:crypto'

"text-fuchsia-300">function verify(rawBody, header, secret) {
  "text-fuchsia-300">const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')
  "text-fuchsia-300">return crypto.timingSafeEqual(
    Buffer."text-fuchsia-300">from(header),
    Buffer."text-fuchsia-300">from(`sha256=${expected}`)
  )
}

Retries & idempotency

  • Retried with exponential backoff for up to 72 hours on non-2xx responses.
  • Each delivery includes Idempotency-Key — your handler should be safe to retry.
  • Failures surface in Dashboard → Webhooks with full request/response history.

Errors

Errors return a stable machine-readable code plus a human-readable message.

HTTPCodeMeaning
400 invalid_request Required field missing or malformed.
401 unauthorized Token missing, malformed, or revoked.
404 not_found Resource does not exist or is not yours.
409 conflict State transition not allowed (e.g. cancel a paid order).
429 rate_limited Too many requests. Inspect Retry-After.
500 server_error Transient — safe to retry with idempotency.

Rate limits

Default: 100 req / minute / token. Bursts up to 200 are allowed via token bucket. We expose the standard headers:

response headers
BASH
X-RateLimit-Limit:     100
X-RateLimit-Remaining: 87
X-RateLimit-Reset:     1714053600

Testing & sandbox

The sandbox at api.sandbox.magenpay.com mirrors production but settles testnet stablecoins. Use it to test integration end-to-end before going live.

Auto-fund testnet
Sandbox merchants receive 10,000 USDT-testnet on signup. Need more? Ping us.

Changelog

  • 2025-04-22
    Polygon & Arbitrum live. Two new low-fee networks now selectable in network.
  • 2025-04-08
    Webhook v2. Signed payloads + idempotency keys. Migration guide on the blog.
  • 2025-01-15
    v1 stabilized. Initial public release of the REST API.