Agent API
Agents integrate with Treasury Copilot through HTTP only. The platform signs GenLayer transactions, enforces per-agent policy bindings, executes approved requests through 1Shot, and returns JSON. No wallet library, gas management, or GenLayer SDK is required.
Base URL: https://treasury-copilot-genjury.vercel.app. All agent paths are under /api/v1. Human-facing setup and policy pages are separate and require wallet authentication.
Machine-readable contract: OpenAPI 3.1 JSON
Authentication
Send the bearer API key issued during owner setup. The key is a stateless signed token encoding owner, agent, policy, chain, token, decimals, and version. Every request validates the key, the claimed agent_address, registry binding, and policy state.
Authorization: Bearer tcp_***
The MetaMask permission does not create the key. A fresh unique key is issued only after the GenLayer policy and delegation are finalized, registered, and read back successfully. Keys are shown once and expire after 30 days. Store them securely. Rotation increments the on-chain key version and invalidates older keys; revocation deactivates the policy binding.
Quickstart
- 1. Store the one-time API key in a secret manager or environment variable.
- 2. Call GET /policy. Choose a recipient from whitelisted_recipients, or obtain an invoice recipient that the owner policy explicitly permits.
- 3. Submit a decimal string amount with a stable idempotency key.
- 4. Save the request ID and poll the request endpoint after timeouts.
The key identifies the agent but never signs a blockchain transaction. Every GenLayer write is signed by the server platform wallet after the key, registry, policy, funding account, chain, token, and execution reporter are verified.
Merchant names are not recipient proof. A merchant-specific policy needs an owner-approved recipient or independently verified invoice evidence; otherwise requests fail closed.
POST /api/v1/spend
Validates the request, verifies evidence, submits it to GenLayer, and returns 202 Accepted immediately. The worker reviews finalized queued requests with prompt-comparative consensus and executes approved requests through 1Shot.
curl -X POST https://treasury-copilot-genjury.vercel.app/api/v1/spend \
-H "Authorization: Bearer ***" \
-H "Content-Type: application/json" \
-d '{
"agent_address": "0xYourRegisteredAgent",
"recipient": "0xabc...",
"amount": "25.00",
"category": "api_subscription",
"justification": "Monthly API renewal, invoice #4471",
"idempotency_key": "billing-4471-2026-07",
"evidence": [{
"type": "signed_invoice",
"invoice_id": "4471",
"merchant_id": "vercel",
"expected_recipient": "0xabc...",
"expected_amount": "25000000",
"issued_at": 1784800000,
"expires_at": 1785400000,
"content_hash": "0x...",
"signer": "0xMerchantSigner",
"signature": "0x..."
}]
}'Request body
{
"agent_address": "0xYourRegisteredAgent",
"recipient": "0xRecipient",
"amount": "25.00",
"category": "api_subscription",
"justification": "Monthly API renewal invoice #4471",
"idempotency_key": "billing-4471-2026-07",
"evidence": []
}Response
{
"request_id": "0x...",
"verdict": "pending",
"reasoning": "Submitted to GenLayer and awaiting finalized policy review",
"status": "submitted",
"poll_url": "/api/v1/requests/0x...",
"request": {
"status": "submitted",
"recipient": "0x...",
"amount": "25",
"amount_units": "25000000",
"decision_mode": "prompt_comparative",
"execution_status": "submitted",
"tx_hash": "",
"explorer_url": null,
"created_at": "2026-07-21T12:10:00.000Z",
"updated_at": "2026-07-21T12:11:00.000Z"
},
"chain": {
"chain_id": 84532,
"name": "Base Sepolia",
"explorer_url": "https://sepolia.basescan.org"
},
"idempotent_replay": false,
"genlayer": {
"request_tx_hash": "0x..."
}
}The response includes Location and Retry-After: 10. Poll until the request reaches denied, executed, or a retryable failed state.
GET /api/v1/balance
Returns live token balance, weekly spent, weekly cap, and per-request cap. Values include display decimals and raw integer units.
curl -X GET https://treasury-copilot-genjury.vercel.app/api/v1/balance \ -H "Authorization: Bearer ***"
GET /api/v1/history
Returns on-chain request history from GenLayer for the current API key binding. Includes status, verdict, reasoning, and execution hash when available.
curl -X GET "https://treasury-copilot-genjury.vercel.app/api/v1/history?limit=50" \ -H "Authorization: Bearer ***"
Merchant identity and policy safety
Category and justification are untrusted claims. Policy V5 accepts up to three verified evidence items: an HTTPS invoice whose fetched bytes match a SHA-256 digest, or an EIP-712 signed invoice bound to the exact policy, chain, token, recipient, amount, timestamps, and content hash.
Fast approval has been removed. Every valid V5 request begins GenLayer prompt-comparative review in the original submission transaction. V4 remains supported through automatic recovery; V2 and V3 policies are blocked.
GET /api/v1/requests/:id
Returns one request record by ID, scoped to the authenticated API key. Use this endpoint for status polling or to recover the explorer link after submission.
curl -X GET https://treasury-copilot-genjury.vercel.app/api/v1/requests/0xREQUEST_ID \ -H "Authorization: Bearer ***"
Recover by idempotency key
curl -X GET "https://treasury-copilot-genjury.vercel.app/api/v1/requests?idempotency_key=billing-4471-2026-07" \ -H "Authorization: Bearer ***"
GET /api/v1/policy returns safe caps and policy metadata. Raw delegation payloads, permission contexts, signatures, and signer secrets are never returned to agents.
Lifecycle and polling
submitted
The platform signer submitted the policy transaction; the API returned 202.
reviewing
V5 comparative consensus is running in the submission transaction.
review_pending
A legacy V4 queue is waiting for automatic recovery review.
pending
A legacy review transaction is processing.
denied
A deterministic guard or comparative review rejected the request.
ready
The approved finalized request is ready for 1Shot.
executing
The platform holds the on-chain execution lease.
failed
The lease is released and the request can retry.
executed
The confirmed EVM transaction hash is recorded.
not_applicable
Execution does not apply, normally because the request was denied.
If the client times out before receiving the POST response, call GET /api/v1/requests?idempotency_key=... or retry the original POST with the same body and idempotency key. Never create a replacement key for the same payment.
An identical replay returns idempotent_replay: true, the same request ID, and the same Base transaction hash without another payment.
Amounts and decimals
Send amount as a positive decimal string. Never send JavaScript floating-point values. The server converts amounts using the configured asset decimals, which may be 6 for USDC. Every balance, cap, and history response returns both a display decimal value and the raw on-chain integer units. Requests whose request ID has already been recorded are returned idempotently instead of creating a duplicate spend.
Error codes
All errors return JSON with machine-readable structure and machine-parseable fields when available.
{
"error": "invalid_api_key",
"message": "API key is missing or invalid",
"fields": { "authorization": ["missing bearer token"] },
"request_id": "abc-123"
}
{
"error": "agent_mismatch",
"message": "The agent_address in this request does not match the API key claim",
"fields": { "agent_address": ["0x... does not match 0x..."] }
}
{
"error": "insufficient_balance",
"message": "Delegated balance is below the requested amount",
"fields": { "amount": ["requested 25.00 USDC, available 4.20 USDC"] }
}
{
"error": "genlayer_unavailable",
"message": "submit_request submission failed on GenLayer: ...",
"fields": {},
"retryable": true
}Retry only 502 and 503 responses, honor Retry-After when present, use exponential backoff, and keep the same idempotency key. Do not automatically retry authentication, validation, policy, or conflict errors. Malformed idempotency keys return 422; 409 is reserved for reusing an existing key with different payment data.
Trust model
The agent never receives custody and does not need a wallet library or gas. The owner grants bounded token spending to the platform signer. GenLayer verifies the registered agent and policy. Only approved requests are executed through 1Shot, then the EVM transaction hash is written back to GenLayer. Relayer failures leave on-chain records so requests can be retried safely with no duplicate payout risk.
Current execution support is Base Sepolia test USDC. Base Mainnet and other chains remain disabled until their isolated production configuration and live 1Shot capability checks pass.