Payment links
A payment link is a secure, hosted payment page for one amount. You create it, the payer opens it (or scans its QR code) and pays, and Payofy tells your app with a webhook. Your app never sees or stores card numbers.
The flow
- Find or create the customer. Call
POST /customerswith your own id asexternalRef. Calling it again for the same merchant returns the same customer. - Create the link with
POST /payment-links. - Show it or send it. Open
urlfor the payer, showqrUrl, or email the link. - Wait for the webhook.
payment.succeededarrives with the link'sidand yourreference. A declined card sendspayment.failed, and the link stays open so the payer can try again.
const link = await payofy.paymentLinks.create({
merchantId,
customerId,
amountCents: 4500,
currency: "USD",
description: "Haircut and colour",
reference: "booking-77",
purpose: "desk",
redirectUrl: "https://yourapp.example/paid",
cancelUrl: "https://yourapp.example/cancelled",
idempotencyKey: "booking-77",
});
At the counter or by email
purpose tells Payofy how the link will be used:
purpose | Use it when |
|---|---|
desk | The payer is in front of you. Open url for staff to type the card, or let the payer scan qrUrl on their phone. |
email (default) | You send the link to the payer to pay later. |
Expiry
A link works for expiresInSeconds (default 24 hours, 5 minutes to 30 days). After that Payofy marks it expired and sends payment_link.expired. Create a new link if the payer still needs to pay.
Statuses
| Status | Meaning |
|---|---|
open | Waiting for the payer |
paid | Paid. paymentId and paidAt are set |
expired | Reached its expiry unpaid |
cancelled | You cancelled it |
failed | The payment processor refused to create it. lastFailureReason says why |
Check a link any time with GET /payment-links/{id}.
Cancelling
POST /payment-links/{id}/cancel stops an unpaid link from being used. A link that was already paid can't be cancelled (409).
Fees
By default the payer pays exactly amountCents and the business absorbs the processing fees. Whether fees are passed on to payers is a per-merchant setting (feesPassedToCustomer on each link).
Safe retries
Send an idempotencyKey (for example your order id). If you retry a request that timed out, Payofy returns the link it already made instead of creating a second one.