API & MCP Reference

Complete reference for the AgentLedger Local Edition REST API and MCP tool definitions. Both interfaces expose the same ledger — the API via HTTP, MCP tools via any MCP-compatible client.

Installation

Download the latest binary for your platform from GitHub Releases:

[GITHUB_RELEASES_LINK]

macOS & Linux

# Rename to remove the platform suffix and make executable
mv agentledger-linux-amd64 agentledger      # adjust filename for your platform
chmod +x agentledger

# Move to a directory on your PATH (optional but recommended)
sudo mv agentledger /usr/local/bin/

# Verify
agentledger

On macOS, if you see a Gatekeeper warning on first run, go to System Settings → Privacy & Security and click Allow Anyway.

Windows

# Rename the downloaded file
Rename-Item agentledger-windows-amd64.exe agentledger.exe

# Run from the current directory
.\agentledger.exe

# Or add the directory to your PATH for system-wide access.

Available platform binaries: linux-amd64, linux-arm64, darwin-amd64, darwin-arm64, windows-amd64, windows-arm64.

MCP Servers Setup

The MCP servers are a Node.js package that wraps the REST API for use with MCP-compatible clients — Claude Desktop, Cursor, Windsurf, OpenClaw, and others. Requires Node.js >= 18 and a running AgentLedger instance.

Install from the repository

# Clone the repository
git clone [GITHUB_REPO_LINK]
cd agentledger/apps/mcp

npm install
npm run build

A standalone npx agentledger-mcp installer (no clone required) is coming soon.

Configure your MCP client

Add both servers to your MCP client configuration. For Claude Desktop, edit claude_desktop_config.json:

{
  "mcpServers": {
    "agentledger-user": {
      "command": "node",
      "args": ["/path/to/agentledger/apps/mcp/dist/index.js", "user"],
      "env": {
        "AGENTLEDGER_USER_TOKEN": "alu_your-token-here"
      }
    },
    "agentledger-supervisor": {
      "command": "node",
      "args": ["/path/to/agentledger/apps/mcp/dist/index.js", "supervisor"],
      "env": {
        "AGENTLEDGER_SUPERVISOR_TOKEN": "als_your-token-here",
        "AGENTLEDGER_SUPERVISOR_TIER": "1"
      }
    }
  }
}

Replace /path/to/agentledger with the actual path where you cloned the repository. Replace the token values with the tokens from your .env file (generated during agentledger init). The same JSON structure works for Cursor, Windsurf, and other MCP-compatible tools — consult their documentation for the config file location.

Supervisor tiers in MCP

Set AGENTLEDGER_SUPERVISOR_TIER to control which tools the supervisor server exposes. Tier 1 (default) covers approve/deny. Tier 2 adds budget management. Tier 3 adds vault replacement. This must match the tier set during agentledger init --supervisor-tier N.

Quick Start

# 1. Initialize (generates tokens, encryption key, database)
agentledger init

# 2. Vault a payment card
agentledger vault add

# 3. Set a budget for an agent (e.g. $50.00 cumulative)
agentledger budget set agent-1 5000

# 4. Start the server
agentledger serve
# Listening on http://127.0.0.1:9119

The server is now ready. Agents authenticate with the tokens printed during init, which are stored in .env.

Authentication

AgentLedger uses two bearer tokens with distinct roles. Tokens are generated during agentledger init and use prefixes to prevent accidental swap.

RoleEnv VarPrefixPurpose
User agent AGENTLEDGER_USER_TOKEN alu_ Initiate spends, check budget, poll status, read history
Supervisor agent AGENTLEDGER_SUPERVISOR_TOKEN als_ Approve/deny, manage budgets, credit, vault update (tiered)

Pass the token in the Authorization header:

Authorization: Bearer alu_your-user-token-here

Supervisor Tiers

Supervisor capabilities are gated by tier, set at agentledger init --supervisor-tier N:

TierDefault?Capabilities
1YesApprove, deny, list pending
2Opt-in+ Set budget, credit budget
3Opt-in, explicit consent+ Update vault (replace card)

Multiple Agents

There is no agent registration step. An agent comes into existence the moment you set a budget for it — the agent_id is simply a free-form string you choose. You can run as many logical agents as you like, each with its own independently tracked budget and transaction history:

agentledger budget set researcher-agent 5000
agentledger budget set purchasing-agent 20000
agentledger budget set ops-agent 10000

Agents authenticate using the shared user token (alu_) — there is no per-agent credential. The agent_id field in POST /authorize is self-reported by the calling agent and determines which budget is checked and consumed. The security boundary is the token, not the agent ID: any bearer of the user token can submit requests under any agent ID string.

All agents share a single vaulted card. Budget accounting and transaction history are tracked per agent_id, but the underlying payment credential is the same for all of them.

Running multiple isolated instances

For full isolation between separate groups of agents — for example, two independent "virtual companies" — you can run two separate AgentLedger instances simultaneously, each in its own directory with its own .env, encryption key, token pair, card vault, and database. Use AGENTLEDGER_PORT to assign each instance a different port:

# Company A — default port
cd ~/company-a
agentledger init
agentledger serve
# Listening on http://127.0.0.1:9119

# Company B — different port (separate terminal)
cd ~/company-b
agentledger init
# Edit .env: uncomment and set AGENTLEDGER_PORT=9120
agentledger serve
# Listening on http://127.0.0.1:9120

Point each set of agents at the appropriate base URL (AGENTLEDGER_BASE_URL in the MCP server config). Each instance is completely isolated — separate tokens, separate encryption key, separate card, separate budget and transaction ledger.

Running on a VPS

AgentLedger works on a VPS or cloud server, but requires a reverse proxy with TLS. The API transmits bearer tokens and card credentials — these must never travel over plain HTTP on a network.

Recommended setup: keep AgentLedger bound to 127.0.0.1 (the default) and place Caddy or nginx in front for automatic HTTPS.

# 1. Initialize and start AgentLedger (binds to 127.0.0.1:9119 by default)
agentledger init
agentledger vault add
agentledger serve

# 2. Install Caddy (Ubuntu/Debian example)
sudo apt install -y caddy

# 3. Create /etc/caddy/Caddyfile
#    Replace agentledger.example.com with your domain
agentledger.example.com {
    reverse_proxy 127.0.0.1:9119
}

# 4. Restart Caddy (auto-obtains a Let's Encrypt certificate)
sudo systemctl restart caddy

Your agents now connect to https://agentledger.example.com instead of http://127.0.0.1:9119. Set AGENTLEDGER_BASE_URL=https://agentledger.example.com in your MCP client config.

Firewall

Only expose port 443 (HTTPS) to the internet. Port 9119 should remain accessible only from 127.0.0.1. On most VPS providers:

# UFW (Ubuntu)
sudo ufw allow 443/tcp
sudo ufw deny 9119/tcp

Advanced: binding to all interfaces

If you need AgentLedger to accept connections directly (e.g. inside a private network or Docker bridge), set AGENTLEDGER_HOST in your .env:

# .env
AGENTLEDGER_HOST=0.0.0.0

The default is 127.0.0.1 (localhost only). Do not bind to 0.0.0.0 without TLS termination in front — tokens and card data would be transmitted in plaintext.

Ledger Semantics

AgentLedger uses an authorize-is-final model. Once the budget is deducted and the card is released, the spend is permanent. There is no agent-accessible path to restore budget after card release.

Transaction Status Lifecycle

POST /authorize
   spent  (auto mode: budget consumed, card released immediately)
   pending  (manual mode: awaiting approval)
     spent  (approved: card released)
     denied  (denied or TTL expired: budget refunded)
   denied  (insufficient budget or invalid request)

GET /health

GET/health
No auth

Health check. Returns 200 if the server is running.

curl http://127.0.0.1:9119/health

Response

{
  "status": "ok"
}

POST /authorize

POST/authorize
User token

Request payment authorization. If the agent's budget is sufficient, funds are reserved and card details may be returned immediately (auto mode) or held for approval (manual mode).

Request Body

FieldTypeRequiredDescription
amountintegerYesAmount in cents (e.g. 2500 = $25.00). Must be greater than zero.
merchantstringYesMerchant name
purposestringYesWhy this payment is needed
requesting_agent_idstringYesAgent identifier
metadataobjectNoArbitrary key-value pairs
curl -X POST http://127.0.0.1:9119/authorize \
  -H "Authorization: Bearer alu_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 2500,
    "merchant": "AWS",
    "purpose": "EC2 instance for data pipeline",
    "requesting_agent_id": "agent-1"
  }'

Response (auto mode — spent)

{
  "status": "spent",
  "transaction_id": "tx_abc123",
  "holder_name": "Jane Doe",
  "card_number": "4111111111111111",
  "expiry_date": "12/27",
  "cvv": "123",
  "country": "US",
  "zip_code": "94105"
}

Response (manual mode — pending)

{
  "status": "pending",
  "transaction_id": "tx_abc123",
  "expires_at": "2026-04-12T20:30:00Z"
}

Response (denied)

{
  "status": "denied",
  "reason": "insufficient budget"
}

GET /status/{tx_id}

GET/status/{tx_id}
User token

Poll the current status of a transaction. In manual mode, this is how the user agent retrieves card details after a supervisor approves the transaction. Card details are included only when status is spent and the agent_id query parameter matches the transaction's owning agent.

Query Parameters

ParameterRequiredDescription
agent_idYes (for card data)Must match the requesting_agent_id used in the original POST /authorize. If omitted or mismatched, the response includes status and metadata but no card fields.
curl http://127.0.0.1:9119/status/tx_abc123?agent_id=agent-1 \
  -H "Authorization: Bearer alu_..."

Response (pending)

{
  "transaction_id": "tx_abc123",
  "status": "pending",
  "amount": 2500,
  "merchant": "AWS",
  "purpose": "EC2 instance for data pipeline",
  "agent_id": "agent-1",
  "expires_at": "2026-04-12T20:30:00Z"
}

Response (spent, with matching agent_id)

{
  "transaction_id": "tx_abc123",
  "status": "spent",
  "amount": 2500,
  "merchant": "AWS",
  "purpose": "EC2 instance for data pipeline",
  "agent_id": "agent-1",
  "holder_name": "Jane Doe",
  "card_number": "4111111111111111",
  "expiry_date": "12/27",
  "cvv": "123",
  "country": "US",
  "zip_code": "94105"
}

If agent_id is omitted or does not match, the response contains the same fields except the card fields are excluded.

GET /budget/{agent}

GET/budget/{agent}
User or Supervisor token

Check the remaining budget for a specific agent. Accessible to both user agents and supervisor agents.

curl http://127.0.0.1:9119/budget/agent-1 \
  -H "Authorization: Bearer alu_..."

Response

{
  "agent_id": "agent-1",
  "limit": 5000,
  "used": 2500,
  "available": 2500,
  "period": "cumulative"
}

GET /transactions/{agent}

GET/transactions/{agent}
User or Supervisor token

Retrieve the full transaction history for an agent. Accessible to both user agents and supervisor agents.

curl http://127.0.0.1:9119/transactions/agent-1 \
  -H "Authorization: Bearer alu_..."

Response

[
  {
    "id": "tx_abc123",
    "agent_id": "agent-1",
    "amount": 2500,
    "merchant": "AWS",
    "purpose": "EC2 instance for data pipeline",
    "status": "spent",
    "created_at": "2026-04-12T14:00:00Z",
    "updated_at": "2026-04-12T14:00:00Z"
  }
]

GET /pending

GET/pending
Supervisor token · Tier 1+

List all transactions currently awaiting approval.

curl http://127.0.0.1:9119/pending \
  -H "Authorization: Bearer als_..."

Response

[
  {
    "id": "tx_abc123",
    "agent_id": "agent-1",
    "amount": 2500,
    "merchant": "AWS",
    "purpose": "EC2 instance for data pipeline",
    "expires_at": "2026-04-12T20:30:00Z",
    "created_at": "2026-04-12T14:00:00Z"
  }
]

POST /approve

POST/approve
Supervisor token · Tier 1+

Approve a pending transaction. The transaction transitions to spent and the reserved budget is consumed. Card details are not returned in this response — the user agent retrieves them by polling GET /status/{tx_id}?agent_id=....

Request Body

FieldTypeRequiredDescription
transaction_idstringYesID of the pending transaction
curl -X POST http://127.0.0.1:9119/approve \
  -H "Authorization: Bearer als_..." \
  -H "Content-Type: application/json" \
  -d '{"transaction_id": "tx_abc123"}'

Response

{
  "transaction_id": "tx_abc123",
  "status": "spent",
  "amount": 2500,
  "merchant": "AWS",
  "purpose": "EC2 instance for data pipeline",
  "agent_id": "agent-1"
}

POST /deny

POST/deny
Supervisor token · Tier 1+

Deny a pending transaction. Reserved budget is fully refunded.

Request Body

FieldTypeRequiredDescription
transaction_idstringYesID of the pending transaction
curl -X POST http://127.0.0.1:9119/deny \
  -H "Authorization: Bearer als_..." \
  -H "Content-Type: application/json" \
  -d '{"transaction_id": "tx_abc123"}'

Response

{
  "status": "denied"
}

POST /budget/{agent}

POST/budget/{agent}
Supervisor token · Tier 2+

Create or update the spending budget for an agent.

Request Body

FieldTypeRequiredDescription
limitintegerYesBudget limit in cents
periodstringNocumulative (default) or monthly
curl -X POST http://127.0.0.1:9119/budget/agent-1 \
  -H "Authorization: Bearer als_..." \
  -H "Content-Type: application/json" \
  -d '{"limit": 10000, "period": "monthly"}'

Response

{
  "agent_id": "agent-1",
  "limit": 10000,
  "used": 0,
  "available": 10000,
  "period": "monthly",
  "period_start": "2026-04-01T00:00:00Z"
}

POST /credit

POST/credit
Supervisor token · Tier 2+

Restore previously consumed budget. Use after a payment bounces or a refund is received. A reason is required for audit trail.

Request Body

FieldTypeRequiredDescription
agent_idstringYesAgent to credit
amountintegerYesAmount to restore in cents
reasonstringYesAudit reason (e.g. "Payment bounced")
curl -X POST http://127.0.0.1:9119/credit \
  -H "Authorization: Bearer als_..." \
  -H "Content-Type: application/json" \
  -d '{"agent_id": "agent-1", "amount": 2500, "reason": "Merchant refund received"}'

Response

{
  "agent_id": "agent-1",
  "credited": 2500,
  "new_used": 0,
  "new_limit": 5000,
  "available": 5000
}

POST /vault/update

POST/vault/update
Supervisor token · Tier 3

Replace the vaulted payment card. High-privilege operation — only available when Tier 3 was explicitly enabled during agentledger init. All future approved transactions will use the new card.

Request Body

FieldTypeRequiredDescription
holder_namestringYesCardholder name
card_numberstringYesCard number (digits only)
expiry_datestringYesExpiry in MM/YY format
cvvstringYesSecurity code
countrystringYesTwo-letter country code
zip_codestringYesBilling ZIP / postal code
curl -X POST http://127.0.0.1:9119/vault/update \
  -H "Authorization: Bearer als_..." \
  -H "Content-Type: application/json" \
  -d '{
    "holder_name": "Jane Doe",
    "card_number": "4111111111111111",
    "expiry_date": "12/27",
    "cvv": "123",
    "country": "US",
    "zip_code": "94105"
  }'

Response

{
  "status": "vault updated"
}

Webhook (Transaction Notifications)

Set TRANSACTION_CALLBACK_URL in your .env to receive an HTTP POST on every POST /authorize outcome. The URL must use http:// or https://. A single URL receives all event types — filter by the event field.

# .env
TRANSACTION_CALLBACK_URL=http://your-service/webhook

The request is fired asynchronously (non-blocking) with a 10-second timeout. A non-2xx response or timeout is logged as a warning but does not affect the transaction.

Scope: Webhooks fire only on POST /authorize outcomes. Subsequent state changes from POST /approve, POST /deny, or TTL-based auto-expiry do not currently trigger webhooks. To monitor approval outcomes, have your supervisor agent or handler poll GET /status/{tx_id} after acting on a transaction.pending event.

HMAC Signature Verification

Each webhook request includes an X-Agentledger-Signature header containing an HMAC-SHA256 hex digest of the request body, signed with AGENTLEDGER_WEBHOOK_SECRET (auto-generated during agentledger init). Use this to verify that the webhook came from your AgentLedger instance.

# Header format
X-Agentledger-Signature: sha256=<hex digest>

# Verification (Python example)
import hmac, hashlib
expected = hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
assert hmac.compare_digest(expected, received_sig)

Recommended for manual approval mode. When running with APPROVAL_MODE=manual, configuring this webhook is the preferred way to get notified that a transaction is waiting for approval — rather than having your supervisor agent poll GET /status/{tx_id}. The transaction.pending event fires immediately when the transaction is created, and the payload includes expires_at so your handler knows the approval deadline.

Event types

EventWhen
transaction.spentAuto mode: budget consumed and card released immediately
transaction.pendingManual mode: awaiting supervisor approval. expires_at is included
transaction.deniedInsufficient budget or invalid request — no budget consumed

Payload

{
  "event": "transaction.pending",
  "transaction_id": "tx_abc123",
  "amount": 1500,
  "merchant": "AWS",
  "purpose": "Spin up EC2 instance for crawl job",
  "agent_id": "crawler-agent",
  "expires_at": "2026-04-12T11:30:00Z",
  "created_at": "2026-04-12T11:00:00Z",
  "metadata": { "job_id": "crawl-42" }
}
FieldTypeDescription
eventstringSee event types above
transaction_idstringUse with POST /approve, POST /deny, or GET /status/{tx_id}
amountintegerAmount in cents
merchantstringMerchant name from the authorize request
purposestringAgent-provided reason for the spend
agent_idstringRequesting agent identifier
expires_atstring (ISO 8601)Only present on transaction.pending; deadline before auto-denial
created_atstring (ISO 8601)When the transaction was created
metadataobjectOptional key-value pairs passed in the authorize request

MCP Tools Overview

AgentLedger ships two MCP servers matching the two-token role model. Each server is a thin stdio proxy: it receives MCP tool calls and forwards them as HTTP requests to the AgentLedger REST API. Both are included in the repository under apps/mcp/ — see MCP Servers Setup above for installation instructions. The x-base-url defaults to http://127.0.0.1:9119 and is configurable via AGENTLEDGER_BASE_URL.

Tools are split into two sets matching the two-token role model:

SetTokenTools
User agent alu_ request_payment, check_budget, get_status, get_transactions
Supervisor agent als_ list_pending_transactions, approve_transaction, deny_transaction, set_budget, credit_budget, update_vault, get_transactions

Ship the user MCP config to your spending agent and the supervisor MCP config to your overseer agent. Never give both to the same agent unless you explicitly want full delegation.

User Agent MCP Tools

request_payment

Request payment authorization. Maps to POST /authorize. In auto mode, card details are returned immediately. In manual mode, the transaction enters pending and the agent must poll get_status to retrieve card details after supervisor approval. Authorize is final — there is no confirmation step.

ParameterTypeRequiredDescription
amountintegerYesAmount in cents
merchantstringYesMerchant name
purposestringYesReason for payment
requesting_agent_idstringYesAgent identifier

check_budget

Check available budget before spending. Accepts either user or supervisor token. Maps to GET /budget/{agent}.

ParameterTypeRequiredDescription
agent_idstringYesAgent identifier

get_status

Poll transaction status. Use in manual mode to check if a pending request was approved. Card details are returned only when the transaction is spent and agent_id matches. Maps to GET /status/{tx_id}?agent_id=....

ParameterTypeRequiredDescription
transaction_idstringYesTransaction ID from request_payment
agent_idstringYesYour agent identifier (must match the original request to receive card data)

get_transactions

Retrieve transaction history. Maps to GET /transactions/{agent}. Accessible to both user and supervisor agents.

ParameterTypeRequiredDescription
agent_idstringYesAgent identifier

Supervisor Agent MCP Tools

list_pending_transactions Tier 1+

List all transactions awaiting approval. Maps to GET /pending. No parameters.

approve_transaction Tier 1+

Approve a pending transaction. Maps to POST /approve.

ParameterTypeRequiredDescription
transaction_idstringYesTransaction ID to approve

deny_transaction Tier 1+

Deny a pending transaction. Budget is refunded. Maps to POST /deny.

ParameterTypeRequiredDescription
transaction_idstringYesTransaction ID to deny

set_budget Tier 2+

Create or update an agent's budget. Maps to POST /budget/{agent}.

ParameterTypeRequiredDescription
agent_idstringYesAgent identifier
limitintegerYesBudget limit in cents
periodstringNocumulative or monthly

credit_budget Tier 2+

Restore consumed budget. Maps to POST /credit.

ParameterTypeRequiredDescription
agent_idstringYesAgent to credit
amountintegerYesAmount in cents
reasonstringYesAudit reason

update_vault Tier 3

Replace the vaulted card. Maps to POST /vault/update.

ParameterTypeRequiredDescription
holder_namestringYesCardholder name
card_numberstringYesCard number (digits only)
expiry_datestringYesMM/YY format
cvvstringYesSecurity code
countrystringYesTwo-letter country code
zip_codestringYesBilling ZIP / postal code

© 2026 AgentLedger. Local Edition.