Take your first payment
This guide walks through the basic flow with a test key: register a business, add a customer, and take a payment through a payment link. The example is a café, but the steps are the same for a salon, a gym, a shop, or a school.
The examples use the Node SDK, @payofy/node. The API reference shows the same calls in cURL and JavaScript.
import { Payofy } from "@payofy/node";
const payofy = new Payofy({ apiKey: process.env.PAYOFY_SECRET_KEY });
1. Register the business (merchant)
A merchant is a business that takes payments through your app.
const merchant = await payofy.merchants.create({
schoolName: "Blue Door Café",
contactEmail: "owner@bluedoorcafe.example",
});
The business name field is currently called schoolName. It will be renamed to a general name before general availability.
2. Add a customer
A customer is the person who pays the business. Send your own id for them as externalRef: calling this again with the same externalRef returns the same customer, so you can call it every time without creating duplicates.
const customer = await payofy.customers.create({
merchantId: merchant.id,
externalRef: "member-381",
firstName: "Jane",
lastName: "Smith",
email: "jane@example.com",
});
3. Create a payment link
The payer pays on a secure, hosted payment page: your app never handles card numbers. Amounts are in cents: 1250 is $12.50.
const link = await payofy.paymentLinks.create({
merchantId: merchant.id,
customerId: customer.id,
amountCents: 1250,
description: "Order #1042",
reference: "order-1042",
redirectUrl: "https://yourapp.example/paid",
idempotencyKey: "order-1042",
});
console.log(link.url); // the payment page: open it, or email it
console.log(link.qrUrl); // a QR code image, for paying on a phone at the counter
Why idempotencyKey matters
Networks fail. If your request times out, you don't know whether the link was created. Always send the same idempotencyKey when you retry, so Payofy returns the link it already made instead of a second one. Use something unique to the purchase, such as your order ID.
4. Find out when it's paid
When the payer pays, Payofy sends your webhook a payment.succeeded event with the link's id and your reference. You can also check the link at any time:
const latest = await payofy.paymentLinks.get(link.id);
console.log(latest.status); // "open", "paid", "expired" or "cancelled"
See Payment links for taking payments at the counter, emailing links, expiry and cancelling.
Handling errors
Errors come back with an HTTP status and a JSON body:
{ "statusCode": 401, "error": "UNAUTHORIZED", "message": "Missing or malformed Authorization header" }
| Status | Meaning |
|---|---|
400 | Something in the request is missing or invalid |
401 | The API key is missing or invalid |
404 | The merchant, customer or link doesn't exist, or belongs to another account |
502 | The payment processor refused the request. The message says why. |
500 | Something went wrong on Payofy's side. Retry with the same idempotencyKey. |
Payofy is in active development, and some endpoints still return sample data. Use test keys only.