Skip to main content
The PanoFlow MCP server lets an AI agent use one agent account of a business, inside guardrails that people in the business set. The agent can check its balance, read its transactions, save recipients, pay them, and create invoices. Each tool is one call to the public API, made as the agent, with the same inputs and outputs.

Connect

Sandbox uses the same URL. A grant on a sandbox agent gets sandbox tokens, and the token decides whether the agent reaches sandbox or live. Sandbox calls never reach a real partner.

Sign in

PanoFlow is the OAuth 2.1 authorization server. MCP clients that support OAuth discover and run this flow on their own:
1

Discover

A call without a token gets 401 with WWW-Authenticate: Bearer resource_metadata="https://mcp.panoflow.io/.well-known/oauth-protected-resource". That document (RFC 9728) points to the authorization server, whose metadata (RFC 8414) is at https://api.panoflow.io/.well-known/oauth-authorization-server.
2

Register

The client registers itself with dynamic client registration (RFC 7591) at POST https://api.panoflow.io/v1/oauth/register. Only public clients are accepted (token_endpoint_auth_method: none), and redirect URIs must be https:// or http://localhost / 127.0.0.1.
3

Get consent

The client starts an authorization code flow with PKCE (S256 only) and resource=https://mcp.panoflow.io. In the browser, at https://app.panoflow.io/oauth/authorize, a person whose role can manage agents picks the business and one agent account, reviews what the client will be able to do, and confirms with their two-factor code. This creates a grant (grt_...), shown in the app as a connected app. Paused agents can’t be picked.
4

Get tokens

The client exchanges the code and refreshes tokens at POST https://api.panoflow.io/v1/oauth/token, and revokes them at POST https://api.panoflow.io/v1/oauth/revoke.

Scopes

Agents can hold only these seven scopes: accounts:read, transfers:read, transfers:write, recipients:read, recipients:write, collections:read, collections:write A grant holds the scopes the client requested that the agent is also allowed. They are checked again against the agent’s current allowed scopes on every call. Payroll, team, API key and agent management, and anything that changes limits, can never be granted to an agent. A token used on any operation outside its scopes gets 403 scope_missing.

Token lifetimes

Tokens stop working early when the owner pauses the agent (every token of every grant of that agent is revoked, and each app must sign in again after the agent is turned back on), when someone disconnects the app, when the client revokes its refresh token, or when the grant expires. An expired or revoked token gets 401 with WWW-Authenticate: Bearer error="invalid_token"; refresh it or sign in again.

Tools

Tool inputs use the REST operation’s parameter and field names. The server fills in the agent’s own account where the REST operation takes one, and pay always makes a payout to a saved recipient_id with a reason (it can’t pay a raw bank account or move money between accounts). Tool results (structuredContent) are the REST response bodies unchanged: snake_case, Money objects in kobo, RFC 3339 times, and the list envelope for list tools. pay requires idempotency_key; create_recipient and create_invoice accept it. It is sent as the Idempotency-Key header, stored for 7 days, and you reuse it on retries. See Idempotency.

Guardrails

People in the business set an agent’s guardrails in the web app. No tool can change limits, allowlists, scopes or ask-first rules, approve a payment, pause or resume an agent, or touch any account other than the agent’s own. For pay, limits block and ask-first holds:
  • Blocked: a payment over the per-payment or monthly limit (limit_exceeded), over the daily limit (daily_limit_exceeded), or to a recipient outside the allowlist when ask-first for new recipients is off (recipient_not_allowed) is refused as a tool error and nothing is created. PanoFlow sends agent.payment.blocked.
  • Held: a payment over the agent’s ask-first amount, outside business hours (08:00 to 18:00 Lagos time, Monday to Saturday), or to a recipient outside the allowlist when ask-first for new recipients is on, becomes a transfer in pending_approval with an agent_payment approval, and PanoFlow sends agent.payment.held. The money is reserved and counts toward the daily limit. A person approves or rejects it in the web app. Rejected payments become rejected; payments nobody decides within 30 minutes become canceled with status_reason: approval_expired. The agent polls get_payment to find out.
Other checks return ordinary errors: a paused agent gets agent_paused, an amount in another currency gets currency_mismatch, and an available balance below the amount plus fee gets insufficient_balance.

Results and errors

  • Money-moving results (pay, get_payment and each list_transactions row) carry response_code and response_message: 09 held or processing, 01 bank status not confirmed yet, 00 completed, 21 when a person rejected it or the approval expired, or the bank’s NIP code (or PanoFlow’s) when it failed. See Payment statuses.
  • A failed tool call returns isError: true with structuredContent set to the PanoFlow error object (error.type, error.code, error.response_code, error.message, error.param, error.request_id, error.details).
  • Protocol problems, such as an unknown tool or malformed JSON-RPC, are JSON-RPC errors, not tool errors.

Rate limits

Each agent has its own rate limit, tighter than an API key’s. Over it, a tool returns rate_limited with details.retry_after in seconds.

Activity log

Every tool call, whether allowed, held, blocked or refused, is recorded in the agent’s activity log with the grant, client, arguments, decision, error code, response code and request id. The business’s owners see it in the web app.