MCP guides

Deciding approval requests

For assistants

An assistant connected to the Qualy MCP server reads this guide as the resource qualy://guides/approvals. Generated from the Qualy MCP server’s guide registry.

Your account's approval policies hold some charges, payouts, payment splits, direct-debit agreements, refunds and export deliveries until approvers decide, and approving can release money. Do it in this order: find what is waiting, check what you may do, then decide.

1. Find what is waiting

Call approval_request_list with status pending. You see what the dashboard shows you: every request, your team's, or only those you created, are assigned or have acted on. Narrow it with entityType (and entityId for one record). Each row carries viewer, so you can tell which ones you may decide now.

A record shows its own approval too:

  • payout_get returns approval: who approves, in order, under which strategy, who already decided, and viewer.
  • payment_split_get returns the split's own approval and, when a direct-debit charge on it is held for an approver, chargeApproval. A split's approval is decided when its payout is prepared, so a new split has none yet; an automatic split's release is approved on its payout.
  • A refund names its approval request; qualy://guides/refunds covers deciding refunds.

2. Check what you may do

approval_request_get returns the request with its policy, approvers, assignment and decisions, and viewer: the same check approving and rejecting run.

  • canApprove: it is pending, you are a listed approver, it is your turn (Sequential) or you are assigned (Round-robin), you are active and still hold an approver role, and you haven't decided yet.
  • canReject: it is pending, you are a listed approver (any of them, at any time), and you haven't decided yet.
  • approveRefusal and rejectRefusal: when you may not, the code and message the action would return.
  • progress: what your approval would do, approved of required, and wouldResolve when yours is the one that passes it.

The strategy decides when a request passes:

  • Any approver and Round-robin (the assignedApprover): one approval passes it.
  • All approvers: every listed approver must approve.
  • Sequential: every listed approver, one after another, in order.
  • Any listed approver may reject at any time, even out of turn, and one rejection stops it.

3. Decide

approval_request_approve and approval_request_reject take the requestId and an optional comment recorded on the request. Their previews refuse up front what deciding would refuse, and say in the dashboard's words what approving does:

  • A payout sends the amount to its recipient. In another currency, what you approve is what the recipient receives; what you send is a live quote, re-priced when the money moves.
  • A payment split sends the amount to its recipient as their split.
  • A refund refunds the customer and sends the money. It can't be undone.
  • A charge charges the customer. An external payment is only recorded, and an offset moves no money.
  • A direct-debit agreement moves no money: its amount is the most that could ever be debited over the agreement's whole period. Rejecting it cancels the agreement, which leaves that payment unable to go out.
  • An export delivery delivers the export file to its destination. Rejecting it cancels that delivery, and nothing is delivered.

Under All approvers or Sequential, the preview says when your approval is not the last one needed. The result is the request: status approved means it passed and what it held goes ahead; still pending means your approval is recorded and the rest are needed. Rejecting stops what it held.

When a decision no longer counts

A record's approval reads superseded when the decision no longer covers it: when it was released, its amount or currency had changed, or, for a cross-currency payout, the amount funding it had risen more than the policy's FX drift tolerance (5% by default), so the release was refused. Its status stays as it was, and the next attempt to release it raises a new request. When a newer request replaces one, the record shows the newer request; the old one (approval_request_list with entityId) has supersededReason and supersededBy, the request that replaced it.

Worked examples

See what is waiting

{
  "tool": "approval_request_list",
  "arguments": {
    "status": "pending"
  }
}

Per row, viewer.canApprove and viewer.canReject say what you may do now. Use count and hasMore for totals.

Check one request before deciding

{
  "tool": "approval_request_get",
  "arguments": {
    "requestId": "66f1d0a3e4b0a1b2c3d4e5f8"
  }
}

If viewer.canApprove is false, approveRefusal says why. progress says whether your approval would pass it.

Approve it

{
  "tool": "approval_request_approve",
  "arguments": {
    "requestId": "66f1d0a3e4b0a1b2c3d4e5f8",
    "comment": "Matches the signed agreement."
  }
}

Read status in the result: approved means it passed; pending means others still need to approve.

Previews first: the call returns a preview to show the person. Call it again with the same arguments plus confirmationId and userConfirmed: true only after they approve.

Reject it

{
  "tool": "approval_request_reject",
  "arguments": {
    "requestId": "66f1d0a3e4b0a1b2c3d4e5f8",
    "comment": "The amount does not match the invoice."
  }
}

Previews first: the call returns a preview to show the person. Call it again with the same arguments plus confirmationId and userConfirmed: true only after they approve.

Previous
Payouts and reconciliation