Create a hosted crypto invoice
const url = 'https://api.flotera.com/api/v1/billing/topups';const options = { method: 'POST', headers: { cookie: '__Host-erm_session=<__Host-erm_session>', 'Idempotency-Key': 'example', 'Content-Type': 'application/json' }, body: '{"amount_usd":"example","payment_method":"example","purpose":{"kind":"wallet","target_plan":"example","change_id":"2489E9AD-2EE2-8E00-8EC9-32D5F69181C0"}}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api.flotera.com/api/v1/billing/topups \ --header 'Content-Type: application/json' \ --header 'Idempotency-Key: example' \ --cookie __Host-erm_session=<__Host-erm_session> \ --data '{ "amount_usd": "example", "payment_method": "example", "purpose": { "kind": "wallet", "target_plan": "example", "change_id": "2489E9AD-2EE2-8E00-8EC9-32D5F69181C0" } }'Creates a top-up with the payment provider and returns the hosted
checkout_url. Allowed while the account is in grace or
frozen: a top-up is the only way out of a freeze (14 §3.6), so
denying it would make the state unrecoverable.
The balance moves only on a verified terminal finished IPN, for the
amount actually confirmed (D-13). Never treat the browser redirect as
success — poll GET /billing/topups/{topup_id} and accept only
status=succeeded.
Retrying with the same Idempotency-Key returns the same top-up and
the same invoice; it never creates a second payment.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Header Parameters
Section titled “Header Parameters”Idempotency key, 1–128 ASCII, unique per (tenant_id, operation, key) for at least 24 hours. Retrying with the same body replays the stored response; a different body returns 409 idempotency_conflict.
Request Bodyrequired
Section titled “Request Bodyrequired”object
Top-up amount in USD as a decimal string. Must be at least the confirmed minimum of the chosen method (GET /billing/payment-methods).
Code from the server-owned catalogue, e.g. card or usdt_tron. The catalogue depends on which providers the operator has enabled, so a code that worked yesterday may be absent today — always take the list from GET /billing/payment-methods.
What the money is for. wallet — plain balance top-up; subscription — the payment that activates a pending upgrade, in which case the activation happens inside the verified payment transaction and never from a browser redirect (14 §3.2).
Responses
Section titled “Responses”Top-up created; open checkout_url as external navigation.
object
UUID (v7 for new entities; v4 accepted during migration).
Internal top-up state (14 §6.3). Exactly one of them means the money
arrived: succeeded.
partially_paid is progress information — the customer under-paid but
the payment is still moving. It does not park the top-up for an
operator and it does not move the balance (D-13).
review means invoice/order/currency disagreement, an unknown provider
status or an ambiguous create — a human has to look.
Invoiced amount. What was credited is the confirmed amount, not this.
Code from the server-owned catalogue, e.g. card or usdt_tron. The catalogue depends on which providers the operator has enabled, so a code that worked yesterday may be absent today — always take the list from GET /billing/payment-methods.
Hosted provider page. Open it as external navigation — never inject it as HTML. Absent once the top-up reaches a terminal state.
RFC 3339 UTC with microsecond precision, or null.
RFC 3339 UTC with microsecond precision.
Example
{ "status": "creating", "created_at": "2026-07-25T10:15:30.123456Z"}Missing/invalid credentials (code=unauthorized).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Authenticated but not permitted. code=forbidden — role/scope mismatch; code=feature_not_entitled — the plan does not include the capability; code=account_frozen — the account is frozen and this operation is declared x-ermeon-frozen: deny. The three are deliberately distinct: only the last one is fixed by a top-up (13 §5.6).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}State conflict (code=conflict, idempotency_conflict, offline_queue_full or online_queue_full).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Request failed validation (code=validation_failed), with per-field errors.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Rate limit exceeded (code=rate_limited).
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}Headers
Section titled “Headers”Seconds to wait before retrying.
A dependency the endpoint needs is not configured or is temporarily unavailable (code=unavailable). The rest of the API keeps working — an absent external integration must not take the service down.
RFC 9457 problem document with a stable machine code.
object
Stable machine-readable error code (03 §2.4).
UUID (v7 for new entities; v4 accepted during migration).
object
JSON Pointer to the offending field.
Example
{ "type": "https://ermeon.com/problems/validation", "code": "unauthorized"}