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.
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"
Option B: X-Project-Slug (recommended for scripts)
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
| Event | Payload | When |
|---|---|---|
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." }
| Status | Meaning |
|---|---|
400 | Bad request — check the request body |
401 | Missing or invalid token |
403 | Insufficient role for this operation |
404 | Resource not found or not in this project |
422 | Validation error — check field types |
429 | Rate limited — back off and retry |
502 | LLM 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