Skip to content

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.

ModeThe merchantThe moneyUse it for
direct (default)A full Wajub account they run themselvesWajub rail, or their own provider contractsMerchants already set up
liteA light hosted portalWajub rail, alwaysSmall sellers, the common case
relayNo Wajub account: a payout destinationYours: you collect and Wajub relays the payoutsMarketplaces that are merchant of record

What follows from the mode:

  • a lite connection refuses to start a payment while the merchant is not on the Wajub rail (409);
  • a relay connection has no onboarding: there is no merchant account to claim. It is created with POST /accounts only, since the Dashboard form refuses it, and it has no authorization link: authorization_url is null, and POST /accounts/{id}/token answers 422. So nobody claims the connection: it stays pending, its payment_status stays inactive, and X-Sync refuses it with 403, as it refuses any connection that is not active. You run a Relay marketplace with your own key, paying your sellers from your own balance;
  • a relay connection carries no invitation date: expires_at is null and it never reads expired;
  • 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

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.

CapabilityWhat it names
readReading the events of what the connection brought
paymentsInitiating payments and payment links
withdrawalsPaying out, and the beneficiaries paid
refundsIssuing refunds
disputesAnswering disputes
customersManaging customers
invoicesIssuing 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 touchesThe capability checked
/payments, /linkspayments
/invoicesinvoices
/customers, /customers/{id}/tax_idscustomers
/refundsrefunds
GET /payments/{id}/refunds, POST /payments/{id}/close with outcome: refundpayments and refunds
/disputesdisputes
/transfers, /beneficiaries, /identitywithdrawals
/, /providers, /eventsread
/channels, /countries, /currenciesnone: the catalogues answer the same to everyone
/balance, /webhooks, /shield, /taxcannot be called with X-Sync at all: they belong to the merchant's whole account
/accountscannot 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.

ResourceWhat the platform reaches
/payments, /refundsOnly those carrying this connection
/disputesOnly disputes on this connection's payments
/links, /invoicesOnly those created with this connection's X-Sync
/beneficiariesOnly those created with this connection's X-Sync, including a beneficiary given inline in a transfer
/transfersOnly payouts this connection initiated, and only to its own beneficiaries
/customers, /customers/{id}/tax_idsCustomers 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
/eventsOnly 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.

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.

ThenWhat happens
The merchant acceptsThe new terms apply from that moment, and account.change_accepted fires
The merchant declinesNothing changes, and account.change_declined fires
You propose againThe 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_feenumberoptional
Percentage of the payment amount, between 0 and 100, with up to four decimal places.
fixed_feenumberoptional
Flat amount added on top of the percentage, in major units of the rule currency.
min_feenumberoptional
Floor. A computed fee below it is raised to it.
max_feenumberoptional
Cap. A computed fee above it is lowered to it.
currencystringoptional
Three-letter code the fee figures are expressed in. Required as soon as you set fixed_fee, min_fee or max_fee.

The 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.

StepWhat happens
1The payment succeeds and carries a connection
2The connection's pricing applies
3The fee currency is the rule's currency, or the payment's when the rule has none
4Percentage and fixed fee are summed, then clamped by min_fee and max_fee
5A fee of zero is not charged
6The fee is charged once for the payment
7The 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.

PolicyOn a refund
prorata (default)The commission is returned in proportion to the amount refunded
fullThe whole commission is returned on the first refund, partial or not
noneNothing 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.

What stays editable outright

Two fields survive acceptance without the merchant's say-so, and they are the only two.

FieldWhy it stays open
callbackThe 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_statusactive 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.

What did you think of this content?