Account capabilities
The eleven capabilities, which ones are enforced, and how your commission is computed.
The three modes
account_type says what the merchant owns at Wajub and where the money sits. Everything else —
capabilities, commission, consent, webhooks, KYC — is the same across the three. It is chosen when
you create the connection and never changes afterwards: switching mode changes what the merchant
agreed to, so it is a new connection they accept again.
| Mode | The merchant | The money | Use it for |
|---|---|---|---|
direct (default) | A full Wajub account they run themselves | Wajub rail, or their own provider contracts | Merchants already set up |
lite | A light hosted portal | Wajub rail, always | Small sellers — the common case |
relay | No Wajub account: a payout destination | Yours — you collect and Wajub relays the payouts | Marketplaces that are merchant of record |
Two rules follow from the mode, and only two:
- a
liteconnection refuses to start a payment while the merchant is not on the Wajub rail (409) — it exists so the commission is taken at the source and the payout is automatic, and both need the money to pass through Wajub; - a
relayconnection has no onboarding: there is no merchant account to claim.
These are not Standard, Express or Custom tiers
The mode is not a level of service and does not gate features. Two connections in different modes can hold exactly the same capabilities and the same pricing.
The eleven capabilities
A connection is granted a subset of this list, and the list is closed. At least one is required at
creation, and an unknown value is refused with 422.
| Capability | What it names |
|---|---|
read | Reading the connected account's own resources |
write | Creating and updating resources on its behalf |
payments | Initiating and managing payments |
withdrawals | Initiating transfers and payouts |
refunds | Issuing refunds |
disputes | Managing disputes |
customers | Managing customers |
invoices | Managing invoices |
subscriptions | Managing subscriptions |
analytics | Reading analytics and reporting |
settings | Managing the connected account's settings |
Every resource states what it requires
Capabilities are a real boundary: each resource declares the capability it takes, and a request
carrying X-Sync without that capability is refused with 403.
| The request touches | The capability checked |
|---|---|
/payments, /links | payments |
/invoices | invoices |
/customers, /customers/{id}/tax_ids | customers |
/refunds | refunds |
/disputes | disputes |
/transfers, /beneficiaries, /identity | withdrawals |
/webhooks, /tax, /shield | settings |
/, /providers, /balance, /events, /listen | read |
/channels, /countries, /currencies | none — the catalogues answer the same to everyone |
/accounts, /keys/current | cannot be called with X-Sync at all |
A capability covers what the connection brought
Capabilities say what a platform may touch; the connection says whose. With X-Sync, a platform
sees the payments it initiated, the refunds of those payments, the customers who bought through it
and the payouts it sent — never the merchant's direct sales, and never another platform's.
| Resource | What the platform sees |
|---|---|
/payments, /refunds | Only those carrying this connection |
/customers | Only customers seen on this connection's payments |
/transfers | Only payouts this connection initiated |
/balance | The merchant's balance as a whole — a balance is not per connection |
A resource that names no capability cannot be reached on behalf of a connection, so a capability
you did not grant is a capability the platform does not have. write, subscriptions and
analytics name no resource today: they are recorded on the connection and shown to the merchant,
but nothing checks them yet.
Changing the terms of a live connection
Capabilities and pricing are what the merchant agreed to, so once a connection is active they are
proposed rather than changed. PUT /accounts/{id} answers 202 Accepted and returns the proposal
in pending_changes; the connection keeps running on its current terms until the merchant accepts
or declines in their own dashboard.
| Then | What happens |
|---|---|
| The merchant accepts | The new terms apply from that moment, and account.change_accepted fires |
| The merchant declines | Nothing changes, and account.change_declined fires |
| You propose again | The new proposal replaces the one still on the table |
Sales already made keep the terms they were made under: a pricing change never re-prices a
commission already charged. While the connection is still pending, nobody has agreed to anything
yet and PUT applies the change outright, answering 200.
Pricing
Pricing is what your platform retains on the connected account's activity. It is a set of rules
attached to the connection, not a single number, and POST /accounts creates the first one for you
from the pricing object.
percentage_feenumberoptionalfixed_feenumberoptionalmin_feenumberoptionalmax_feenumberoptionalcurrencystringoptionalThe two kinds combine rather than compete: a rule with both a percentage and a fixed fee charges the percentage of the amount plus the flat figure, then applies the floor and the cap in that order.
How a fee is computed
Reading this sequence once explains every figure you will see on a fee.received.
| Step | What happens |
|---|---|
| 1 | The payment succeeds and carries a connection |
| 2 | The connection's rules are walked, specific rules before the fallback |
| 3 | The first rule whose conditions match the amount and currency wins |
| 4 | Percentage and fixed fee are summed, then clamped by min_fee and max_fee |
| 5 | A fee of zero is dropped, nothing is recorded |
| 6 | The fee is written once against the payment |
| 7 | The amount leaves the merchant's balance and lands on yours, held under the sale's own retention |
Step 6 is idempotent, and the database enforces it: one payment carries at most one commission, whatever happens to the event that triggered it. Step 7 posts in the currency the sale settled in, so the ledger never carries an exchange position; the fee's own currency and the rate applied are recorded on the movement.
A commission is a share of a sale, so a sale that comes undone takes its share with it.
When the sale is refunded
commission_refund_policy, set on the connection, decides what comes back.
| Policy | On a refund |
|---|---|
prorata (default) | The commission is returned in proportion to the amount refunded |
full | The whole commission is returned on the first refund, partial or not |
none | Nothing is returned; the merchant carries the refund alone |
Set it with POST /accounts, and change it with PUT /accounts/{id} only while the connection is
still pending — it is a commercial term the merchant accepted. Nothing is ever given back twice, and
several refunds on one sale can never return more than was charged.
The rule currency is the denomination, not a filter
currency says what the fee is expressed in, not which payments the rule applies to. Charging a
flat 500 XAF on a payment made in NGN converts at the active rate, and converts a second time if
your platform's own balance is in a third currency. The metadata on the fee records both rates.
Conditions
A rule can carry conditions, which decide whether it applies at all.
| Condition | Effect |
|---|---|
min_amount | The rule is skipped for payments below it |
max_amount | The rule is skipped for payments above it |
currency | The rule only applies to payments made in that currency |
Conditions are how you charge a different commission on small baskets, or exempt a currency. A connection with several rules needs one without conditions to act as the fallback, otherwise a payment that matches none of them carries no commission at all.
Pricing needs consent on acceptance too
Like capabilities, pricing on a connected merchant is proposed rather than changed: PUT answers
202 and the merchant decides. Set the commission you mean before you send the authorisation
link, and you never have to ask.
What stays editable outright
Two fields survive acceptance without the merchant's say-so, and they are the only two.
| Field | Why it stays open |
|---|---|
callback | The URL notified of this connection's lifecycle events |
payment_status | active or suspended, your own switch on the connection's ability to charge |
Suspending a connection stops both inbound payments and outbound transfers on it, and fires
account.payment_suspended. It is the lever to reach for when you would otherwise want to revoke a
capability, and unlike a capability it is reversible.