Base URL
{{ rtrim(config('app.url'), '/') }}
Authentication
Use your Merchant API Key on every request:
Authorization: Bearer YOUR_MERCHANT_API_KEY
You can also use:
X-API-KEY: YOUR_MERCHANT_API_KEY
Create your Merchant API Key from your dashboard: Gateway → API Keys.
Create Payment
POST {{ rtrim(config('app.url'), '/') }}/api/gateway/payments/initiate
Body fields:
amount (number, min 100)
currency (string, default NGN)
method (card | transfer | ussd)
customer_email (email)
customer_phone (string, optional)
customer_name (string, optional)
return_url (url)
merchant_webhook_url (url, optional)
reference (string, optional)
Amount sent in the request is in major units (e.g. NGN). Amount stored/returned may be in minor units depending on provider (kobo).
Example (cURL)
curl -X POST "{{ rtrim(config('app.url'), '/') }}/api/gateway/payments/initiate" \
-H "Authorization: Bearer YOUR_MERCHANT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 2000,
"currency": "NGN",
"method": "card",
"customer_email": "customer@example.com",
"customer_phone": "08000000000",
"customer_name": "John Doe",
"return_url": "https://yourapp.com/paid",
"merchant_webhook_url": "https://yourapp.com/webhook/payment-gateway-ng"
}'
Response contains provider.checkout_url. Redirect your customer to that URL to complete payment.
Response (example)
{
"status": "success",
"message": "Payment initialized",
"data": {
"reference": "gtw_xxxxxxxxxxxxxxxxxxxxxxxx",
"amount": 200000,
"currency": "NGN",
"method": "card",
"status": "unpaid",
"provider": {
"name": "flutterwave",
"reference": "gtw_xxxxxxxxxxxxxxxxxxxxxxxx",
"transaction_id": null,
"checkout_url": "https://checkout.flutterwave.com/..."
}
}
}
Get Payment
GET {{ rtrim(config('app.url'), '/') }}/api/gateway/payments/{reference}
Refresh Payment Status
POST {{ rtrim(config('app.url'), '/') }}/api/gateway/payments/{reference}/refresh
For Flutterwave, refresh requires provider_transaction_id which is set after the customer completes payment and is redirected back via the callback flow.
Webhooks
If you set merchant_webhook_url, {{ config('app.name') }} will attempt to POST payment events to your endpoint.
Webhook delivery is best-effort. You can view and repush webhook deliveries from the Webhook Events page.
Webhook payload (example)
{
"reference": "gtw_xxxxxxxxxxxxxxxxxxxxxxxx",
"status": "success",
"paid_at": "2026-05-01T12:34:56.000000Z",
"amount": 200000,
"currency": "NGN",
"method": "card",
"provider": "flutterwave",
"provider_reference": "gtw_xxxxxxxxxxxxxxxxxxxxxxxx",
"provider_transaction_id": "1234567890"
}
Webhooks are not currently signed. Recommended: treat webhooks as notifications and confirm final status by calling
GET /api/gateway/payments/{reference}.
Common Errors
401 Missing API key / Invalid API key
422 Validation error (missing fields, invalid method, min amount)
400 Provider error (Flutterwave/PalmPay not configured or request failed)