API Documentation

Add AI governance to any agent in minutes. TrustLoop works as an OpenAI-compatible proxy or via direct API — no SDK required.

Quickstart

The fastest way to add TrustLoop to an existing agent is the OpenAI proxy. Change one line of code — that's it.

python
from openai import OpenAI

client = OpenAI(
    api_key="sk-your-openai-key",
    base_url="https://trustloop-production.up.railway.app/v1",
    default_headers={"x-api-key": "tl_your_trustloop_key"}
)

# Your existing code works unchanged — TrustLoop intercepts automatically
response = client.chat.completions.create(
    model="gpt-4o-mini",
    messages=[{"role": "user", "content": "Transfer £5000 to supplier"}],
    tools=[...]
)
That's it. TrustLoop intercepts all tool calls, evaluates them against your governance rules, and either allows, blocks, or routes them for human approval — automatically.

Authentication

All API requests require a TrustLoop API key. Pass it in the x-api-key header or as a query parameter.

http
# Header (recommended)
x-api-key: tl_your_api_key_here

# Query parameter (for browser/CSV export)
GET /api/logs/export?api_key=tl_your_api_key_here

Get your API key by signing up at trustloop.live/signup or from your dashboard.

Base URL

url
https://trustloop-production.up.railway.app

OpenAI Proxy

The proxy intercepts tool_calls in OpenAI responses and applies your governance rules before returning results to the client.

POST /v1/chat/completions 🔑 x-api-key required OpenAI-compatible proxy

How it works

1. Your agent sends a request exactly as it would to OpenAI (with Authorization: Bearer sk-xxx).
2. TrustLoop forwards to OpenAI and intercepts the response.
3. If the response contains tool_calls, each is evaluated against your rules.
4. Result is either ALLOWED, BLOCKED, or PENDING (routed for approval).

Response format

All responses include a _trustloop field:

json — allowed
// Tool was allowed — normal OpenAI response + metadata
{
  "choices": [...],
  "_trustloop": { "status": "allowed", "tool": "read_file" }
}
json — blocked
{
  "choices": [{ "message": { "content": "Tool 'delete_file' is blocked by governance policy." } }],
  "_trustloop": { "blocked": true, "tool": "delete_file", "rule": "Block all file deletions" }
}
json — pending approval
{
  "choices": [{ "message": { "content": "Tool requires human approval. Retry once approved." } }],
  "_trustloop": {
    "status": "pending_approval",
    "approval_id": "uuid-here",
    "tool": "wire_transfer"
  }
}

Direct Intercept API

For non-OpenAI frameworks (LangChain custom tools, AutoGen, custom agents), use the intercept endpoint directly in your tool execution logic.

POST /api/intercept 🔑 x-api-key required

Request body

FieldTypeDescription
tool_namestringThe name of the tool being called
argumentsobjectThe tool's arguments (optional)
python — langchain example
import requests

def trustloop_check(tool_name, args):
    res = requests.post(
        "https://trustloop-production.up.railway.app/api/intercept",
        headers={"x-api-key": "tl_your_key"},
        json={"tool_name": tool_name, "arguments": args}
    ).json()

    if not res["allowed"]:
        raise PermissionError(res["message"])

# In your tool executor:
trustloop_check("delete_records", {"table": "customers"})
# Tool only executes if TrustLoop allows it

MCP Protocol

Connect Claude Desktop or any MCP-compatible client via Server-Sent Events.

GET /sse?api_key=tl_xxx MCP SSE
Add TRUSTLOOP_MCP_URL=https://trustloop-production.up.railway.app/sse?api_key=tl_xxx to your .env and configure your MCP client to use it.

Audit Logs

GET /api/logs 🔑 required Last 100 tool calls
GET /api/logs/export 🔑 required Download as CSV
GET /api/stats 🔑 required Counts by status

Approval Rules

Natural language rules evaluated by AI against every tool call.

GET /api/approval-rules 🔑 required
POST /api/approval-rules 🔑 required
DELETE /api/approval-rules/:id 🔑 required

Create a rule

FieldTypeDescription
rule_textstringPlain English rule (e.g. "Any wire transfer over £1,000 needs approval")
actionapprove | block"approve" = route for human approval. "block" = reject immediately.
approver_emailstring?Email to notify. Overrides default notification email.

Pending Approvals

GET /api/pending-approvals 🔑 required
POST /api/pending-approvals/:id/decide 🔑 required Body: {"action": "approved" | "denied"}
GET /api/approve/:token public One-click approve from email
GET /api/deny/:token public One-click deny from email
Auto-expiry: Pending approvals are automatically denied after 24 hours of inactivity. The approver receives an expiry notification email.

Notification Settings

GET /api/notification-settings 🔑 required
PUT /api/notification-settings 🔑 required
FieldTypeDescription
notify_emailstring?Default approver email (used when rule has no approver_email)
slack_webhook_urlstring?Slack incoming webhook URL
teams_webhook_urlstring?Microsoft Teams incoming webhook URL

Blocked Tools (Kill Switch)

GET /api/blocked-tools 🔑 required
POST /api/blocked-tools 🔑 required Body: {"tool_name": "delete_file"}
DELETE /api/blocked-tools/:tool_name 🔑 required

Errors

StatusMeaning
401Missing or invalid x-api-key
400Missing required field in request body
500Internal server error — contact support if this persists