API

REST API

The SDKs are thin wrappers over a plain HTTP API. Every method maps to one request, so you can drive Caspian directly from any language, a shell script, or an edge function. This page is the reference for that surface.

Base URL and auth

All endpoints live under a single base URL. Authenticate with your API key as a bearer token on every request.

Base URL:  https://api.trycaspianai.com
Header:    Authorization: Bearer <api_key>

Requests and responses are JSON (Content-Type: application/json on any request with a body). Errors return a non-2xx status with a {"detail": "..."} body. A key is either an anonymous sandbox key (comm_sandbox_...) or a signed-in key (comm_...). See Authentication. The two endpoints that mint keys are the only ones that take no bearer token.

Building with a coding agent? Point it at api.trycaspianai.com/SKILL.md (also served as llms.txt), a machine-readable guide that walks the whole integration end to end. An interactive OpenAPI explorer lives at /docs.

Wherever the SDK is more convenient, the equivalent call is one line:

agent.py
from caspian_sdk import CommClient

client = CommClient()               # reads COMM_API_KEY / COMM_BASE_URL
client.reply(message_id, text="hi") # → POST /v1/messages/{id}/reply
agent.ts
import { CommClient } from "caspian-sdk";

const client = new CommClient();              // reads COMM_API_KEY / COMM_BASE_URL
await client.reply(messageId, "hi");          // → POST /v1/messages/{id}/reply

Projects and auth

Mint a key, or run the OAuth 2.0 device flow to sign a user in. The sandbox and device-start endpoints need no bearer token.

MethodPathPurpose
POST/v1/projects/sandboxMint an anonymous sandbox project + key (free channels).
POST/v1/auth/device/startBegin device sign-in; returns a user code and verification link.
POST/v1/auth/device/tokenPoll for the signed-in key once the user approves.
Mint a sandbox key (no auth)
curl -s -X POST https://api.trycaspianai.com/v1/projects/sandbox \
  -H 'Content-Type: application/json' -d '{"name":"my-agent"}'
# → {"project_id":"...","api_key":"comm_sandbox_..."}
Start device sign-in (pass current key to carry the project over)
curl -s -X POST https://api.trycaspianai.com/v1/auth/device/start \
  -H 'Content-Type: application/json' -d '{"api_key":"comm_sandbox_..."}'
# → {"user_code":"WXYZ-2345","device_code":"...",
#    "verification_uri_complete":"https://api.trycaspianai.com/device?code=WXYZ-2345","interval":5}
Poll for the token (every ~5s until approved)
curl -s -X POST https://api.trycaspianai.com/v1/auth/device/token \
  -H 'Content-Type: application/json' -d '{"device_code":"..."}'
# pending: {"status":"pending"}
# done:    {"status":"approved","api_key":"comm_...","base_url":"https://api.trycaspianai.com"}

First sign-in grants $100 in free credit and unlocks the paid channels (X, WhatsApp on Caspian's number, iMessage). Write the returned key to .env; future runs reuse it.

Connections

A connection is one channel bound to your project. Create one by POSTing to /v1/connections/{channel} with channel-specific fields in the body. The channel path segment is email, telegram, discord, slack, whatsapp, phone, imessage, x, instagram, or facebook. OAuth channels return a connection carrying an authorize_url; token channels return one that provisions in the background (poll GET /v1/connections/{id} until status is active).

MethodPathPurpose
POST/v1/connections/{channel}Create a connection for a channel.
GET/v1/connections/{id}Fetch a connection (status, address, error).
PATCH/v1/connections/{id}Update branding (display_name, icon_url), no re-install.
POST/v1/connections/slack/installOne-click install of the shared Slack app.
POST/v1/connections/discord/installOne-click install of the shared Discord bot.
POST/v1/connections/x/installOne-click connect of an X account ("Sign in with X").
POST/v1/connections/whatsapp/onboarding-sessionBegin Meta WhatsApp Embedded Signup; returns a launcher_url.
POST/v1/connections/{id}/initiateCold-start a conversation (needs the initiate capability).
Connect an email inbox
curl -s -X POST https://api.trycaspianai.com/v1/connections/email \
  -H "Authorization: Bearer $COMM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"display_name":"My Agent"}'
# → {"id":"conn_...","status":"active","address":"...@trycaspianai.com"}
Connect a Telegram bot
curl -s -X POST https://api.trycaspianai.com/v1/connections/telegram \
  -H "Authorization: Bearer $COMM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"bot_token":"7123456789:AAE..."}'
Install the shared Slack app (returns an authorize_url)
curl -s -X POST https://api.trycaspianai.com/v1/connections/slack/install \
  -H "Authorization: Bearer $COMM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"display_name":"Acme Support","icon_url":"https://.../icon.png"}'
# → {"id":"conn_...","status":"pending","authorize_url":"https://slack.com/oauth/..."}
Poll a connection until active, then re-brand it
curl -s https://api.trycaspianai.com/v1/connections/conn_123 \
  -H "Authorization: Bearer $COMM_API_KEY"

curl -s -X PATCH https://api.trycaspianai.com/v1/connections/conn_123 \
  -H "Authorization: Bearer $COMM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"display_name":"Acme Bot"}'

The full body each channel accepts is documented per channel. See the Channels overview and the individual channel pages (Slack, Discord, X, WhatsApp, SMS).

Messaging

Reply to an inbound message, show a typing indicator, or work with conversations and their history. Replies route back on the source channel automatically; you only pass the message id.

MethodPathPurpose
POST/v1/messages/{id}/replyReply to an inbound message on its channel.
POST/v1/messages/{id}/typingShow a "thinking…" indicator (Discord/Telegram; no-op elsewhere).
GET/v1/conversationsList conversations; optional ?connection_id= filter.
GET/v1/conversations/{id}/messagesList messages in a conversation.
POST/v1/conversations/{id}/messagesProactively send into an existing conversation (needs the send capability).
Reply to a message
curl -s -X POST https://api.trycaspianai.com/v1/messages/msg_123/reply \
  -H "Authorization: Bearer $COMM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"text":"Thanks! On it."}'
Show a typing indicator
curl -s -X POST https://api.trycaspianai.com/v1/messages/msg_123/typing \
  -H "Authorization: Bearer $COMM_API_KEY"
List conversations and one thread's messages
curl -s "https://api.trycaspianai.com/v1/conversations?connection_id=conn_123" \
  -H "Authorization: Bearer $COMM_API_KEY"

curl -s https://api.trycaspianai.com/v1/conversations/cnv_123/messages \
  -H "Authorization: Bearer $COMM_API_KEY"

Events

Inbound messages and lifecycle changes are delivered as an ordered event stream. Poll GET /v1/events with an after_seq cursor, or register a webhook to receive events by push. Events are strictly ordered by seq; persist the last seq you handled to resume across restarts.

MethodPathPurpose
GET/v1/eventsRead events after a cursor. Params: after_seq, limit, type.
PUT/v1/webhookRegister a push endpoint (url, optional signing secret).
GET/v1/webhookRead the current webhook config.
Poll for new events
curl -s "https://api.trycaspianai.com/v1/events?after_seq=0&type=message.received" \
  -H "Authorization: Bearer $COMM_API_KEY"
# → [{"seq":42,"type":"message.received","data":{"message":{...}}}, ...]
Register a webhook
curl -s -X PUT https://api.trycaspianai.com/v1/webhook \
  -H "Authorization: Bearer $COMM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"url":"https://your.app/caspian/hook","secret":"whsec_..."}'

The SDK's listen() loop is just GET /v1/events polling with backoff and dispatch on top. If you build your own loop, advance the cursor only after you finish handling each event.

Behavior guides

Fetch ready-to-inject, per-channel etiquette to append to your agent's system prompt. These endpoints return text/plain, not JSON.

MethodPathPurpose
GET/v1/behavior-promptCombined guide for every channel you've connected.
GET/v1/channels/{channel}/guideGuide for a single channel (e.g. slack, discord).
curl -s https://api.trycaspianai.com/v1/behavior-prompt \
  -H "Authorization: Bearer $COMM_API_KEY"

curl -s https://api.trycaspianai.com/v1/channels/slack/guide \
  -H "Authorization: Bearer $COMM_API_KEY"

See Behavior guides for how to wire these into a system prompt.

Channels

List the transports enabled on this gateway right now and their capabilities. A channel may appear more than once: one row per provider (for example WhatsApp via both twilio-whatsapp and meta-whatsapp). Only channels listed here are connectable; others 400 on connect.

MethodPathPurpose
GET/v1/channelsList live channels, their providers, and capabilities.
curl -s https://api.trycaspianai.com/v1/channels \
  -H "Authorization: Bearer $COMM_API_KEY"

Domains

Register a subdomain you control to send agent email under your own brand. Registering returns the DNS records to add; poll until the domain is active, then connect email with domain=.

MethodPathPurpose
POST/v1/domainsRegister a subdomain; returns DNS records to add.
GET/v1/domainsList registered domains and their status.
GET/v1/domains/{id}Fetch one domain; poll until status is active.
curl -s -X POST https://api.trycaspianai.com/v1/domains \
  -H "Authorization: Bearer $COMM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"domain":"agents.acme.com"}'
# → {"id":"dom_...","status":"pending","dns_records":[...]}

curl -s https://api.trycaspianai.com/v1/domains/dom_123 \
  -H "Authorization: Bearer $COMM_API_KEY"

A zone file for bulk import is served at /v1/domains/{id}/zone-file. See Email for the full custom-domain walkthrough.

Test

Inject a synthetic inbound email into a connection so you can watch your handler run without a mail client.

MethodPathPurpose
POST/v1/test-emailsDeliver a test email to your email connection.
curl -s -X POST https://api.trycaspianai.com/v1/test-emails \
  -H "Authorization: Bearer $COMM_API_KEY" -H 'Content-Type: application/json' \
  -d '{"text":"hello, are you alive?"}'

Within a few seconds a running listener fires a message.received event and your handler replies. Confirm with GET /v1/events?type=message.sent.

The SDKs cover this whole surface with typed methods in Python and JavaScript. Unless you need raw HTTP, reach for them first; see the SDK reference.

Related

Introduction →
The one-handler model and the big picture.
SDK reference →
Every method, Python and JS.
Authentication →
Sandbox keys, device sign-in, free vs paid.