• Fintech
  • Payments
  • KYC

CrossBorda

Cross-border payouts for African corridors

Role
Lead Product Designer
Timeline
2023, seven months
Team
Two engineers, one PM, me
Platforms
Web dashboard and customer portal
Status
Shipped, in production
Outcome
Support tickets about payment status dropped noticeably after the status rework. Directional

Directional: observed in practice, not instrumented

The problem

Cross-border payouts aren't one transaction, they're a chain of them, and every link can fail differently. A business had to onboard, get verified against rules that change by jurisdiction, add recipients, initiate payouts, then track them through states that could sit unchanged for two days without anything being wrong. The people doing this were finance and operations staff. They were being shown raw webhook state names and asked to work out what to do next.

What made it hard

  • Compliance came first, not the user experience. Verification steps that people would rather skip were legally required, so the design had to make them feel purposeful instead of hiding them.
  • Nobody using the product was technical. All the system complexity had to stop at the interface.
  • "Pending" is a legitimate state that can last days. The design had to communicate patience without communicating breakage.
  • The recipient model had to support both one-off and recurring payouts from launch, because rebuilding it later would have meant migrating live financial data.

Three decisions

With what I turned down, and what each one cost.

Decision 01

Verification gates moved to the point of need

Chose
Basic access at sign-up, with each verification requirement introduced at the moment the action requiring it is attempted.
Rejected
Collecting every identity document upfront in a single onboarding wizard, which is what the compliance team originally asked for.
Why
Front-loading the documents meant a business had to hand over its incorporation papers before seeing a single screen of the product. The drop-off happens before anyone has a reason to push through it. Tying each gate to the action it unlocks gives the requirement an obvious purpose.
What it cost
It's harder to build. Every gated action needs its own state, and the compliance team had to sign off on a flow they couldn't read top-to-bottom on one page.

Decision 02

Recipients became an entity, not a form

Chose
A recipient directory of saved, validated profiles that payouts reference.
Rejected
Entering recipient details per transaction, which was simpler and matched how the API already worked.
Why
Operations teams don't send one-off payments to strangers. They pay the same twenty suppliers every month. Re-entering an account number each time is both slow and the single most likely place for a costly typo.
What it cost
It forced a data model change mid-build and added a whole management surface — editing, archiving, and handling a recipient whose bank details change between payouts.

Decision 03

Status names describe what to do, not what happened

Chose
A translation layer mapping technical webhook states to operator language with an explicit next action. FAILED_RETRY became "Payment rejected. Check the reason and send again."
Rejected
Surfacing the underlying state names with tooltips explaining each one.
Why
A finance operator doesn't need to know the system's internal vocabulary. They need to know whether this is their problem and what to do about it. Tooltips put that answer one hover away from someone under time pressure.
What it cost
The mapping has to be maintained. Every new webhook event needs an operator-facing translation, and if that step gets skipped the untranslated state leaks through.