Skip to main content
ShadhinPay Docs

Quickstart

Take your first payment end to end in the sandbox in a few minutes.

This walkthrough takes a payment from creation to a verified webhook — entirely in the sandbox, so no real money moves.

Before you start

You'll need, from the dashboard:

  • A business with a test API key (sk_test_…)
  • Your Client-Id and Business-Id
  • A webhook URL pointed at your endpoint (a tunnel like ngrok works for local dev) and its signing secret

See Businesses & providers to set these up.

Create a payment

Call the sandbox with the test phone number that forces a successful payment (01770618575 — see Testing):

curl -X POST https://sandbox.shadhinpay.pay/api/v1/payments \
  -H "Client-Id: HM_4f8c2b1a" \
  -H "Business-Id: HB_71c4a09e" \
  -H "X-Api-Key: sk_test_aB3kC9...9xQ2" \
  -H "X-Idempotency-Key: quickstart-order-1" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "500.00",
    "currency": "BDT",
    "merchantTxnId": "quickstart-order-1",
    "callbackUrl": "http://localhost:3000/return",
    "customerPhone": "01770618575"
  }'

You get back a paymentId and a paymentUrl, with status: "PENDING".

Send the customer to checkout

Redirect the customer's browser to the paymentUrl from the response. In the sandbox the outcome is decided by the phone number, so the payment will complete. After paying, the customer returns to your callbackUrl.

Receive and verify the webhook

Your endpoint receives a payment.completed event. Verify its signature before trusting it — see the Webhooks guide for the full Node.js example:

if (!verifyWebhook(rawBody, req.headers['x-shadhinpay-signature'], secret)) {
  return res.status(400).end()       // reject forgeries
}
const event = JSON.parse(rawBody)
if (event.eventType === 'payment.completed') {
  fulfilOrder(event.payload.merchantTxnId)   // 'quickstart-order-1'
}
res.status(200).json({ status: 'received' }) // acknowledge

Confirm the status

As a belt-and-braces check (and in case you miss a webhook), read the payment:

curl https://sandbox.shadhinpay.pay/api/v1/payments/PAY_20260517_K8X3M2 \
  -H "Client-Id: HM_4f8c2b1a" \
  -H "Business-Id: HB_71c4a09e" \
  -H "X-Api-Key: sk_test_aB3kC9...9xQ2"

status is now COMPLETED. That's a full payment, end to end.

Don't fulfil on the redirect alone

The browser returning to your callbackUrl is just a UX signal. Treat the verified webhook (or a status read) as the source of truth before releasing goods.

Where to go next

On this page