2xx means success, 4xx
means the request can’t succeed as sent, and 5xx means something
went wrong on our side or at the PSP.
Status codes
Error bodies
Bodies are always JSON. Their shape depends on the kind of error:- Business errors (400, 402, 405, 409, 500, 503)
- Not found (404)
- Validation (422)
- Authentication (401)
string
A stable, machine-readable class. See Error codes.
string
A specific message key (sometimes the PSP’s own text). Each
endpoint’s Errors table lists the ones it returns.
array | object
Values for placeholders in
message. Usually empty.Error codes
Retries and idempotency
Kwugwo has noIdempotency-Key header. Use ref instead: it is
unique per workspace on ugwos and refunds, so a retried create can
never produce a duplicate.
Common pitfalls
401 on every request, even with a valid key
401 on every request, even with a valid key
The header must be exactly
Authorization: Bearer sk.…. Check for a
trailing newline from your secrets store, and that you’re using the
sandbox key against sandbox-api.kwugwo.africa (or the live key
against api.kwugwo.africa). Regenerating a key revokes the old one
immediately.422 provider should not be blank when charging
422 provider should not be blank when charging
Medium parameters belong in
data.medium_params, not directly in
data. A provider placed at data.provider is ignored, so the
request fails as if you sent none. See Charge an
ugwo.404 for an ugwo you just created
404 for an ugwo you just created
IDs are scoped to the workspace and environment of the key. A
sandbox ID (ending in
_t) is never found with a live key.405 when creating an ugwo
405 when creating an ugwo
amount_too_low / amount_too_high: amounts are in the smallest
unit, so ₦5,000 is 500000. currency_not_allowed: none of your
PSPs is set up for that currency.405 checkout_not_found when charging
405 checkout_not_found when charging
The ugwo has
checkout: null. Pass a checkout on create, or set up
routing rules in the dashboard so one is picked automatically.503 payment_routing_error when charging
503 payment_routing_error when charging
None of the PSPs on the checkout’s route could take the charge (for
example, every PSP on the route rejected it or is unavailable). No
activity is created, no webhooks are sent, and the ugwo stays
requires_ugwo. Retry after a short wait or offer another medium,
and check your PSP connections and routing rules in the dashboard.
If you set a custom failure message in your routing rules, it’s
returned as-is in message, so you can show it to the customer.For mediums that take a provider (ussd, pay_with_bank), a bank
that no PSP on the checkout supports is rejected earlier, with a
422 on provider.409 already_processed when charging
409 already_processed when charging
The ugwo is already paid (or refunded) or was cancelled. Fetch it
to check
status; there is nothing left to collect.A refund came back 200 but nothing was refunded
A refund came back 200 but nothing was refunded
Check
status. A PSP declining a refund is a normal outcome:
"status": "failed" with the reason in error. For bank-transfer
and USSD payments, you may need to send a
destination.