FOR DEVELOPERS

One AI gateway for every internal app you ship

Stop scattering OpenAI, Anthropic, and Azure keys across half a dozen services. Point your apps, agents, and back-office jobs at Curie and get auth, rate limits, tool forwarding, audit, and cost tracking for free — under the same policies your chat users already follow.

HTTP + SSE Tool forwarding Conversation audit Per-key rate limits
# your app, your endpoint, your key
curl https://curie.your-org.com/v1/conversations \
  -H "Authorization: Bearer curie_pat_..." \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "model": "gpt-4.1",
    "messages": [{"role":"user","content":"..."}],
    "tools": [...],
    "agent_profile": "lattice_assistant"
  }'

What the gateway gives your apps

Curie is the conversation system of record for every programmatic call

Managed credentials

Your operator configures the OpenAI / Anthropic / Azure key once on Curie. Your apps authenticate with user-issued curie_pat_* tokens scoped to one organization. Rotate or revoke without redeploying anything.

Shared rate & cost limits

API traffic counts against the same per-user, per-org, and per-usage-group limits as chat. One token-per-minute ceiling, one monthly cost cap — consistent whether the request came from a browser or a job.

Tool forwarding

Send your tool catalog with each request; Curie forwards it to the provider's native tools field, streams back tool_call events over SSE, and lets your app execute and post results. Curie never executes tools itself.

Conversation persistence

Every API conversation is durable in Curie's database. Your app stores only a curie_conversation_id; Curie owns the transcript, the tool-call sidecar, and the audit view at /external_interactions.

Agent profiles

Reference an agent profile by slug; Curie composes the layered prompt stack server-side. New slugs auto-provision a draft profile that admins can refine in the console — no code change to update an in-flight integration's behavior.

Read-only audit

Admins see every programmatic conversation at /external_interactions — system prompt, tool calls, results, token usage. Same UI shape as the chat audit; same content-free logging guarantees.

Wire shape

A small, conversation-centric protocol. Your app POSTs a conversation, streams an SSE response, and POSTs follow-up messages or tool results to resume the stream. Full spec at docs/curie-integration-protocol.md in the repo.

Endpoints
  • GET   /v1/models — enabled providers
  • POST  /v1/conversations — start, stream SSE
  • POST  /v1/conversations/:id/messages — resume turn
  • GET   /v1/conversations — list (paginated)
  • GET   /v1/conversations/:id — full transcript
  • DELETE /v1/conversations/:id — soft-delete
SSE event types
  • message_delta — assistant content chunk
  • tool_call — buffered, complete tool call
  • usage — token counts
  • done — terminal (stop / tool_call_pending)
  • error — structured error
# 1. Start a conversation. Curie streams SSE.
curl -N https://curie.your-org.com/v1/conversations \
  -H "Authorization: Bearer $CURIE_PAT" \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "model": "gpt-4.1",
    "agent_profile": "support_assistant",
    "messages": [
      {"role": "user", "content": "Look up ticket 4421"}
    ],
    "tools": [
      {"name": "get_ticket", "input_schema": {...}}
    ]
  }'

# 2. On a tool_call event, your app executes the tool
#    and POSTs the result back to resume the same turn:
curl https://curie.your-org.com/v1/conversations/$CID/messages \
  -H "Authorization: Bearer $CURIE_PAT" \
  -d '{"role":"tool","call_id":"curie_call_abc","result":{...}}'
import { CurieClient } from "@your-org/curie";

const curie = new CurieClient({
  baseUrl: "https://curie.your-org.com",
  apiKey: process.env.CURIE_PAT!,
});

const stream = await curie.conversations.create({
  model: "gpt-4.1",
  agent_profile: "support_assistant",
  messages: [{ role: "user", content: "..." }],
  tools: myToolCatalog,
});

for await (const event of stream) {
  if (event.type === "message_delta") writeChunk(event.content_delta);
  if (event.type === "tool_call") await handleTool(event);
}
curie = Curie::Client.new(
  base_url: "https://curie.your-org.com",
  api_key:  ENV.fetch("CURIE_PAT")
)

curie.conversations.create(
  model: "gpt-4.1",
  agent_profile: "support_assistant",
  messages: [{ role: "user", content: question }],
  tools: tool_catalog
) do |event|
  case event.type
  when "message_delta" then stream_to_user(event.content_delta)
  when "tool_call"     then handle_tool(event)
  end
end

Sample SDKs are illustrative. The wire is plain HTTP + SSE; any language with an SSE client (Python httpx, Go net/http, Node fetch) works directly.

Where customers point it

In-house agents

Embedded chat panels in line-of-business apps. The host app owns tools and approval UI; Curie owns the model call and the transcript.

Batch jobs & workers

Background classifiers, summarizers, and enrichment pipelines. One key, one cost cap, one place to audit what ran overnight.

SaaS modules you build for clients

Each tenant brings their own LLM credentials via Curie. You ship one integration; they keep their data residency posture.

Ready to wire up your apps?

The gateway is part of every Curie license — no separate procurement, no extra vendor.

See Pricing