API reference
Every merchant endpoint, request field, response and webhook payload, generated from openapi.yaml.
This page is generated from openapi.yaml in the repository. The file is an OpenAPI 3.1 document. Load it into your own tools to generate a client or to test requests.
The base URL is your site URL, for example https://pay.example.com. Send the project API key in the x-api-key header. Payout endpoints also need a JWT from POST /v1/auth in the Authorization: Bearer header. The Merchant API guide explains each flow with examples.
Payments
Create payments and read their status.
GET/v1/payment
List payments
Auth: apiKey
Parameters
limit- integerPayments per page. Turmite changes a value below 1 to 1 and a value above 500 to 500.
page- integerPage number. The first page is 0.
sortBy- string
payment_idpayment_statuspay_addressprice_amountprice_currencypay_amountactually_paidpay_currencyorder_idorder_descriptionpurchase_idoutcome_amountoutcome_currencycreated_atupdated_at orderBy- string
ascdesc dateFrom- stringEarliest `created_at`. A date or a date-time.
dateTo- stringLatest `created_at`. A date or a date-time.
invoiceId- integer (int64)Only the payments of this invoice.
payment_status- stringOnly the payments with this status.
waitingconfirmingconfirmedsendingpartially_paidfinishedfailedrefundedexpired order_id- stringOnly the payments with this `order_id`.
200One page of payments.
{
"data": [
{
"invoice_id": 0,
"payment_status": "waiting",
"pay_address": "string",
"payin_extra_id": "string",
"price_amount": 0,
"price_currency": "usd",
"pay_amount": 0,
"actually_paid": 0,
"pay_currency": "btc",
"order_id": "string",
"order_description": "string",
"outcome_amount": 0,
"outcome_currency": "string",
"network": "btc",
"network_precision": 0,
"smart_contract": "string",
"payin_hash": "string",
"payout_hash": "string",
"payment_url": "string",
"created_at": "2026-10-23T12:00:00Z",
"updated_at": "2026-10-23T12:00:00Z",
"expiration_estimate_date": "2026-10-23T12:00:00Z",
"parent_payment_id": null,
"type": "crypto2crypto",
"time_limit": null,
"burning_percent": null,
"payment_extra_ids": null,
"amount_received": 0,
"actually_paid_at_fiat": 0,
"fee": {
"currency": "btc",
"depositFee": 0,
"withdrawalFee": 0,
"serviceFee": 0
},
"payment_id": 0,
"purchase_id": 6084815412
}
],
"limit": 0,
"page": 0,
"pagesCount": 0,
"total": 0
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}POST/v1/payment
Create a payment
Reserves a deposit address and fixes the amount to pay in `pay_currency`. Send the customer to your own page with `pay_address` and `pay_amount`, or use an invoice for the hosted checkout. A retry with the same `idempotency_key` returns the first payment. In this response `payment_id` and `purchase_id` are strings.
Auth: apiKey
Parameters
Idempotency-Key- stringThe same as `idempotency_key` in the body. The body field has priority.
Body
price_amount- number | stringA positive amount, as a JSON number or a decimal string.
price_currency- stringA fiat code or a ticker.
pay_currency- stringThe ticker the customer pays with.
pay_amount- number | stringA fixed amount in `pay_currency`. Without it, Turmite converts `price_amount` at the current rate.
order_id- stringYour order reference. Webhooks include it.
order_description- string
ipn_callback_url- string (uri)Turmite sends payment webhooks to this URL. On mainnet it must be a public `https` URL.
success_url- string (uri)Where the checkout sends the customer after payment.
cancel_url- string (uri)
purchase_id- stringYour id for the purchase. Without it, Turmite makes numeric text.
idempotency_key- stringA request with a key that the project used before returns the first payment. This is also true for two requests at the same time. Turmite does not compare the other fields.
Request body
{
"price_amount": 100,
"price_currency": "usd",
"pay_currency": "btc",
"order_id": "1042",
"order_description": "Order #1042",
"ipn_callback_url": "https://shop.example.com/turmite/ipn",
"idempotency_key": "order-1042"
}201The new payment.
{
"payment_id": "5077125051",
"invoice_id": null,
"payment_status": "waiting",
"pay_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"payin_extra_id": null,
"price_amount": 100,
"price_currency": "usd",
"pay_amount": 0.00123,
"actually_paid": 0,
"pay_currency": "btc",
"order_id": "1042",
"order_description": "Order #1042",
"purchase_id": "6084815412",
"outcome_amount": null,
"outcome_currency": "btc",
"network": "btc",
"network_precision": 8,
"smart_contract": null,
"payin_hash": null,
"payout_hash": null,
"payment_url": "https://pay.example.com/pay/Q7mX2pK9vT4nB8cR1sW6yZ3h",
"created_at": "2026-10-23T12:00:00.000Z",
"updated_at": "2026-10-23T12:00:00.000Z",
"expiration_estimate_date": "2026-10-23T12:15:00.000Z",
"parent_payment_id": null,
"type": "crypto2crypto",
"time_limit": null,
"burning_percent": null,
"payment_extra_ids": null,
"amount_received": 0.00123,
"actually_paid_at_fiat": 0,
"fee": {
"currency": "btc",
"depositFee": 0,
"withdrawalFee": 0,
"serviceFee": 0
}
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}503A service that the request needs is not available, for example the exchange rates. Try again later.
{
"status": false,
"statusCode": 503,
"code": "UNAVAILABLE",
"message": "Exchange rates are not available. Try again in a minute."
}GET/v1/payment/{payment_id}
Get a payment
Ship the order only when `payment_status` is `finished`. Use webhooks instead of frequent polls.
Auth: apiKey
Parameters
payment_id- integer (int64)
200The payment.
{
"payment_id": 5077125051,
"invoice_id": 4522625843,
"payment_status": "finished",
"pay_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"payin_extra_id": null,
"price_amount": 100,
"price_currency": "usd",
"pay_amount": 0.00123,
"actually_paid": 0.00123,
"pay_currency": "btc",
"order_id": "1042",
"order_description": "Order #1042",
"purchase_id": 6084815412,
"outcome_amount": 0.00123,
"outcome_currency": "btc",
"network": "btc",
"network_precision": 8,
"smart_contract": null,
"payin_hash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"payout_hash": null,
"payment_url": "https://pay.example.com/pay/Q7mX2pK9vT4nB8cR1sW6yZ3h",
"created_at": "2026-10-23T12:00:00.000Z",
"updated_at": "2026-10-23T12:14:03.512Z",
"expiration_estimate_date": "2026-10-23T12:15:00.000Z",
"parent_payment_id": null,
"type": "crypto2crypto",
"time_limit": null,
"burning_percent": null,
"payment_extra_ids": null,
"amount_received": 0.00123,
"actually_paid_at_fiat": 100,
"fee": {
"currency": "btc",
"depositFee": 0,
"withdrawalFee": 0,
"serviceFee": 0
}
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}404Not found, or it belongs to another project.
{
"status": false,
"statusCode": 404,
"code": "NOT_FOUND",
"message": "not found"
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}Invoices
Hosted invoices. The customer selects the coin on the invoice page.
POST/v1/invoice
Create an invoice
Returns `invoice_url`, a hosted checkout page. Send the customer there. The customer selects a coin, and Turmite creates a payment for the invoice. The payment copies `order_id`, `order_description`, `ipn_callback_url`, `success_url` and `cancel_url` from the invoice. Webhooks for that payment go to the invoice's `ipn_callback_url`.
Auth: apiKey
Body
price_amount- number | stringA positive amount, as a JSON number or a decimal string.
price_currency- string
pay_currency- stringSet it to skip the coin selection on the invoice page.
order_id- string
order_description- string
ipn_callback_url- string (uri)Turmite sends the webhooks of the invoice's payments to this URL.
success_url- string (uri)
cancel_url- string (uri)
Request body
{
"price_amount": 49.9,
"price_currency": "eur",
"order_id": "1042",
"order_description": "Order #1042",
"ipn_callback_url": "https://shop.example.com/turmite/ipn",
"success_url": "https://shop.example.com/checkout/order-received/1042",
"cancel_url": "https://shop.example.com/checkout"
}201The new invoice.
{
"id": "4522625843",
"token_id": "k3J9xQ2vT8mZ5wR1nB7cY4pL",
"order_id": "1042",
"order_description": "Order #1042",
"price_amount": "49.9",
"price_currency": "eur",
"pay_currency": null,
"ipn_callback_url": "https://shop.example.com/turmite/ipn",
"invoice_url": "https://pay.example.com/i/k3J9xQ2vT8mZ5wR1nB7cY4pL",
"success_url": "https://shop.example.com/checkout/order-received/1042",
"cancel_url": "https://shop.example.com/checkout",
"created_at": "2026-10-23T12:00:00.000Z",
"updated_at": "2026-10-23T12:00:00.000Z",
"expiration_estimate_date": "2026-10-23T13:00:00.000Z"
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}POST/v1/invoice-payment
Create a payment for an invoice
Use this to build your own coin selection for an invoice. The payment gets the invoice's price, order and URLs. If the invoice has an open payment in `pay_currency`, Turmite returns that payment. In this response `payment_id` and `purchase_id` are strings.
Auth: apiKey
Body
iid- integer (int64) | stringThe invoice `id`.
pay_currency- string
purchase_id- string
Request body
{
"iid": "4522625843",
"pay_currency": "usdttrc20"
}201The new payment.
{
"payment_id": "5077125051",
"invoice_id": null,
"payment_status": "waiting",
"pay_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"payin_extra_id": null,
"price_amount": 100,
"price_currency": "usd",
"pay_amount": 0.00123,
"actually_paid": 0,
"pay_currency": "btc",
"order_id": "1042",
"order_description": "Order #1042",
"purchase_id": "6084815412",
"outcome_amount": null,
"outcome_currency": "btc",
"network": "btc",
"network_precision": 8,
"smart_contract": null,
"payin_hash": null,
"payout_hash": null,
"payment_url": "https://pay.example.com/pay/Q7mX2pK9vT4nB8cR1sW6yZ3h",
"created_at": "2026-10-23T12:00:00.000Z",
"updated_at": "2026-10-23T12:00:00.000Z",
"expiration_estimate_date": "2026-10-23T12:15:00.000Z",
"parent_payment_id": null,
"type": "crypto2crypto",
"time_limit": null,
"burning_percent": null,
"payment_extra_ids": null,
"amount_received": 0.00123,
"actually_paid_at_fiat": 0,
"fee": {
"currency": "btc",
"depositFee": 0,
"withdrawalFee": 0,
"serviceFee": 0
}
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}404Not found, or it belongs to another project.
{
"status": false,
"statusCode": 404,
"code": "NOT_FOUND",
"message": "not found"
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}503A service that the request needs is not available, for example the exchange rates. Try again later.
{
"status": false,
"statusCode": 503,
"code": "UNAVAILABLE",
"message": "Exchange rates are not available. Try again in a minute."
}Payouts
Send funds from the project's hot wallets.
GET/v1/payout
List payouts
Auth: apiKey, bearerAuth
Parameters
batch_id- stringOnly the payouts of this batch.
status- stringOnly the payouts with this status. An unknown status returns `400`.
pending-approvalpending-otp-verificationpendingsigninginitiatedsentfailedrejectedcancelledneeds-review date_from- stringEarliest `created_at`. A date or a date-time.
date_to- stringLatest `created_at`. A date or a date-time.
order- string
ascdesc limit- integerPayouts per page. Turmite changes a value below 1 to 1 and a value above 500 to 500.
page- integerPage number. The first page is 0.
200One page of payouts.
{
"payouts": [
{
"id": "string",
"batch_withdrawal_id": "string",
"address": "string",
"extra_id": "string",
"currency": "string",
"network": "string",
"amount": "250",
"fee": "string",
"fee_currency": "string",
"status": "pending-approval",
"hash": "string",
"error": "string",
"ipn_callback_url": "string",
"payout_description": "string",
"unique_external_id": "string",
"created_at": "2026-10-23T12:00:00Z",
"requested_at": "2026-10-23T12:00:00Z",
"updated_at": "2026-10-23T12:00:00Z"
}
],
"limit": 0,
"page": 0,
"pagesCount": 0,
"total": 0
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}403The key or the user cannot do this action.
{
"status": false,
"statusCode": 403,
"code": "FORBIDDEN",
"message": "Only a project admin can create or verify payouts."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}POST/v1/payout
Create a payout batch
Creates one payout per withdrawal. The bearer token must belong to a project admin of the API key's project. Each address must be in the project's address book. New payouts are `pending-otp-verification` until you verify the batch with `POST /v1/payout/{batch_id}/verify`. A withdrawal with a `unique_external_id` that already exists returns the existing payout. The same id with other fields returns `409`. At most 100 withdrawals per batch. Bitcoin and Monero have no payouts.
Auth: apiKey, bearerAuth
Body
withdrawals- object[]
withdrawals[].address- stringThe destination. It must be in the project's address book.
withdrawals[].currency- string
withdrawals[].amount- number | stringA positive amount, as a JSON number or a decimal string.
withdrawals[].extra_id- stringThe memo or tag of the destination.
withdrawals[].ipn_callback_url- string (uri)Turmite sends payout webhooks to this URL. Without it, the batch's `ipn_callback_url` is used.
withdrawals[].payout_description- string
withdrawals[].unique_external_id- stringYour id for this payout. A second request with the same id and fields returns the existing payout. The same id with other fields returns `409`.
ipn_callback_url- string (uri)Payout webhooks for each withdrawal without its own `ipn_callback_url`.
Request body
{
"withdrawals": [
{
"address": "TQrZ9wBzhXnHdAdKwRBfdMH2RiTjH6yGtW",
"currency": "usdttrc20",
"amount": "250.00",
"ipn_callback_url": "https://shop.example.com/turmite/payout-ipn",
"unique_external_id": "refund-1042"
}
]
}201The new batch.
{
"id": "5000000713",
"withdrawals": [
{
"id": "5000248325",
"batch_withdrawal_id": "5000000713",
"address": "TQrZ9wBzhXnHdAdKwRBfdMH2RiTjH6yGtW",
"extra_id": null,
"currency": "usdttrc20",
"network": "tron",
"amount": "250",
"fee": null,
"fee_currency": "trx",
"status": "pending-otp-verification",
"hash": null,
"error": null,
"ipn_callback_url": "https://shop.example.com/turmite/payout-ipn",
"payout_description": null,
"unique_external_id": "refund-1042",
"created_at": "2026-10-23T13:00:00.000Z",
"requested_at": null,
"updated_at": "2026-10-23T13:00:00.000Z"
}
]
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}403The key or the user cannot do this action.
{
"status": false,
"statusCode": 403,
"code": "FORBIDDEN",
"message": "Only a project admin can create or verify payouts."
}409The request conflicts with an existing object.
{
"status": false,
"statusCode": 409,
"code": "CONFLICT",
"message": "`unique_external_id` is used with other fields."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}POST/v1/payout/{batch_id}/verify
Verify a payout batch
Send the current TOTP code of the user who got the bearer token. That user must be a project admin. Each payout of the batch that waits for verification then goes through the project limits: within them it is `pending`; above the auto-approve amount or the hourly or daily limit it is `pending-approval` until an admin approves it in the dashboard. A wrong code returns `400`. After 5 wrong codes the user is locked for 15 minutes and gets `429`. A user without two-factor authentication gets `403`.
Auth: apiKey, bearerAuth
Parameters
batch_id- stringThe `id` of the payout batch.
Body
verification_code- stringThe current TOTP code of the dashboard user.
Request body
{
"verification_code": "123456"
}200The batch after verification.
{
"id": "string",
"withdrawals": [
{
"id": "string",
"batch_withdrawal_id": "string",
"address": "string",
"extra_id": "string",
"currency": "string",
"network": "string",
"amount": "250",
"fee": "string",
"fee_currency": "string",
"status": "pending-approval",
"hash": "string",
"error": "string",
"ipn_callback_url": "string",
"payout_description": "string",
"unique_external_id": "string",
"created_at": "2026-10-23T12:00:00Z",
"requested_at": "2026-10-23T12:00:00Z",
"updated_at": "2026-10-23T12:00:00Z"
}
]
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}403The key or the user cannot do this action.
{
"status": false,
"statusCode": 403,
"code": "FORBIDDEN",
"message": "Only a project admin can create or verify payouts."
}404Not found, or it belongs to another project.
{
"status": false,
"statusCode": 404,
"code": "NOT_FOUND",
"message": "not found"
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}GET/v1/payout/{batch_id}
Get a payout batch
Auth: apiKey
Parameters
batch_id- stringThe `id` of the payout batch.
200The batch.
{
"id": "5000000713",
"withdrawals": [
{
"id": "5000248325",
"batch_withdrawal_id": "5000000713",
"address": "TQrZ9wBzhXnHdAdKwRBfdMH2RiTjH6yGtW",
"extra_id": null,
"currency": "usdttrc20",
"network": "tron",
"amount": "250",
"fee": null,
"fee_currency": "trx",
"status": "pending-otp-verification",
"hash": null,
"error": null,
"ipn_callback_url": "https://shop.example.com/turmite/payout-ipn",
"payout_description": null,
"unique_external_id": "refund-1042",
"created_at": "2026-10-23T13:00:00.000Z",
"requested_at": null,
"updated_at": "2026-10-23T13:00:00.000Z"
}
]
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}404Not found, or it belongs to another project.
{
"status": false,
"statusCode": 404,
"code": "NOT_FOUND",
"message": "not found"
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}POST/v1/payout/validate-address
Validate a payout address
Auth: apiKey
Body
address- string
currency- string
Request body
{
"address": "TQrZ9wBzhXnHdAdKwRBfdMH2RiTjH6yGtW",
"currency": "usdttrc20"
}200The address is valid. The body is the JSON string `"OK"`. An invalid address or an unknown currency returns `400`.
"OK"400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}GET/v1/payout/fee
Estimate the network fee of a payout
The fee is an estimate from the chain. Turmite measures the real fee when it sends the payout. The hot wallet pays the fee in the native coin of the network (`network_fee` in `fee_currency`); the recipient gets the full amount. `fee` is that cost in `currency`. A Solana token payout to a wallet without a token account also pays the rent of that account.
Auth: apiKey
Parameters
currency- string
amount- string
200The estimated fee in `currency`.
{
"currency": "usdttrc20",
"amount": "250",
"fee": 1.1,
"network_fee": 4.4,
"fee_currency": "trx"
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}503A service that the request needs is not available, for example the exchange rates. Try again later.
{
"status": false,
"statusCode": 503,
"code": "UNAVAILABLE",
"message": "Exchange rates are not available. Try again in a minute."
}Reference
Currencies, minimum amounts, estimates and balances.
GET/v1/status
Check that the API is up
200The API is up.
{
"message": "OK"
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}GET/v1/currencies
List enabled tickers
With a key, the tickers enabled for the key's project. Without a key, the tickers that at least one project takes.
Auth: apiKey
200Enabled tickers.
{
"currencies": [
"btc",
"eth",
"usdttrc20",
"sol"
]
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}GET/v1/full-currencies
List currencies with details
One entry for each ticker that the server has turned on. `enable` tells if the project takes it.
Auth: apiKey
200One entry per ticker.
{
"currencies": [
{
"id": 7,
"code": "USDTTRC20",
"name": "Tether USD",
"enable": true,
"wallet_regex": null,
"priority": 7,
"extra_id_exists": false,
"extra_id_regex": null,
"logo_url": null,
"track": false,
"cg_id": "tether",
"is_maxlimit": false,
"network": "tron",
"smart_contract": "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t",
"network_precision": "6",
"ticker": "usdttrc20"
}
]
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}GET/v1/merchant/coins
List the tickers enabled for the project
Auth: apiKey
200Tickers enabled for the key's project.
{
"selectedCurrencies": [
"btc",
"usdttrc20"
]
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}GET/v1/min-amount
Get the minimum payment amount
No API key is necessary. Turmite ignores a key that you send.
Parameters
currency_from- stringThe ticker the customer pays with.
currency_to- stringTurmite does not convert. It copies this value to the response. The default is `currency_from`.
fiat_equivalent- stringA fiat code. When set and a rate is available, the response has `fiat_equivalent`.
200The minimum payment amount in `currency_from`.
{
"currency_from": "btc",
"currency_to": "btc",
"min_amount": 0.00001,
"fiat_equivalent": 1.07
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}GET/v1/estimate
Estimate a price in a coin
No API key is necessary. Turmite ignores a key that you send.
Parameters
amount- stringThe amount in `currency_from`.
currency_from- stringThe price currency, such as `usd`.
currency_to- stringThe ticker the customer pays with.
200The estimate at the current rate.
{
"currency_from": "usd",
"amount_from": 100,
"currency_to": "btc",
"estimated_amount": "0.00107"
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}503A service that the request needs is not available, for example the exchange rates. Try again later.
{
"status": false,
"statusCode": 503,
"code": "UNAVAILABLE",
"message": "Exchange rates are not available. Try again in a minute."
}GET/v1/balance
Get the project balance per ticker
Auth: apiKey
200One entry per ticker.
{
"btc": {
"amount": 0.0153,
"pendingAmount": 0.0012
},
"usdttrc20": {
"amount": 1250.5,
"pendingAmount": 0
}
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}Auth
Bearer tokens for the payout endpoints.
POST/v1/auth
Get a bearer token for the payout endpoints
Use the email and password of a dashboard user. The token is valid for 5 minutes.
Body
email- string (email)
password- string (password)
Request body
{
"email": "[email protected]",
"password": "correct-horse-battery-staple"
}200The token.
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxIn0.c2lnbmF0dXJl"
}400The request is not valid.
{
"status": false,
"statusCode": 400,
"code": "INVALID_REQUEST_PARAMS",
"message": "`price_amount` must be greater than 0."
}401The API key or the bearer token is missing or not valid.
{
"status": false,
"statusCode": 401,
"code": "AUTH_REQUIRED",
"message": "Invalid API key."
}429Too many requests.
{
"status": false,
"statusCode": 429,
"code": "TOO_MANY_REQUESTS",
"message": "too many requests, try again later"
}500The server failed. The message has no details.
{
"status": false,
"statusCode": 500,
"code": "INTERNAL_ERROR",
"message": "Internal error."
}Webhooks
POSTpayment
A payment changed
Turmite sends the payment object to the `ipn_callback_url` of the payment, or of its invoice. It sends one on each status change, one for each new confirmation count while the payment is `confirming`, and one on each extra credit after `finished`. Ship the order only on `finished`. In this body `payment_id` is a number and `purchase_id` is a string. Check the signature before you use the body. The signature header (default `x-turmite-sig`) holds the hex HMAC-SHA512 of the key-sorted JSON body. The key is the project IPN secret. To get the key-sorted JSON from the raw body: 1. Sort the members of each object by key. Compare keys as UTF-8 bytes. Keep the order of arrays. 2. Write compact JSON with no whitespace. 3. Copy each number exactly as it is in the raw body, for example `0.5` or `1e-6`. 4. In strings, escape only `"`, `\` and control characters. Do not escape `/` or non-ASCII characters. `x-turmite-signature` holds `v1=` and the hex HMAC-SHA256 of `<x-turmite-timestamp>.<raw body>`, with the same secret. Refuse a timestamp more than 5 minutes from your clock. Use `x-turmite-delivery` to ignore a delivery that you already processed. A 2xx response acknowledges the delivery. Progress events get 3 attempts: now, after 10 s and after 60 s. Final events get attempts now and after 10 s, 1 m, 5 m, 30 m, 1 h, 2 h, 4 h, 8 h, 24 h and 48 h. Then the delivery is dead. You can retry it from the dashboard.
Parameters
x-turmite-sig- stringHex HMAC-SHA512 of the key-sorted JSON body. The key is the project IPN secret for an `ipn_callback_url`, or the endpoint secret for a project endpoint. The header name is a project setting. The default is `x-turmite-sig`.
x-turmite-timestamp- stringUnix time in seconds when Turmite signed this attempt.
x-turmite-signature- string`v1=` and the hex HMAC-SHA256 of `<x-turmite-timestamp>.<raw body>`. The key is the same as for the signature header.
x-turmite-event- stringThe event name, such as `payment.finished`, `payout.sent` or `test`.
x-turmite-delivery- stringThe delivery id. Retries of a delivery use the same id. Use it to ignore duplicates.
user-agent- string
Body
invoice_id- integer (int64) | null
payment_status- string`waiting`: no deposit yet. `confirming`: a deposit is on the chain with too few confirmations.
`confirmed`: the deposit has enough confirmations. `sending`: Turmite moves the funds to the wallet of the
project. `partially_paid`: the customer sent less than `pay_amount`. `finished`: paid in full. Ship the
order now. `failed`, `refunded` and `expired` are final.
waitingconfirmingconfirmedsendingpartially_paidfinishedfailedrefundedexpired pay_address- stringThe deposit address.
payin_extra_id- string | nullThe memo or tag the customer must add, on networks that use one.
price_amount- numberThe price in `price_currency`.
price_currency- stringLowercase.
pay_amount- numberThe amount to pay in `pay_currency`.
actually_paid- numberThe amount received so far.
pay_currency- string
order_id- string | null
order_description- string | null
outcome_amount- number | nullThe amount credited to the project after network fees.
outcome_currency- string
network- stringThe network code. One of `btc`, `xmr`, `eth`, `base`, `polygon`, `bsc`, `tron`, `sol`, `ton`.
network_precision- integerThe decimals of `pay_currency`.
smart_contract- string | nullThe token contract. Null for a native coin.
payin_hash- string | nullThe transaction hash of the latest deposit.
payout_hash- string | nullThe transaction hash of the latest transfer from the deposit address to the project wallet.
payment_url- string (uri)The hosted payment page, `<site URL>/pay/<token>`. The token is random.
created_at- string (date-time)
updated_at- string (date-time)
expiration_estimate_date- string (date-time)When the payment expires if no deposit comes.
parent_payment_id- nullAlways null.
type- stringAlways `crypto2crypto`.
crypto2crypto time_limit- nullAlways null.
burning_percent- nullAlways null.
payment_extra_ids- nullAlways null.
amount_received- numberThe amount the project gets in `outcome_currency`. `outcome_amount` once funds are credited, else `pay_amount`.
actually_paid_at_fiat- number`actually_paid` in `price_currency`, at the rate of the payment. A payment with a fixed `pay_amount` uses `price_amount / pay_amount` as the rate.
fee- objectTurmite takes no fee. `withdrawalFee` is the network fee of the sweeps to the project wallet.
fee.currency- stringThe same as `pay_currency`.
fee.depositFee- numberAlways 0.
fee.withdrawalFee- number
fee.serviceFee- numberAlways 0.
payment_id- integer (int64)
purchase_id- stringThe `purchase_id` of the request, or numeric text that Turmite makes.
Request body
{
"payment_id": 5077125051,
"invoice_id": 4522625843,
"payment_status": "finished",
"pay_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"payin_extra_id": null,
"price_amount": 100,
"price_currency": "usd",
"pay_amount": 0.00123,
"actually_paid": 0.00123,
"pay_currency": "btc",
"order_id": "1042",
"order_description": "Order #1042",
"purchase_id": "6084815412",
"outcome_amount": 0.00123,
"outcome_currency": "btc",
"network": "btc",
"network_precision": 8,
"smart_contract": null,
"payin_hash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"payout_hash": null,
"payment_url": "https://pay.example.com/pay/Q7mX2pK9vT4nB8cR1sW6yZ3h",
"created_at": "2026-10-23T12:00:00.000Z",
"updated_at": "2026-10-23T12:14:03.512Z",
"expiration_estimate_date": "2026-10-23T12:15:00.000Z",
"parent_payment_id": null,
"type": "crypto2crypto",
"time_limit": null,
"burning_percent": null,
"payment_extra_ids": null,
"amount_received": 0.00123,
"actually_paid_at_fiat": 100,
"fee": {
"currency": "btc",
"depositFee": 0,
"withdrawalFee": 0,
"serviceFee": 0
}
}200Any 2xx status acknowledges the delivery.400Any other status makes Turmite retry on the schedule.POSTpayout
A payout changed
Turmite sends the payout object to the `ipn_callback_url` of the withdrawal (or of its batch) on each status change, with the event `payout.<status>` in `x-turmite-event`. The key is the project IPN secret. The headers, signatures and retries are the same as for the payment webhook. `sent`, `failed`, `rejected` and `cancelled` are final events.
Parameters
x-turmite-sig- stringHex HMAC-SHA512 of the key-sorted JSON body. The key is the project IPN secret for an `ipn_callback_url`, or the endpoint secret for a project endpoint. The header name is a project setting. The default is `x-turmite-sig`.
x-turmite-timestamp- stringUnix time in seconds when Turmite signed this attempt.
x-turmite-signature- string`v1=` and the hex HMAC-SHA256 of `<x-turmite-timestamp>.<raw body>`. The key is the same as for the signature header.
x-turmite-event- stringThe event name, such as `payment.finished`, `payout.sent` or `test`.
x-turmite-delivery- stringThe delivery id. Retries of a delivery use the same id. Use it to ignore duplicates.
user-agent- string
Body
id- string
batch_withdrawal_id- string
address- string
extra_id- string | null
currency- string
network- stringThe network code in lower case, such as `eth` or `tron`.
amount- stringA decimal number as text.
fee- string | nullThe network fee in `fee_currency`, when known. The hot wallet pays it.
fee_currency- stringThe native coin of the network, such as `eth` or `trx`.
status- string`pending-otp-verification`: waits for a one-time code. An API batch waits for `verify`, or the admin who
clicked Approve in the dashboard must enter the code that Turmite emailed. `pending-approval`: above a
project limit; waits for an admin in the dashboard. `pending`: cleared to send. `signing`: signed and
stored, no node took it yet. `initiated`: a node took the transaction. `sent`: on the chain with the
network's confirmations. `sent`, `failed`, `rejected` and `cancelled` are final. `needs-review`: Turmite
cannot tell whether the payout went out (its nonce is used by another transaction). An admin checks the
chain and records the result.
pending-approvalpending-otp-verificationpendingsigninginitiatedsentfailedrejectedcancelledneeds-review hash- string | nullThe transaction hash.
error- string | null
ipn_callback_url- string (uri) | null
payout_description- string | null
unique_external_id- string | null
created_at- string (date-time)
requested_at- string (date-time) | null
updated_at- string (date-time)
Request body
{
"id": "5000248325",
"batch_withdrawal_id": "5000000713",
"address": "TQrZ9wBzhXnHdAdKwRBfdMH2RiTjH6yGtW",
"extra_id": null,
"currency": "usdttrc20",
"network": "tron",
"amount": "250",
"fee": "4.4",
"fee_currency": "trx",
"status": "sent",
"hash": "9f4c0e5b2a7d1c3e8f6a0b4d2c9e7f1a3b5d8c0e2f4a6b8d0c2e4f6a8b0d2c4e",
"error": null,
"ipn_callback_url": "https://shop.example.com/turmite/payout-ipn",
"payout_description": "Refund for order 1042",
"unique_external_id": "refund-1042",
"created_at": "2026-10-23T13:00:00.000Z",
"requested_at": "2026-10-23T13:01:10.000Z",
"updated_at": "2026-10-23T13:02:45.000Z"
}200Any 2xx status acknowledges the delivery.400Any other status makes Turmite retry on the schedule.POSTevent
An event for a project endpoint
Turmite sends this envelope to each endpoint that you add under Webhooks in the dashboard. `event` is `payment.<status>` with a payment in `data`, `payout.<status>` with a payout in `data`, or `test` with a message in `data`. Each endpoint has its own secret. The dashboard shows it. Turmite signs both signature headers with it. The headers, the signature rules and the retries are the same as for the payment webhook.
Parameters
x-turmite-sig- stringHex HMAC-SHA512 of the key-sorted JSON body. The key is the project IPN secret for an `ipn_callback_url`, or the endpoint secret for a project endpoint. The header name is a project setting. The default is `x-turmite-sig`.
x-turmite-timestamp- stringUnix time in seconds when Turmite signed this attempt.
x-turmite-signature- string`v1=` and the hex HMAC-SHA256 of `<x-turmite-timestamp>.<raw body>`. The key is the same as for the signature header.
x-turmite-event- stringThe event name, such as `payment.finished`, `payout.sent` or `test`.
x-turmite-delivery- stringThe delivery id. Retries of a delivery use the same id. Use it to ignore duplicates.
user-agent- string
Body
event- string`payment.<status>`, `payout.<status>` or `test`.
delivery_id- stringThe same value as the `x-turmite-delivery` header.
created_at- integer (int64)Unix time in seconds when Turmite made the event.
data- any | object | object
Request body
{
"event": "payment.finished",
"delivery_id": "dK4rT8wQ2mN6xP1vB9cL5zH7",
"created_at": 1761221644,
"data": {
"payment_id": 5077125051,
"invoice_id": 4522625843,
"payment_status": "finished",
"pay_address": "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh",
"payin_extra_id": null,
"price_amount": 100,
"price_currency": "usd",
"pay_amount": 0.00123,
"actually_paid": 0.00123,
"pay_currency": "btc",
"order_id": "1042",
"order_description": "Order #1042",
"purchase_id": "6084815412",
"outcome_amount": 0.00123,
"outcome_currency": "btc",
"network": "btc",
"network_precision": 8,
"smart_contract": null,
"payin_hash": "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
"payout_hash": null,
"payment_url": "https://pay.example.com/pay/Q7mX2pK9vT4nB8cR1sW6yZ3h",
"created_at": "2026-10-23T12:00:00.000Z",
"updated_at": "2026-10-23T12:14:03.512Z",
"expiration_estimate_date": "2026-10-23T12:15:00.000Z",
"parent_payment_id": null,
"type": "crypto2crypto",
"time_limit": null,
"burning_percent": null,
"payment_extra_ids": null,
"amount_received": 0.00123,
"actually_paid_at_fiat": 100,
"fee": {
"currency": "btc",
"depositFee": 0,
"withdrawalFee": 0,
"serviceFee": 0
}
}
}200Any 2xx status acknowledges the delivery.400Any other status makes Turmite retry on the schedule.