API authentication

The Seny REST API uses bearer-token authentication. Every request must include an Authorization header with a valid API key. All traffic is HTTPS only.

Base URL

https://app.seny.ai

See the full interactive API reference for every endpoint and try-it-out console.

Creating an API key

Open the dashboard and go to Settings → API keys. Click New key, give it a label that describes where it will be used ("production backend", "staging", etc.), pick the scopes you need, and copy the key.

The full key is shown only once. Seny stores a SHA-256 hash — if you lose it, revoke and mint a new one. Keys belong to the organization that created them and can access every agent under that org.

Using a key

curl https://app.seny.ai/api/v1/rest/agents \
  -H "Authorization: Bearer seny_..."

Keys are formatted seny_followed by a 32-char random string. There's no separate test/live mode — scopes (below) gate destructive actions instead.

Permissions

Each key carries a list of capabilities drawn from the same catalog used for team-member permissions. Pick the minimum set the key needs at creation time. You can tighten or loosen a key's permissions later without rotating it.

CapabilityAllows
agents.readList/get agents, voice profiles, phone numbers, sites.
agents.writeCreate, update, delete agents (including channel/voicemail config).
sites.readList crawled sites and pages.
sites.writeRe-crawl and delete sites.
knowledge.writeUpload, link, or remove knowledge documents fed to the agent.
conversations.readRead transcripts, recordings, extracted data.
conversations.writeDelete conversations.
calls.readList and inspect calls.
calls.writePlace, cancel, and requeue calls.
simulations.readList simulation runs and scenarios.
simulations.writeCreate and step simulations, manage scenarios.
campaigns.readList campaigns, lists, contacts, and approval queues.
campaigns.writeCreate, edit, pause, or delete campaigns and their lists/contacts.
campaigns.approveApprove or reject queued outbound messages.
phone_numbers.writeConfigure and release rented phone numbers.
voice_profiles.writeCurate the org-wide voice library.
webhooks.readList webhook endpoints and recent deliveries.
webhooks.writeCreate, edit, and delete webhook endpoints.
integrations.readSee connected third-party integrations.
integrations.writeConnect, configure, and disconnect org-level integrations.
analytics.readRead analytics dashboards.
reports.readList reports and their runs.
reports.writeCreate, edit, and run reports.
clients.accessCreate and manage white-label client workspaces (see Client workspaces).
billing.readRead plan, invoices, and credit balance.
api_keys.readList existing keys and their permissions.
team.readSee members and their roles.
org.readRead workspace settings.
audit_log.readRead the workspace audit log.

A handful of admin capabilities — org.write, api_keys.write, billing.write, and the team.* management caps — are grantable to a bearer API key too, but are held back by a non-escalation guard: you can only put a cap on a key that youalready hold, and they're excluded from the one-click "full access" preset (tick them individually). Money movement itself (Stripe checkout, buying phone numbers) stays in the dashboard.

A request with an insufficient permission returns 403 insufficient_permission and names the missing capability in the response body.

OAuth connectors

Instead of pasting a bearer key, you can connect an AI tool (claude.ai, ChatGPT, Cursor) to Seny over OAuth — see MCP. The consent screen lets you pick a default workspace and the exact permissions to grant. One difference from bearer keys: the admin caps above (org.write, api_keys.write, billing.write, team.*) cannot be granted to an OAuth connector at all. To manage white-label client workspaces from a connector, grant clients.access — the dedicated capability that covers creating and configuring clients without needing org.write.

Every tool or endpoint is filtered to the key or connector's permissions — a call needing a capability you didn't grant returns 403, and (over MCP) the tool is hidden from the tool list entirely. If a capability seems missing, check the grants on the key or connector first.

Legacy scopes: keys created before this migration carry the old agents:read, agents:write, conversations:read, conversations:write, and * scope strings. They keep working — the auth layer translates them to the new capability list on every request. Rotate to a key with explicit permissions next time you provision one.

TypeScript SDK

The fastest way to talk to the API is @seny/sdk:

npm install @seny/sdk
import { createSenyClient } from "@seny/sdk";

const seny = createSenyClient({ apiKey: process.env.SENY_API_KEY! });

// List agents
const agents = await seny.agents.list({ limit: 20 });

// Pull a conversation
const conv = await seny.conversations.get("uuid-...");
console.log(conv.transcript, conv.tool_calls);

The SDK throws SenyApiError on non-2xx responses so you can branch on err.status / err.code / err.docs. Full reference and call signatures: see /docs/api/reference.

Errors

All errors return JSON with a consistent shape:

{
  "error":   "missing_api_key",
  "message": "Include your API key in the Authorization header: Bearer seny_...",
  "docs":    "https://seny.ai/docs/api/auth"
}

HTTP status codes follow REST conventions:

  • 200 — success
  • 201 — resource created
  • 400 — bad request (validation failure or malformed JSON)
  • 401 — missing or invalid API key
  • 403 — authenticated but missing the required permission
  • 404 — resource not found or not owned by your org
  • 500 — server error (please retry with backoff)

Revoking a key

Delete the key from the Settings → API keys page. It stops working immediately — any in-flight request using it gets a 401 on its next call.

MCP server (alternative)

If you'd rather drop the API into an LLM-aware tool directly, install the workspace admin MCP server: @seny/mcp-server. Same auth model (your API key in SENY_API_KEY), but exposed as MCP tools that Claude / Cursor / etc. can call natively. See /docs/mcp.