AgentLeash API Documentation
Blockchain-authenticated dynamic authorization for AI agents
Getting Started
What is AgentLeash?
AgentLeash is a blockchain-based authorization system that provides fine-grained, time-limited permissions for AI agents. By minting permission tokens on-chain, you can:
- Define granular permissions - Control exactly what an agent can access
- Set time constraints - Permissions automatically expire
- Verify authenticity - Cryptographic proof of authorization
- Revoke instantly - Burn tokens to immediately remove access
How It Works
- Define permissions → Specify what the agent can do
- Mint token → Create blockchain-backed authorization
- Enforce → Verify token before granting access
Quick Start Guide
1. Get Your API Key
Sign up at tokenform.com and retrieve your API key from the dashboard.
2. Make Your First Mint Call
curl -X POST https://api.tokenform.com/api/mint \
-H "Content-Type: application/json" \
-H "x-api-key: your-api-key-here" \
-d '{
"agent_id": "my-first-agent",
"permissions": ["read", "write"],
"resource": "documents/*",
"expires_in_hours": 24,
"chain": "algorand"
}'
const response = await fetch('https://api.tokenform.com/api/mint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'your-api-key-here'
},
body: JSON.stringify({
agent_id: 'my-first-agent',
permissions: ['read', 'write'],
resource: 'documents/*',
expires_in_hours: 24,
chain: 'algorand'
})
});
const result = await response.json();
console.log('Minted token:', result.asset_id);
3. Verify the Token
Use the returned asset_id to verify permissions before granting access:
// In your application
async function checkPermissions(assetId, action, resource) {
// Fetch token metadata from Algorand
const tokenData = await getAlgorandAsset(assetId);
// Parse permissions from token metadata
const permissions = parseTokenPermissions(tokenData);
// Check if action is allowed
return permissions.includes(action) &&
matchesResource(permissions.resource, resource) &&
!isExpired(permissions.expires_at);
}
Quick Start: Connect Your Agent in 5 Minutes
Get your AI agent protected with blockchain-backed permissions in under 5 minutes. This guide walks you through the complete setup process with copy-pasteable examples.
Prerequisites
- A TokenForm account (sign up at tokenform.com)
- An API key (generate from your dashboard at tokenform.com/keys)
- An AI agent you want to constrain (OpenClaw, LangChain, AutoGPT, custom, etc.)
Step 1: Get Your API Key (30 seconds)
- Sign in to tokenform.com
- Go to Dashboard → API Keys
- Click "Generate New Key"
- Copy the key (starts with
al_live_) - Store it securely — you won't see it again
Verify your key is working:
curl -H "x-api-key: YOUR_KEY" https://mint.tokenform.com/health
Step 2: Mint Your First Token (60 seconds)
Create a permission token that grants specific capabilities to your agent:
curl -X POST https://mint.tokenform.com/mint \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_KEY" \
-d '{
"agent_id": "my-agent-001",
"permissions": ["read", "write", "web_search"],
"resource": "myapp.com",
"chain": "algorand"
}'
Understanding the Response
A successful mint returns important details:
{
"success": true,
"asset_id": "1234567890",
"explorer_url": "https://testnet.algoexplorer.io/asset/1234567890",
"wallet_address": "TOKENFORM_ISSUER_ADDRESS...",
"expires_at": "2026-04-12T23:52:00Z",
"transaction_id": "ABC123...",
"permissions": ["read", "write", "web_search"],
"agent_id": "my-agent-001"
}
- asset_id: Unique identifier for your permission token
- explorer_url: View the token on the blockchain explorer
- wallet_address: TokenForm's issuing address
- expires_at: When the token automatically expires (24h default)
Step 3: Install the OpenClaw Plugin (2 minutes)
For OpenClaw Users
If you're using OpenClaw, install our pre-built AgentLeash plugin:
# 1. Copy the AgentLeash plugin to extensions directory
mkdir -p ~/.openclaw/extensions/agentleash/
# Download and extract plugin files (contact support for plugin package)
# 2. Add configuration to openclaw.json
{
"plugins": {
"entries": {
"agentleash": {
"config": {
"agentId": "my-agent-001",
"mode": "strict",
"verifyEndpoint": "https://mint.tokenform.com/verify"
}
}
}
}
}
# 3. Restart the gateway
openclaw gateway restart
For Other Frameworks
Integrate AgentLeash with any framework using our verification pattern:
// Check permissions before each action
async function checkPermissions(agentId, action, resource) {
// 1. Get agent's current token from storage
const token = await getAgentToken(agentId);
// 2. Verify token is valid on blockchain
const isValid = await verifyToken(token.asset_id, "algorand");
// 3. Check if action is permitted
const hasPermission = token.permissions.includes(action);
return isValid && hasPermission;
}
import requests
from functools import wraps
def require_permission(action, resource="*"):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
# Get agent's current token
token_data = get_agent_token(agent_id)
# Verify with TokenForm API
response = requests.post(
"https://mint.tokenform.com/verify/algorand/{token_data['asset_id']}",
json={"action": action, "resource": resource}
)
if not response.json()["valid"]:
raise PermissionError(f"Action '{action}' not permitted")
return await func(*args, **kwargs)
return wrapper
return decorator
# Usage
@require_permission("write", "documents/*")
async def create_document(content):
# This function can only run if agent has 'write' permission
pass
// Middleware for Express.js
const checkAgentPermission = (action, resource = "*") => {
return async (req, res, next) => {
try {
const { agentId } = req.headers;
const tokenData = await getAgentToken(agentId);
// Verify token with TokenForm
const verifyResponse = await fetch(
`https://mint.tokenform.com/verify/algorand/${tokenData.asset_id}`,
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ action, resource })
}
);
const { valid } = await verifyResponse.json();
if (!valid) {
return res.status(403).json({
error: `Permission denied: ${action} on ${resource}`
});
}
next();
} catch (error) {
res.status(500).json({ error: 'Permission check failed' });
}
};
};
// Usage
app.post('/documents',
checkAgentPermission('write', 'documents/*'),
createDocument
);
Step 4: Verify It Works (30 seconds)
Test that your token is properly configured:
curl -X POST https://mint.tokenform.com/verify/algorand/YOUR_ASSET_ID
Successful Verification Response
{
"valid": true,
"asset_id": "1234567890",
"agent_id": "my-agent-001",
"permissions": ["read", "write", "web_search"],
"resource": "myapp.com",
"expires_at": "2026-04-12T23:52:00Z",
"issued_at": "2026-04-11T23:52:00Z",
"status": "active",
"chain": "algorand"
}
"valid": true, your agent is now protected by blockchain-backed permissions.
Step 5: Monitor in Dashboard
Keep track of your agent's activities:
- Go to tokenform.com/app to see your active tokens
- Every tool call is logged with timestamps
- Revoke tokens instantly if needed
- Set up alerts for suspicious activity
- Monitor token expiration dates
What's Next?
Now that your agent is connected, explore advanced features:
- API Reference: Read the full API documentation
- Advanced Constraints: Set up time-based restrictions, IP whitelisting, and action limits
- Permission Scoping: Learn about resource patterns and constraint objects
- Multiple Chains: Deploy tokens on Base for different use cases
- Webhooks: Set up real-time notifications for token events (coming soon)
🚀 Pro Tip: Test Different Permission Sets
Try minting tokens with different permission combinations to see how they affect your agent's behavior:
# Read-only agent
{"permissions": ["read"]}
# Content creator
{"permissions": ["read", "write"]}
# Full automation
{"permissions": ["read", "write", "execute", "send"]}
# Time-limited admin access
{
"permissions": ["admin"],
"constraints": {"allowed_hours": "09:00-17:00"},
"expires_in_hours": 8
}
Authentication
API Key Authentication
Most API endpoints require authentication via API key in the request header:
x-api-key: your-api-key-here
Dashboard Authentication
The TokenForm dashboard uses OTP email authentication:
- Enter your email address
- Receive one-time password via email
- Enter OTP to access dashboard
- Session token valid for 24 hours
Session Tokens
Dashboard sessions use JWT tokens stored in secure cookies. These are automatically managed by the browser and expire after 24 hours of inactivity.
API Reference
POST /api/mint
Mint a new permission token for an AI agent on the specified blockchain.
Headers
| Header | Value | Required |
|---|---|---|
| Content-Type | application/json | Yes |
| x-api-key | Your API key | Yes |
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| agent_id | string | Yes | Unique identifier for the agent |
| permissions | array | Yes | Array of permission strings |
| resource | string | No | Resource pattern (supports wildcards) |
| constraints | object | No | Additional constraints object |
| expires_in_hours | number | No | Token expiration time (default: 24) |
| chain | string | Yes | "algorand" or "base" |
Example Request
curl -X POST https://api.tokenform.com/api/mint \
-H "Content-Type: application/json" \
-H "x-api-key: tf-mint-2026-secure" \
-d '{
"agent_id": "customer-support-bot",
"permissions": ["read", "write", "send"],
"resource": "support-tickets/*",
"constraints": {
"max_actions": 100,
"allowed_hours": "09:00-17:00",
"ip_whitelist": ["192.168.1.0/24"]
},
"expires_in_hours": 8,
"chain": "algorand"
}'
const response = await fetch('https://api.tokenform.com/api/mint', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': 'tf-mint-2026-secure'
},
body: JSON.stringify({
agent_id: 'customer-support-bot',
permissions: ['read', 'write', 'send'],
resource: 'support-tickets/*',
constraints: {
max_actions: 100,
allowed_hours: '09:00-17:00',
ip_whitelist: ['192.168.1.0/24']
},
expires_in_hours: 8,
chain: 'algorand'
})
});
const result = await response.json();
Example Response
{
"success": true,
"asset_id": "1234567890",
"transaction_id": "YXZ123...",
"agent_id": "customer-support-bot",
"permissions": ["read", "write", "send"],
"resource": "support-tickets/*",
"expires_at": "2026-04-12T07:52:00Z",
"chain": "algorand",
"created_at": "2026-04-11T23:52:00Z",
"metadata": {
"token_version": "1.0",
"issuer": "TokenForm"
}
}
POST /api/revoke
Revoke (burn) an active permission token, immediately removing all associated permissions.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| asset_id | string | Yes (Algorand) | Token asset ID on Algorand |
| token_id | string | Yes (Base) | Token ID on Base |
| agent_id | string | Yes | Agent identifier for verification |
| reason | string | No | Reason for revocation |
| chain | string | Yes | "algorand" or "base" |
Example Request
curl -X POST https://api.tokenform.com/api/revoke \
-H "Content-Type: application/json" \
-H "x-api-key: tf-mint-2026-secure" \
-d '{
"asset_id": "1234567890",
"agent_id": "customer-support-bot",
"reason": "Agent task completed",
"chain": "algorand"
}'
POST /api/verify-signature
Verify a cryptographic signature against an agent's blockchain address.
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| message | string | Yes | Original message that was signed |
| signature | string | Yes | Cryptographic signature (hex) |
| address | string | Yes | Blockchain address to verify against |
| chain | string | Yes | "algorand" or "base" |
Example Request
curl -X POST https://api.tokenform.com/api/verify-signature \
-H "Content-Type: application/json" \
-d '{
"message": "I am agent customer-support-bot requesting access",
"signature": "0x1234567890abcdef...",
"address": "ALGO123ABC...",
"chain": "algorand"
}'
GET /api/health
Check the health and status of the AgentLeash API service.
Example Response
{
"status": "healthy",
"timestamp": "2026-04-11T23:52:00Z",
"version": "1.0.0",
"services": {
"database": "connected",
"algorand_node": "synced",
"base_node": "synced",
"redis": "connected"
},
"uptime_seconds": 86400
}
Dashboard Proxy Endpoints
The following endpoints are available through the Cloudflare Worker proxy for dashboard integration:
POST /api/tokens/mint
Same functionality as /api/mint but routed through the dashboard proxy.
POST /api/tokens/revoke
Same functionality as /api/revoke but routed through the dashboard proxy.
Permissions Reference
Available Permission Types
| Permission | Description | Use Cases |
|---|---|---|
read |
Read access to resources | Viewing documents, checking status, reading configurations |
write |
Create and modify resources | Creating files, updating records, modifying settings |
execute |
Execute operations or scripts | Running commands, triggering workflows, processing tasks |
delete |
Remove or destroy resources | Deleting files, removing records, cleanup operations |
send |
Send messages or notifications | Email sending, API calls, webhook triggers |
admin |
Administrative access | System configuration, user management, full control |
Permission Structure in Tokens
Permissions are embedded in the token metadata as a JSON object:
{
"agent_id": "customer-support-bot",
"permissions": ["read", "write", "send"],
"resource": "support-tickets/*",
"constraints": {
"max_actions": 100,
"allowed_hours": "09:00-17:00"
},
"expires_at": "2026-04-12T07:52:00Z",
"issued_at": "2026-04-11T23:52:00Z",
"issuer": "TokenForm",
"version": "1.0"
}
Permission Combinations
Common permission combinations for different agent types:
// Read-only agent
{
"permissions": ["read"],
"resource": "documents/*"
}
// Content creator agent
{
"permissions": ["read", "write"],
"resource": "content/*"
}
// Automation agent
{
"permissions": ["read", "write", "execute"],
"resource": "workflows/*"
}
// Communication agent
{
"permissions": ["read", "send"],
"resource": "notifications/*"
}
// Administrative agent
{
"permissions": ["admin"],
"resource": "*"
}
Constraint Objects
Constraints provide additional fine-grained control:
Time-Based Constraints
{
"allowed_hours": "09:00-17:00",
"allowed_days": ["monday", "tuesday", "wednesday", "thursday", "friday"],
"timezone": "UTC"
}
Resource-Scoped Constraints
{
"ip_whitelist": ["192.168.1.0/24", "10.0.0.0/8"],
"max_actions": 1000,
"rate_limit": "100/hour",
"allowed_methods": ["GET", "POST"]
}
Action-Limited Constraints
{
"max_file_size": "10MB",
"max_recipients": 50,
"approval_required": ["delete", "admin"],
"audit_trail": true
}
Chain Support
Algorand Testnet
AgentLeash tokens on Algorand are implemented as Algorand Standard Assets (ASAs) with metadata stored in the asset configuration.
Key Features:
- Asset ID: Unique identifier for each permission token
- Metadata: Permissions and constraints stored in asset URL field
- Revocation: Assets can be destroyed to revoke permissions
- Verification: Read asset info directly from Algorand node
Example Asset Structure:
{
"asset-id": 1234567890,
"params": {
"creator": "TOKENFORM_ISSUER_ADDRESS",
"decimals": 0,
"default-frozen": false,
"name": "AgentLeash-customer-support-bot",
"name-b64": "QWdlbnRMZWFzaC1jdXN0b21lci1zdXBwb3J0LWJvdA==",
"total": 1,
"unit-name": "ALEASH",
"url": "https://api.tokenform.com/metadata/1234567890",
"url-b64": "aHR0cHM6Ly9hcGkudG9rZW5mb3JtLmNvbS9tZXRhZGF0YS8xMjM0NTY3ODkw"
}
}
Base Mainnet
On Base, AgentLeash tokens are implemented as ERC-721 NFTs with metadata stored on IPFS or our API.
Key Features:
- Token ID: Unique identifier for each permission token
- Smart Contract: ERC-721 contract with custom burning functionality
- Metadata URI: Points to JSON metadata with permissions
- Gas Efficiency: Optimized for minimal transaction costs
Smart Contract Address:
Base Mainnet: 0x742d35Cc6bF3b4570b3F0Fc10C6C9C8D6C8E9c4F
Dual Verification
For security, both the blockchain state and our API endpoint must agree on token validity:
async function verifyToken(assetId, chain) {
// 1. Check blockchain state
const onChainExists = await checkBlockchain(assetId, chain);
// 2. Verify with TokenForm API
const apiValid = await verifyWithAPI(assetId);
// 3. Both must be true
return onChainExists && apiValid;
}
Chain-Specific Parameters
| Parameter | Algorand | Base |
|---|---|---|
| Token Identifier | asset_id | token_id |
| Network | Testnet | Mainnet |
| Block Time | ~4.5 seconds | ~2 seconds |
| Transaction Costs | ~0.001 ALGO | Variable gas fees |
Rate Limits
Default Limits by Plan
| Plan | Requests/Minute | Requests/Hour | Requests/Day |
|---|---|---|---|
| Beta (Free) | 10 | 100 | 1,000 |
| Starter | 60 | 1,000 | 10,000 |
| Pro | 300 | 5,000 | 50,000 |
| Enterprise | 1,000 | 25,000 | Custom |
Rate Limit Headers
All API responses include rate limit information in headers:
HTTP/1.1 200 OK
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1734567890
X-RateLimit-Window: 60
| Header | Description |
|---|---|
| X-RateLimit-Limit | Maximum requests allowed in current window |
| X-RateLimit-Remaining | Requests remaining in current window |
| X-RateLimit-Reset | Unix timestamp when window resets |
| X-RateLimit-Window | Window duration in seconds |
429 Rate Limit Handling
When rate limits are exceeded, the API returns a 429 status code:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1734567890
{
"error": "Rate limit exceeded",
"message": "Too many requests. Try again in 60 seconds.",
"retry_after": 60,
"limit": 60
}
Best Practices
- Implement exponential backoff when receiving 429 responses
- Monitor rate limit headers to avoid hitting limits
- Cache responses when appropriate to reduce API calls
- Batch operations where possible to use fewer requests
async function makeAPICall(url, options) {
const response = await fetch(url, options);
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After');
console.log(`Rate limited. Retrying in ${retryAfter} seconds.`);
await new Promise(resolve =>
setTimeout(resolve, parseInt(retryAfter) * 1000)
);
return makeAPICall(url, options); // Retry
}
return response;
}
Error Codes
HTTP Status Codes
| Status Code | Error Type | Description | Common Causes |
|---|---|---|---|
| 400 | Bad Request | Invalid request format or parameters | Missing required fields, invalid JSON, wrong parameter types |
| 401 | Unauthorized | Missing or invalid authentication | Missing x-api-key header, invalid API key |
| 403 | Forbidden | Insufficient permissions | API key lacks required permissions, account suspended |
| 404 | Not Found | Resource does not exist | Invalid endpoint, token not found, agent not found |
| 429 | Rate Limited | Too many requests | Exceeded rate limits for your plan |
| 500 | Internal Error | Server-side error | Database issues, blockchain connectivity problems |
Error Response Format
All error responses follow a consistent JSON format:
{
"error": "error_code",
"message": "Human-readable error description",
"details": {
"field": "Additional context",
"code": "SPECIFIC_ERROR_CODE"
},
"timestamp": "2026-04-11T23:52:00Z",
"request_id": "req_1234567890abcdef"
}
Specific Error Codes
Authentication Errors (401)
{
"error": "unauthorized",
"message": "Invalid API key",
"details": {
"code": "INVALID_API_KEY"
}
}
{
"error": "unauthorized",
"message": "API key required",
"details": {
"code": "MISSING_API_KEY"
}
}
Validation Errors (400)
{
"error": "validation_failed",
"message": "Required field missing: agent_id",
"details": {
"field": "agent_id",
"code": "REQUIRED_FIELD_MISSING"
}
}
{
"error": "validation_failed",
"message": "Invalid chain specified",
"details": {
"field": "chain",
"allowed_values": ["algorand", "base"],
"code": "INVALID_CHAIN"
}
}
Resource Errors (404)
{
"error": "not_found",
"message": "Token not found",
"details": {
"asset_id": "1234567890",
"code": "TOKEN_NOT_FOUND"
}
}
{
"error": "not_found",
"message": "Agent not found",
"details": {
"agent_id": "non-existent-agent",
"code": "AGENT_NOT_FOUND"
}
}
Blockchain Errors (500)
{
"error": "blockchain_error",
"message": "Failed to connect to Algorand network",
"details": {
"chain": "algorand",
"code": "BLOCKCHAIN_CONNECTIVITY_ERROR"
}
}
{
"error": "transaction_failed",
"message": "Token minting failed on blockchain",
"details": {
"transaction_id": "failed_tx_123",
"code": "MINT_TRANSACTION_FAILED"
}
}
Try It
Test the AgentLeash API directly from your browser. This playground generates curl commands you can copy and execute.
API Endpoint Tester
# Select an endpoint and fill in the form to generate a curl command
Webhooks
Planned Webhook Events
- token.minted - A new permission token has been created
- token.revoked - A token has been manually revoked
- token.expired - A token has reached its expiration time
- token.used - A token has been used for verification
- agent.created - A new agent has been registered
Expected Webhook Payload Format
{
"event": "token.minted",
"timestamp": "2026-04-11T23:52:00Z",
"data": {
"asset_id": "1234567890",
"agent_id": "customer-support-bot",
"permissions": ["read", "write"],
"expires_at": "2026-04-12T23:52:00Z"
},
"webhook_id": "wh_1234567890"
}
Stay tuned for updates on webhook availability. Subscribe to our changelog for notifications.
SDKs & Libraries
Planned SDK Support
🐍 Python SDK
Full-featured Python library with async support
- Type hints included
- Poetry/pip compatible
- Comprehensive examples
pip install agentleash
🟨 JavaScript/Node SDK
Native TypeScript support for Node.js and browsers
- ES6+ modules
- TypeScript definitions
- React hooks included
npm install @tokenform/agentleash
🐹 Go SDK
High-performance Go client library
- Context support
- Structured logging
- Minimal dependencies
go get github.com/tokenform/agentleash-go
Community Libraries
We encourage community-developed libraries and will feature them here. If you've built an AgentLeash integration, let us know!
Current Integration
Until official SDKs are available, you can integrate directly using HTTP requests as shown in the API Reference section.
Changelog
v1.0.0 — Initial API Release
Released: April 11, 2026
- Core API endpoints: mint, revoke, verify-signature, health
- Blockchain support: Algorand Testnet and Base Mainnet
- Permission system: 6 permission types with constraint support
- Rate limiting: Tiered limits based on subscription plan
- Dashboard integration: Web UI for token management
- Security features: Dual verification (blockchain + API)
Upcoming Releases
- v1.1.0: Webhook support for real-time notifications
- v1.2.0: Python SDK release
- v1.3.0: JavaScript/TypeScript SDK release
- v2.0.0: Additional blockchain support (Ethereum, Polygon)
Subscribe to our newsletter or follow @tokenform on Twitter for release announcements.