The Oren AI API
One REST API to deploy agents, run outbound campaigns, score risk, automate workflows, and query your business data. Every action your team can take in the dashboard is available programmatically, with an official SDK and a native MCP server.
The API is organized around predictable, resource-oriented URLs. It accepts JSON request bodies, returns JSON responses, and uses standard HTTP response codes, verbs, and authentication. Every request is served over TLS, and all timestamps are Unix epoch seconds in UTC.
The example below sends a message to a deployed agent and returns the agent's reply along with any billable actions it took.
curl https://api.oren.ai/v1/agents/agt_0X8aZ2/messages \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \ -H "Content-Type: application/json" \ -d '{"contact": "con_8Hd2Kp", "channel": "sms", "content": "Hi, is my renewal still on file?"}'from orenai import Oren oren = Oren(api_key="sk_live_4eC39HqLyjWDarjtT1zdp7dc") reply = oren.agents.messages.create( "agt_0X8aZ2", contact="con_8Hd2Kp", channel="sms", content="Hi, is my renewal still on file?", ) print(reply.content)import Oren from "orenai"; const oren = new Oren({ apiKey: "sk_live_4eC39HqLyjWDarjtT1zdp7dc" }); const reply = await oren.agents.messages.create("agt_0X8aZ2", { contact: "con_8Hd2Kp", channel: "sms", content: "Hi, is my renewal still on file?", }); console.log(reply.content);
Authentication
The API authenticates with secret keys. Each request must include your key as a bearer token in the Authorization header. Keys carry the privileges of the workspace that created them, so treat them like passwords.
- Live keys are prefixed with
sk_live_and operate on real contacts, campaigns, and billing. - Test keys are prefixed with
sk_test_and run against an isolated sandbox with simulated agents and no metered charges. - Scoped keys can be restricted to specific platforms (for example, read-only Compute access) from the dashboard.
Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc
Never embed a secret key in browser code, mobile apps, or public repositories. For client-side agent chat, mint short-lived session tokens with the Portal sessions endpoint instead.
Making requests
Send JSON with a Content-Type: application/json header. Resource identifiers are prefixed by type, so an ID is always self-describing: agt_ for agents, conv_ for conversations, con_ for contacts, act_ for actions, cmp_ for campaigns, and run_ for model and workflow runs.
Successful responses return the affected object. List endpoints return a wrapped collection described under Pagination.
Response envelope
{
"id": "msg_3Lp9Qr",
"object": "message",
"role": "assistant",
"conversation": "conv_7Yb1Nm",
"channel": "sms",
"content": "Yes, your renewal is on file and due July 1. Want me to send the link?",
"actions": ["act_5Zk0Wd"],
"created_at": 1781740812
}
Errors
Oren AI uses conventional HTTP status codes. Codes in the 2xx range indicate success, 4xx indicate a request that failed given the information provided, and 5xx indicate an error on our side. Every error body shares one shape.
200 | Request succeeded. |
400 | Malformed or missing parameters. |
401 | Invalid or missing API key. |
403 | Key lacks scope for this resource. |
404 | Resource does not exist. |
409 | Idempotency or state conflict. |
429 | Rate limit exceeded. |
5xx | Internal error. Safe to retry. |
{
"error": {
"type": "invalid_request_error",
"code": "contact_consent_missing",
"message": "Contact con_8Hd2Kp has not granted SMS consent.",
"param": "contact",
"doc_url": "https://oren.ai/api#contacts"
}
}
Pagination
List endpoints are cursor-based. Pass limit (1 to 100, default 20) and page forward with starting_after using the last ID from the previous page. The has_more flag tells you when to stop.
curl "https://api.oren.ai/v1/conversations?limit=20&starting_after=conv_7Yb1Nm" \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc"{ "object": "list", "url": "/v1/conversations", "has_more": true, "data": [ { "id": "conv_7Yb1Nm", "object": "conversation", "status": "open" }, { "id": "conv_2Fa8Lw", "object": "conversation", "status": "escalated" } ] }
Idempotency
Safely retry write requests by sending an Idempotency-Key header with a unique value, such as a UUID. If a request is repeated with the same key within 24 hours, the original response is replayed instead of performing the action twice. This protects against duplicate messages and double-charged actions during network retries.
curl https://api.oren.ai/v1/outreach/campaigns/cmp_1Aa2Bb/launch \
-H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \
-H "Idempotency-Key: 9f1c8b2e-4d77-4a0e-9b1a-2c3d4e5f6071" \
-X POST
Rate limits
Limits are applied per workspace. Standard workspaces allow 1,000 requests per minute for reads and 200 per minute for writes. Compute and Intel inference endpoints carry separate concurrency limits. Every response includes headers describing your current budget.
| Header | Description |
|---|---|
| Oren-RateLimit-Limit | Maximum requests in the current window. |
| Oren-RateLimit-Remaining | Requests left in the current window. |
| Oren-RateLimit-Reset | Unix time when the window resets. |
| Retry-After | Seconds to wait, returned on a 429. |
When you exceed a limit, the API returns 429. Back off using the Retry-After header. The official SDKs retry with exponential backoff automatically.
Versioning
The API is versioned by date. Your workspace is pinned to the version that was current when you first integrated, and that behavior is held stable. Override it per request with the Oren-Version header to adopt newer behavior on your own schedule.
Oren-Version: 2026-06-01
Agents
An agent is a deployed worker bound to one platform. It carries a model, a set of instructions, the tools it can call, and an optional voice. Agents are the unit you create, configure, and talk to. Everything an agent does is recorded as an action.
The agent object
agt_.outreach, portal, flow, intel, compute.oren-1.schedule_callback or knowledge_base.active, paused, or draft.{
"id": "agt_0X8aZ2",
"object": "agent",
"name": "Renewals Specialist",
"platform": "portal",
"model": "oren-1",
"instructions": "You help clients review and renew their policies...",
"tools": ["knowledge_base", "schedule_callback"],
"voice": { "enabled": true, "voice_id": "ava" },
"status": "active",
"created_at": 1781740800,
"metadata": {}
}
curl https://api.oren.ai/v1/agents \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \ -H "Content-Type: application/json" \ -d '{"name": "Renewals Specialist", "platform": "portal", "instructions": "You help clients renew...", "tools": ["knowledge_base", "schedule_callback"]}'agent = oren.agents.create( name="Renewals Specialist", platform="portal", instructions="You help clients renew...", tools=["knowledge_base", "schedule_callback"], )
Conversations
A conversation is a durable thread between one agent and one contact over a single channel. It tracks status as the agent works: open while the agent is handling it, escalated when a human is looped in, and closed when resolved.
sms, voice, chat, or email.{
"id": "conv_7Yb1Nm",
"object": "conversation",
"agent": "agt_0X8aZ2",
"contact": "con_8Hd2Kp",
"channel": "sms",
"status": "open",
"messages_count": 0,
"created_at": 1781740806
}
agent, contact, status, or channel.Messages
Messages are the turns within a conversation. Posting a user message runs the agent, which appends its assistant reply and records any actions it took. You can also post a message directly to an agent with the convenience endpoint below, which opens or reuses a conversation for the contact automatically.
{
"id": "msg_3Lp9Qr",
"object": "message",
"role": "assistant",
"conversation": "conv_7Yb1Nm",
"content": "Yes, your renewal is on file and due July 1.",
"actions": ["act_5Zk0Wd"],
"intent": "renewal_inquiry",
"created_at": 1781740812
}
Contacts
Contacts are the people your agents talk to: leads, applicants, and clients. A contact stores identity, channel addresses, consent state, and arbitrary attributes you attach. Consent is enforced at send time, so an agent cannot text a contact who has not opted in to SMS.
curl https://api.oren.ai/v1/contacts \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \ -H "Content-Type: application/json" \ -d '{"name": "Dana Mercer", "phone": "+15145550142", "email": "dana@acme.co", "consent": {"sms": true}, "attributes": {"policy": "AC-4471"}}'{ "id": "con_8Hd2Kp", "object": "contact", "name": "Dana Mercer", "phone": "+15145550142", "email": "dana@acme.co", "consent": { "sms": true, "voice": false, "email": true }, "attributes": { "policy": "AC-4471" }, "created_at": 1781740790 }
Actions
An action is one discrete thing an agent does for you: a message sent, a lead qualified, a document collected, a callback booked. Actions are the metered unit of the platform, so the Actions endpoint doubles as your usage and billing ledger. Each action links back to the agent and conversation that produced it.
agent, type, or a created time range to reconcile usage.{
"id": "act_5Zk0Wd",
"object": "action",
"type": "message.sent",
"agent": "agt_0X8aZ2",
"conversation": "conv_7Yb1Nm",
"billable": true,
"created_at": 1781740812
}
Outreach
Outreach runs SMS and voice campaigns autonomously. A campaign pairs an agent with an audience and a channel. Once launched, the agent texts each contact, handles inbound replies, detects buying intent, escalates hot prospects, and respects opt-outs, all within TCPA, CRTC, and CASL rules.
draft. It will not send until launched.sms or voice.segment ID or an explicit list of contacts.curl https://api.oren.ai/v1/outreach/campaigns \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \ -H "Content-Type: application/json" \ -d '{"name": "June renewals", "agent": "agt_0X8aZ2", "channel": "sms", "audience": {"segment": "seg_due_july"}}'{ "id": "cmp_1Aa2Bb", "object": "campaign", "name": "June renewals", "agent": "agt_0X8aZ2", "channel": "sms", "status": "draft", "stats": { "queued": 412, "delivered": 0, "replied": 0, "qualified": 0 }, "created_at": 1781740900 }
Idempotency-Key to make launch safe to retry.Compute
Compute exposes statistical models as endpoints: risk scoring, pricing optimization, and demand forecasting. You send features, you get a structured result with the drivers behind it. Models are configured to your schema in the dashboard and referenced by name and version.
credit_risk_v3.curl https://api.oren.ai/v1/compute/risk/scores \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \ -H "Content-Type: application/json" \ -d '{"model": "credit_risk_v3", "features": {"monthly_revenue": 84000, "months_active": 19, "industry": "retail"}}'{ "id": "run_9Qm4Ts", "object": "compute.run", "model": "credit_risk_v3", "score": 0.182, "band": "low", "factors": [ { "feature": "monthly_revenue", "impact": -0.21 }, { "feature": "months_active", "impact": -0.08 } ], "created_at": 1781741000 }
Flow
Flow turns a manual process into a workflow that runs on demand or on a trigger. Define a workflow once, then start runs with structured input. Each run is tracked to completion with full step history, so you can replace tab-to-tab copy work with a single API call.
flow.run.completed webhook.curl https://api.oren.ai/v1/flow/workflows/wf_6Rd3Cv/runs \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \ -H "Content-Type: application/json" \ -d '{"input": {"invoice_id": "INV-2087", "amount": 4200, "vendor": "Northwind"}}'{ "id": "run_4Kp7Yx", "object": "flow.run", "workflow": "wf_6Rd3Cv", "status": "running", "steps": [ { "name": "validate", "status": "succeeded" }, { "name": "route_approval", "status": "running" } ], "created_at": 1781741100 }
Intel
Intel answers questions over your connected business data and returns grounded answers with citations. Ask in plain language, scope to specific sources, and get back a structured answer you can render or act on.
curl https://api.oren.ai/v1/intel/queries \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \ -H "Content-Type: application/json" \ -d '{"question": "Which accounts are up for renewal next month and at risk of churn?", "sources": ["crm", "billing"]}'{ "id": "qry_2Wn8Hb", "object": "intel.query", "answer": "7 accounts renew in July. 2 show declining usage and missed payments.", "citations": [ { "source": "crm", "record": "acct_5512", "label": "Northwind Co" }, { "source": "billing", "record": "inv_77310", "label": "Past due 14d" } ], "created_at": 1781741200 }
Portal
Portal hosts a white-labeled, client-facing experience with an embedded agent. Mint a short-lived session for a contact and either redirect them to the hosted URL or drop the embed snippet into your own app. Sessions are scoped to one contact and expire automatically, so they are safe to use from the browser.
curl https://api.oren.ai/v1/portal/sessions \ -H "Authorization: Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" \ -H "Content-Type: application/json" \ -d '{"contact": "con_8Hd2Kp", "agent": "agt_0X8aZ2"}'{ "id": "ps_3Tg5Vn", "object": "portal.session", "contact": "con_8Hd2Kp", "agent": "agt_0X8aZ2", "url": "https://portal.oren.ai/s/3Tg5VnQ0r8", "client_secret": "psec_a1B2c3D4e5", "expires_at": 1781744800 }
Webhooks
Webhooks push events to your server as things happen: a lead is qualified, a model run finishes, a workflow completes. Register an endpoint in the dashboard, then verify each delivery with the signature in the Oren-Signature header before trusting the payload.
Each delivery is an event object wrapping the resource that changed. Respond with any 2xx status to acknowledge. We retry failed deliveries with exponential backoff for up to 24 hours.
{
"id": "evt_8Jd1Kf",
"object": "event",
"type": "outreach.lead.qualified",
"created_at": 1781741300,
"data": {
"object": {
"id": "con_8Hd2Kp",
"object": "contact",
"intent": "renewal_inquiry",
"campaign": "cmp_1Aa2Bb"
}
}
}
Verifying signatures
The Oren-Signature header contains a timestamp and an HMAC-SHA256 of the raw request body, signed with your endpoint's secret. Compute the same HMAC and compare in constant time. The SDKs ship a one-line helper.
event = oren.webhooks.construct_event( payload=request.body, signature=request.headers["Oren-Signature"], secret="whsec_PNs9Kqf2Lm", ) if event.type == "outreach.lead.qualified": notify_sales(event.data.object)const event = oren.webhooks.constructEvent( req.rawBody, req.headers["oren-signature"], "whsec_PNs9Kqf2Lm" ); if (event.type === "outreach.lead.qualified") { notifySales(event.data.object); }
Event types
Subscribe to any subset of events per endpoint. These are the events emitted across the platform.
| Event | Fires when |
|---|---|
| conversation.message.created | An agent or contact adds a message to a conversation. |
| conversation.escalated | An agent hands a conversation to a human. |
| outreach.lead.qualified | A campaign agent detects buying intent. |
| outreach.contact.opted_out | A contact opts out. Sending stops immediately. |
| compute.run.completed | A risk, pricing, or forecast run finishes. |
| flow.run.completed | A workflow run reaches a terminal state. |
| action.recorded | A billable action is written to the ledger. |
Official SDKs
Official libraries wrap the API with typed methods, automatic retries with backoff, and webhook verification. They read your key from the OREN_API_KEY environment variable by default.
pip install orenainpm install orenaigo get github.com/oren-ai/oren-go
Model Context Protocol
The Oren MCP server exposes your workspace to any MCP-compatible client, including Claude, Cursor, and VS Code. Once connected, an assistant can list and operate your agents, launch campaigns, score risk, run workflows, and query Intel, all with the same permissions as the API key it authenticates with.
The remote server speaks Streamable HTTP and authenticates with a bearer API key. A local stdio server is also published for desktop clients that prefer to run it as a subprocess.
The MCP server inherits the exact scope of the key it runs with. Issue a read-only or platform-scoped key when you want an assistant to look but not act.
Connecting a client
Add the server to your client's MCP configuration. The remote transport needs only the URL and your key. The local transport runs the published package over stdio.
Claude Desktop
Add Oren to claude_desktop_config.json, then restart the app.
{
"mcpServers": {
"oren": {
"command": "npx",
"args": ["-y", "@orenai/mcp"],
"env": { "OREN_API_KEY": "sk_live_4eC39HqLyjWDarjtT1zdp7dc" }
}
}
}
Remote server (Cursor, VS Code)
Point any client that supports remote MCP at the hosted endpoint and pass your key as a bearer token.
{
"mcpServers": {
"oren": {
"url": "https://mcp.oren.ai",
"headers": { "Authorization": "Bearer sk_live_4eC39HqLyjWDarjtT1zdp7dc" }
}
}
}
MCP tools
The server advertises a focused set of tools that map to the API. An assistant discovers them automatically once connected.
MCP resources and prompts
Alongside tools, the server exposes read-only resources that clients can attach as context, and prompts that package common operator workflows into one click.
| Resource URI | Returns |
|---|---|
| oren://agents | The current roster of agents and their status. |
| oren://conversations/{id} | A full conversation transcript with intent tags. |
| oren://campaigns/{id} | Live campaign stats and qualified leads. |
| oren://actions/recent | The most recent billable actions across agents. |
Prompts
| Prompt | What it does |
|---|---|
| triage_escalations | Reviews escalated conversations and drafts next steps for a human. |
| campaign_readout | Summarizes a campaign's performance and surfaces qualified leads. |
| weekly_digest | Compiles agent activity, actions, and Intel highlights for the week. |
API keys and MCP access are managed from your workspace settings. Start a free trial to provision a sandbox key in under a minute.