Authentication
CertusOrdo uses a two-layer authentication system: API keys for organization-level operations and JWT tokens for agent operations.
Authentication Overview
| Layer | Credential | Use Case | Lifetime |
|---|---|---|---|
| Organization | API Key | Create agents, manage org | Permanent (until rotated) |
| Agent | JWT Token | Execute operations | 1 hour (access), 7 days (refresh) |
API Key Authentication
API keys authenticate your organization for administrative operations.
Getting Your API Key
API keys are generated when you create an organization:
import httpx
response = httpx.post(
"https://web-production-b910f.up.railway.app/v1/organizations",
json={"name": "My Company"}
)
data = response.json()
api_key = data["api_key"] # aa_xxxxx... - Save this!
API Key Security
- API keys are only shown once at creation
- Store securely (environment variables, secrets manager)
- Never commit to version control
- Rotate immediately if compromised
Using API Keys
Include the API key in the X-API-Key header:
from certusrodo import CertusOrdoClient
# SDK handles this automatically
client = CertusOrdoClient(api_key="aa_your_api_key")
# Or manually with httpx/requests
headers = {"X-API-Key": "aa_your_api_key"}
response = httpx.get(
"https://web-production-b910f.up.railway.app/v1/agents",
headers=headers
)
Agent JWT Authentication
Agents authenticate using JWT tokens obtained by exchanging their credentials.
Authentication Flow
┌─────────┐ ┌───────────┐
│ Agent │ │ CertusOrdo│
└────┬────┘ └─────┬─────┘
│ │
│ POST /v1/auth/token │
│ {agent_id, secret} │
│──────────────────────────────>│
│ │
│ {access_token, refresh_token}│
│<──────────────────────────────│
│ │
│ GET /v1/... + Bearer token │
│──────────────────────────────>│
│ │
Getting Tokens
from certusrodo import CertusOrdoClient
client = CertusOrdoClient(api_key="aa_your_api_key")
# Create an agent first
agent = client.agents.create(
name="my-agent",
scopes=["read", "write"]
)
# Exchange credentials for tokens
tokens = client.auth.get_token(
agent_id=agent.id,
secret=agent.secret
)
print(f"Access Token: {tokens.access_token}")
print(f"Refresh Token: {tokens.refresh_token}")
print(f"Expires In: {tokens.expires_in} seconds")
Token Contents
The JWT access token contains:
{
"agent_id": "uuid",
"org_id": "uuid",
"scopes": ["read", "write"],
"iat": 1705420800,
"exp": 1705424400
}
Using Tokens
# SDK handles token management automatically
tokens = client.auth.get_token(agent_id=agent.id, secret=agent.secret)
# Tokens are now used for subsequent operations
txn = client.transactions.begin(
pre_state={"data": "value"},
action_type="update"
)
Refreshing Tokens
Access tokens expire after 1 hour. Use refresh tokens to get new ones:
# When access token expires
new_tokens = client.auth.refresh_token(refresh_token=tokens.refresh_token)
print(f"New Access Token: {new_tokens.access_token}")
Revoking Tokens
Revoke tokens when an agent should no longer have access:
Scopes
Scopes define what an agent can do. Define them at agent creation:
agent = client.agents.create(
name="read-only-agent",
scopes=["data:read"] # Can only read, not write
)
agent = client.agents.create(
name="full-access-agent",
scopes=["data:read", "data:write", "admin:manage"]
)
Common Scope Patterns
| Scope | Permission |
|---|---|
read |
Read-only access |
write |
Create and update |
delete |
Delete resources |
admin |
Administrative operations |
transactions:rollback |
Can initiate rollbacks |
Security Best Practices
1. Use Environment Variables
import os
from certusrodo import CertusOrdoClient
client = CertusOrdoClient(
api_key=os.environ["CERTUSRODO_API_KEY"]
)
2. Implement Token Refresh Logic
from datetime import datetime, timedelta
class AgentAuth:
def __init__(self, client, agent_id, secret):
self.client = client
self.agent_id = agent_id
self.secret = secret
self.tokens = None
self.token_expiry = None
def get_valid_token(self):
# Check if token needs refresh
if self.tokens is None or datetime.now() >= self.token_expiry:
self.refresh()
return self.tokens.access_token
def refresh(self):
if self.tokens and self.tokens.refresh_token:
try:
self.tokens = self.client.auth.refresh_token(
self.tokens.refresh_token
)
except:
# Refresh token expired, get new tokens
self.tokens = self.client.auth.get_token(
self.agent_id, self.secret
)
else:
self.tokens = self.client.auth.get_token(
self.agent_id, self.secret
)
# Set expiry with 5-minute buffer
self.token_expiry = datetime.now() + timedelta(
seconds=self.tokens.expires_in - 300
)
3. Revoke Compromised Credentials
# If agent secret is compromised, revoke the agent
client.agents.revoke(agent.id)
# Create a new agent with fresh credentials
new_agent = client.agents.create(
name="my-agent-v2",
scopes=["read", "write"]
)
Error Handling
from certusrodo import CertusOrdoClient, AuthenticationError
client = CertusOrdoClient(api_key="aa_your_key")
try:
tokens = client.auth.get_token(
agent_id="invalid-id",
secret="wrong-secret"
)
except AuthenticationError as e:
print(f"Authentication failed: {e}")
Next Steps
- Managing Agents - Create and manage agents
- Sessions Guide - Bounded operational contexts
- API Reference - Full auth endpoint docs