Skip to content

Partners and routing

Partners → Partners is the institutions we actually move money through: Hubtel, Paystack, PaySwitch and GT Bank. Partners → Routing decides which one carries a given transaction.

So that a failing partner is a configuration change on our side rather than an integration change on every merchant’s. That promise is on the marketing site, and routing is where it is kept.

It only holds if the routing is actually configured for failover and if somebody notices the failure. Both are this page.

Routing selects a partner by channel, currency and capability. A transaction that nothing is configured to carry — or whose every candidate is out of service — returns no_route_available.

That error is a 503, not a 4xx, and the status code is the point: it is our configuration problem, not the merchant’s request. A merchant seeing no_route_available has done nothing wrong and can do nothing about it.

So treat no_route_available in the logs as an alert about us. It usually means either a gap in the routing rules for a combination somebody just started using, or every partner for a channel being down at once.

When a partner is failing — timeouts, rejections, an outage they have told us about — take them out of service so traffic routes elsewhere.

Before you do:

  • Check there is somewhere else for the traffic to go on that channel and currency. Removing the only route for a channel converts partner failures into no_route_available for everyone, which is worse: at least some of the failing partner’s traffic was succeeding.
  • Know what is in flight. Transactions already dispatched to that partner still need their outcome resolved. Removing a route stops new traffic; it does not settle what is already out there.

Bringing them back is the same decision in reverse, and it deserves the same care — a partner returned to service too early sends a second wave of failures to merchants who had just stopped seeing the first.

partner_rejected versus partner_unavailable

Section titled “partner_rejected versus partner_unavailable”

These look similar in a log and mean opposite things:

  • partner_rejected (409) — the partner looked at it and said no. A terminal answer about that attempt. Retrying is pointless.
  • partner_unavailable (503) / partner_timeout (504) — we could not get an answer. The transaction’s outcome is unknown, not failed.

A rash of partner_rejected is a configuration or credential problem with that partner — or a merchant doing something the partner will not carry. A rash of partner_unavailable is an outage. They call for different actions, so read which one you have before acting.

Held sealed. Rotating them is a coordinated operation with the partner, not a unilateral change, and getting it wrong takes a rail offline for everybody.

The sandbox does not use partner credentials at all. Test-environment traffic routes to a partner called sandbox-sim, whose adapter is simulator and which holds no credentials because there is no vendor behind it. That is the entire difference between sandbox and live: same code, same schema, same routing logic, and one substituted rail at the end.

It was not always so, and the reason it changed is worth knowing when a merchant asks. Hubtel publishes no test environment for Programmable Payments; PaySwitch’s caps the amount and authorises only a short list of card numbers. Pointing the sandbox at those made our sandbox the intersection of four other companies’ restrictions, so a merchant whose checkout sold a GHS 4,000 item could not test their own checkout.

You will therefore see no test-environment rows for the real partners, and that is correct rather than missing configuration. A simulator row in the live environment is refused by the database, so there is no way to create one here.

When merchants report failures on one method

Section titled “When merchants report failures on one method”

Check in this order:

  1. Is one partner failing? Partners → Partners.
  2. Is routing sending that combination anywhere at all? Partners → Routing.
  3. Is it one merchant or all of them? One merchant is a capability or limit question (Merchants); all of them is this page.
  4. Is it one channel or all channels? One channel narrows it to a rail.