API

Put a coworker inside your product.

One call hands the coworker a job. It works in your workspace, then answers with the documents it used.

  • Streams over server-sent events
  • One key, scoped to what it needs, revoked any time
  • The same key opens an MCP endpoint
RequestPOSThttps://api.alfera.ai/v1/answers
{
  "input": "When does Northwind renew, and what notice do we owe?",
  "conversation_id": "northwind-renewal",
  "include": ["sources"],
  "stream": false
}
Response202 Accepted
{
  "data": {
    "answer_id": "event_01k9m4rx7te2v8b0qz5cd3ny4f",
    "status": "queued"
  }
}
ThenGET/v1/answers/event_01k9m4rx7te2v8b0qz5cd3ny4f200 OK
{
  "data": {
    "status": "completed",
    "output_text": "Northwind renews on 30 September 2026.",
    "sources": [{ "subject": "Northwind", "fact_text": "60 days' notice" }]
  }
}

Streaming

Watch a job as it runs

Some jobs finish in a second. Some take minutes. Keep the connection open and read every frame, or take an id and come back later.

POST/v1/answerstext/event-streamOpen
  1. 0.0s

    answer.created

    { "answer_id": "event_01k9m4rx7te2v8b0qz5cd3ny4f", "conversation_id": "northwind-renewal" }

  2. 14.2s

    answer.delta

    { "text": "Northwind renews on 30 " }

    Those fourteen seconds are the work. It read the drive and checked the record before it wrote a word.

  3. 14.3s

    answer.delta

    { "text": "September 2026. Notice is due by " }

  4. 15.4s

    answer.completed

    { "status": "completed", "sources": [{ "subject": "Northwind" }] }

    Ask for sources and the last frame carries the facts it used. Each one names the subject it came from.

  5. 15.4s

    done

    { "ok": true }

Send an Idempotency-Key and a retry reads the same run back instead of paying for a second one.

Sessions

Or hand it the whole job

An answer is a question. A session is the work: it opens with one of your agents, keeps its history, uses the agent’s real tools, and stops to ask you before anything that needs asking.

The endpoints

POST /v1/sessions
Open one with an agent, and send its first message.
GET /v1/sessions
The ones this key opened, newest first, paged.
GET /v1/sessions/{id}
Status, agent, title, tags, and what it spent.
POST /v1/sessions/{id}/events
Send a message, an interrupt, or a decision.
GET /v1/sessions/{id}/events
The whole timeline, oldest first.
GET /v1/sessions/{id}/events/stream
The same timeline live, and resumable.
POST /v1/sessions/{id}/archive
Close it. Archive is the terminal verb.
GET /v1/sessions/{id}/files
What its runs produced.
GET /v1/files/{id}/content
The bytes of one of those files.
PATCH /v1/sessions/{id}
File it into a project, or out of one.

The rest of the workspace

POST /v1/automations
A standing job: an instruction and every way it starts. automations.write.
GET /v1/automations
The standing jobs, with their triggers. automations.read.
PATCH /v1/automations/{id}
Pause, resume, or rewrite one. automations.write.
POST /v1/automations/{id}/trigger
Start one now; Idempotency-Key dedups. automations.write.
GET /v1/automations/{id}/runs
What it ran, newest first. automations.read.
PATCH /v1/agents/{slug}
Rename an agent or rewrite its instructions. agents.write.
GET /v1/skills
The skills an agent can load. skills.read.
GET /v1/projects
The projects shared with the workspace. projects.read.
GET /v1/workspace
The workspace name. workspace.read; rename with PATCH.
GET /v1/usage/summary
Total spend in a window, by kind. usage.read.
GET /v1/usage/daily
Per-day spend for the window. usage.read.
GET /v1/credits
The credit balance left, in microcents. usage.read.
GET /v1/integrations
What the workspace is connected to. integrations.read.
GET /v1/integrations/{key}/tools
One integration’s tools and parameters. integrations.read.

A session runs with the agent’s whole tool surface, so a call that needs approval stops it with requires_action and names the tool. Your key answers it — allow or deny — and the run goes on.

Three calls

Open itPOSThttps://api.alfera.ai/v1/sessions
{
  "agent": "main",
  "title": "Nightly report",
  "initial_events": [
    { "type": "user.message",
      "content": [{ "type": "text", "text": "Summarize yesterday's payouts." }] }
  ]
}
Watch itGET/v1/sessions/ses_01k9m4rx7te2v8b0qz5cd3ny4f200 OK
{
  "data": {
    "status": "idle",
    "usage": { "input_tokens": 5000, "output_tokens": 3200,
               "cache_read_input_tokens": 29000,
               "cache_creation_input_tokens": 4100 },
    "last_activity_time": "2026-09-06T14:03:10Z"
  }
}
Take the filesGET/v1/sessions/ses_01k9m4rx7te2v8b0qz5cd3ny4f/files200 OK
{
  "data": [
    { "file_id": "file_01k9m4s2", "filename": "payouts.csv",
      "mime_type": "text/csv", "size_bytes": 4213 }
  ]
}

What comes back

user.message
A turn you sent, echoed back.
user.tool_confirmation
A decision you made, echoed back.
agent.message
What it said.
agent.thinking
That it thought. Never a word of it.
agent.tool_use
A tool it called, and what it called it with.
agent.tool_result
What came back, or that it failed.
session.status_running
A turn started.
session.status_idle
It stopped, and why. Read until this one.
session.status_terminated
Archived.
session.error
A named failure: out of credits, busy, or run_failed.
session.usage
Token totals, once before each stop.
  • The product scopes — sessions, agents, automations, skills, projects, usage, integrations, workspace — are refused on a key meant for your end users. A session or an automation acts through your workspace’s connections, and spend is yours to read, never theirs. A write scope also grants its read.
  • The event stream is what decides where a turn ends: a session.status_idle is the turn stopping. The status field on GET /v1/sessions/{id} can still read running for a few seconds after it.
  • Files appear under GET /v1/sessions/{id}/files when the agent writes them into files/, artifacts/, downloads/ or screenshots/ — say so in the message ("write it to files/report.csv") and the endpoint has it.
  • Every key-authed response carries X-RateLimit-Limit and X-RateLimit-Remaining, and a refused one carries Retry-After.
  • The same seven verbs are MCP tools on the same key, so an agent in your editor can open a session, wait for it, approve a call and read the files without a line of glue.
  • Additive-only within /v1: fields may appear, never change type or vanish; breaking changes are a new prefix. Clients must ignore unknown fields.

The same rules

Your setup carries over

The API is the same workspace, not a second product with its own settings. Every control you already set is on before the first call lands.

The same permissions

A key carries scopes. The workspace carries tool grants, and reading a tool is not the same grant as acting in it. A call has to clear both.

ToolReadAct
Customer inbox✓✓
HubSpot✓✓
Stripe✓—
Payroll——

403{ "code": "scope_missing" }

The same credit usage

Review workspace usage alongside the jobs your product starts.

Spend against cap

Support68%
Sales100%

{ "code": "out_of_credits" }

Your own model keys

Point the workspace at your Anthropic, OpenAI or Google key. The model bill goes to you.

Anthropicsk-ant-••••4f21yours
OpenAIsk-••••9c07yours
GoogleBilled through usours

Every run in one list

A run your product started sits beside one somebody started in Slack, in the same list.

09:14Asked about NorthwindAPI
09:22Asked about renewalsSlack
09:31Taught it a new priceAPI

Auth

API keys

Make a key in the app and you see the secret once. Give it only the scopes it needs. Revoke it and the next call fails.

The same key opens the MCP endpoint, so Claude or Cursor reaches the same coworker.

Renewals botak_live_x7f4••••••••••••
Scopesanswers.writememory.read
Sent asAuthorization: Bearer ak_live_x7f4…
Rate120 requests a minute429 rate_limited
RevokeAny time401 api_key_revoked

Add an AI Coworker to your product.

Make a key, send one call, and read what comes back.