Skip to main content

What you can build

The Manexx Merchant API turns a checkout into three moving parts: you create an invoice, send your customer to a hosted payment page, and receive a webhook when the money settles.

Accept a payment

Create an invoice, get a ready-to-use payment link.

Get notified

Receive a signed callback the moment an invoice settles.

Offer the right methods

Show only the methods and currencies enabled for you.

Track your payouts

List and inspect withdrawals programmatically.

Quickstart

1

Get your API key

Grab your secret key from the dashboard. It authenticates every request via the X-Api-Key header. Keep it server-side only.
2

Create an invoice

Send your order details. Use your own order id as external_id — it makes retries safe (see Idempotency).
3

Redirect the customer

The response contains a ready-to-use payment_url. Send your customer there; they pick a method and pay on our hosted page.
payment_url is returned only to the creator (the X-Api-Key call). Store it or redirect immediately — a later public GET returns it as null.
4

Receive the webhook

When the invoice settles, we POST to your callback_url with the final status. Acknowledge with 2xx. Treat the webhook as the source of truth for fulfillment — see WebHooks.

Payment lifecycle

An invoice moves through a small, predictable set of states. Only success is terminal-and-good; the rest are final ways an invoice can end.
Created and waiting for the customer to pay. Has a live payment_url and an expires_at.
Paid and credited. Fulfill the order. A webhook is delivered.
The payment window elapsed before payment. Create a new invoice to retry.
Cancelled before payment.
A rare technical failure during settlement. Safe to treat like a non-success.
Fulfill strictly on success. Never fulfill on pending, and never infer payment from the customer landing on your success_url — always confirm via the webhook or a GET on the invoice.

Core concepts

Base URL

Authentication

Send your secret key in the X-Api-Key header on every request.
Your key is a secret: server-side only, never in a browser, mobile app, or git. Leaked? Revoke it in the dashboard and the old key dies instantly.

Response envelope

Every response uses one envelope, so you write one parser. Success puts the payload under data:
Errors mirror it under error:
true on success, false on error. Always check this first.
Present when success is true. The endpoint’s payload (an object, or a page for lists).
Present when success is false.

HTTP status codes

The HTTP status gives the class of outcome; error.code gives the exact reason. The full catalog lives on the Errors page.
A 422 returns details as {field: [messages]}, e.g. {"amount": ["must have at most 2 decimal places"]}. Log it to debug bad requests fast.

Pagination

List endpoints take two query parameters and return a page object under data. 1-based page number. Items per page.
To walk everything: start at page=1 and keep going while has_next is true.

Money & amounts

All amounts are strings"1050.00", never 1050.0. Parse with a decimal type (decimal.Decimal, BigDecimal), never a binary float, to avoid rounding errors.
Fiat amounts carry at most two decimal places; sending more is rejected with 422. USDT amounts follow their own precision and are likewise strings.

Timestamps

ISO 8601, always UTC ("2026-07-16T09:24:11Z"). Convert to local time for display only; store and compare in UTC.

Idempotency

Creating an invoice is idempotent on your ****external_id. Retry POST /external/invoices with an id you’ve already used and you won’t create a duplicate — you get 409 INVOICE_ALREADY_EXISTS with the existing invoice’s status in details.
Always set a stable external_id per order. Network retries then become safe: a retried create can never double-charge your customer.

Rate limiting

Requests are rate limited per API key. The current limit is 100 requests per 60 seconds. Over the limit → 429 RATE_LIMITED; back off and retry with exponential backoff. Some resources add their own guard, e.g. 429 TOO_MANY_UNPAID_INVOICES when too many invoices sit unpaid. Every response carries your current budget in headers: On a 429, the response also includes a Retry-After header (seconds) and details.retry_after_seconds.
These limits are current defaults and may change without notice. Don’t hardcode the numbers — read the X-RateLimit-* headers and honor Retry-After on 429.

Errors

Branch on the stable error.code — never on the HTTP status alone or the message. The complete, grouped list is on the Errors page.