Skip to content

Create a payment

POST /v1/partners/payments

Creates the thing a customer pays with: a virtual account number, a QRIS payload, or an e-wallet checkout link. It does not take any money — that happens when the customer pays.

Permissioncollect-payment
IdempotencyRequiredX-Idempotency-Key, 8–128 characters
Answers200
POST /v1/partners/payments
Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx
x-partner-signature: <hmac-sha256 of the raw body, hex>
X-Idempotency-Key: order-2026-09-03-00417
Content-Type: application/json
{
"method": "virtual_account",
"amount": "100000",
"channel": "BRI",
"external_ref": "INV-2026-0912",
"customer_name": "Siti Rahmawati",
"expires_in_minutes": 1440
}
FieldRequiredNotes
methodyesvirtual_account, qris, or ewallet
amountyesDecimal string. "100000" or "100000.00". The provider-facing gross for this payment method must be a whole IDR amount; under the default DEDUCTED mode, use a whole-IDR amount
channeldependsIssuing bank for a virtual account (BRI); wallet vendor for e-wallet (EWALLET_DANA). Omit for QRIS — one QR is scannable by every wallet
external_refnoYour own reference, echoed on every response and searchable in the console. Strongly recommended
organization_idnoWhich co-operative under you this belongs to, so you can reconcile per organisation. Must be one Moria has linked to your account — an unlinked id is refused with RESOURCE_NOT_LINKED rather than quietly attributed
customer_nameno
customer_emailno
customer_phoneno
expires_in_minutesnoHow long the instrument stays payable. Defaults to 24 hours

Answers 200, not 201 — the payment exists, but nothing has been paid.

{
"data": {
"id": "0f3c…",
"reference": "INV-2026-0912",
"status": "pending",
"is_final": false,
"method": "virtual_account",
"channel": "BRI",
"amount": "100000.0000",
"net_amount": "96000.0000",
"fee": "4000.0000",
"currency": "IDR",
"payment_code": "888801000157508",
"status_url": "/v1/partners/payments/0f3c…",
"expires_at": "2026-09-04T07:00:00.000Z",
"created_at": "2026-09-03T07:00:00.000Z",
"finalized_at": null
},
"request_id": "req_…"
}

payment_code is what the customer pays with, and its meaning follows method:

Methodpayment_code holds
virtual_accountThe VA number to transfer to
qrisThe QR payload to render
ewalletThe checkout URL to send them to

reference echoes your external_ref when you sent one, and falls back to Moria’s own reference when you did not — which is one reason to always send one.

Fees are reported as one partner-facing figure: amount is the gross, fee is the combined charge, and net_amount is yours. Moria keeps the provider/margin split internally for accounting and reconciliation.

CodeMeans
REQUEST_IDEMPOTENCY_KEY_REUSEDThe key is already attached to a different request. Usually a bug where one key is reused across orders
REQUEST_INVALID_PAYLOADThe provider-facing gross is fractional; money-in instruments require a whole IDR amount
RESOURCE_NOT_LINKEDThe organization_id is not linked to your account, or its link was revoked
AUTH_PARTNER_INACTIVEYour account is not active yet — KYB has not passed
PROVIDER_INDETERMINATEWe asked the provider and cannot tell whether it worked. Poll; do not re-send

The full list is on Errors.