PayLane

Get started

Quickstart

From sign-up to first verified payment in three steps.

  1. 01

    Create workspace

    Sign up and create your merchant workspace. Add your website and verify ownership.

  2. 02

    Generate API keys

    From the Developers tab, generate a publishable + secret key pair. Save the secret once.

  3. 03

    Create a session

    Call POST https://api.mypayu.xyz/v1/sessions from your backend and redirect the customer to checkout_url.

curl
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.

Publishable
pk_live_…

Safe to embed in client-side code. Used by the embed widget to identify your merchant.

Secret
sk_live_…

Server-side only. Never expose to browsers. Rotate immediately if leaked.

http
POST /v1/sessions HTTP/1.1
Host: api.mypayu.xyz
Authorization: Bearer sk_live_xxx
Content-Type: application/json

REST API

Create a payment session

POST https://api.mypayu.xyz/v1/sessions — returns a hosted checkout_url to redirect your customer to.

javascript
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

FieldTypeDescription
amountnumberRequired. Amount in major units (e.g. 4250 = ৳4,250).
currencystringDefaults to BDT.
reference_idstringYour internal order/invoice id.
customer_emailstringOptional. Pre-fills checkout.
success_urlurlRedirect after merchant approval.
cancel_urlurlRedirect on customer cancellation.
callback_urlurlWebhook URL for status events.
metadataobjectUp 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.

html
<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.

javascript
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.submitted

Customer submitted TXID/proof — pending merchant review.

transaction.approved

You approved the proof. Fulfil the order.

transaction.rejected

You rejected the proof.

session.expired

Session timed out before submission.

Verify the signature

javascript
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.