Get started
Quickstart
From sign-up to first verified payment in three steps.
- 01
Create workspace
Sign up and create your merchant workspace. Add your website and verify ownership.
- 02
Generate API keys
From the Developers tab, generate a publishable + secret key pair. Save the secret once.
- 03
Create a session
Call POST https://api.mypayu.xyz/v1/sessions from your backend and redirect the customer to checkout_url.
curl https://api.mypayu.xyz/v1/sessions \
-H "Authorization: Bearer sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"amount": 4250,
"currency": "BDT",
"reference_id": "INV-2046",
"customer_email": "alice@example.com",
"success_url": "https://yoursite.com/thanks",
"callback_url": "https://yoursite.com/api/paylane-webhook"
}'Authentication
API keys & headers
All server-side requests are authenticated with a secret key. Pass it as a Bearer token or via x-api-key header.
pk_live_…Safe to embed in client-side code. Used by the embed widget to identify your merchant.
sk_live_…Server-side only. Never expose to browsers. Rotate immediately if leaked.
POST /v1/sessions HTTP/1.1
Host: api.mypayu.xyz
Authorization: Bearer sk_live_xxx
Content-Type: application/jsonREST API
Create a payment session
POST https://api.mypayu.xyz/v1/sessions — returns a hosted checkout_url to redirect your customer to.
const res = await fetch("https://api.mypayu.xyz/v1/sessions", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAYLANE_SECRET}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
amount: 4250,
currency: "BDT",
reference_id: "INV-2046",
customer_email: "alice@example.com",
success_url: "https://yoursite.com/thanks",
}),
});
const session = await res.json();
return res.redirect(session.checkout_url);Request fields
| Field | Type | Description |
|---|---|---|
| amount | number | Required. Amount in major units (e.g. 4250 = ৳4,250). |
| currency | string | Defaults to BDT. |
| reference_id | string | Your internal order/invoice id. |
| customer_email | string | Optional. Pre-fills checkout. |
| success_url | url | Redirect after merchant approval. |
| cancel_url | url | Redirect on customer cancellation. |
| callback_url | url | Webhook URL for status events. |
| metadata | object | Up to 50 keys, returned in webhooks. |
Drop-in
Embed widget (no backend)
Add a Pay button anywhere on your site. The widget creates the session via your server endpoint and opens hosted checkout in a modal.
<script src="https://pay.mypayu.xyz/widget.js" defer></script>
<button
data-paylane
data-public-key="pk_live_xxx"
data-create-url="/api/create-paylane-session"
data-amount="4250"
data-reference="INV-2046"
>
Pay with PayLane
</button>The widget POSTs to data-create-url on your backend, which calls our Sessions API with your secret key and returns the JSON response. Then it opens checkout_url in a centered modal and listens for completion.
window.PayLane.open({
publicKey: "pk_live_xxx",
createUrl: "/api/create-paylane-session",
amount: 4250,
reference: "INV-2046",
onSuccess: (session) => console.log("paid", session),
onCancel: () => console.log("cancelled"),
});Events
Webhooks & callbacks
We POST signed JSON events to your endpoint when a transaction status changes.
transaction.submittedCustomer submitted TXID/proof — pending merchant review.
transaction.approvedYou approved the proof. Fulfil the order.
transaction.rejectedYou rejected the proof.
session.expiredSession timed out before submission.
Verify the signature
import { createHmac, timingSafeEqual } from "crypto";
app.post("/api/paylane-webhook", express.raw({ type: "*/*" }), (req, res) => {
const signature = req.headers["x-paylane-signature"];
const expected = createHmac("sha256", process.env.PAYLANE_WEBHOOK_SECRET)
.update(req.body)
.digest("hex");
if (!signature || !timingSafeEqual(
Buffer.from(signature, "hex"),
Buffer.from(expected, "hex")
)) {
return res.status(401).send("invalid signature");
}
const event = JSON.parse(req.body.toString());
// event = { event: "transaction.approved", created_at, data: { ... } }
if (event.event === "transaction.approved") {
const orderId =
event.data.metadata?.order_id ?? event.data.reference_id;
// mark order as paid in your DB
}
res.send("ok");
});Failed deliveries retry with exponential backoff up to 6 hours. View the full delivery log in your dashboard's Webhooks tab.
Hardening
Security best practices
A short checklist for production-grade integrations.
- Never expose sk_live_ keys client-side — use environment variables.
- Always verify the X-PayLane-Signature HMAC on incoming webhooks.
- Treat amounts as integers in major units to avoid floating-point errors.
- Use HTTPS for callback_url, success_url, cancel_url.
- Rotate API keys periodically; revoke unused ones.
- Whitelist our outbound IP range for webhook delivery if your firewall requires it.
Ready to integrate?
Spin up a merchant workspace, generate a key pair, and start accepting payments in under 5 minutes.