Agent keys
An agent key is a keypair you authorize to trade on your account. Your bot holds the private key and signs its own transactions, submitting them straight to the validator. Parcl never holds it.
This is the fastest and the recommended way to trade programmatically. Compared to an API key, an agent key skips the enclave-signing hop entirely, and the key never leaves your infrastructure.
Which should I use?
| Agent key | API key | |
|---|---|---|
| Who signs | Your bot, locally | A secure enclave holding your key |
| Key location | With you | Secure enclave — Parcl never has access |
| Submit | POST /v1/tx (validator, direct) | POST /tx/sign-and-submit (REST API) |
| Latency | Lowest | Higher (extra signing hop) |
| Best for | Market-making, EMS/venue adapters, latency-sensitive bots | Webhooks, no-code tools, simple scripts that can't sign locally |
| Can withdraw | No | No |
Both can trade but neither can move funds. Withdrawals always require your account owner key. If your integration can hold a key and sign locally, use an agent key.
Capabilities
An agent can PlaceOrder, CancelOrder, CancelAllOrders, ModifyOrder, and
AdjustIsolatedMargin. It cannot deposit, withdraw, transfer, or manage other
agent keys. Those require your account owner key. The chain enforces this: it
rejects a transaction that moves funds unless the owner signed it. A leaked
agent key therefore cannot drain your account.
Scope
Agent authorization is family-inherited:
- An agent approved on a master account can trade the master and every subaccount under it.
- An agent approved on a specific subaccount can trade only that subaccount.
So a market maker running one book approves an agent on the master and trades the whole family. A desk that wants a key scoped to a single strategy approves it on that subaccount.
Each account family may hold 3 + 2 × (number of subaccounts) agents.
Approving an agent
Generate an ed25519 keypair, then authorize its public key with an
ApproveAgent transaction signed by your account owner key. From the trading UI:
Settings → Agent keys → Approve a new agent key generates the keypair and
submits the transaction for you (the UI shows the private key once).
Programmatically, the owner submits ApproveAgent:
{
"ApproveAgent": {
"account_id": 27,
"agent": [
/* 32-byte ed25519 public key */
],
"name": "MM bot 1",
"expires_at": 1780000000
}
}name and expires_at (integer unix seconds) are optional. The agent remains
active strictly before that second and is inactive at or after it. Millisecond
timestamps are invalid. Re-approving the same agent updates its name and expiry
in place. An expired agent stops trading but stays in the list until revoked.
Trading with an agent key
Your bot signs the canonical transaction bytes with the agent private key and
POSTs the signed transaction to the validator's public /v1/tx endpoint. There
is no API key, no REST API, and no round-trip through Parcl:
curl -X POST https://v4-api.dev.parcllabs.com/v1/tx \
-H "Content-Type: application/json" \
-d '{
"signer": "0x<agent public key hex>",
"signature": "0x<ed25519 signature over the transaction bytes>",
"transaction": {
"PlaceOrder": {
"account_id": 27, "market_id": 0, "side": "Long",
"order_type": "Limit", "price": 28000000000, "size": 100000,
"trigger_price": null, "reduce_only": false, "post_only": true,
"time_in_force": "GTC", "take_profit": null, "stop_loss": null
}
}
}'The validator verifies the signature against signer, confirms the agent has
approval on account_id (directly or via its master), and applies the order. The
response carries the resulting events. See Transactions for
the signing-bytes format and the full set of transaction shapes.
Revoking an agent
Submit RevokeAgent, signed by the account owner (Settings → Agent keys →
Revoke in the UI):
{
"RevokeAgent": {
"account_id": 27,
"agent": [
/* 32-byte pubkey */
]
}
}The agent can no longer trade once the transaction confirms. Revocation does not affect open positions or resting orders.
Listing an account's agents
GET /v1/accounts/{id} returns the account's approved agents:
{
"accountId": 27,
"agents": [
{ "pubkey": "0xabc…", "name": "MM bot 1", "expiresAt": 1780000000 }
]
}