Pay recipients from your Quid account.
Send GHS from your Quid balance to a recipient’s bank account or Mobile Money wallet. Save a recipient once, then submit each payout in one API call. Receive status updates through webhooks.
Connect your Quid account.
You need payout access, an available Quid balance and an active webhook linked to your API key. Contact support if payouts are not enabled for your account.
Send Authorization: Bearer <merchant_api_key> on every request to https://api.quiddpayments.com. The key fixes the merchant and Test or Live environment. Omit merchant_id and environment; conflicting values are rejected.
Use the same API key to create and retrieve your payouts. Keep recipient details, supporting files and receipts private.
New recipient: two creation calls. Saved recipient: one payout call. No quote or verification request is required before submission.
Check your available balance.
GET /api/v1/payouts/capabilities returns enabled account_types, supported banks, mobile_money_networks and payout settings. Use a returned bank or network ID. Your account’s payout and daily limits also apply.
GET /api/v1/payouts/balance returns available funds and current holds. Amounts are integer pesewas: 50000 means GHS 500.00.
{
"environment": "test",
"currency": "GHS",
"eligible_minor": 100000,
"held_minor": 0,
"available_minor": 100000
}eligible_minor equals available funds plus holds. Holds include amount and fee for requested or processing payouts. Availability can change before your request is accepted.
Add a recipient.
curl https://api.quiddpayments.com/api/v1/payouts/recipients \
-H "Authorization: Bearer ak_test_example" \
-H "Content-Type: application/json" \
-d '{
"bank_id": "gcb-bank",
"account_number": "1234567890",
"account_name": "Example Supplier"
}'For Mobile Money, use account_type: momo, the recipient’s registered wallet name, selected network and wallet number.
POST /api/v1/payouts/recipients
Authorization: Bearer ak_test_example
Content-Type: application/json
{
"account_type": "momo",
"network": "mtn",
"phone": "0241234567",
"account_name": "Example Supplier"
}Networks are mtn (MTN MoMo), telecel (Telecel Cash) and at (AT Money). Select the recipient’s current network; do not infer it from the number.
Use a Ghana mobile number such as 0241234567 or +233241234567. Spaces and hyphens are accepted. The response returns the number in +233 format.
Bank recipients require bank_id, account_number and account_name; account_type defaults to bank. Wallet recipients require account_type: momo, network, phone and account_name. Do not mix bank and wallet fields. Both use the same payout request below.
The response is 201 Created. Save its id. The recipient starts with verified: false and verification_status: pending_verification. Account numbers must contain 4–34 digits.
You can submit a payout as soon as you have the recipient ID. For Live payouts, checks run during processing; you do not need to request verification or poll the recipient first. If the recipient is rejected, the payout fails and its amount and fee are released. The recipient detail includes rejection_reason.
GET /api/v1/payouts/recipients returns an unpaginated list, including inactive recipients. After an uncertain creation response, check this list before retrying: recipient creation is not idempotent.
To change recipient details, create a recipient with previous_version_id. The old version becomes inactive and the new one needs verification. To deactivate directly, use DELETE /api/v1/payouts/recipients/{recipient_id} (204, no body). Open payouts prevent replacement or deactivation.
Submit your payout in one call.
POST /api/v1/payouts
Authorization: Bearer ak_test_example
Content-Type: application/json
{
"recipient_id": "00000000-0000-4000-8000-000000000001",
"amount_minor": 50000,
"currency": "GHS",
"max_fee_minor": 100,
"client_reference": "supplier-invoice-104",
"notes": "September supplies"
}currency defaults to GHS. max_fee_minor is optional; the example accepts a fee up to GHS 1.00. The accepted response includes the fee and total debit. Use your account’s published fee from capabilities, or the optional preview below.
A successful request returns 201 with the payout ID, Quid reference, amounts, recipient and status. Save the ID to track your payout. See the complete response fields.
A valid Test payout returns paid immediately in the creation response. Its receipt is available immediately, and no money is sent.
A Live payout starts as processing, including while recipient checks run. If your account requires approval, it starts as requested until an authorized administrator approves it in Merchant Dashboard. The requester cannot approve their own payout. API keys cannot approve payouts. Your available balance accounts for the payout amount and fee.
Retry safely
After a timeout, reuse the same key, reference and request fields. The existing payout returns 200 with its original amount and fee, even if pricing or recipient status has changed. A changed request or different key with the same reference returns 409 REFERENCE_CONFLICT.
References are unique per merchant and environment, across keys. Payouts use client_reference, not the Idempotency-Key header.
A reference starts with a letter or digit and allows letters, digits, _ . : -, up to 80 characters. Notes allow 500 characters.
Preview the fee.
POST /api/v1/payouts/quote
Authorization: Bearer ak_test_example
Content-Type: application/json
{
"recipient_id": "00000000-0000-4000-8000-000000000001",
"amount_minor": 50000
}{
"quote_id": "00000000-0000-4000-8000-000000000002",
"recipient_id": "00000000-0000-4000-8000-000000000001",
"amount_minor": 50000,
"fee_minor": 100,
"total_debit_minor": 50100,
"currency": "GHS",
"expires_at": "2026-09-15T10:15:00Z"
}This optional preview does not reserve funds or lock pricing. Submit the recipient and amount directly; quote_id is not accepted by payout creation. You can set max_fee_minor to the previewed fee. If pricing increases, submission returns 409 FEE_LIMIT_EXCEEDED without creating a payout or holding funds.
Track your payout.
Use GET /api/v1/payouts/{payout_id} for the current state. List with GET /api/v1/payouts?page=1&limit=25. The response contains payouts, page, limit and total. Limit is clamped to 1–100. Add reference=supplier-invoice-104 for an exact client-reference match.
Waiting for merchant approval.
Your payout is in progress.
Your payout is complete.
The amount and fee have been released.
A previously paid transfer was returned; amount and fee released.
A paid transfer can later be returned. Reconciliation is separate: unreconciled, matched or exception for Live payouts. Test payouts return not_required. Use status for program logic; status_label is display text. Processing times are estimates.
When can_cancel is true, you can request cancellation at POST /api/v1/payouts/{payout_id}/cancel with an optional {"reason":"..."}. Repeating a successful cancellation returns the cancelled record. If the payout can no longer be cancelled, the API returns 409. Refresh its status or contact support.
After paid or returned, download the PDF at GET /api/v1/payouts/{payout_id}/receipt. Use an ID from evidence at GET /api/v1/payouts/{payout_id}/evidence/{evidence_id} for a PDF, PNG or JPEG. Downloads require authentication.
Handle the payout subject in signed events.
Handle payout.requested, payout.processing, payout.paid, payout.failed, payout.cancelled and payout.returned. Test creation queues payout.paid directly. Webhook delivery remains asynchronous. Live creation emits payout.requested or payout.processing.
{
"id": "evt_payout_example",
"type": "payout.paid",
"environment": "test",
"livemode": false,
"data": {
"payout": {
"id": "00000000-0000-4000-8000-000000000003",
"reference": "po_example",
"status": "paid",
"amount_minor": 50000,
"fee_minor": 100,
"currency": "GHS",
"bank_reference": "TEST-BANK-104",
"return_reference": "",
"reconciliation_status": "unreconciled"
}
}
}bank_reference contains the payment transaction reference for both bank and Mobile Money payouts.
Read data.payout. Payout events do not contain data.session, the client reference, recipient details or evidence. Join your stored record by payout ID or fetch its detail.
Events go only to the endpoint paired with the creating key. Verify the signed raw body and timestamp, compare signatures in constant time, and deduplicate by event ID. Delivery is at least once. Retries reuse the ID; arrival order is not guaranteed. Fetch the payout for its current state.
Use the response to decide the next step.
Conflicts return 409 with error.code and error.message. Validation errors use field messages or a list (400). Permission and missing-record errors can use detail (403/404). Missing or invalid credentials return 401.
Use an active recipient that has not been rejected.
Review the current fee before submitting a new request with a higher fee limit.
Retrieve the original payout; keep retries unchanged.
Check that your available Quid balance covers the amount and fee.
Use an amount within your limits, wait for your daily limit to reset or contact support.
Payouts are temporarily unavailable. Try again later or contact support.
Work through the payout collection one step at a time.
Use a Test key with payout access, a test balance and test recipients. Test payouts do not send real money. The payout test requests send environment=test, so a Live key is rejected. Replace variables with returned IDs. Submit directly after creating the recipient; no verification or quote call is needed. Contact support if you need help setting up Test payouts.
A valid bank or Mobile Money Test payout completes immediately with status: paid, a TEST- transaction reference and reconciliation_status: not_required. No recipient verification or approval step is needed. Test amounts and fees use only your Test balance. Invalid requests still return errors. Test unchanged retries, validation errors, the payout.paid webhook and receipt downloads. Completed Test payouts cannot be cancelled.