Docs/Payments

Payments

One API call creates a Midtrans checkout session. The user pays. We verify the webhook, assign the plan claim to the user, and POST a payment.settled event to your server. Free plans skip checkout entirely โ€” the claim is assigned instantly. You don't touch Midtrans directly.

What payment methods are supported?

All the ones your Indonesian users actually use:

QRIS
Scan to pay
GoPay
E-wallet
ShopeePay
E-wallet
Bank Transfer
BCA, BNI, BRI, Mandiri
Credit Card
Visa, Mastercard
BCA KlikPay
Internet banking
BRI e-Pay
Internet banking
E-Channel
Mandiri Bill

How it works

1
You call our API
POST /api/platform/payment with your client credentials, the user's ID, and the plan they're paying for.
2
We create a Midtrans checkout
You get back an invoice_url. Redirect the user there.
3
User pays
Midtrans handles the checkout UI, payment processing, and fraud checks.
4
We handle the webhook
Midtrans notifies us. We verify the signature, update the payment record, and auto-assign the plan claim to the user.
5
We notify you
If you've configured a webhook URL on your project, we POST a payment.settled event to it.

Create a payment

Call this from your backend โ€” never from the browser. The client_secret must stay server-side.

create-payment.tstypescript
const res = await fetch("https://astapa.com/api/platform/payment", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    client_id: process.env.ASTAPA_CLIENT_ID,
    client_secret: process.env.ASTAPA_CLIENT_SECRET,
    end_user_id: "user-uuid",          // from your JWT's sub claim
    plan_id: "plan-uuid",              // from your plan registry
    customer_email: "user@example.com",
    customer_name: "John Doe",         // optional
    metadata: { ref: "upgrade-flow" }, // optional, passed to webhook
  }),
});

const { invoice_url, order_id, payment_id } = await res.json();

// Redirect the user to complete payment
return redirect(invoice_url);

Payment statuses

StatusWhat it means
pendingCheckout created, waiting for the user to pay
settlementPayment confirmed โ€” plan claim updated, webhook fired
captureCredit card captured (treat same as settlement)
denyPayment denied by the provider
cancelUser cancelled
expirePayment window expired (usually 24h)
refundFull or partial refund processed

Get notified when payments settle

Set a webhook URL on your project (Settings tab in the dashboard, or PATCH /api/platform/projects/[id] with webhook_url). We'll POST to it after every settled payment โ€” subscriptions and item purchases.

webhook-payload.jsonjson
{
  "event": "payment.settled",
  "order_id": "proj-abc123-1a2b3c4d",
  "plan_id": "plan-uuid",
  "plan_key": "pro",
  "plan_display_name": "Pro Plan",
  "plan_period": "monthly",
  "end_user_id": "user-uuid",
  "amount": 29000,
  "currency": "IDR",
  "paid_at": "2026-05-06T10: 00: 00Z",
  "metadata": { "ref": "upgrade-flow" }
}
X-Astapa-Event header
Every webhook request includes X-Astapa-Event: payment.settled. Use it to route events in a single handler.
webhook-handler.tstypescript
export async function POST(req: Request) {
  const event = req.headers.get("X-Astapa-Event");
  const body = await req.json();

  if (event === "payment.settled") {
    // Plan claim is already updated on the user โ€” this is just your chance
    // to do anything else: send a receipt, provision resources, etc.
    await sendReceiptEmail(body.end_user_id, body.amount);
  }

  return new Response("ok");
}
Webhook delivery is logged
Every delivery attempt โ€” including failures โ€” is logged with the full payload and response. Check the Payments โ†’ Webhook Logs tab in your dashboard. Failed deliveries show a Retry button.

Want the full webhook story? See the Webhooks page.

View payment history

Testing in sandbox

Use your sandbox credentials and Midtrans routes to their test environment automatically. No real money moves.

MethodTest credentials
Credit card4811 1111 1111 1114 ยท any future expiry ยท CVV 123
GoPay / QRISAuto-approve in Midtrans sandbox dashboard

Related

API Playground
Click "Try it" on any endpoint to get started.
Payments | Astapa