Sessions
A session represents a single attempt at collecting a payment from a customer. It is the foundation of every minnha integration.
Lifecycle
| Status | Meaning |
|---|---|
PENDING | Created but not yet paid. |
PROCESSING | Customer submitted payment; awaiting gateway. |
REQUIRES_ACTION | 3-D Secure or extra step needed. |
SUCCESS | Captured. |
FAILED | Authorization declined. |
CANCELLED | Customer abandoned the checkout. |
REFUNDED / PARTIALLY_REFUNDED | After a refund. |
Create a session
POST /api/v1/sessions
X-Api-Key: mp_test_...
{
"amount": 1000.00,
"currency": "SAR",
"description": "Annual tuition fee",
"includeEnrollmentFees": true,
"customerEmail": "customer@example.com",
"customerPhone": "+966512345678",
"successUrl": "https://yourapp.com/orders/123/success",
"cancelUrl": "https://yourapp.com/orders/123/cancel",
"metadata": { "orderId": "ord_123" },
"lineItems": [
{
"skuItem": "TUITION-2026",
"description": "Annual tuition fee",
"amount": 1000.00
}
],
"expiresInMinutes": 60
}amount is the total including VAT and must equal the sum of lineItems[].amount when line items are provided.description (optional) is shown on the hosted checkout.customerPhone (optional) triggers an SMS with the description and payment link.includeEnrollmentFees: true is required for Jeel on tuition/enrollment checkouts.
lineItems to control VAT invoice lines. See Educational billing for templates, PDF export, and ERP delivery.Response
{
"transactionId": "8f8a…",
"sessionToken": "sess_abc123…",
"checkoutUrl": "https://minnha-checkout.vercel.app/pay/sess_abc123…",
"amount": 1000.00,
"currency": "SAR",
"status": "PENDING",
"description": "Annual tuition fee",
"customerPhone": "+966512345678",
"smsSent": true,
"expiresAt": "2026-07-01T12:00:00Z",
"availableGateways": ["JEEL", "MOYASAR", "TABBY"],
"environment": "TEST",
"successUrl": "…",
"cancelUrl": "…"
}Open the checkout
Pass sessionToken to one of the client SDKs. They handle redirect / popup / iframe and emit a normalised event when the customer is done:
// @minnha/pay-js
import { MinnhaPay } from "@minnha/pay-js";
const result = await MinnhaPay.open({ sessionToken, mode: "popup" });
// result.status: "success" | "failed" | "cancelled" | "requires_action"Look up a session
The GET /api/v1/sessions/{token} endpoint is public (no API key) — the session token itself is the credential. This is how the hosted checkout page reads the data.
expiresInMinutes). Pass customerPhone to send the customer an SMS with the payment link — configure Twilio in production or check API logs locally.Customising the checkout page
Each merchant can create custom checkout pages (rich content + branding) from Dashboard → Custom Pages. Only one page can be active at a time. If none exists, the default minnha layout is used.
Use {{description}} in your page HTML to show what the customer is paying for (from the session, or the page name as fallback). Also available: {{amount}}, {{currency}}, {{merchantName}}, {{customerEmail}}.