Developer Docs · v1

One endpoint.
Typed tools.

Paystack ships as a Model Context Protocol server plus a REST API. Everything is typed. Every call carries a ReasoningLog. Every state change is signed.

§ Connect via MCP

Point your agent at it.

Nothing to install or self-host. Paystack runs a hosted MCP server on the current Streamable HTTP transport — add the config below to your MCP client (Claude Desktop, Cursor, Continue, or any A2A agent) and paste an API key as the Bearer token. The session is scoped to your workspace; every tool call passes the safety switch.

~/.mcp.json
{
  "mcpServers": {
    "paystack": {
      "url": "https://api.getpaystack.com/mcp",
      "headers": { "Authorization": "Bearer pk_live_..." }
    }
  }
}

Mint a key in Dashboard → Integrations → API keys (POST /auth/api-keys). Older clients that only speak the deprecated HTTP+SSE transport can use https://api.getpaystack.com/mcp/sse. Verify a connection by calling tools/list — it returns the full tool catalog with JSON Schemas.

§ Tool surface

A focused verb set.

The API is small on purpose. Each verb has a clear posture, clear scope, and a documented risk level. Most agents only need two: initiate_escrow_payout and check_payout_status.

ToolPurposeRisk
initiate_escrow_payoutOpen an escrow: charge/hold + scheduled payout. Returns escrowId + VFP.medium · reasoningLog
release_escrowRelease held funds. Verifier checks proof before the outbound leg fires.high · reasoningLog
pause_escrow / cancel_escrowDispute gate (halts auto-release) and full unwind (refund inbound).medium · reasoningLog
check_payout_statusStatus, settlement timeline, reversibility window, fee breakdown.read
quote_fees / explain_routingPreview fees + the router decision. No side effects.read
get_spending_limitAgent’s workspace auto-transfer caps + current usage.read
attach_bank_account / verify_bank_account / list_bank_accountsOnboard + verify bank accounts (micro-deposit flow).medium · reasoningLog
redeem_vfpVerify a VFP token signature and return its payload.public
§ initiate_escrow_payout

The MCP schema.

paystack.mcp.json
{
  "name": "initiate_escrow_payout",
  "description": "Open an escrow: charge/hold the payer, then pay out on release. Router picks strategy + rails. Returns escrowId + VFP.",
  "inputSchema": {
    "payer":        { "type": {"enum": ["tenant","landlord","pm","agent","system"]}, "id": "string" },
    "payerCaps":    { "hasCard": "boolean", "hasVerifiedBank": "boolean" },
    "payee":        { "type": "...", "id": "string" },
    "payeeBankAccountId": "string",
    "amountCents":  "string | number",
    "tier":         "'standard' | 'priority' | 'instant'",
    "category":     "'vendor' | 'maintenance' | 'payroll' | 'rent' | 'other'",
    "condition":    "{ kind: 'manual' | 'deadline' | 'webhook' | 'api_trigger' }",
    "maxHoldDays":  "number",
    "reasoningLog": "object   // required, non-empty"
  }
}
§ ReasoningLog

The envelope every call carries.

Every agent-triggered payment includes a ReasoningEnvelope. It travels with the ledger entry and through webhooks. Finance, compliance, and engineering all read the same field — no after-the-fact reconstruction.

reasoning.ts
type ReasoningEnvelope = {
  // Why the agent chose to act
  policy:      string           // dotted policy path (e.g. 'maintenance.repair')
  confidence:  number           // [0, 1]
  agent_id:    string           // stable id for the acting agent
  model:       string           // model version that authorized

  // Evidence
  inputs_hash: sha256           // hash of the prompt/context that produced this
  citations:   string[]?        // source ids the agent grounded on
  tool_trace:  string[]?        // upstream tool calls that led here

  // Operator overrides
  approved_by: string?          // operator id if human-in-the-loop fired
  override:    boolean?         // true if policy would have blocked
}
§ Webhooks

Signed events on every state change.

webhook.json
// POST to your endpoint · headers:
//   x-paystack-signature: sha256=<hex>   (HMAC-SHA256 of the raw body)
//   x-paystack-event:     escrow.released
//   x-paystack-delivery:  01J8...        (unique id; use to dedupe)
{
  "id":        "01J8...",              // delivery id
  "type":      "escrow.released",
  "createdAt": "2026-07-09T12:00:00.000Z",
  "data": {                            // event-specific payload
    "escrowId":    "esc_01J...",
    "amountCents": 120000
  }
}

Event types

  • escrow.releasedHeld funds cleared to the counter-party.
  • escrow.refundedFunds returned to the payer.
  • escrow.haltedNACHA return / dispute → HALTED.
  • debt.createdA return created an actor debt.
  • verification.approvedIdentity verification approved.
  • plan.changedWorkspace subscription changed.
Next step

Stuck, or sizing an integration?

Bring the system you need to wire up and we will tell you what the integration actually looks like — including if the honest answer is that you do not need us yet.

Rates, in full: inbound ACH pull $0.75 flat, same-day ACH $1.50, instant / push-to-card 0.95% capped at $10, and card acceptance interchange + 2.00% + $0.30 with interchange passed straight through. A fixed $250/mo platform fee applies and is not offset by usage.