Create an invoice
Charge an exact amount and receive a hosted checkout URL.
/api/invoicesCreate an invoice and hosted checkout URL. Requires merchant-id and signature headers.
| Field | Type | Required | Description |
|---|---|---|---|
fee_payer | string | No | |
original_price | string | No | |
discount | object | No | |
currency | string | Yes | Pricing currency supported by the deployment. Fiat denomination does not imply fiat payment acceptance. |
amount | string | Yes | Base price before any discount, as a positive plain decimal string below 1e18 with at most 18 decimal places. Response amount is the discounted goods price. No exponent or sign. |
network | string | No | Optional network constraint for a crypto-priced invoice. Does not select a method for a fiat-priced invoice. |
order_id | string | No | Stable order reference. Retry the original base amount and pricing fields unchanged to retrieve the saved price, discount and fee snapshot. Changed pricing conditions return 409 ORDER_ID_ALREADY_EXISTS. |
expires_at | string | No | For a new invoice, a future ISO timestamp no more than 60 minutes ahead. Omission defaults to 30 minutes. Existing reservations and identical retries retain their original deadline. |
webhook_url | string | No | Public HTTPS receiver. Pass explicitly for invoice events; merchant settings are not inherited. |
success_url | string | null | No | Absolute HTTP/HTTPS return URL without credentials. Not a payment confirmation. Null is allowed. |
description | string | No | Optional invoice description; not returned in the create summary. |
metadata | object | No | Optional JSON object. Not echoed by create, public read, or webhook payload. |
Source: download OpenAPI 3.1. Examples below use illustrative values.
Example request
{
"currency": "USD",
"amount": "100",
"fee_payer": "CUSTOMER",
"discount": { "type": "PERCENT", "value": "20" },
"order_id": "order-1001",
"webhook_url": "https://shop.example/webhooks/cryptiumpay",
"success_url": "https://shop.example/payment/success",
"metadata": { "reference": "customer-123" }
}Example response
{
"id": "22222222-2222-4222-8222-222222222222",
"amount": "80",
"original_price": "100",
"discount": { "type": "PERCENT", "value": "20", "amount": "20" },
"fee_payer": "CUSTOMER",
"fee": { "payer": "CUSTOMER", "rate_bps": 150, "amount": "1.2", "currency": "USD" },
"total_amount": "81.2",
"currency": "USD",
"currency_type": "FIAT",
"status": "NEW",
"expires_at": "2026-10-24T15:00:00.000Z",
"order_id": "order-1001",
"webhook_url": "https://shop.example/webhooks/cryptiumpay",
"success_url": "https://shop.example/payment/success",
"url": "https://checkout.example/pay/22222222-2222-4222-8222-222222222222"
}Example hostnames and timestamps are illustrative. A new invoice accepts a future expires_at up to 60 minutes ahead. If omitted, expiry defaults to 30 minutes. Existing reservations and identical retries retain their original deadline.
Price, discount and service fee
Send all monetary values and discount values as plain decimal strings. Input prices and discount values must have at most 18 decimal places of precision; more precise values are rejected rather than silently rounded. Request amount is the base price before the discount. Response amount is the discounted goods price, excluding any service fee paid by the customer. The server calculates and saves the pricing result when the invoice is created.
fee_payer accepts MERCHANT (default) or CUSTOMER. With MERCHANT, the customer total equals the goods price and the service fee is deducted from the merchant's proceeds. With CUSTOMER, the service fee is added to the discounted goods price. For example, at 150 basis points (1.5%), goods priced at "100" produce a customer total of "100" for MERCHANT or "101.5" for CUSTOMER. The example above applies 20% off first: goods "80", customer service fee "1.2", total "81.2".
Optional discount accepts { "type": "PERCENT", "value": "20" } or { "type": "FIXED", "value": "20" }. Its value must be positive; a percentage must be below 100, and a fixed discount must be less than the base price. The final price must remain positive. The server rounds the final goods price once to at most 18 decimal places using ROUND_HALF_UP; response discount.amount is the base minus that final goods price. The service fee is then calculated from the discounted price and rounded to at most 18 decimal places.
original_price is optional. Without discount, you can send an already reduced final amount with its original price:
{ "currency": "USD", "amount": "80", "original_price": "100" }In that case, original_price must be at least amount; it does not trigger another reduction. With discount, the server infers original_price from the base amount. If you also supply it explicitly, it must equal that base amount. Do not send an already discounted amount together with a discount intended for a different base.
Responses can include original_price, applied discount (including its amount), fee_payer, fee and total_amount. fee describes the service commission in the invoice currency; it is added to total_amount only when its payer is CUSTOMER. These fields reflect the saved server snapshot, rather than a later fee policy. Older invoices may omit pricing fields; their total falls back to amount.
Payment method selection
For a crypto-priced invoice, network can constrain the route. It does not choose the payment method for a fiat-priced invoice. If only one eligible route exists, it may be issued immediately and the returned status can be PENDING.
The optional response network describes a saved route. Creation does not return the payment address or pay object; read the invoice for those details.
Retries and errors
Use a stable order_id. Identical retries return the saved invoice; changed conditions produce 409 ORDER_ID_ALREADY_EXISTS. Amount formatting can normalize, for example "19.950" to "19.95".
Keep the original base amount, payer, original price and discount unchanged when retrying, including after a lost response. The saved invoice retains its price, discount and fee rate even if the merchant's current fee changes. Reusing an order with different pricing conditions is a conflict; changing the current fee policy alone does not recalculate an identical retry.
Unknown request fields are rejected. Optional fields do not accept explicit null, except success_url. Metadata is not echoed in the create or webhook response. See errors.