Skip to navigation

Connect Python

Connect from Python over the REST API, make your first authenticated call, and stream an agent

There is no Python SDK for Recursiv. The @recursiv/sdk is TypeScript only. From Python you connect directly to the REST API at https://api.recursiv.io/api/v1 using any HTTP client. This guide uses requests for plain calls and httpx for streaming.

The REST API exposes the same resources as the SDK. Project-scoped responses use a { "data": ... } envelope, and some return { "data": ..., "meta": ... }.

Install

pip install requests httpx

Configure the key

No account yet? Sign up and mint a key at recursiv.io/account/api-keys.

export RECURSIV_API_KEY=sk_live_...

Send the key as a bearer token on every request:

import os
import requests
API_BASE = "https://api.recursiv.io/api/v1"
API_KEY = os.environ["RECURSIV_API_KEY"]
HEADERS = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
}

First authenticated call

Most resources hang off a project. Create one, then run a query. Project IDs are UUIDs, so always use the id the API returns.

# Create a project
resp = requests.post(
f"{API_BASE}/projects",
headers=HEADERS,
json={"name": "my-app"},
)
resp.raise_for_status()
project = resp.json()["data"]
project_id = project["id"]
# Ensure a database
requests.post(
f"{API_BASE}/databases/ensure",
headers=HEADERS,
json={"project_id": project_id, "name": "main"},
).raise_for_status()
# Run a query
resp = requests.post(
f"{API_BASE}/databases/query",
headers=HEADERS,
json={"project_id": project_id, "sql": "SELECT NOW() as time"},
)
resp.raise_for_status()
print(resp.json()["data"]["rows"])

Run an agent

Create an agent against any model, then chat with it. The model field is model agnostic. Pass any supported model id.

# Create an agent
resp = requests.post(
f"{API_BASE}/agents",
headers=HEADERS,
json={
"project_id": project_id,
"name": "Support Bot",
"model": "anthropic/claude-sonnet-4.6",
"instructions": "You are a helpful assistant.",
},
)
resp.raise_for_status()
agent_id = resp.json()["data"]["id"]
# Non-streaming chat
resp = requests.post(
f"{API_BASE}/agents/{agent_id}/chat",
headers=HEADERS,
json={"message": "Help me build a landing page"},
)
resp.raise_for_status()
print(resp.json()["data"])

Stream an agent

The streaming endpoint returns Server-Sent Events. Use httpx to read the stream line by line. Each data: line is a JSON chunk with a type. Text arrives as text_delta chunks; the stream ends with [DONE].

import json
import httpx
with httpx.stream(
"POST",
f"{API_BASE}/agents/{agent_id}/chat/stream",
headers=HEADERS,
json={"message": "Help me build a landing page"},
timeout=None,
) as resp:
resp.raise_for_status()
for line in resp.iter_lines():
if not line or not line.startswith("data:"):
continue
payload = line[len("data:"):].strip()
if payload == "[DONE]":
break
chunk = json.loads(payload)
if chunk.get("type") == "text_delta" and chunk.get("delta"):
print(chunk["delta"], end="", flush=True)

Run code in a sandbox

The sandbox runs code without an account. It returns a { "data", "meta" } envelope. This call needs no Authorization header.

resp = requests.post(
f"{API_BASE}/sandbox/try",
headers={"Content-Type": "application/json"},
json={"code": "console.log(1 + 1)", "language": "typescript"},
)
resp.raise_for_status()
body = resp.json()
print(body["data"]["output"]) # "2\n"
print(body["meta"]["remaining_executions"], "executions remaining today")

Where to go next

  • Quickstart for the canonical first calls
  • API Reference for every REST endpoint, request shape, and response envelope
  • Recursiv ships hundreds of data integrations (Slack, email, databases, and more) that agents can call as tools