Skip to main content

Developer Guide

Add AI governance to any application with ARQERA's API. This guide covers authentication, the core API, SDKs, and common patterns.

Quick Start​

1. Get an API Key​

  1. Log in to arqera.io
  2. Go to Settings → API Keys
  3. Click Create Key
  4. Copy the key (starts with ak_)

2. Make Your First Call​

curl -X POST https://api.arqera.io/v1/governance/evaluate \
-H "Authorization: Bearer ak_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"action": "send_email",
"context": {
"to": "john@example.com",
"subject": "Meeting follow-up"
}
}'

Response:

{
"verdict": "PROCEED",
"evidence_id": "ev_abc123",
"reasoning": "Action matches policy: routine communications allowed",
"evaluated_at": "2026-04-13T10:30:00Z",
"duration_ms": 12
}

3. Act on the Verdict​

const response = await fetch('https://api.arqera.io/v1/governance/evaluate', {
method: 'POST',
headers: {
'Authorization': 'Bearer ak_your_api_key',
'Content-Type': 'application/json'
},
body: JSON.stringify({
action: 'send_email',
context: { to: 'john@example.com', subject: 'Meeting follow-up' }
})
});

const { verdict, evidence_id } = await response.json();

if (verdict === 'PROCEED') {
// Execute the action
await sendEmail(to, subject, body);
} else if (verdict === 'ESCALATE') {
// Route to human approval
await createApprovalRequest(evidence_id);
} else if (verdict === 'BLOCK') {
// Stop and log
console.log('Action blocked by governance');
}

Core Concepts​

Actions​

An action is anything your AI wants to do:

Action TypeExamples
send_emailSend an email
read_fileAccess a document
create_recordAdd to database
call_apiExternal API call
spend_moneyPurchase, payment

Context​

Context is the details of the action. The more context, the better the evaluation:

{
"action": "send_email",
"context": {
"to": "john@example.com",
"cc": ["team@company.com"],
"subject": "Q4 Contract Discussion",
"body_preview": "I'd like to discuss the terms...",
"has_attachments": true,
"attachment_types": ["pdf"],
"sender_role": "sales_rep",
"recipient_type": "external"
}
}

Verdicts​

VerdictWhat to doHTTP Status
PROCEEDExecute the action200
ESCALATEQueue for human approval200
BLOCKDo not execute200

Note: All verdicts return 200. The verdict itself tells you what to do.

Evidence​

Every evaluation creates an evidence record. This is your audit trail:

{
"evidence_id": "ev_abc123",
"action": "send_email",
"verdict": "PROCEED",
"reasoning": "Policy: routine-comms matched. All laws passed.",
"laws_evaluated": [
{"law": "safety_dominance", "passed": true},
{"law": "budget_conservation", "passed": true},
{"law": "bounded_autonomy", "passed": true}
],
"timestamp": "2026-04-13T10:30:00Z",
"signature": "sha256:abc123..."
}

API Reference​

POST /v1/governance/evaluate​

Evaluate an action against governance policies.

Request:

{
"action": "string (required)",
"context": "object (required)",
"agent_id": "string (optional)",
"user_id": "string (optional)",
"tenant_id": "string (optional)",
"idempotency_key": "string (optional)"
}

Response:

{
"verdict": "PROCEED | ESCALATE | BLOCK",
"evidence_id": "string",
"reasoning": "string",
"evaluated_at": "ISO 8601 timestamp",
"duration_ms": "number",
"escalation_id": "string (if ESCALATE)",
"block_reason": "string (if BLOCK)"
}

POST /v1/evidence​

Submit evidence for an action that bypassed real-time evaluation.

Request:

{
"action": "string",
"context": "object",
"outcome": "success | failure",
"executed_at": "ISO 8601 timestamp"
}

GET /v1/evidence/{evidence_id}​

Retrieve a specific evidence record.

GET /v1/evidence​

List evidence records with filters.

Query params:

  • from — Start timestamp
  • to — End timestamp
  • action — Filter by action type
  • verdict — Filter by verdict
  • limit — Max results (default 100)
  • cursor — Pagination cursor

POST /v1/approvals/{approval_id}/approve​

Approve an escalated action.

POST /v1/approvals/{approval_id}/reject​

Reject an escalated action.

GET /v1/approvals​

List pending approvals.


SDKs​

Python​

pip install arqera
from arqera import ArqeraClient

client = ArqeraClient(api_key="ak_your_api_key")

# Evaluate an action
result = client.evaluate(
action="send_email",
context={
"to": "john@example.com",
"subject": "Meeting follow-up"
}
)

if result.verdict == "PROCEED":
# Execute
pass
elif result.verdict == "ESCALATE":
# Queue for approval
approval_id = result.escalation_id

Full Python SDK documentation →

TypeScript​

npm install @arqera/sdk
import { ArqeraClient } from '@arqera/sdk';

const client = new ArqeraClient({ apiKey: 'ak_your_api_key' });

const result = await client.evaluate({
action: 'send_email',
context: {
to: 'john@example.com',
subject: 'Meeting follow-up'
}
});

if (result.verdict === 'PROCEED') {
// Execute
} else if (result.verdict === 'ESCALATE') {
// Queue for approval
}

Full TypeScript SDK documentation →


Common Patterns​

Governed Agent​

Wrap your AI agent to evaluate every action:

class GovernedAgent:
def __init__(self, arqera_client, agent):
self.governance = arqera_client
self.agent = agent

async def execute(self, action, context):
# Evaluate first
result = await self.governance.evaluate(action, context)

if result.verdict == "PROCEED":
return await self.agent.execute(action, context)
elif result.verdict == "ESCALATE":
return {"status": "pending_approval", "id": result.escalation_id}
else:
return {"status": "blocked", "reason": result.block_reason}

Governed Chatbot​

Add governance to LLM function calls:

async def handle_function_call(function_name, arguments):
# Evaluate the function call
result = await arqera.evaluate(
action=f"function_call:{function_name}",
context=arguments
)

if result.verdict == "PROCEED":
return await execute_function(function_name, arguments)
elif result.verdict == "ESCALATE":
return f"This action needs approval. Reference: {result.escalation_id}"
else:
return f"I can't do that. Reason: {result.block_reason}"

Batch Evaluation​

Evaluate multiple actions at once:

results = await client.evaluate_batch([
{"action": "send_email", "context": {...}},
{"action": "read_file", "context": {...}},
{"action": "create_record", "context": {...}}
])

for result in results:
print(f"{result.action}: {result.verdict}")

Async Evidence​

For high-throughput scenarios, submit evidence asynchronously:

# Execute first, submit evidence after
await execute_action(action, context)

# Submit evidence (non-blocking)
await client.submit_evidence(
action=action,
context=context,
outcome="success"
)

Webhooks​

Get notified when things happen:

# In your webhook handler
@app.post("/webhooks/arqera")
async def handle_webhook(request):
event = request.json()

if event["type"] == "approval.created":
# Notify the right person
await notify_approver(event["data"]["approval_id"])

elif event["type"] == "approval.resolved":
# Continue the workflow
if event["data"]["resolution"] == "approved":
await resume_action(event["data"]["evidence_id"])

Configure webhooks at Settings → Webhooks in the dashboard.


Rate Limits​

PlanEvaluations/secondEvidence records/day
Free1010,000
Personal50100,000
Pro100Unlimited
Team200Unlimited
EnterpriseCustomUnlimited

Rate limit headers:

  • X-RateLimit-Limit — Your limit
  • X-RateLimit-Remaining — Remaining calls
  • X-RateLimit-Reset — Reset timestamp

Error Handling​

try:
result = await client.evaluate(action, context)
except ArqeraAuthError:
# Invalid API key
except ArqeraRateLimitError as e:
# Wait and retry
await asyncio.sleep(e.retry_after)
except ArqeraServerError:
# Temporary issue, retry with backoff

HTTP status codes:

CodeMeaning
200Success (check verdict)
400Bad request (invalid input)
401Unauthorized (bad API key)
429Rate limited
500Server error

Testing​

Sandbox Mode​

Use the sandbox for testing without affecting production data:

curl -X POST https://sandbox.api.arqera.io/v1/governance/evaluate \
-H "Authorization: Bearer ak_sandbox_your_key" \
...

Test Policies​

Create test policies in the dashboard under Governance → Test Policies.

Mock Responses​

The SDK supports mock mode:

client = ArqeraClient(api_key="ak_test", mock=True)
client.set_mock_verdict("PROCEED") # All evaluations return PROCEED

Security​

  • API keys are tenant-scoped. One key per environment.
  • TLS 1.3 for all connections
  • Evidence is signed with SHA-256
  • Audit logs are immutable

Rotate keys regularly: Settings → API Keys → Rotate.


Next Steps​


Questions? developers@arqera.io