Billing
Your plan, your operational balance, and where to send money to top it up (merchant accounts).
/v1/billingEvery fee on the rate card is drawn from a prepaid OPERATIONAL BALANCE in USD cents. You fund it by sending USDT or USDC (credited at par) or a chain's native coin (credited at spot) to one of your funding addresses (GET /v1/billing/funding).
live.ok says whether live invoices are accepted right now; activation says how much more the balance needs before the plan you chose switches on. The balance stays yours: it is refundable on request.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/billing"{ "object": "billing", "plan": "drift", "plan_name": "string", "plan_status": "pending", "plan_activated_at": "2019-08-24T14:15:22Z", "requested_plan": "string", "requested_plan_name": "string", "balance_cents": "string", "onboarding_paid_cents": "string", "live": { "ok": true, "reason": "plan_not_active" }, "low_balance": { "line_cents": "string", "source": "custom", "automatic_cents": "string", "alerted_at": "2019-08-24T14:15:22Z", "exhausted_at": "2019-08-24T14:15:22Z" }, "auto_topup": { "enabled": true, "source": "service", "last_attempt_at": "2019-08-24T14:15:22Z" }, "onboarding": { "steps": [ { "step": "plan", "done": true, "bypassed": true, "complete": true } ], "bypassed": [ "address" ], "skipped_at": "2019-08-24T14:15:22Z", "can_skip": true, "remaining": 0 }, "activation": { "plan": "string", "plan_name": "string", "onboarding_due_cents": "string", "balance_required_cents": "string", "shortfall_cents": "string" }, "fees": { "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "address_fee_cents": "string", "min_monthly_cents": "string", "history_days": 0, "chains_included": 0, "extra_chain_cents": "string", "webhooks": true, "auto_conversion": true, "statements": true }, "plans": [ { "key": "string", "name": "string", "onboarding_fee_cents": "string", "min_monthly_cents": "string", "operational_balance_cents": "string", "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "negotiated": true } ], "billing_account": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "shared": true, "merchants": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "display_name": "string", "current": true } ] }}/v1/billing/planActivates immediately when the balance already covers the plan's onboarding fee (an upgrade pays only the difference) plus its operational balance; otherwise the plan is recorded as requested and activates on the funding credit that closes the gap. Enterprise is agreed with us and cannot be self-selected.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/billing/plan" \ -H "Content-Type: application/json" \ -d '{ "plan": "drift" }'{ "object": "billing", "plan": "drift", "plan_name": "string", "plan_status": "pending", "plan_activated_at": "2019-08-24T14:15:22Z", "requested_plan": "string", "requested_plan_name": "string", "balance_cents": "string", "onboarding_paid_cents": "string", "live": { "ok": true, "reason": "plan_not_active" }, "low_balance": { "line_cents": "string", "source": "custom", "automatic_cents": "string", "alerted_at": "2019-08-24T14:15:22Z", "exhausted_at": "2019-08-24T14:15:22Z" }, "auto_topup": { "enabled": true, "source": "service", "last_attempt_at": "2019-08-24T14:15:22Z" }, "onboarding": { "steps": [ { "step": "plan", "done": true, "bypassed": true, "complete": true } ], "bypassed": [ "address" ], "skipped_at": "2019-08-24T14:15:22Z", "can_skip": true, "remaining": 0 }, "activation": { "plan": "string", "plan_name": "string", "onboarding_due_cents": "string", "balance_required_cents": "string", "shortfall_cents": "string" }, "fees": { "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "address_fee_cents": "string", "min_monthly_cents": "string", "history_days": 0, "chains_included": 0, "extra_chain_cents": "string", "webhooks": true, "auto_conversion": true, "statements": true }, "plans": [ { "key": "string", "name": "string", "onboarding_fee_cents": "string", "min_monthly_cents": "string", "operational_balance_cents": "string", "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "negotiated": true } ], "billing_account": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "shared": true, "merchants": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "display_name": "string", "current": true } ] }}/v1/billing/low_balanceYour own line for billing.balance_low, in USD cents as a string, or null for the automatic one (about 7 days of your recent fees, never under $20). On a shared balance it is the account's line: every merchant sharing it is alerted by the same one. A new line that puts the current balance under it alerts at once.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://example.com/v1/billing/low_balance" \ -H "Content-Type: application/json" \ -d '{ "line_cents": "string" }'{ "object": "billing", "plan": "drift", "plan_name": "string", "plan_status": "pending", "plan_activated_at": "2019-08-24T14:15:22Z", "requested_plan": "string", "requested_plan_name": "string", "balance_cents": "string", "onboarding_paid_cents": "string", "live": { "ok": true, "reason": "plan_not_active" }, "low_balance": { "line_cents": "string", "source": "custom", "automatic_cents": "string", "alerted_at": "2019-08-24T14:15:22Z", "exhausted_at": "2019-08-24T14:15:22Z" }, "auto_topup": { "enabled": true, "source": "service", "last_attempt_at": "2019-08-24T14:15:22Z" }, "onboarding": { "steps": [ { "step": "plan", "done": true, "bypassed": true, "complete": true } ], "bypassed": [ "address" ], "skipped_at": "2019-08-24T14:15:22Z", "can_skip": true, "remaining": 0 }, "activation": { "plan": "string", "plan_name": "string", "onboarding_due_cents": "string", "balance_required_cents": "string", "shortfall_cents": "string" }, "fees": { "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "address_fee_cents": "string", "min_monthly_cents": "string", "history_days": 0, "chains_included": 0, "extra_chain_cents": "string", "webhooks": true, "auto_conversion": true, "statements": true }, "plans": [ { "key": "string", "name": "string", "onboarding_fee_cents": "string", "min_monthly_cents": "string", "operational_balance_cents": "string", "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "negotiated": true } ], "billing_account": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "shared": true, "merchants": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "display_name": "string", "current": true } ] }}/v1/billing/auto_topupWhen your prepaid balance reaches zero, MolnPay refills it back to the alert line from your service wallet or your own wallet (source first, the other second). On by default. Top-ups are a non-refundable credit for MolnPay fees. On a shared balance this is the account's setting.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
At least one of the two.
At least one of the two.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X PUT "https://example.com/v1/billing/auto_topup" \ -H "Content-Type: application/json" \ -d '{}'{ "object": "billing", "plan": "drift", "plan_name": "string", "plan_status": "pending", "plan_activated_at": "2019-08-24T14:15:22Z", "requested_plan": "string", "requested_plan_name": "string", "balance_cents": "string", "onboarding_paid_cents": "string", "live": { "ok": true, "reason": "plan_not_active" }, "low_balance": { "line_cents": "string", "source": "custom", "automatic_cents": "string", "alerted_at": "2019-08-24T14:15:22Z", "exhausted_at": "2019-08-24T14:15:22Z" }, "auto_topup": { "enabled": true, "source": "service", "last_attempt_at": "2019-08-24T14:15:22Z" }, "onboarding": { "steps": [ { "step": "plan", "done": true, "bypassed": true, "complete": true } ], "bypassed": [ "address" ], "skipped_at": "2019-08-24T14:15:22Z", "can_skip": true, "remaining": 0 }, "activation": { "plan": "string", "plan_name": "string", "onboarding_due_cents": "string", "balance_required_cents": "string", "shortfall_cents": "string" }, "fees": { "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "address_fee_cents": "string", "min_monthly_cents": "string", "history_days": 0, "chains_included": 0, "extra_chain_cents": "string", "webhooks": true, "auto_conversion": true, "statements": true }, "plans": [ { "key": "string", "name": "string", "onboarding_fee_cents": "string", "min_monthly_cents": "string", "operational_balance_cents": "string", "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "negotiated": true } ], "billing_account": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "shared": true, "merchants": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "display_name": "string", "current": true } ] }}/v1/billing/onboarding/skipHides the four-step panel on your console overview. It is a display preference and grants nothing: the steps after the first — issue an address, take a test payment, go live — were never gates, and the only thing standing between your account and a live payment is an active plan with a positive balance.
Refused with plan_not_active until your plan is on, because until then the panel is the only thing explaining why live invoices are being declined. Idempotent: calling it twice does not move the recorded timestamp.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X POST "https://example.com/v1/billing/onboarding/skip"{ "object": "billing", "plan": "drift", "plan_name": "string", "plan_status": "pending", "plan_activated_at": "2019-08-24T14:15:22Z", "requested_plan": "string", "requested_plan_name": "string", "balance_cents": "string", "onboarding_paid_cents": "string", "live": { "ok": true, "reason": "plan_not_active" }, "low_balance": { "line_cents": "string", "source": "custom", "automatic_cents": "string", "alerted_at": "2019-08-24T14:15:22Z", "exhausted_at": "2019-08-24T14:15:22Z" }, "auto_topup": { "enabled": true, "source": "service", "last_attempt_at": "2019-08-24T14:15:22Z" }, "onboarding": { "steps": [ { "step": "plan", "done": true, "bypassed": true, "complete": true } ], "bypassed": [ "address" ], "skipped_at": "2019-08-24T14:15:22Z", "can_skip": true, "remaining": 0 }, "activation": { "plan": "string", "plan_name": "string", "onboarding_due_cents": "string", "balance_required_cents": "string", "shortfall_cents": "string" }, "fees": { "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "address_fee_cents": "string", "min_monthly_cents": "string", "history_days": 0, "chains_included": 0, "extra_chain_cents": "string", "webhooks": true, "auto_conversion": true, "statements": true }, "plans": [ { "key": "string", "name": "string", "onboarding_fee_cents": "string", "min_monthly_cents": "string", "operational_balance_cents": "string", "rate_bps": 0, "fixed_cents": "string", "cap_cents": "string", "negotiated": true } ], "billing_account": { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "shared": true, "merchants": [ { "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "display_name": "string", "current": true } ] }}/v1/billing/fundingOne address per chain, created on first call and stable forever. EVM chains on the MolnPay factory share one address; read the list rather than assuming. Send only the assets listed for that chain; anything else is not credited.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/billing/funding"{ "object": "list", "has_more": true, "next_cursor": "string", "data": [ { "object": "funding_address", "chain": "ethereum", "address": "string", "memo": "string", "account_kind": "contract", "assets": [ { "symbol": "string", "decimals": 0, "par": true, "logo_url": "string" } ] } ]}/v1/billing/statementsOne row per CLOSED calendar month of the billing ledger with at least one line, oldest first: the balance it opened on, what was funded, what was charged, the balance it closed on. The current month is never listed — it has not closed. Included from the Growth plan up; the ledger itself (GET /v1/billing/entries) is on every plan.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/billing/statements"{ "object": "list", "has_more": true, "next_cursor": "string", "data": [ { "object": "statement_summary", "month": "string", "opening_cents": "string", "closing_cents": "string", "funded_cents": "string", "charged_cents": "string", "entries": 0 } ]}/v1/billing/statements/{month}The opening balance, every ledger line of the month in order, totals by kind, and the closing balance. ?format=csv returns the same as a spreadsheet (text/csv, one row per line with a running balance) — what an accountant reconciles against. Not windowed by your plan's history: a statement always covers its whole month.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Path Parameters
YYYY-MM, a month that has closed.
^\d{4}-(0[1-9]|1[0-2])$Query Parameters
"json"Value in
- "json"
- "csv"
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/billing/statements/string"{ "object": "statement", "month": "string", "period_start": "2019-08-24T14:15:22Z", "period_end": "2019-08-24T14:15:22Z", "opening_cents": "string", "closing_cents": "string", "funded_cents": "string", "charged_cents": "string", "by_kind": [ { "kind": "string", "amount_cents": "string", "entries": 0 } ], "entries": [ { "object": "billing_entry", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "merchant_id": "500924a8-3f5e-4c00-beb8-2efcde988aea", "merchant_name": "string", "kind": "funding", "amount_cents": "string", "ref_type": "string", "ref_id": "string", "chain": "string", "asset": "string", "asset_logo_url": "string", "amount_atomic": "string", "rate": "string", "rate_source": "string", "note": "string", "created_at": "2019-08-24T14:15:22Z", "transfer": { "amount_decimal": "string", "tx_hash": "string", "explorer_url": "string", "from_address": "string", "confirmations": 0, "required_confirmations": 0, "status": "detected", "block_time": "2019-08-24T14:15:22Z" } } ], "generated_at": "2019-08-24T14:15:22Z"}/v1/billing/entriesThe BILLING ACCOUNT's ledger: when several of your merchants share one plan and balance, every one of them sees the same lines, each stamped with merchant_id / merchant_name for the merchant it came from. merchant_id (one of billing_account.merchants on GET /v1/billing) narrows to that merchant's lines.
Authorization
apiKey Authorization: Bearer mp<64 hex> for live, mptest<64 hex> for test.
The token is the prefix plus 64 lowercase hex characters (32 CSPRNG bytes) and nothing else — no separators, no embedded fields — so nothing in it needs quoting, escaping or encoding.
Send it in the Authorization header and nowhere else. Never put it in a query string: URLs reach access logs, proxy logs, browser history and Referer headers, and a key that lands in any of those is a leaked key.
A key's KIND (checkout, payout or wallet) is a property of the key, not of the string: it is chosen at creation, returned by GET /v1/ping, and decides which routes the key may reach.
The full key is shown exactly once, at creation. No endpoint can return it afterwards. Moving funds additionally requires signing to be enabled globally, for your project, and for that key — so a read-only key is a supported configuration.
In: header
Query Parameters
1 <= value <= 10025Opaque cursor from the previous page's next_cursor.
Value in
- "funding"
- "onboarding_fee"
- "payment_fee"
- "address_fee"
- "payout_fee"
- "withdrawal_fee"
- "monthly_minimum"
- "refund"
- "adjustment"
- "conversion_fee"
- "release"
- "bridge_fee"
- "extra_chain"
- "payout_network_fee"
- "extra_seat"
- "conversion_network_fee"
- "bridge_network_fee"
- "fee_rebate"
- "network_markup"
- "sweep_network_fee"
A merchant's public id on this billing account.
uuidResponse Body
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v1/billing/entries"{ "object": "list", "has_more": true, "next_cursor": "string", "data": [ { "object": "billing_entry", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "merchant_id": "500924a8-3f5e-4c00-beb8-2efcde988aea", "merchant_name": "string", "kind": "funding", "amount_cents": "string", "ref_type": "string", "ref_id": "string", "chain": "string", "asset": "string", "asset_logo_url": "string", "amount_atomic": "string", "rate": "string", "rate_source": "string", "note": "string", "created_at": "2019-08-24T14:15:22Z", "transfer": { "amount_decimal": "string", "tx_hash": "string", "explorer_url": "string", "from_address": "string", "confirmations": 0, "required_confirmations": 0, "status": "detected", "block_time": "2019-08-24T14:15:22Z" } } ]}