Payofy API
Payments for any small business: restaurants, salons, gyms, shops, schools, and service businesses.
Base URLs
https://api.payofy.si/v1Productionhttps://api.dev.payofy.si/v1Developmenthttp://localhost:3000/v1Local
Authentication
Send your secret API key in the Authorization header: Authorization: Bearer pfy_test_…. Use pfy_test_ keys while building; pfy_live_ keys move real money. Keep keys on your server.
Try it
Set a server and paste a pfy_test_ key in Authorize (left), then use Send request on any endpoint. Live keys are blocked here.
Tenants
Retrieve a tenant
/v1/tenants/{id}Returns the partner account (tenant) that owns the API key.
Path parameters
| Field | Type | Details |
|---|---|---|
idrequired | string | Tenant ID |
Response
200 The tenant.
| Field | Type | Details |
|---|---|---|
idrequired | string | |
namerequired | string | |
statusrequired | string |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X GET 'https://api.dev.payofy.si/v1/tenants/{id}' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY"
@payofy/node has no method for this endpoint yet. Use the JavaScript tab.
const res = await fetch("https://api.dev.payofy.si/v1/tenants/{id}", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
},
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"id": "string",
"name": "Jane Smith",
"status": "string"
}
Merchants
Create a merchant
/v1/merchantsRegisters a business that will take payments through your app, and starts its application with the payment processor.
Request body
| Field | Type | Details |
|---|---|---|
schoolNamerequired | string | Min length 2 |
contactEmailrequired | string (email) | |
businessRegistrationNumberoptional | string |
Response
201 The new merchant.
| Field | Type | Details |
|---|---|---|
idrequired | string (uuid) | |
tenantIdrequired | string (uuid) | |
schoolNamerequired | string | Min length 2 |
contactEmailrequired | string (email) | |
kurvMidoptional | string | null | |
statusrequired | string | One of: "pending_onboarding", "under_review", "approved", "rejected", "suspended" |
feeScheduleIdoptional | string (uuid) | |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X POST 'https://api.dev.payofy.si/v1/merchants' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"schoolName":"Blue Door Café","contactEmail":"owner@bluedoorcafe.example","businessRegistrationNumber":"12-3456789"}'
import { Payofy } from "@payofy/node";
const payofy = new Payofy({
apiKey: process.env.PAYOFY_SECRET_KEY,
baseUrl: "https://api.dev.payofy.si/v1",
});
const merchant = await payofy.merchants.create({
"schoolName": "Blue Door Café",
"contactEmail": "owner@bluedoorcafe.example",
"businessRegistrationNumber": "12-3456789"
});
const res = await fetch("https://api.dev.payofy.si/v1/merchants", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"schoolName": "Blue Door Café",
"contactEmail": "owner@bluedoorcafe.example",
"businessRegistrationNumber": "12-3456789"
}),
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"id": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"tenantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"schoolName": "Blue Door Café",
"contactEmail": "owner@bluedoorcafe.example",
"kurvMid": "string",
"status": "pending_onboarding",
"feeScheduleId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:00:00.000Z"
}
Retrieve a merchant
/v1/merchants/{id}Path parameters
| Field | Type | Details |
|---|---|---|
idrequired | string | Merchant ID |
Response
200 The merchant.
| Field | Type | Details |
|---|---|---|
idrequired | string (uuid) | |
tenantIdrequired | string (uuid) | |
schoolNamerequired | string | Min length 2 |
contactEmailrequired | string (email) | |
kurvMidoptional | string | null | |
statusrequired | string | One of: "pending_onboarding", "under_review", "approved", "rejected", "suspended" |
feeScheduleIdoptional | string (uuid) | |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X GET 'https://api.dev.payofy.si/v1/merchants/{id}' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY"
import { Payofy } from "@payofy/node";
const payofy = new Payofy({
apiKey: process.env.PAYOFY_SECRET_KEY,
baseUrl: "https://api.dev.payofy.si/v1",
});
const merchant = await payofy.merchants.get("{id}");
const res = await fetch("https://api.dev.payofy.si/v1/merchants/{id}", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
},
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"id": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"tenantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"schoolName": "Blue Door Café",
"contactEmail": "owner@bluedoorcafe.example",
"kurvMid": "string",
"status": "pending_onboarding",
"feeScheduleId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:00:00.000Z"
}
Onboarding
Submit a merchant application
/v1/onboarding/{merchantId}/submitSends the merchant's business details for review.
Path parameters
| Field | Type | Details |
|---|---|---|
merchantIdrequired | string | Merchant ID |
Request body
Any JSON object.
Response
201 The application was received.
| Field | Type | Details |
|---|---|---|
applicationIdrequired | string (uuid) | |
merchantIdrequired | string | |
statusrequired | string | |
receivedFieldsrequired | string[] |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X POST 'https://api.dev.payofy.si/v1/onboarding/{merchantId}/submit' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{}'
@payofy/node has no method for this endpoint yet. Use the JavaScript tab.
const res = await fetch("https://api.dev.payofy.si/v1/onboarding/{merchantId}/submit", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"applicationId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"merchantId": "string",
"status": "string",
"receivedFields": [
"string"
]
}
Customers
Create a customer
/v1/customersSaves a payer for a merchant.
Request body
| Field | Type | Details |
|---|---|---|
merchantIdrequired | string (uuid) | |
namerequired | string | Min length 1 |
emailrequired | string (email) | |
phoneoptional | string |
Response
201 The new customer.
| Field | Type | Details |
|---|---|---|
idrequired | string (uuid) | |
tenantIdrequired | string (uuid) | |
merchantIdrequired | string (uuid) | |
namerequired | string | Min length 1 |
emailrequired | string (email) | |
phoneoptional | string | null | |
kurvVaultTokenoptional | string | null | |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X POST 'https://api.dev.payofy.si/v1/customers' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"merchantId":"3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b","name":"Jane Smith","email":"owner@bluedoorcafe.example","phone":"+15555550123"}'
import { Payofy } from "@payofy/node";
const payofy = new Payofy({
apiKey: process.env.PAYOFY_SECRET_KEY,
baseUrl: "https://api.dev.payofy.si/v1",
});
const customer = await payofy.customers.create({
"merchantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"name": "Jane Smith",
"email": "owner@bluedoorcafe.example",
"phone": "+15555550123"
});
const res = await fetch("https://api.dev.payofy.si/v1/customers", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"merchantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"name": "Jane Smith",
"email": "owner@bluedoorcafe.example",
"phone": "+15555550123"
}),
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"id": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"tenantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"merchantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"name": "Jane Smith",
"email": "owner@bluedoorcafe.example",
"phone": "+15555550123",
"kurvVaultToken": "tok_test_4242",
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:00:00.000Z"
}
Retrieve a customer
/v1/customers/{id}Path parameters
| Field | Type | Details |
|---|---|---|
idrequired | string | Customer ID |
Response
200 The customer.
| Field | Type | Details |
|---|---|---|
idrequired | string (uuid) | |
tenantIdrequired | string (uuid) | |
merchantIdrequired | string (uuid) | |
namerequired | string | Min length 1 |
emailrequired | string (email) | |
phoneoptional | string | null | |
kurvVaultTokenoptional | string | null | |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X GET 'https://api.dev.payofy.si/v1/customers/{id}' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY"
import { Payofy } from "@payofy/node";
const payofy = new Payofy({
apiKey: process.env.PAYOFY_SECRET_KEY,
baseUrl: "https://api.dev.payofy.si/v1",
});
const customer = await payofy.customers.get("{id}");
const res = await fetch("https://api.dev.payofy.si/v1/customers/{id}", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
},
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"id": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"tenantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"merchantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"name": "Jane Smith",
"email": "owner@bluedoorcafe.example",
"phone": "+15555550123",
"kurvVaultToken": "tok_test_4242",
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:00:00.000Z"
}
Payments
Create a payment
/v1/payments/intentsCharges a tokenized payment method. Send a unique `idempotencyKey` so a retried request never charges twice. Amounts are in cents.
Request body
| Field | Type | Details |
|---|---|---|
merchantIdrequired | string (uuid) | |
customerIdoptional | string (uuid) | |
amountCentsrequired | integer | Greater than 0 |
currencyoptional | string | Exactly 3 characters Default "USD" |
paymentMethodTokenrequired | string | Min length 1 |
idempotencyKeyrequired | string | Min length 1 |
Response
201 The payment.
| Field | Type | Details |
|---|---|---|
idrequired | string (uuid) | |
tenantIdrequired | string (uuid) | |
merchantIdrequired | string (uuid) | |
customerIdoptional | string (uuid) | null | |
amountCentsrequired | integer | |
currencyrequired | string | Exactly 3 characters |
statusrequired | string | One of: "pending", "processing", "succeeded", "failed", "voided", "refunded" |
kurvTransactionIdoptional | string | null | |
idempotencyKeyrequired | string | |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X POST 'https://api.dev.payofy.si/v1/payments/intents' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"merchantId":"3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b","customerId":"3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b","amountCents":1250,"currency":"USD","paymentMethodToken":"tok_test_4242","idempotencyKey":"order-1042-attempt-1"}'
import { Payofy } from "@payofy/node";
const payofy = new Payofy({
apiKey: process.env.PAYOFY_SECRET_KEY,
baseUrl: "https://api.dev.payofy.si/v1",
});
const payment = await payofy.payments.createIntent({
"merchantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"customerId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"amountCents": 1250,
"currency": "USD",
"paymentMethodToken": "tok_test_4242",
"idempotencyKey": "order-1042-attempt-1"
});
const res = await fetch("https://api.dev.payofy.si/v1/payments/intents", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"merchantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"customerId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"amountCents": 1250,
"currency": "USD",
"paymentMethodToken": "tok_test_4242",
"idempotencyKey": "order-1042-attempt-1"
}),
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"id": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"tenantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"merchantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"customerId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"amountCents": 1250,
"currency": "USD",
"status": "pending",
"kurvTransactionId": "string",
"idempotencyKey": "order-1042-attempt-1",
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:00:00.000Z"
}
Retrieve a payment
/v1/payments/{id}Path parameters
| Field | Type | Details |
|---|---|---|
idrequired | string | Payment ID |
Response
200 The payment.
| Field | Type | Details |
|---|---|---|
idrequired | string (uuid) | |
tenantIdrequired | string (uuid) | |
merchantIdrequired | string (uuid) | |
customerIdoptional | string (uuid) | null | |
amountCentsrequired | integer | |
currencyrequired | string | Exactly 3 characters |
statusrequired | string | One of: "pending", "processing", "succeeded", "failed", "voided", "refunded" |
kurvTransactionIdoptional | string | null | |
idempotencyKeyrequired | string | |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X GET 'https://api.dev.payofy.si/v1/payments/{id}' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY"
import { Payofy } from "@payofy/node";
const payofy = new Payofy({
apiKey: process.env.PAYOFY_SECRET_KEY,
baseUrl: "https://api.dev.payofy.si/v1",
});
const payment = await payofy.payments.get("{id}");
const res = await fetch("https://api.dev.payofy.si/v1/payments/{id}", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
},
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"id": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"tenantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"merchantId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"customerId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"amountCents": 1250,
"currency": "USD",
"status": "pending",
"kurvTransactionId": "string",
"idempotencyKey": "order-1042-attempt-1",
"createdAt": "2026-01-15T10:00:00.000Z",
"updatedAt": "2026-01-15T10:00:00.000Z"
}
Refunds
Refund a payment
/v1/refunds/{paymentId}Returns money from a payment to the customer, fully or partly. Amounts are in cents.
Path parameters
| Field | Type | Details |
|---|---|---|
paymentIdrequired | string | Payment ID |
Request body
| Field | Type | Details |
|---|---|---|
amountCentsrequired | integer | Greater than 0 |
Response
201 The refund.
| Field | Type | Details |
|---|---|---|
refundIdrequired | string (uuid) | |
statusrequired | string | One of: "succeeded", "failed" |
amountCentsrequired | integer |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X POST 'https://api.dev.payofy.si/v1/refunds/{paymentId}' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"amountCents":1250}'
@payofy/node has no method for this endpoint yet. Use the JavaScript tab.
const res = await fetch("https://api.dev.payofy.si/v1/refunds/{paymentId}", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
"amountCents": 1250
}),
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"refundId": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"status": "succeeded",
"amountCents": 1250
}
Payouts
List a merchant's payouts
/v1/payouts/merchant/{merchantId}Money sent to the merchant's bank account.
Path parameters
| Field | Type | Details |
|---|---|---|
merchantIdrequired | string | Merchant ID |
Response
200 The merchant's payouts.
See the example.
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X GET 'https://api.dev.payofy.si/v1/payouts/merchant/{merchantId}' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY"
@payofy/node has no method for this endpoint yet. Use the JavaScript tab.
const res = await fetch("https://api.dev.payofy.si/v1/payouts/merchant/{merchantId}", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
},
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
[
{
"id": "3f2b8c1e-4a5d-4e6f-9a7b-1c2d3e4f5a6b",
"merchantId": "string",
"amountCents": 1250,
"currency": "USD",
"status": "string",
"settledAt": "2026-01-15T10:00:00.000Z"
}
]
Reports
Get a merchant summary
/v1/reports/merchants/{id}/summaryPayment totals for a merchant.
Path parameters
| Field | Type | Details |
|---|---|---|
idrequired | string | Merchant ID |
Response
200 The summary.
| Field | Type | Details |
|---|---|---|
merchantIdrequired | string | |
grossVolumeCentsrequired | integer | |
successfulChargesrequired | integer | |
refundCountrequired | integer | |
currencyrequired | string | Exactly 3 characters |
Errors
- 400 The request was invalid.
- 401 Missing or invalid API key.
- 500 Unexpected server error.
Errors return { statusCode, error, message }.
- cURL
- Node SDK
- JavaScript
curl -X GET 'https://api.dev.payofy.si/v1/reports/merchants/{id}/summary' \
-H "Authorization: Bearer $PAYOFY_SECRET_KEY"
@payofy/node has no method for this endpoint yet. Use the JavaScript tab.
const res = await fetch("https://api.dev.payofy.si/v1/reports/merchants/{id}/summary", {
method: "GET",
headers: {
Authorization: `Bearer ${process.env.PAYOFY_SECRET_KEY}`,
},
});
const data = await res.json();
Set PAYOFY_SECRET_KEY in your server environment. Samples never include your key.
{
"merchantId": "string",
"grossVolumeCents": 1250,
"successfulCharges": 1,
"refundCount": 1,
"currency": "USD"
}