Basic Integration
Two ways to issue a bill — you only need one:
- Payment Form — drop-in widget with a SADAD button.
- Payments API — create it server-side (B2B, custom flows).
Either way, you then show the SADAD number and reconcile by webhook.
Before you start
- Get your API keys — publishable for the form, secret for the API.
- Make sure SADAD Bill is enabled (on by default in test; contact support for live).
- Set up a webhook for
payment_paidandpayment_expired— SADAD is paid out of band, so this is how you learn the outcome.
Option 1: Payment Form
Add sadadbill to methods and the form shows a SADAD button.
Include the form
Add these to your page <head>:
Initialize
<div class="mysr-form"></div>
<script>
window.Moyasar.init({
element: '.mysr-form',
amount: 10000, // halalas; min 10000 (100.00 SAR)
currency: 'SAR',
description: 'Order #1001',
publishable_api_key: 'pk_test_YOUR_PUBLISHABLE_KEY',
callback_url: 'https://your-site.com/sadad/return',
methods: ['sadadbill'],
});
</script>
After the customer confirms
The form issues the bill and redirects to callback_url — note status=initiated (issued, not paid):
https://your-site.com/sadad/return?id=e21048bc-378e-47f8-860f-129cfde465a0&status=initiated&message=
On your return page, fetch the payment by id, then show the number and reconcile (below). To capture the id even if the redirect is interrupted, use on_completed:
Moyasar.init({
// ...same options as above
on_completed: async function (payment) {
await savePaymentOnBackend(payment);
},
});
Option 2: Payments API
Set source[type] to sadadbill. Amount is in halalas; minimum 10000 (100.00 SAR).
Endpoint: POST /v1/payments
Authentication: Secret key
- JSON body
- cURL
{
"amount": 10000,
"currency": "SAR",
"description": "Order #1001",
"source": { "type": "sadadbill" }
}
curl https://api.moyasar.com/v1/payments \
-u sk_test_YOUR_SECRET_KEY: \
-d "amount=10000" \
-d "currency=SAR" \
-d "description=Order #1001" \
-d "source[type]=sadadbill"
Returns initiated with the bill in source:
{
"id": "e21048bc-378e-47f8-860f-129cfde465a0",
"status": "initiated",
"amount": 10000,
"currency": "SAR",
"source": {
"type": "sadadbill",
"provider_name": "sandbox-اختبار",
"biller_code": "001",
"sadad_number": "1234567890123",
"gateway_id": "moyasar_sb_aQHM2nEqvGKHQyBns4We8",
"expired_at": "2026-08-15",
"message": null
}
}
A test key uses the sandbox provider (biller_code 001). Live accounts show your real provider.
Set an expiry
Default is 29 days. Pass source[expired_at] (a YYYY-MM-DD future date, ≤29 days) for earlier:
- JSON body
- cURL
{
"amount": 10000,
"currency": "SAR",
"description": "Order #1001",
"source": { "type": "sadadbill", "expired_at": "2026-08-01" }
}
curl https://api.moyasar.com/v1/payments \
-u sk_test_YOUR_SECRET_KEY: \
-d "amount=10000" \
-d "currency=SAR" \
-d "description=Order #1001" \
-d "source[type]=sadadbill" \
-d "source[expired_at]=2026-08-01"
Display the SADAD number
Show source.sadad_number and how to pay it, e.g.:
Your SADAD bill is ready. In your bank app or an ATM, choose SADAD bill payment, select biller "X" (or code "Y"), enter "1234 5678 90123", and pay before "15 Aug 2026".
Reconcile the payment
A SADAD bill is paid later at the bank, so you learn the outcome by webhook (same for form and API):
payment_paid— fulfil the order.payment_expired— treat the order as unpaid.
Each event carries the full payment; match by data.id and check data.status.
For an invoice
If you use Moyasar invoices, SADAD appears on the hosted invoice page automatically when enabled. The bill's expiry matches the invoice (capped at 29 days); the invoice goes on_hold while awaiting payment, then paid.
To create the payment yourself against an invoice, add invoice_id:
- JSON body
- cURL
{
"amount": 10000,
"currency": "SAR",
"description": "Invoice #1001",
"invoice_id": "8d444d87-3d8f-4fc4-a928-497496fdfdd4",
"source": { "type": "sadadbill" }
}
curl https://api.moyasar.com/v1/payments \
-u sk_test_YOUR_SECRET_KEY: \
-d "amount=10000" \
-d "currency=SAR" \
-d "description=Invoice #1001" \
-d "invoice_id=8d444d87-3d8f-4fc4-a928-497496fdfdd4" \
-d "source[type]=sadadbill"
Not supported
Refund, capture, and void — SADAD bills are paid out of band; calling them returns an unsupported_operation error.