Zeny merchant API
Create payments, pay out money and hear about the result, from your own server.
The API is REST over HTTPS and speaks JSON. Every request goes to https://api.usezeny.com and carries your secret key. The API reference lists every endpoint with its fields; these guides explain the rules that apply to all of them.
Your first payment
- Create a secret key in the dashboard and keep it on your server only. Use a
sk_test_key while you build. See Authentication. - Create a payment with
POST /api/merchant/v1/payments. Nothing is charged yet. - Start an attempt with
POST /api/merchant/v1/payments/{id}/attemptsfor the method the payer picked (virtual account, QRIS or e-wallet). The answer carries anextActionthat tells you what to show the payer. - Wait for the
payment.paidwebhook, then fulfil the order. You can also read the payment withGET /api/merchant/v1/payments/{id}.
curl https://api.usezeny.com/api/merchant/v1/payments \
-H "Authorization: Bearer $ZENY_SECRET_KEY" \
-H "Idempotency-Key: order-1042-create" \
-H "Content-Type: application/json" \
-d '{
"reference": "order-1042",
"amount": { "value": "150000.00", "currency": "IDR" },
"description": "Order 1042"
}'
Every POST that creates or moves money needs an Idempotency-Key, so a retry never charges twice. See Idempotency.
Conventions
- JSON keys are camelCase. Every documented key of a response is always present: an empty object or time is
null, an empty list[], an empty string"". - Ids carry a prefix for their kind:
pay_…,att_…,po_…,evt_…,dsp_…. Treat an id as an opaque string. - Amounts are
Moneyobjects: a decimal stringvalueand acurrency. Never send or read an amount as a floating point number. - Times are UTC, in RFC 3339.
- A field that lists values (a status, an event type) can gain new values in v1. Your code must accept a value it does not know.
- A request field the endpoint does not declare is refused with
400 unknown_field.