Approvals
Queues → Approvals is where dual control is visible. “Ten actions on this platform need a second person. This is where they wait.”
Needs approval.read to see. Deciding needs the permission the action itself
requires — see below.
The ten actions
Section titled “The ten actions”| Action | What it changes |
|---|---|
| Accounting period lock | Closes a period to further posting. |
| Accounting period reopen | Reopens a closed period. |
| Balance hold release | Frees money held against a merchant’s balance. |
| KYC check override | Marks a failed or unrun check as satisfied. |
| Merchant deposit | Credits a merchant’s balance with money they sent us. See Deposits. |
| Merchant fee settings | Changes what a merchant is charged. |
| Merchant live status | Enables or disables real money for a merchant. |
| Merchant suspension | Stops a merchant trading. |
| MFA reset | Clears a staff member’s authenticator. |
| Settlement release | Makes a batch payable. |
Each has its own decision route, and each route answers 404 for anything that is not its own action — deliberately, so that a refusal cannot reveal the existence of a pending change you were not shown.
The filter bar
Section titled “The filter bar”| Control | Type | Values |
|---|---|---|
| Action | One of | The ten action codes. |
| Status | Multi-select | Pending, Approved, not applied, Applied, Rejected, Expired, Cancelled. |
| Raised by | Toggle | Raised by me — what you are waiting on others for. |
The columns
Section titled “The columns”| Column | What it holds |
|---|---|
| Action | Which of the ten. |
| Against | The merchant, period, batch or staff account affected. |
| Raised by | The requester. Your own requests show as You. |
| Approvals | “1 of 2” — see below. |
| An approver needs | The permission required to decide it. |
| Amount | “The figure the policy’s amount band was chosen on.” |
| Expires | Time remaining. A lapsed request cannot be decided. |
| Status | — |
| You | Needs you, or the reason your account cannot decide it. |
| Raised | When. |
“1 of 2” means one more signature
Section titled ““1 of 2” means one more signature”The required count is approvers besides the person who raised it. So a request showing 1 of 2 needs one more signature, not two more. The detail panel spells this out, because “2” on its own reads as “two people in total” — which would make a one-approver policy look as though it needed nobody.
The “You” column is the answer to the most common question
Section titled “The “You” column is the answer to the most common question”“Why can I not decide this one?” It is one of four reasons, and the column says which:
- You raised it. A requester cannot approve their own request. The API refuses it: “maker and checker must be different people — that is the entire control.” The row says so rather than offering a button that will be refused.
- You lack the permission. An approver who could not have made the change themselves is a signature, not an approval, so the permission required to decide is the permission required to act.
- It has lapsed. A pending request past its deadline stays
pendinguntil something touches it, so the platform’s ownlapsedflag — not your clock — decides whether a decision is offered. - It is about you. A change to a staff account — an MFA reset, a password
reissue, a status change, a role assignment, or any held change to
/v1/users/{id}/…— can never be approved by the person it changes. It is refused with 403. The Authorised by picker leaves that person out, and a held change naming them is refused before anything is held.
Deciding a request
Section titled “Deciding a request”Open the row. The detail panel shows everything the decision should be made on:
| Fact | Why it is there |
|---|---|
| Status | — |
| Approvals | “Required counts approvers besides the person who raised it.” |
| An approver must hold | The permission. |
| Environment | Test or live. Check it. |
| Raised by / Raised | — |
| Expires | “A lapsed request is refused rather than queued.” |
| Amount | “Recorded so the policy’s amount band stays auditable after the policy changes.” |
| Request | The change itself, in full. |
| Policy | “Recorded so an auditor can reconstruct the decision from the policy as it stood.” |
| Reason given | What the requester wrote. |
| Decisions recorded | Every signature so far, with Step-up verified where the approver proved identity at the point of deciding. |
To decide, you provide:
| Field | Notes |
|---|---|
| Reason | Yours, recorded against your decision. |
| Authenticator code | “A current code from your own authenticator. A recovery code is not accepted here.” |
Approving records your signature. The change applies once the required number of approvals is in.
Withdrawing your own request
Section titled “Withdrawing your own request”If you raised it, you can withdraw it — “it can be raised again if the change is still wanted.” One field: Reason, e.g. “Raised against the wrong merchant.”
Withdrawing a wrong request is always better than leaving it for somebody to approve by mistake.
Two shapes of dual control, and the form tells you which
Section titled “Two shapes of dual control, and the form tells you which”Most dual control here is after the fact: the write raises a request, this register holds it, and somebody else decides it. Nothing has changed when you submit, and the dialog says so.
The other writes — pricing rules, a blocklist entry, a risk rule’s mode, a limit, a routing rule, an FX rate, a statement close, a staff account, a settlement batch, a withdrawal, verifying a settlement destination by hand, settling a payment on evidence, releasing a payment from risk review — carry an Authorised by picker. Naming a colleague there holds the change until they approve it: “They are asked to approve {what} in Approvals; nothing changes until they do. It cannot be you.”
| Approval request | Held for a co-signer | |
|---|---|---|
| What the dialog says | “This raises a request” | Authorised by |
| When it takes effect | When the second person approves | When the person you named approves |
| Where it waits | Approval requests | Waiting on you (theirs) and Asked by you (yours) |
Held changes: co-signing
Section titled “Held changes: co-signing”When you submit a form naming a colleague in Authorised by, nothing changes. The console shows a blue notice — “Sent to {name} for approval. Nothing changes until they approve it in Approvals; it lapses if not decided within 72 hours.”
Three tabs on this page:
| Tab | What it holds |
|---|---|
| Waiting on you | “Changes a colleague made and named you as authorising. Nothing has happened until you approve.” The tab shows how many. |
| Asked by you | “Changes you made that name a colleague. They take effect when that colleague approves.” |
| Approval requests | The policy queue described above. |
Opening a held change shows exactly what will be sent — the method, the path and the request body — with the requester’s reason. Then:
- Approve and apply — the change is run again, as the person who made it, with their permissions as they stand at that moment. Every check the action normally makes applies again, and the audit entry names you as the approver. The sheet then shows “Approved and applied”, or “Approved, but the change was refused” with what the server returned — a permission removed or a record changed since, for example.
- Reject — needs “Why you are rejecting it”, at least eight characters. “They read this.”
- Withdraw this request — for the person who made it, while it waits.
A held change not decided within 72 hours lapses.
Naming yourself is not held. The action’s own rule applies, and nearly all of them refuse it. The exceptions:
- Creating a staff account while yours is the only active one.
- Changing a partner’s addresses or setting its credentials while yours is the only active account. See Partners.
- Approving a withdrawal, verifying a settlement destination by hand, settling a payment on evidence, or releasing one from risk review, while yours is the only active account. See Withdrawals and Merchants.
- Credential recovery (a password reissue or an authenticator rebind) while no active account exists other than yours and the person being recovered. They can’t approve their own recovery, so nobody else could decide it.
All take effect at once and are recorded as self-authorised. See Staff and When there are only two accounts.
From the API (approval.read): GET /v1/cosign-requests?side=to_me|by_me,
GET /v1/cosign-requests/{id}, POST /v1/cosign-requests/{id}/decide with
approve or reject and a reason, and POST /v1/cosign-requests/{id}/cancel. A
held write answers 202 with the code approval_pending and a
cosign_request_id.
Who is emailed
Section titled “Who is emailed”| When | Who | Subject |
|---|---|---|
| An approval request is raised | Every active staff member who holds the policy’s approver permission, or is a super admin, except the person who raised it. At most 25 people. | Approval needed: {action} |
| A change is held for co-signing | The colleague named in Authorised by. | Approval needed: {action} |
| A request or held change is decided | The person who raised it, whether it was approved and applied, rejected, or approved but refused when it ran. | Your request was {decision}: {action} |
The emails have no button. They name the page to open, Approvals, because a link in a staff email would point at the merchant portal. The email is queued in the same transaction as the request or decision, so nobody is told about a decision that rolled back.
Raising one
Section titled “Raising one”You do not raise approvals from this page. Each request is raised where the change is made — a suspension from the merchant’s page, a period lock from Periods, an MFA reset from Staff. This page is only where they wait.
What makes a request easy to approve:
- A reason that states the facts, not the conclusion. “Merchant requested limit raise” is not a reason; “trading history since March supports GHS 50k, dispute rate 0.3%, KYC level 2 approved 14 Aug” is.
- The right amount band. The amount decides which policy applies, and it is recorded for audit.
- Raised in the right environment. A live change raised against test is the most common wasted request.
How to work this queue
Section titled “How to work this queue”- Filter to Pending and sort your attention by Expires — a lapsed request means somebody has to start again.
- Read the request, not the title. The action code tells you what kind of change it is; the request body tells you what it actually does.
- Check the environment.
- Ask yourself whether you would have made this change. That is the question dual control asks you. If the answer is “I would want to know more”, that is not an approval.
- Write the reason you would want to read in six months.

