API reference for integrating payments into your application.
Base URL: https://msdzul.com
All endpoints require your per-app API key. Send it as a bearer token on every request.
Authorization: Bearer <per-app-api-key>
Transaction endpoints for your application. All requests require your per-app API key.
/api/v1/transactions/create
Headers
Authorization: Bearer <per-app-api-key>
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
webhook_url
|
string
|
Yes
|
URL to receive webhook when payment completes |
order_id
|
string
|
Yes
|
Unique order ID from your system |
amount
|
int
|
Yes
|
Payment amount in IDR (e.g., 50000) |
payment_method
|
string
|
Yes
|
Payment method (see below) |
Payment methods
| Method | Description |
|---|---|
qris
|
QRIS (QR Code) |
bri_va
|
BRI Virtual Account |
bni_va
|
BNI Virtual Account |
permata_va
|
Permata Virtual Account |
cimb_niaga_va
|
CIMB Niaga Virtual Account |
sampoerna_va
|
Sampoerna Virtual Account |
bnc_va
|
Bank Neo Commerce Virtual Account |
maybank_va
|
Maybank Virtual Account |
atm_bersama_va
|
ATM Bersama Virtual Account |
artha_graha_va
|
Artha Graha Virtual Account |
Example request
curl -X POST https://msdzul.com/api/v1/transactions/create \
-H "Authorization: Bearer <per-app-api-key>" \
-H "Content-Type: application/json" \
-d '{
"webhook_url": "https://your-app.com/webhook/pakasir",
"order_id": "INV20260819-001",
"amount": 50000,
"payment_method": "qris"
}'
Success response (201 Created)
{
"payment": {
"project": "my-shop",
"order_id": "INV20260819-001",
"amount": 50000,
"fee": 750,
"total_payment": 50750,
"payment_method": "qris",
"payment_number": "00020101021226610016ID.CO.SHOPEE.WWW0118...",
"expired_at": "2026-08-20T12:00:00.000Z"
}
}
Error responses
| Status | Error | Description |
|---|---|---|
400
|
invalid request body
|
Malformed JSON |
400
|
webhook_url is required
|
Missing webhook_url |
400
|
order_id is required
|
Missing order_id |
400
|
amount must be greater than 0
|
Invalid amount |
400
|
invalid payment_method
|
Unknown payment method |
401
|
unauthorized
|
Invalid or missing API key |
409
|
transaction already exists
|
Duplicate order_id for this project |
502
|
Pakasir error message | Error from Pakasir (message forwarded) |
500
|
failed to save transaction
|
Database error |
/api/v1/transactions/cancel
Headers
Authorization: Bearer <per-app-api-key>
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
order_id
|
string
|
Yes
|
Order ID to cancel |
amount
|
int
|
Yes
|
Original transaction amount |
Example request
curl -X POST https://msdzul.com/api/v1/transactions/cancel \
-H "Authorization: Bearer <per-app-api-key>" \
-H "Content-Type: application/json" \
-d '{
"order_id": "INV20260819-001",
"amount": 50000
}'
Success response (200 OK)
{
"status": "cancelled"
}
Error responses
| Status | Error | Description |
|---|---|---|
400
|
invalid request body
|
Malformed JSON |
400
|
order_id is required
|
Missing order_id |
400
|
transaction is already cancelled
|
Already cancelled |
400
|
transaction is already completed
|
Already completed |
400
|
transaction is expired
|
Payment window expired |
401
|
unauthorized
|
Invalid or missing API key |
404
|
transaction not found
|
Transaction not in database |
502
|
Pakasir error message | Error from Pakasir (message forwarded) |
500
|
failed to update transaction status
|
Database error |
/api/v1/transactions/{order_id}
Header
Authorization: Bearer <per-app-api-key>
| Parameter | Description |
|---|---|
order_id
|
The order ID to look up |
Example request
curl https://msdzul.com/api/v1/transactions/INV20260819-001 \
-H "Authorization: Bearer <per-app-api-key>"
Success response (200 OK)
{
"id": "507f1f77bcf86cd799439011",
"app": "my_app",
"webhook_url": "https://your-app.com/webhook/pakasir",
"project": "my-shop",
"order_id": "INV20260819-001",
"amount": 50000,
"fee": 750,
"total_payment": 50750,
"payment_method": "qris",
"payment_number": "00020101021226610016ID.CO.SHOPEE.WWW0118...",
"status": "completed",
"expired_at": "2026-08-20T12:00:00.000Z",
"completed_at": "2026-08-19T15:30:00.000Z",
"created_at": "2026-08-19T15:00:00.000Z",
"updated_at": "2026-08-19T15:30:00.000Z"
}
Transaction statuses
| Status | Description |
|---|---|
pending
|
Waiting for payment |
completed
|
Payment received |
cancelled
|
Transaction cancelled |
expired
|
Payment window expired |
Error responses
| Status | Error | Description |
|---|---|---|
400
|
order_id is required
|
Missing order_id parameter |
401
|
unauthorized
|
Invalid or missing API key |
404
|
transaction not found
|
Transaction not found in database |
/api/v1/transactions/simulate
Simulate a payment for testing. Only available for apps with mode: "sandbox".
Headers
Authorization: Bearer <per-app-api-key>
Content-Type: application/json
| Field | Type | Required | Description |
|---|---|---|---|
order_id
|
string
|
Yes
|
Order ID to simulate |
amount
|
int
|
Yes
|
Payment amount |
Example request
curl -X POST https://msdzul.com/api/v1/transactions/simulate \
-H "Authorization: Bearer <per-app-api-key>" \
-H "Content-Type: application/json" \
-d '{
"order_id": "INV20260819-001",
"amount": 50000
}'
Success response (200 OK)
{
"status": "simulated"
}
Error responses
| Status | Error | Description |
|---|---|---|
400
|
payment simulation only available in sandbox mode
|
App is in production mode |
400
|
invalid request body
|
Malformed JSON |
400
|
order_id is required
|
Missing order_id |
401
|
unauthorized
|
Invalid or missing API key |
502
|
Pakasir error message | Error from Pakasir (message forwarded) |
This endpoint receives webhooks from Pakasir. It does not require authentication.
/webhook/pakasir
Pakasir sends
{
"amount": 50000,
"order_id": "INV20260819-001",
"project": "my-shop",
"status": "completed",
"payment_method": "qris",
"completed_at": "2026-08-19T15:30:00+07:00"
}
project + order_idwebhook_urlResponse
200 OK
The proxy always returns 200 OK to Pakasir to prevent retries. Errors are logged but don't affect the response.
When Pakasir sends a webhook, the proxy forwards the exact same payload to your application. Your app should handle this payload and process the payment accordingly.
{
"amount": 50000,
"order_id": "INV20260819-001",
"project": "my-shop",
"status": "completed",
"payment_method": "qris",
"completed_at": "2026-08-19T15:30:00+07:00"
}
Request and response payloads used by the App API.
CreateTransactionRequest
{
"webhook_url": "string",
"order_id": "string",
"amount": "int",
"payment_method": "string"
}
CancelTransactionRequest
{
"order_id": "string",
"amount": "int"
}
TransactionResponse
{
"payment": {
"project": "string",
"order_id": "string",
"amount": "int",
"fee": "int",
"total_payment": "int",
"payment_method": "string",
"payment_number": "string",
"expired_at": "string"
}
}
WebhookPayload
{
"amount": "int",
"order_id": "string",
"project": "string",
"status": "string",
"payment_method": "string",
"completed_at": "string"
}
ErrorResponse
{
"error": "string"
}
For Pakasir API errors (status 502), the error message contains the raw response from Pakasir. For validation errors (status 400), the message describes the specific field issue.