Skip to main content

How do I create a payment?

Send POST /payment with the amount, method code, and buyer details. The 201 Created response contains the invoice, a payment_link to the SekaliPay payment page, and method-specific payment details. The payment is valid for 30 minutes.

This page was checked against the API code as of October 16, 2026.

Where do I send the request?#

POST/api/v1/gateway/payment
Limit per minute:
5 requests per minute per API key
Signature:
Required in both modes

Which fields do I send?#

merchant_ref_idstringRequired
Order ID from your system, up to 191 characters, unique per account (another account may use the same ref). Stick to letters, digits, -, and _ so it is safe in the status-check URL.
amountintegerRequired
The amount you receive, in rupiah. At least 100 and within the method's min_amount and max_amount.
payment_codestringRequired
Method code from GET /payment-methods. The method must be enabled on your account.
customer_namestringRequired
Buyer name, up to 100 characters.
customer_emailstringRequired
A valid buyer email, up to 100 characters.
customer_phonestringRequired
Buyer phone number, up to 20 characters.
callback_urlstringOptional
Webhook URL for this payment only, up to 500 characters. Must be a public address; localhost and private IPs are rejected. Empty means the dashboard URL.
return_urlstringOptional
Where the buyer's browser goes after paying, up to 500 characters. Empty means the dashboard URL. See Buyer redirects.
metadataobjectOptional
Free-form data for your own use. Stored with the transaction, but not returned in API responses or webhooks.

How much does the buyer pay?#

amount is what you receive. The method fee is added on top, so the buyer pays total = amount + fee. In the example below you receive Rp 150,000 and the buyer pays Rp 151,500. Fees per method are on the fees page.

What does a request look like?#

BODY='{"merchant_ref_id":"ORDER-2026-00184","amount":150000,"payment_code":"QRIS","customer_name":"Budi Santoso","customer_email":"[email protected]","customer_phone":"081234567890","callback_url":"https://toko-anda.id/webhook/sekalipay","return_url":"https://toko-anda.id/checkout/selesai"}'
SIGNATURE=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SEKALIPAY_SECRET_KEY" | sed 's/^.* //')

curl -X POST https://sekalipay.com/api/v1/gateway/payment \
  -H "X-API-Key: $SEKALIPAY_API_KEY" \
  -H "X-Signature: $SIGNATURE" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  --data-raw "$BODY"

The examples above are for IP Whitelist mode. For Enhanced HMAC, use the helper in Authentication.

What does a successful response contain?#

201 Created
{
  "status": true,
  "message": "OK",
  "data": {
    "merchant_ref_id": "ORDER-2026-00184",
    "invoice": "SPY1791446400K3QZ",
    "amount": 150000,
    "fee": 1500,
    "total": 151500,
    "payment_code": "QRIS",
    "payment_link": "https://sekalipay.com/payment/SPY1791446400K3QZ",
    "qr_link": "https://sekalipay.com/payment/SPY1791446400K3QZ/qris",
    "virtual_account": null,
    "checkout_url": null,
    "payment_guide": null,
    "expired_at": "2026-10-08T08:30:00.000000Z",
    "status": "pending",
    "is_sandbox": false
  }
}
invoicestring
SekaliPay invoice number, e.g. SPY1791446400K3QZ. Keep it for reconciliation and support requests.
amountinteger
The amount you receive.
feeinteger
Transaction fee, paid by the buyer.
totalinteger
What the buyer has to pay.
payment_linkstring
The SekaliPay payment page. Always present; sending the buyer here is the simplest option.
qr_linkstring | null
QR image for QRIS methods.
virtual_accountstring | null
VA number for virtual account methods.
checkout_urlstring | null
Link to the e-wallet app or page.
payment_guidestring | null
Payment instructions as HTML when the partner provides them. Sanitize before rendering.
expired_atstring
Payment deadline, ISO 8601 UTC, 30 minutes after creation.
statusstring
Always pending at creation.
is_sandboxboolean
true when created in sandbox mode.

Which payment details are filled depends on the method; the rest are null.

How do I retry a request safely?#

merchant_ref_id is the idempotency key. If a request times out and you do not know the outcome, send it again with the same ref. If the payment already exists, you get 409 PAYMENT_ALREADY_EXISTS with that payment's data instead of a second payment.

409 Conflict
{
  "status": false,
  "message": "PAYMENT_ALREADY_EXISTS",
  "data": {
    "merchant_ref_id": "ORDER-2026-00184",
    "invoice": "SPY1791446400K3QZ",
    "amount": 150000,
    "fee": 1500,
    "total": 151500,
    "payment_code": "QRIS",
    "payment_link": "https://sekalipay.com/payment/SPY1791446400K3QZ",
    "qr_link": "https://sekalipay.com/payment/SPY1791446400K3QZ/qris",
    "expired_at": "2026-10-08T08:30:00.000000Z",
    "status": "pending"
  }
}

Requests rejected with any other error (4xx other than 409, or 5xx) store nothing, so the same ref can be used again.

Which errors are specific to this endpoint?#

HTTPCodeMeaning
403MERCHANT_KYC_INCOMPLETEMerchant verification is incomplete. data.onboarding_url points to the page to complete it.
400PAYMENT_METHOD_NOT_AVAILABLEUnknown method code, or the method is currently disabled.
403PAYMENT_METHOD_NOT_ENABLEDThe method exists but is not enabled on your account.
400AMOUNT_OUT_OF_RANGEThe amount is outside the method's range; data holds min_amount and max_amount.
409PAYMENT_ALREADY_EXISTSThis merchant_ref_id already has a payment; data contains it.
409DUPLICATE_REF_IDTwo requests with the same ref arrived at the same time and this one lost. Check that ref's status.
500PAYMENT_GATEWAY_ERRORThe payment partner rejected the request or did not answer. Nothing was stored; retry with the same ref or another method.
500INTERNAL_SERVER_ERRORAn error on our side; details are not sent. Retry, or contact support with the time and merchant_ref_id.

Plus 422 validation errors and authentication errors; see Error codes.

Ready to use your own keys?

Sign in to the merchant dashboard to copy your API key and secret key, set the access mode and webhook URL, and download a Postman collection with your account's keys.

Sign in to the dashboard