Account capabilities
The seven capabilities, what each one reaches, and how your commission is computed.
The three modes
account_type says what the merchant owns at Wajub and where the money sits. Capabilities,
commission and the consent to a change of terms work the same way in the three; what follows from
the mode is listed below the table. 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 |
What follows from the mode:
- a
liteconnection refuses to start a payment while the merchant is not on the Wajub rail (409); - a
relayconnection has no onboarding: there is no merchant account to claim. It is created withPOST /accountsonly, since the Dashboard form refuses it, and it has no authorization link:authorization_urlisnull, andPOST /accounts/{id}/tokenanswers422. So nobody claims the connection: it stayspending, itspayment_statusstaysinactive, andX-Syncrefuses it with403, as it refuses any connection that is notactive. You run a Relay marketplace with your own key, paying your sellers from your own balance; - a
relayconnection carries no invitation date:expires_atisnulland it never readsexpired; - on a Relay account, each new seller's wallet is checked against the operator's registered name before the first payout. Sellers are checked before their first payout
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 seven 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 events of what the connection brought |
payments | Initiating payments and payment links |
withdrawals | Paying out, and the beneficiaries paid |
refunds | Issuing refunds |
disputes | Answering disputes |
customers | Managing customers |
invoices | Issuing invoices |
Any other capability answers 422 when you create or update a connection.
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 |
GET /payments/{id}/refunds, POST /payments/{id}/close with outcome: refund | payments and refunds |
/disputes | disputes |
/transfers, /beneficiaries, /identity | withdrawals |
/, /providers, /events | read |
/channels, /countries, /currencies | none: the catalogues answer the same to everyone |
/balance, /webhooks, /shield, /tax | cannot be called with X-Sync at all: they belong to the merchant's whole account |
/accounts | cannot be called with X-Sync at all: they are yours |
A resource that cannot be called with X-Sync answers 403 with This endpoint cannot be called on behalf of a Sync account, whatever the connection holds.
A capability covers what the connection brought
Capabilities say what a platform may touch; the connection says whose. With X-Sync, a platform
reaches what this connection brought and nothing else of the merchant's: not their direct sales,
not their own links, invoices or payees, and nothing another platform brought.
| Resource | What the platform reaches |
|---|---|
/payments, /refunds | Only those carrying this connection |
/disputes | Only disputes on this connection's payments |
/links, /invoices | Only those created with this connection's X-Sync |
/beneficiaries | Only those created with this connection's X-Sync, including a beneficiary given inline in a transfer |
/transfers | Only payouts this connection initiated, and only to its own beneficiaries |
/customers, /customers/{id}/tax_ids | Customers seen on this connection's payments, and those it created or named by email or phone, unless the merchant removed its access; without the merchant's notes, block reason and metadata |
/events | Only events about the payments, refunds, transfers, disputes, links, invoices and beneficiaries above |
Anything outside that answers 404, as if it did not exist. A beneficiary the merchant already pays
is no exception: creating one for the same account with X-Sync gives the connection its own, and
paying the merchant's answers 422.
Customers are shared with the merchant
A customer is the merchant's, not the connection's. The connection reaches a customer once they
have bought through it, or once the platform has created them or named them by email or phone.
That is first or create: POST /customers with the email or phone of one of the merchant's
customers (the email whatever its case, the phone however it is written) returns that customer
with 200 instead of a duplicate, and POST /payments attaches the payment to them. Either call
only fills the fields the merchant left empty, never one they set. From then on the platform can
read and list them and use them on its payments and invoices, and the merchant sees the result.
A customer the platform created is its own to manage: it can update and block them. On a customer
the merchant already had, an update only fills the fields the merchant left empty, and blocking,
unblocking, activating, deactivating them or deleting a tax id answers 403. Several connections
can reach the same customer. The platform cannot delete a customer: DELETE /customers/{id} with
X-Sync answers 403, because erasing a customer is the merchant's decision.
The platform sees a customer's identity, contact details and addresses, never the merchant's
notes, block_reason or metadata, and notes it sends is ignored. The metadata it reads
and writes is its own, kept apart for each connection: on a customer the merchant already had,
POST /customers and payments add the keys the platform has not set yet, and
PUT /customers/{id} replaces them. The merchant's metadata never changes through X-Sync.
The merchant sees on the customer's page in the Dashboard which platforms reach the customer, and
since when, and can remove a platform's access. The removal lasts until the merchant restores the
access: the platform no longer reaches the customer, not even on its own past payments, naming them
again by email or phone does not bring them back, and its new payments for that email or phone are
created without a customer. Its metadata on that customer is deleted. Erasing a customer removes
every platform's access.
A customer the connection has neither seen nor named stays out of reach: /customers/{id} answers
404, and their cus_ id given as customer_id on a payment or an invoice answers 422, as an
unknown one does. Changing a customer's email or phone to another customer's answers 422, as it
does for the merchant.
Links and invoices collect for the connection
A payment made on a link or an invoice the connection created carries the connection, like a
payment made with POST /payments and X-Sync: the commission applies and the platform sees it
on /payments. Once the connection may no longer collect (cancelled, its payments suspended, the
capability withdrawn, or Sync no longer on your plan), the link answers 404 to the payer and the
invoice cannot be paid. They collect again when the connection does.
Events, and replaying them
GET /events with X-Sync lists the events recorded about what the connection brought.
POST /events/{id}/resend with X-Sync sends the event to your endpoints, never to the
merchant's, carrying data.account.
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 one rule attached
to the connection, created by POST /accounts from the pricing object and changed afterwards with
PUT /accounts/{id} or from the Dashboard.
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 pricing applies |
| 3 | The fee currency is the rule's currency, or the payment's when the rule has none |
| 4 | Percentage and fixed fee are summed, then clamped by min_fee and max_fee |
| 5 | A fee of zero is not charged |
| 6 | The fee is charged once for the payment |
| 7 | The amount leaves the merchant's balance and lands on yours, held under the sale's own retention |
One payment carries at most one commission. The commission moves in the currency the sale settled in, converted when the rule uses another currency.
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.
When a dispute on the sale is lost
A lost dispute undoes the sale as a refund does, and the same policy applies to the disputed amount: a chargeback the provider reports lost, a dispute your merchant accepts, or one closed past its deadline. Your merchant accepting a dispute pays the buyer back with a refund; the dispute and that refund return the commission once between them, whichever is recorded first. A dispute won returns nothing, since the sale stands.
In sandbox
A sandbox sale moves the commission between the two sandbox balances, and a sandbox refund or a lost sandbox dispute gives it back by the same policy, so you can check what your merchants will see. The reserve, the cover of a negative balance and the commissions a merchant owes when they collect on their own contract are live only.
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.
One rule, for every payment
A connection carries one pricing rule, and it applies to every payment made on the connection. There is no way to charge a different commission on small baskets or to exempt a currency: no endpoint and no Dashboard form sets conditions on a rule.
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 page the merchant is sent back to once they have accepted, and the origin a redirect_uri on the authorisation link has to share. HTTPS only (http://localhost and http://127.0.0.1 with a sandbox key), or 422. No event is sent to it: a connection's events go to your webhook endpoints |
payment_status | active or suspended, your own switch on the connection's ability to charge. active answers 409 while the merchant's verification is pending or rejected |
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.