Skip to main content

API Integration Guide

This guide covers everything you need to build external integrations with TARX — from authenticating with a platform key to streaming chat responses from an agent.


1. Get a Platform API Key

Platform API keys (sk-tarx-...) are the right credential for any non-browser integration: scripts, CI/CD pipelines, server-to-server calls, and long-running services.

Generate one in Settings → Keys & Secrets → Platform API Keys. The key is shown once only — save it somewhere safe.

Don't confuse the three credential scopes

A Platform API key is personal to you — it authenticates the API request as your user. It is not the same as a project's LLM keys or Secrets, which are shared project resources used inside executions. You pick which project a Platform-key request targets with the context header in the next step. See the three credential scopes.

# Test your key
curl https://api.tarx.io/auth/me \
-H "Authorization: Bearer sk-tarx-YOUR_KEY"

2. Set the Project Context

Almost every API call operates inside a project. You have three options — pick whichever is clearest for your use case:

Option A: No header (single-project accounts)

If your account has exactly one project, TARX resolves it automatically. No header needed:

curl https://api.tarx.io/api/v1/agents \
-H "Authorization: Bearer sk-tarx-YOUR_KEY"

Your project slug is the human-readable name in your TARX URL: /{username}/**my-project**/bridge. Use it directly — it's scoped to your account so there's no collision with other users' projects of the same name:

curl https://api.tarx.io/api/v1/agents \
-H "Authorization: Bearer sk-tarx-YOUR_KEY" \
-H "X-Project-Slug: my-project"

Option C: X-Project-ID (UUID)

The raw project UUID. Find it in Settings → Projects (copy icon next to the project name), or by listing your projects:

curl https://api.tarx.io/api/v1/projects \
-H "Authorization: Bearer sk-tarx-YOUR_KEY"
# → copy the "id" field from the project you want

curl https://api.tarx.io/api/v1/agents \
-H "Authorization: Bearer sk-tarx-YOUR_KEY" \
-H "X-Project-ID: 47d74980-e088-4266-bf35-97ed8ccd4d56"

3. Chat with an Agent

The /chat endpoint lets you send messages to any agent and get responses back. This is the primary integration point for building chat products on top of TARX agents.

Streaming (default)

Pass "stream": true (or omit it — true is the default). The response is a Server-Sent Events stream.

import httpx

API = "https://api.tarx.io"
KEY = "sk-tarx-YOUR_KEY"
PROJECT = "proj_abc123"
AGENT = "agent_xyz"

with httpx.stream(
"POST",
f"{API}/api/v1/agents/{AGENT}/chat",
headers={"Authorization": f"Bearer {KEY}", "X-Project-ID": PROJECT},
json={
"message": "Summarise the top risks in this dataset",
"history": [], # previous turns: [{role, content}, ...]
"stream": True,
},
timeout=120,
) as resp:
for line in resp.iter_lines():
if not line.startswith("data:"):
continue
import json
event_type = ""
# event type comes on the preceding "event:" line — track it separately
data = json.loads(line[5:].strip())
print(data)

SSE event types

EventPayloadWhen
delta{"content": "token chunk"}Each streamed token
tool_call{"name": "web_search", "args": {...}}Agent calls a tool
tool_result{"name": "web_search", "result": "...", "success": true}Tool returns
done{"input_tokens": 450, "output_tokens": 312}Stream complete
error{"detail": "message"}Unrecoverable error

A full Python SSE consumer:

import httpx, json

API = "https://api.tarx.io"
KEY = "sk-tarx-YOUR_KEY"
PROJECT = "proj_abc123"
AGENT = "agent_xyz"

def chat_stream(message: str, history: list[dict] = []):
current_event = "message"
with httpx.stream(
"POST",
f"{API}/api/v1/agents/{AGENT}/chat",
headers={"Authorization": f"Bearer {KEY}", "X-Project-ID": PROJECT},
json={"message": message, "history": history, "stream": True},
timeout=120,
) as resp:
resp.raise_for_status()
for line in resp.iter_lines():
if line.startswith("event:"):
current_event = line[6:].strip()
elif line.startswith("data:"):
payload = json.loads(line[5:].strip())
if current_event == "delta":
print(payload["content"], end="", flush=True)
elif current_event == "tool_call":
print(f"\n[tool: {payload['name']}]")
elif current_event == "done":
print(f"\n[tokens: {payload}]")
elif current_event == "error":
raise RuntimeError(payload["detail"])

chat_stream("What's the weather like in Madrid?")

Non-streaming

Pass "stream": false to get a single JSON response (same schema as /test):

import httpx, json

resp = httpx.post(
f"{API}/api/v1/agents/{AGENT}/chat",
headers={"Authorization": f"Bearer {KEY}", "X-Project-ID": PROJECT},
json={"message": "Classify this text as positive or negative.", "stream": False},
timeout=60,
)
result = resp.json()
print(result["response"])
print(result["tool_calls"]) # list of tool calls the agent made

Response schema:

{
"response": "The sentiment is positive.",
"model": "claude-sonnet-4-6",
"provider": "Anthropic",
"input_tokens": 120,
"output_tokens": 45,
"tool_calls": []
}

Multi-turn conversation

Pass previous turns as history:

history = []

def turn(message: str) -> str:
resp = httpx.post(
f"{API}/api/v1/agents/{AGENT}/chat",
headers={"Authorization": f"Bearer {KEY}", "X-Project-ID": PROJECT},
json={"message": message, "history": history, "stream": False},
timeout=60,
).json()
history.append({"role": "user", "content": message})
history.append({"role": "assistant", "content": resp["response"]})
return resp["response"]

print(turn("Who wrote Hamlet?"))
print(turn("What year was it written?")) # uses history — knows "it" = Hamlet

4. Trigger a Workflow and Get Results

Trigger

import httpx, time

resp = httpx.post(
f"{API}/api/v1/workflows/{WORKFLOW_ID}/execute",
headers={"Authorization": f"Bearer {KEY}", "X-Project-ID": PROJECT},
json={"input": "Monthly sales report Q1 2025"},
timeout=30,
)
execution_id = resp.json()["execution_id"]
print("Started:", execution_id)

Poll for results

def wait_for_execution(execution_id: str, timeout: int = 300) -> dict:
deadline = time.time() + timeout
while time.time() < deadline:
ex = httpx.get(
f"{API}/api/v1/executions/{execution_id}",
headers={"Authorization": f"Bearer {KEY}", "X-Project-ID": PROJECT},
).json()
if ex["status"] in ("completed", "failed", "cancelled"):
return ex
time.sleep(3)
raise TimeoutError("Execution did not finish in time")

result = wait_for_execution(execution_id)
print("Status:", result["status"])
print("Output:", result["output"])
print("Node results:", result["node_results"])

Stream live events instead of polling

import sseclient # pip install sseclient-py

resp = httpx.get(
f"{API}/api/v1/executions/{execution_id}/stream",
headers={"Authorization": f"Bearer {KEY}", "X-Project-ID": PROJECT},
timeout=300,
)
for event in sseclient.SSEClient(resp).events():
data = json.loads(event.data)
print(data["type"], data.get("status", ""))
if data["type"] in ("execution_complete", "execution_failed"):
print("Output:", data.get("output"))
break

List a workflow's execution history

executions = httpx.get(
f"{API}/api/v1/workflows/{WORKFLOW_ID}/executions",
headers={"Authorization": f"Bearer {KEY}", "X-Project-ID": PROJECT},
params={"limit": 10},
).json()

for ex in executions:
print(ex["id"], ex["status"], ex.get("completed_at"))

5. Interactive API Reference

Use the API Reference in these docs for a fully interactive reference — every endpoint, request schema, response schema, and a built-in HTTP client to test calls directly from the browser.


6. Error Handling

All errors return JSON with a detail field:

{ "detail": "No API key configured for this agent." }
StatusMeaning
400Bad request — check the request body
401Missing or invalid token
403Insufficient role for this operation
404Resource not found or not in this project
422Validation error — check field types
429Rate limited — back off and retry
502LLM call failed — check agent API key

Rate limits

Default: 200 requests / minute per IP. Headers returned on every response:

X-RateLimit-Limit: 200
X-RateLimit-Remaining: 147
X-RateLimit-Reset: 1716556800

When rate-limited, wait until the Retry-After header value (seconds) before retrying.


7. Security Best Practices

  • Never commit platform keys to source control. Use environment variables or a secrets manager.
  • Rotate keys periodically. Delete the old key after creating a new one.
  • Use the minimum required scope. A script that only reads executions doesn't need a key that can delete agents.
  • One key per integration. This makes it easy to revoke a specific integration if compromised.
# Good: key in env var
export TARX_KEY=sk-tarx-...
curl ... -H "Authorization: Bearer $TARX_KEY"

# Bad: key in source
curl ... -H "Authorization: Bearer sk-tarx-abc123..." # never do this