API Reference

HTTP API

Base URL http://localhost:3000. Prefer the interactive Swagger UI for try-it-out requests.

Authentication

ScopeHeader
Applications APIAuthorization: Bearer <jwt>
Payments & Subscriptions APIX-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

MethodEndpointDescription
POST/applicationsRegister an application
GET/applicationsList applications
GET/applications/:idGet an application
POST/applications/:idUpdate an application
DELETE/applications/:idDelete 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

MethodEndpointDescription
POST/paymentsCreate a payment
POST/payments/payment-linkCreate a hosted payment link
POST/payments/save-payment-methodTokenize a payment method (Xendit/Midtrans)
GET/paymentsList payments for the application

Create a payment

FieldTypeRequiredDescription
amountnumberYesAmount in the smallest currency unit
providerstringYesXENDIT · MIDTRANS · MAYAR
applicationOrderIdstringNoYour internal order id
currencystringNoDefaults to IDR
customerNamestringMayarRequired by Mayar
customerEmailstringNoCustomer email
customerPhonestringMayarRequired by Mayar
xenditPaymentMethodstringXenditSee provider docs
midtransPaymentMethodstringMidtransSee provider docs
midtransBankCodestringConditionalFor bank_transfer
mayarPaymentMethodstringNoe.g. qris, va/bni
mayarExpiredAtstringNoISO 8601 expiry
metadataobjectNoArbitrary 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).

FieldTypeRequiredDescription
successRedirectUrlstringNoAbsolute http(s) URL the customer is sent to after a successful payment
failureRedirectUrlstringNoAbsolute 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

MethodEndpointDescription
POST/subscriptionsCreate a subscription
GET/subscriptionsList subscriptions
GET/subscriptions/:idGet a subscription
PUT/subscriptions/:idUpdate a subscription
POST/subscriptions/:id/pausePause
POST/subscriptions/:id/resumeResume
DELETE/subscriptions/:idCancel
Subscriptions are supported by Xendit and Midtrans. Provide the required metadata: Xendit needs pm_id and customerId; Midtrans needs saved_token_id.

Provider callbacks

MethodEndpointVerification
POST/payments/xendit-callbackx-callback-token
POST/payments/midtrans-callbackSHA256 signature
POST/payments/mayar-callbackx-mayar-token (optional)
POST/subscriptions/xendit-callbackx-callback-token
POST/subscriptions/midtrans-callbackSHA256 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.

MethodEndpointDescription
POST/loginAdmin login (returns a JWT)
GET/admin/dashboardDashboard summary, trends and recent activity
GET/admin/applicationsList applications
GET/admin/applications/:idGet an application
POST/admin/applicationsRegister an application
POST/admin/applications/:idUpdate an application
DELETE/admin/applications/:idDelete an application
GET/admin/paymentsPaginated payments
GET/admin/subscriptionsPaginated subscriptions
GET/admin/providersList providers (add ?includeUnconfigured=true for all)
PUT/admin/providers/:idEnable 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

CodeMeaning
200 / 201Success
400Validation error or unsupported provider
401Missing or invalid API key / JWT
403Application inactive
404Resource not found
502Provider error