eCMRhub.docs

Human approvals

Which calls need a person's approval, what Hub answers (428), where the person approves, and how the agent repeats the call.

In build (backend and dashboard)

Approvals are part of phase 1. The status codes, fields and header below are the agreed contract.

Some operations cannot be undone or reach people outside the company: issuing a document, creating, renewing, revoking or sending signing links, deleting drafts or address book entries, and starting or changing live tracking. For these, Hub does not take the agent's word. A person from the company approves the exact call in the dashboard. The operation catalog marks every such operation; changing a contractor's roles needs approval too.

The check runs on the server. It does not depend on the CLI, the MCP client or the SDK, and no flag, header or tool lets an agent approve its own call.

When approval applies

Approval is required when the operation needs it and the connection has "Require approval" switched on. The company owner sets this per connection in the dashboard. Default: on for OAuth connections (agents, connectors, the CLI after ecmrhub login), off for API keys.

The flow

StepWhoWhat happens
1AgentCalls the operation, for example issues a draft.
2HubRecords an approval request pinned to the exact operation and input, and answers 428 APPROVAL_REQUIRED with a link.
3AgentShows the link to the user and waits.
4PersonOpens the link in the dashboard, reviews the card and approves or rejects.
5AgentRepeats the same call with the approval id. Hub executes it and marks the approval as used.

The 428 answer

{
  "error": {
    "status": 428,
    "code": "APPROVAL_REQUIRED",
    "message": "...",
    "retryable": false,
    "approval": {
      "id": "6f1c2a9e-...",
      "url": "https://ecmrhub-v2.lucaspiera.com/dashboard/approvals/6f1c2a9e-...",
      "expiresAt": "2026-10-20T10:00:00.000Z",
      "operation": "draft.publish",
      "status": "pending"
    }
  }
}

Sending the identical call again without the approval id returns the same pending approval; Hub does not create duplicates.

Repeating the call

Repeat the call with the same input and the approval id:

ChannelHow to pass the approval
HTTPHeader x-ecmr-approval: <id>
SDKWrite option approval: "<id>"
CLIRun error.approval.retry (the same command plus --approval <id>); ecmrhub approvals wait <id> blocks until a decision
MCPArgument approvalId on the same tool

The approval is pinned to a SHA-256 digest of the operation name and its validated input (keys sorted). It is valid for 24 hours and can be used once.

SituationAnswerWhat to do
Still waiting for the person428 APPROVAL_REQUIREDWait; remind the user of the link
Approved, same inputThe operation's normal resultDone; the approval is now used
Approved, input changed409 APPROVAL_MISMATCHRepeat the original input, or start over without the id to request a new approval
Rejected403 APPROVAL_REJECTEDStop and ask the user what to change
Older than 24 hours410 APPROVAL_EXPIREDCall again without the id to request a new approval
Already used409 APPROVAL_CONSUMEDThe call already ran; read the result (e.g. list documents) instead of repeating
Unknown id, or another company's404 APPROVAL_NOT_FOUNDCheck the id you passed
100 approvals pending for this connection429 APPROVAL_LIMITAsk the user to decide the pending ones first

Checking status

ecmrhub approvals list --status pending --json   # approvals this connection requested
ecmrhub approvals status <id> --json             # one approval
ecmrhub approvals wait <id> --timeout 300 --json # exit 0 approved, 4 rejected, 1 expired or used, 5 still pending

Over HTTP: GET /functions/v1/approvals/<id> with the same token that made the request. A connection or API key sees only the approvals it requested; a person sees the whole company. An approval has status pending, approved, rejected, consumed or expired, the operation, the input, who requested it and when it expires. Approving and rejecting is only possible for a signed-in person in the dashboard; connections and API keys get 403.

What to tell the user

Keep it short and concrete, with the link:

I prepared consignment note CMR 2026/104 (Warsaw to Lyon, 33 pallets). Please approve issuing it: https://ecmrhub-v2.lucaspiera.com/dashboard/approvals/6f1c2a9e-.... I will issue it as soon as you approve.

Do not change the data while waiting. If the user asks for a change, make it, then call again without the old approval id: the change needs a new approval.

On this page