Authentication
| Scope | Header |
| Applications API | Authorization: Bearer <jwt> |
| Payments & Subscriptions API | X-API-Key: <application-api-key> |
The API key is generated when an application is registered. In Swagger, click
Authorize and provide the JWT and/or the API key.
Applications
| Method | Endpoint | Description |
| POST | /applications | Register an application |
| GET | /applications | List applications |
| GET | /applications/:id | Get an application |
| POST | /applications/:id | Update an application |
| DELETE | /applications/:id | Delete an application |
curl -X POST http://localhost:3000/applications \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{
"name": "My Store",
"webhookUrl": "https://my-store.com/webhook/payment",
"subscriptionWebhookUrl": "https://my-store.com/webhook/subscription"
}'
Payments
| Method | Endpoint | Description |
| POST | /payments | Create a payment |
| POST | /payments/payment-link | Create a hosted payment link |
| POST | /payments/save-payment-method | Tokenize a payment method (Xendit/Midtrans) |
| GET | /payments | List payments for the application |
Create a payment
| Field | Type | Required | Description |
| amount | number | Yes | Amount in the smallest currency unit |
| provider | string | Yes | XENDIT · MIDTRANS · MAYAR |
| applicationOrderId | string | No | Your internal order id |
| currency | string | No | Defaults to IDR |
| customerName | string | Mayar | Required by Mayar |
| customerEmail | string | No | Customer email |
| customerPhone | string | Mayar | Required by Mayar |
| xenditPaymentMethod | string | Xendit | See provider docs |
| midtransPaymentMethod | string | Midtrans | See provider docs |
| midtransBankCode | string | Conditional | For bank_transfer |
| mayarPaymentMethod | string | No | e.g. qris, va/bni |
| mayarExpiredAt | string | No | ISO 8601 expiry |
| metadata | object | No | Arbitrary metadata |
{
"amount": 50000,
"provider": "MAYAR",
"applicationOrderId": "ORDER-12345",
"customerName": "Budi Santoso",
"customerEmail": "budi@example.com",
"customerPhone": "081234567890",
"mayarPaymentMethod": "qris",
"description": "Order #12345"
}
Response (abridged):
{
"data": {
"id": "uuid",
"externalId": "trx-...",
"status": "PENDING",
"provider": "MAYAR",
"checkoutUrl": "https://.../invoices/abc"
},
"checkoutUrl": "https://.../invoices/abc"
}
Payment link
Same body as /payments plus optional provider options objects:
xenditOptions, midtransOptions and mayarOptions
(expiredAt, paymentMethod).
| Field | Type | Required | Description |
| successRedirectUrl | string | No | Absolute http(s) URL the customer is sent to after a successful payment |
| failureRedirectUrl | string | No | Absolute http(s) URL the customer is sent to after a failed payment |
Redirect URLs must be absolute http/https URLs. Local
hosts such as http://localhost:3000/result are accepted so the
flow can be tested in development. They are applied by Xendit and Midtrans
only — Mayar invoices have no redirect parameter, so the values are ignored
for provider: "MAYAR".
Subscriptions
| Method | Endpoint | Description |
| POST | /subscriptions | Create a subscription |
| GET | /subscriptions | List subscriptions |
| GET | /subscriptions/:id | Get a subscription |
| PUT | /subscriptions/:id | Update a subscription |
| POST | /subscriptions/:id/pause | Pause |
| POST | /subscriptions/:id/resume | Resume |
| DELETE | /subscriptions/:id | Cancel |
Subscriptions are supported by Xendit and Midtrans. Provide the required
metadata: Xendit needs pm_id and customerId;
Midtrans needs saved_token_id.
Provider callbacks
| Method | Endpoint | Verification |
| POST | /payments/xendit-callback | x-callback-token |
| POST | /payments/midtrans-callback | SHA256 signature |
| POST | /payments/mayar-callback | x-mayar-token (optional) |
| POST | /subscriptions/xendit-callback | x-callback-token |
| POST | /subscriptions/midtrans-callback | SHA256 signature |
See the Webhooks guide for payloads and forwarding details.
Admin API
The admin endpoints back the dashboard at /admin. They require an
admin JWT (Authorization: Bearer <jwt>) issued by
POST /login, and are not part of the public merchant API.
| Method | Endpoint | Description |
| POST | /login | Admin login (returns a JWT) |
| GET | /admin/dashboard | Dashboard summary, trends and recent activity |
| GET | /admin/applications | List applications |
| GET | /admin/applications/:id | Get an application |
| POST | /admin/applications | Register an application |
| POST | /admin/applications/:id | Update an application |
| DELETE | /admin/applications/:id | Delete an application |
| GET | /admin/payments | Paginated payments |
| GET | /admin/subscriptions | Paginated subscriptions |
| GET | /admin/providers | List providers (add ?includeUnconfigured=true for all) |
| PUT | /admin/providers/:id | Enable or disable a provider |
List endpoints return { "data": [...], "meta": { "page", "limit", "total", "totalPages" } };
single resources return { "data": { ... } }.
curl -X POST http://localhost:3000/login \
-H "Content-Type: application/json" \
-d '{ "username": "admin", "password": "admin123" }'
curl -X POST http://localhost:3000/admin/applications \
-H "Authorization: Bearer <jwt>" \
-H "Content-Type: application/json" \
-d '{ "name": "My Store", "webhookUrl": "https://my-store.com/webhook" }'
Status codes
| Code | Meaning |
| 200 / 201 | Success |
| 400 | Validation error or unsupported provider |
| 401 | Missing or invalid API key / JWT |
| 403 | Application inactive |
| 404 | Resource not found |
| 502 | Provider error |