Developers
API reference
A small REST API for invoices, payment links, balances and accepted coins. It uses JSON over HTTPS, and every request is made with your secret key.
Base URL
- Production
https://cryptomerchant.online/api/v1- Local development
http://localhost:3000/api/v1
Authentication
Send your secret key in the Authorization header of every request, as a Bearer token. Create keys in the portal under Developers.
Authorization: Bearer cm_live_…- Keys start with
cm_live_on mainnet andcm_test_on testnet. - The full key is shown only once, when you create it. We store only a hash of it, so keep it somewhere safe.
- Use keys only on your server. Never put them in a web page, a mobile app or a public code repository.
- If a key may have leaked, revoke it in the portal and create a new one.
Errors
When a request fails, the response has an HTTP error status and a JSON body with a machine-readable code and a human-readable message:
{
"error": {
"code": "amount_too_small",
"message": "Amount must be at least 0.50 USD."
}
}HTTP status
400- The request is not valid, for example a missing field or an amount that is too small.
401- The API key is missing, wrong or revoked.
403- Your account can't do this: it isn't live yet, or it is suspended.
404- The object doesn't exist, or it belongs to another business.
409- The invoice can't do this in its current status, for example cancelling one that already has a payment.
500- Something went wrong on our side. Try again a little later.
Codes you may see
invalid_json- The request body is not a JSON object.
invalid_request- A field is missing or not valid. The message names the field.
unauthorized- The API key is missing, wrong or revoked.
account_suspended- This merchant account is suspended.
merchant_not_live- Your account isn't live yet. Make the go-live payment first.
invalid_amount- The amount is missing, not a number, or not greater than zero.
amount_too_small- The amount is worth less than 0.50 US dollars.
invalid_asset- The coin ID is not a known coin.
asset_not_accepted- You don't accept that coin.
invalid_state- The invoice can't do this in its current status.
not_found- There is no object with that ID.
server_error- Something went wrong on our side.
The invoice object
Invoices have this shape in API responses and in webhooks. Amounts are decimal strings, so no precision is lost.
idstring- Invoice ID, starting with
inv_. objectstring- Always
invoice. statusstring- The current status. See the list of statuses below.
amountstring- The price you asked for, in
currency. currencystring- The currency of the price, for example
USD. amount_usdstring- The price in US dollars.
descriptionstring | null- Your description, shown to the customer.
order_idstring | null- Your own order reference.
customer_emailstring | null- The customer's email, if you gave one.
metadataobject- The object you passed when creating the invoice, returned unchanged.
coinobject | null- The coin the customer chose, with its
id,symbolandnetwork.nulluntil a coin is chosen. pay_addressstring | null- The deposit address for this invoice.
nulluntil a coin is chosen. pay_amountstring | null- The exact amount to send, in the chosen coin.
rate_usdstring | null- The locked price of one unit of the chosen coin, in US dollars.
received_amountstring- How much has arrived so far, in the chosen coin.
received_usdstring- The US dollar value of what has arrived.
overpaid_amountstring- How much more than the invoice asked for was paid, in the chosen coin.
checkout_urlstring- The invoice page. Send your customer here to pay.
redirect_urlstring | null- Where the customer can go after paying.
expires_atISO 8601- When the invoice expires if no payment is seen.
paid_atISO 8601 | null- When the invoice was paid, or
null. created_atISO 8601- When the invoice was created.
{
"id": "inv_…",
"object": "invoice",
"status": "open",
"amount": "49.9",
"currency": "USD",
"amount_usd": "49.9",
"description": "Annual plan",
"order_id": "1042",
"customer_email": "[email protected]",
"metadata": { "plan": "annual" },
"coin": null,
"pay_address": null,
"pay_amount": null,
"rate_usd": null,
"received_amount": "0",
"received_usd": "0",
"overpaid_amount": "0",
"checkout_url": "https://cryptomerchant.online/pay/i/inv_…",
"redirect_url": "https://yourstore.example/thanks",
"expires_at": "2026-10-28T10:00:00.000Z",
"paid_at": null,
"created_at": "2026-10-28T09:30:00.000Z"
}Invoice statuses
openOpen- Created. The customer hasn't picked a coin yet.
awaiting_paymentAwaiting payment- A coin is chosen, the deposit address is assigned and the rate is locked.
confirmingConfirming- A payment was seen on-chain and is waiting for confirmations.
underpaidUnderpaid- The confirmed payment is short by more than your tolerance. The customer can pay the rest or ask for a refund.
paidPaid- Paid and confirmed. The amount, minus the fee, is in your balance.
expiredExpired- Time ran out before any payment was seen.
cancelledCancelled- The invoice was cancelled before any payment was seen.
refundedRefunded- The customer was refunded what they sent on an underpaid invoice.
Create an invoice
POST/invoices
Creates an invoice and returns the invoice object with status 201. Send your customer to its checkout_url.
Body parameters
amountRequirednumber | string- The price, as a number or a decimal string. Must be worth at least 0.50 US dollars.
currencyOptionalstring- The currency of the price, for example
USD. Defaults toUSD. descriptionOptionalstring- What the customer is paying for, up to 300 characters. Shown on the invoice page.
order_idOptionalstring- Your own order reference, up to 120 characters, to match the invoice to an order.
customer_emailOptionalstring- The customer's email address. Payments are grouped by customer in the portal.
customer_nameOptionalstring- The customer's name, up to 120 characters.
redirect_urlOptionalstring- A full URL where the customer can go after paying.
metadataOptionalobject- Any JSON object up to 4 KB. Returned unchanged on the invoice and in webhooks.
coinOptionalstring- Pre-select a coin by its ID, for example
USDT.TRON. It must be one of your accepted coins.
With a pre-selected coin, the deposit address is assigned and the rate locked straight away, so pay_address and pay_amount are filled in and you can show the payment details in your own interface.
curl https://cryptomerchant.online/api/v1/invoices \
-H "Authorization: Bearer $CM_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": "49.90",
"currency": "USD",
"order_id": "1042",
"description": "Annual plan",
"customer_email": "[email protected]",
"redirect_url": "https://yourstore.example/thanks",
"metadata": { "plan": "annual" }
}'const res = await fetch("https://cryptomerchant.online/api/v1/invoices", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CM_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: "49.90",
currency: "USD",
order_id: "1042",
description: "Annual plan",
}),
});
if (!res.ok) {
const { error } = await res.json();
throw new Error(`${error.code}: ${error.message}`);
}
const invoice = await res.json();
// Send the customer to invoice.checkout_urlList invoices
GET/invoices
Returns your invoices, newest first, one page at a time.
Query parameters
statusOptionalstring- Only invoices with this status, for example
paid. Must be one of the statuses above. limitOptionalnumber- How many invoices to return, from 1 to 100. Defaults to 20.
starting_afterOptionalstring- An invoice ID. Returns the invoices that come after it, for the next page.
The invoices are in data. When has_more is true, ask for the next page with starting_after set to the ID of the last invoice you received.
curl "https://cryptomerchant.online/api/v1/invoices?status=paid&limit=20" \
-H "Authorization: Bearer $CM_SECRET_KEY"{
"object": "list",
"data": [
{ "id": "inv_…", "object": "invoice", "status": "paid", … }
],
"has_more": true
}Retrieve an invoice
GET/invoices/{id}
Returns one invoice by its ID.
curl https://cryptomerchant.online/api/v1/invoices/$INVOICE_ID \
-H "Authorization: Bearer $CM_SECRET_KEY"Cancel an invoice
POST/invoices/{id}/cancel
Cancels an invoice. This only works while the invoice is unpaid and no payment has been seen for it.
curl -X POST https://cryptomerchant.online/api/v1/invoices/$INVOICE_ID/cancel \
-H "Authorization: Bearer $CM_SECRET_KEY"Balances
GET/balances
Returns what your business holds in each coin, the total in US dollars, and your gas balance.
data[].coin- The coin ID, for example
USDT.TRON. data[].symbol- The coin symbol, for example
USDT. data[].network- The network the coin is on.
data[].amount- How much of the coin you hold, as a decimal string.
data[].usd- Its value in US dollars at the current price.
total_usd- The value of all your coins in US dollars.
gas_balance_usd- Your gas balance in US dollars, used to pay network fees.
curl https://cryptomerchant.online/api/v1/balances \
-H "Authorization: Bearer $CM_SECRET_KEY"{
"object": "balance",
"data": [
{ "coin": "USDT.TRON", "symbol": "USDT", "network": "Tron", "amount": "…", "usd": "…" }
],
"total_usd": "…",
"gas_balance_usd": "…"
}Accepted coins
GET/coins
Returns the coins you accept right now, each with its id, symbol, name, network and decimals. Use the id as coin when you create an invoice. For example:
curl https://cryptomerchant.online/api/v1/coins \
-H "Authorization: Bearer $CM_SECRET_KEY"{
"object": "list",
"data": [
{
"id": "ETH.ETH",
"symbol": "ETH",
"name": "Ethereum",
"network": "Ethereum",
"decimals": 18
},
{
"id": "USDT.ETH",
"symbol": "USDT",
"name": "Tether USD",
"network": "Ethereum",
"decimals": 6
},
{
"id": "USDC.ETH",
"symbol": "USDC",
"name": "USD Coin",
"network": "Ethereum",
"decimals": 6
}
]
}Create a payment link
POST/payment-links
Creates a payment link and returns it with status 201, including its id and its shareable url.
Body parameters
titleRequiredstring- The name of what the customer pays for, up to 120 characters.
amountOptionalnumber | string- A fixed price. Leave it out to let the customer enter the amount.
currencyOptionalstring- The currency of the price. Defaults to
USD. descriptionOptionalstring- More detail shown to the customer, up to 300 characters.
curl https://cryptomerchant.online/api/v1/payment-links \
-H "Authorization: Bearer $CM_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Consulting hour",
"amount": "80",
"currency": "USD"
}'{
"id": "…",
"object": "payment_link",
"title": "Consulting hour",
"description": null,
"amount": "80",
"currency": "USD",
"active": true,
"url": "https://cryptomerchant.online/pay/l/…",
"created_at": "2026-10-28T09:30:00.000Z"
}List payment links
GET/payment-links
Returns your 100 most recent payment links, newest first, in data.
curl https://cryptomerchant.online/api/v1/payment-links \
-H "Authorization: Bearer $CM_SECRET_KEY"