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.
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 during setup. 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 /balance and use the returned agent address exactly.
- 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.
POST /api/v1/spend
Submits one spend request and waits for GenLayer finality. Finalized approvals immediately attempt 1Shot execution; the authenticated relay worker retries requests whose execution failed. Use an idempotency_key to avoid duplicate processing.
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"
}'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"
}Response
{
"request_id": "0x...",
"verdict": "approved",
"reasoning": "The request matches the exact recipient and policy",
"request": {
"status": "executed",
"recipient": "0x...",
"amount": "25",
"amount_units": "25000000",
"decision_mode": "prompt_comparative",
"execution_status": "executed",
"tx_hash": "0x...",
"explorer_url": "https://sepolia.basescan.org/tx/0x...",
"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,
"execution": {
"mode": "erc7710",
"fee_amount": "0.01",
"fee_amount_units": "10000"
},
"genlayer": {
"request_tx_hash": "0x...",
"record_execution_tx_hash": "0x..."
}
}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 agent claims. A merchant name does not prove recipient ownership or invoice validity. Put the exact approved recipient address in the policy, enable the recipient whitelist, and set every legacy V2 fast approval limit to zero.
Policy V3 uses GenLayer prompt-comparative review for every amount. Evidence-backed invoice and merchant verification is required before safe fast approval can return.
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 ***"
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
Platform signs and sends the policy request.
finalized
The GenLayer decision is no longer appealable.
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.
If the spend request times out at the HTTP layer, poll GET /api/v1/requests/:id with the same API key. Do not submit a different idempotency key for the same intended 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, use exponential backoff, and keep the same idempotency key. Do not automatically retry authentication, validation, policy, or conflict errors.
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 USDC. X Layer and other chains remain disabled until the live 1Shot capability response confirms the selected token and transaction mode.