Skip to main content

Agent REST API

Base URL: https://api.enclz.com

OpenAPI 3.1 spec: https://api.enclz.com/openapi.json

All requests are authenticated with Authorization: Bearer <api_key>. Mutation endpoints (/v1/transfer, /v1/swap, /v1/deposit, /v1/withdraw) require an Idempotency-Key header — any UUID will do.

Authentication

The agent's API key is exchanged for a one-time invitation code via:

POST /v1/agents/register
{
"invitation_code": "..."
}
→ { "api_key": "ek_...", "agent_wallet_pda": "...", "limits": {...} }

Store api_key securely. From then on, use it as a Bearer token. The invitation code is single-use — it's invalidated immediately after exchange.

Endpoints

POST /v1/transfer

Send tokens to a recipient.

Body:

{
"recipient": "GjwoT1Hf2Rhet9NEr4D5jgN5VdfpxdmxbbPLLgUrjgyy",
"amount": 0.05,
"memo": "rpc-call-#a8f2",
"task_id": "experiment-2026-05"
}
  • recipient — base58 Solana address. Must be in your whitelist.
  • amount — USDC.
  • memo — optional, ≤ 200 UTF-8 bytes. Stored in backend log; SHA-256 hash put on-chain.
  • task_id — optional grouping tag for cost accounting.

Response (200):

{
"status": "confirmed",
"tx_signature": "5JxKp...",
"amount_sent": 0.05,
"fee": 0.00005,
"remaining_today": 0.95,
"recipient_remaining": 4.95
}

Common errors: whitelist_violation, whitelist_expired, whitelist_amount_exhausted, per_tx_limit_exceeded, daily_limit_exceeded, hourly_freq_exceeded, insufficient_funds. See Errors.

POST /v1/swap

Swap one token for another via the whitelisted DEX router (Jupiter).

Body:

{
"input_mint": "EPjFWdd5...USDC",
"output_mint": "So111...wSOL",
"input_amount": 1.00,
"min_output": 0.0066,
"slippage_bps": 50
}

The DEX router is auto-whitelisted as protocol-type at group initialization, so swaps work immediately.

Response: same envelope as transfer, with output_amount added.

POST /v1/deposit / POST /v1/withdraw

Move tokens to/from a whitelisted lending protocol (Kamino, etc.). The lending protocol's program ID must be a type-2 whitelist entry; the orchestrator adds it once per protocol.

Body: protocol-specific. See the protocol's own docs for the cpi_data field shape.

POST /v1/intents/simulate

Dry-run a transfer or swap without submitting on-chain. Free, no signature.

Body: same as /v1/transfer or /v1/swap, with a type discriminator:

{
"type": "transfer",
"recipient": "GjwoT...",
"amount": 0.05
}

Response:

{
"would_succeed": true,
"checks": {
"whitelisted": true,
"ttl_remaining_days": 6,
"amount_remaining": 4.95,
"per_tx_ok": true,
"daily_ok": true,
"hourly_ok": true
},
"fee_preview": 0.00005
}

If a check fails, would_succeed: false and the failing check explains why.

Use this in your agent's planning loop: cheap to call, gives you the same visibility the program has, lets you avoid wasting transactions on known-failing requests.

GET /v1/balance

Returns the agent's current SPL token balance.

Response:

{
"mint": "EPjFWdd5...USDC",
"balance": 0.95,
"associated_token_account": "..."
}

GET /v1/limits

Returns the agent's policy ceiling and current counters.

Response:

{
"per_tx_limit": 0.10,
"daily_limit": 1.00,
"hourly_tx_cap": 10,
"spent_today": 0.05,
"remaining_today": 0.95,
"hourly_count": 1,
"remaining_hourly": 9
}

Read directly from on-chain AgentWallet PDA — what you see is what the program will enforce.

GET /v1/history

Paginated transfer/swap/deposit/withdraw history.

Query params: limit (default 50, max 200), cursor, since (ISO 8601), type (filter by op type).

Response:

{
"items": [
{
"type": "transfer",
"tx_signature": "...",
"amount": 0.05,
"recipient": "...",
"memo": "rpc-call-#a8f2",
"fee": 0.00005,
"confirmed_at": "2026-05-08T17:23:44Z"
}
],
"next_cursor": "..."
}

POST /v1/webhooks

Subscribe to events.

Body:

{
"url": "https://your-server.com/enclz-webhook",
"events": ["transfer.confirmed", "policy.whitelist_voided"],
"secret": "your-shared-secret"
}

See Webhooks for the event list and payload shapes.

Idempotency

Mutating endpoints (/transfer, /swap, /deposit, /withdraw) require an Idempotency-Key header. Recommended: a per-attempt UUID.

If the same idempotency key is replayed within 24h, the original response is returned — no double-spend, no double-tx. This makes safe retries trivial: catch a transient error, retry with the same key.

Rate limits

Default: 60 requests / minute / agent. Higher tiers available for payment-tier agents on request.

Rate-limit responses are HTTP 429 with Retry-After header.

Error format

All errors share the envelope from Errors. Codes are stable; match on error.code, not on error.message.