Create Checkout
curl --request POST \
--url https://api-production.fossapay.com/api/v1/checkouts \
--header 'Content-Type: application/json' \
--header 'X-Idempotency-Key: <x-idempotency-key>' \
--header 'x-api-key: <x-api-key>' \
--data '
{
"amount": 123,
"currency": "<string>",
"reference": "<string>",
"feeBearer": "<string>",
"customer": {},
"metadata": {},
"description": "<string>"
}
'import requests
url = "https://api-production.fossapay.com/api/v1/checkouts"
payload = {
"amount": 123,
"currency": "<string>",
"reference": "<string>",
"feeBearer": "<string>",
"customer": {},
"metadata": {},
"description": "<string>"
}
headers = {
"x-api-key": "<x-api-key>",
"X-Idempotency-Key": "<x-idempotency-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'X-Idempotency-Key': '<x-idempotency-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 123,
currency: '<string>',
reference: '<string>',
feeBearer: '<string>',
customer: {},
metadata: {},
description: '<string>'
})
};
fetch('https://api-production.fossapay.com/api/v1/checkouts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-production.fossapay.com/api/v1/checkouts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'amount' => 123,
'currency' => '<string>',
'reference' => '<string>',
'feeBearer' => '<string>',
'customer' => [
],
'metadata' => [
],
'description' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Idempotency-Key: <x-idempotency-key>",
"x-api-key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-production.fossapay.com/api/v1/checkouts"
payload := strings.NewReader("{\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"reference\": \"<string>\",\n \"feeBearer\": \"<string>\",\n \"customer\": {},\n \"metadata\": {},\n \"description\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<x-api-key>")
req.Header.Add("X-Idempotency-Key", "<x-idempotency-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-production.fossapay.com/api/v1/checkouts")
.header("x-api-key", "<x-api-key>")
.header("X-Idempotency-Key", "<x-idempotency-key>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"reference\": \"<string>\",\n \"feeBearer\": \"<string>\",\n \"customer\": {},\n \"metadata\": {},\n \"description\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-production.fossapay.com/api/v1/checkouts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<x-api-key>'
request["X-Idempotency-Key"] = '<x-idempotency-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"reference\": \"<string>\",\n \"feeBearer\": \"<string>\",\n \"customer\": {},\n \"metadata\": {},\n \"description\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyCheckout Wallet
Create Checkout
Create a one-time 30-minute NGN checkout wallet
POST
/
api
/
v1
/
checkouts
Create Checkout
curl --request POST \
--url https://api-production.fossapay.com/api/v1/checkouts \
--header 'Content-Type: application/json' \
--header 'X-Idempotency-Key: <x-idempotency-key>' \
--header 'x-api-key: <x-api-key>' \
--data '
{
"amount": 123,
"currency": "<string>",
"reference": "<string>",
"feeBearer": "<string>",
"customer": {},
"metadata": {},
"description": "<string>"
}
'import requests
url = "https://api-production.fossapay.com/api/v1/checkouts"
payload = {
"amount": 123,
"currency": "<string>",
"reference": "<string>",
"feeBearer": "<string>",
"customer": {},
"metadata": {},
"description": "<string>"
}
headers = {
"x-api-key": "<x-api-key>",
"X-Idempotency-Key": "<x-idempotency-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-api-key': '<x-api-key>',
'X-Idempotency-Key': '<x-idempotency-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
amount: 123,
currency: '<string>',
reference: '<string>',
feeBearer: '<string>',
customer: {},
metadata: {},
description: '<string>'
})
};
fetch('https://api-production.fossapay.com/api/v1/checkouts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api-production.fossapay.com/api/v1/checkouts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'amount' => 123,
'currency' => '<string>',
'reference' => '<string>',
'feeBearer' => '<string>',
'customer' => [
],
'metadata' => [
],
'description' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Idempotency-Key: <x-idempotency-key>",
"x-api-key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api-production.fossapay.com/api/v1/checkouts"
payload := strings.NewReader("{\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"reference\": \"<string>\",\n \"feeBearer\": \"<string>\",\n \"customer\": {},\n \"metadata\": {},\n \"description\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<x-api-key>")
req.Header.Add("X-Idempotency-Key", "<x-idempotency-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api-production.fossapay.com/api/v1/checkouts")
.header("x-api-key", "<x-api-key>")
.header("X-Idempotency-Key", "<x-idempotency-key>")
.header("Content-Type", "application/json")
.body("{\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"reference\": \"<string>\",\n \"feeBearer\": \"<string>\",\n \"customer\": {},\n \"metadata\": {},\n \"description\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api-production.fossapay.com/api/v1/checkouts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<x-api-key>'
request["X-Idempotency-Key"] = '<x-idempotency-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"amount\": 123,\n \"currency\": \"<string>\",\n \"reference\": \"<string>\",\n \"feeBearer\": \"<string>\",\n \"customer\": {},\n \"metadata\": {},\n \"description\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyCreates a merchant-scoped checkout and returns the exact amount and bank account the customer should pay. If a temporary account cannot be generated after retries, the response falls back to the merchant’s permanent NGN account.
For integration behavior and webhook verification, see the Checkout Wallet Guide.
Headers
string
required
Your existing active FossaPay API key with full permission.
string
required
A unique key of up to 255 characters.
Idempotency-Key is also accepted for backward compatibility. If both headers are present, they must match.Body
integer
required
Underlying merchant order amount in NGN. Minimum
1.string
required
Currency code. Currently only
NGN is supported.string
required
Your unique checkout reference, 1–100 characters. Allowed: letters, numbers,
., _, :, and -.string
required
customer adds the fee to amountPayable; merchant deducts it from settlementAmount.object
Optional customer details containing
name, email, and/or phoneNumber. A payment-confirmation email is queued after success when email is present.object
Optional merchant-defined JSON, up to 4,096 UTF-8 bytes. Returned unchanged in responses and webhooks.
string
Optional description, up to 255 characters.
Request
curl -X POST https://api-production.fossapay.com/api/v1/checkouts \
-H "x-api-key: YOUR_API_KEY" \
-H "X-Idempotency-Key: checkout-order-10025-v1" \
-H "Content-Type: application/json" \
-d '{
"amount": 5000,
"currency": "NGN",
"reference": "ORDER-10025",
"feeBearer": "customer",
"customer": {
"name": "Ada Lovelace",
"email": "ada@example.com"
},
"metadata": {
"orderId": "10025"
}
}'
Response
{
"status": "success",
"statusCode": 201,
"message": "Checkout session created successfully",
"data": {
"id": "35f5f6fb-0c8d-4e96-ba4a-c04750724ff6",
"reference": "ORDER-10025",
"status": "pending",
"amount": "5000.00",
"fee": "80.00",
"amountPayable": "5080.00",
"settlementAmount": "5000.00",
"feeBearer": "customer",
"currency": "NGN",
"account": {
"type": "temporary",
"bankName": "Sterling Bank",
"accountName": "FOSSAPAY CHECKOUT",
"accountNumber": "9541382701",
"expiresAt": "2026-09-11T10:30:00.000Z"
},
"customer": {
"name": "Ada Lovelace",
"email": "ada@example.com"
},
"metadata": {
"orderId": "10025"
},
"transactionId": "3469cd26-a213-431e-96c9-72dc2dea51ae",
"providerCheckoutReference": null,
"expiresAt": "2026-09-11T10:30:00.000Z",
"completedAt": null,
"failedAt": null,
"reversedAt": null,
"createdAt": "2026-09-11T10:00:00.000Z",
"updatedAt": "2026-09-11T10:00:00.000Z"
}
}
Instruct the customer to transfer exactly
data.amountPayable once before data.expiresAt. Fulfill only after a verified checkout.completed webhook.Errors
| HTTP status | When it occurs |
|---|---|
400 | Validation failure; missing/oversized or conflicting idempotency headers; no active permanent NGN account; or an amount not greater than a merchant-borne fee. |
401 | Missing, invalid, or inactive API key. |
403 | Merchant is not eligible or has not completed business verification. |
409 | Reference conflict, or an idempotency key is reused with a different body. |

