Skip to content

Quickstart

Create a test payment with the Baiyar API, pay it in the sandbox, and read the result, using curl or Node.js.


You need a test API key and a project that accepts the payment method you try. If you have neither, create a project in the sandbox (every method is available there) and get a test key. Keep the key in an environment variable:

Terminal window
export BAIYAR_KEY="bk_test_…"
export BAIYAR_API="https://api.baiyar.com"
Terminal window
curl "$BAIYAR_API/v1/account" -H "Authorization: Bearer $BAIYAR_KEY"
{
"data": {
"livemode": false,
"merchant": { "id": "mer_01k7…" },
"project": { "id": "prj_01k7…" },
"key": { "id": "apk_01k7…", "kind": "project", "scopes": ["payments:read", "payments:write"] }
},
"meta": { "request_id": "req_…" }
}

Every answer has the same two parts: data is what you asked for, and meta is about the request (its request_id, and for a list its pagination). data.livemode: false confirms that this is a test key.

A payment needs an Idempotency-Key. When retrying a timed-out request, send the same key and body so Baiyar returns the same payment. API amounts use the currency’s smallest unit: Rp10.000 is 1000000.

Terminal window
curl "$BAIYAR_API/v1/payments" \
-H "Authorization: Bearer $BAIYAR_KEY" \
-H "Idempotency-Key: order-1001-attempt-1" \
-H "Content-Type: application/json" \
-d '{
"amount": 1000000,
"currency": "IDR",
"payment_method": "payment.qris",
"merchant_reference": "order-1001",
"description": "Order 1001",
"customer": { "name": "Sari Wijaya", "email": "sari@example.com" }
}'

The answer (201) has the payment in data. Its initial status is pending; instruction tells the payer how to complete it. For QRIS it is { "type": "qr", "qr_content": "…", "expires_at": "…" }: render qr_content as a QR code. Other methods answer with a virtual account (va), a wallet link (ewallet_link), a wallet push (ewallet_push) or a retail code (retail_code).

Fields used in the request:

Field Purpose
amount, currency The base amount before fees and its currency code. Send IDR as an integer in the smallest unit, not as a rupiah amount.
payment_method The requested method, such as payment.qris. The method must also be available to the project in that environment.
project_id The project that owns the payment. Required for a merchant-wide key; a project key is already bound to its project.
merchant_reference Your order ID, so you can find the payment and match it back to your order.
description A short label to identify the payment in the dashboard.
customer Optional payer details. Some payment methods require a phone number.
metadata Your text key-value pairs, returned on the payment and webhook events. Do not put secrets or sensitive data here.
expires_in How long the payment stays open before it expires, in seconds. It can be 300 seconds to 7 days; the default depends on the method.

The response also includes fee, charged_amount (what the payer is charged, including the fee if they bear it) and net_amount (the merchant amount after Baiyar’s fee). After payment, net_amount enters the pending balance and moves to the available balance after provider settlement.

Use a test key to set the outcome of a sandbox payment. This does not charge a payer:

Terminal window
curl "$BAIYAR_API/v1/sandbox/payments/pay_01k7…/simulate" \
-H "Authorization: Bearer $BAIYAR_KEY" \
-H "Content-Type: application/json" \
-d '{ "outcome": "paid" }'

outcome is paid, failed or expired. This endpoint exists for test keys only.

Terminal window
curl "$BAIYAR_API/v1/payments/pay_01k7…" -H "Authorization: Bearer $BAIYAR_KEY"

data.status is now paid. In your own code, do not poll: register a webhook endpoint and handle payment.succeeded.

const api = "https://api.baiyar.com";
const headers = { Authorization: `Bearer ${process.env.BAIYAR_KEY}`, "Content-Type": "application/json" };
const created = await fetch(`${api}/v1/payments`, {
method: "POST",
headers: { ...headers, "Idempotency-Key": "order-1001-attempt-1" },
body: JSON.stringify({ amount: 1_000_000, currency: "IDR", payment_method: "payment.qris" }),
});
if (!created.ok) throw new Error((await created.json()).error.code);
const { data: payment } = await created.json();
console.log(payment.id, payment.status, payment.instruction);
await fetch(`${api}/v1/sandbox/payments/${payment.id}/simulate`, {
method: "POST",
headers,
body: JSON.stringify({ outcome: "paid" }),
});

You can also run every one of these requests from the API reference: every operation has a Try it button that opens a request client in your browser, against the sandbox.

Live needs a project that has been approved for live and a verified account. Make a live key and keep the code the same: only the key changes.