Documentation

The HTTP API

Give a hire a task over plain HTTP, for callers that do not speak MCP: a cron job, a webhook from another system, a shell script. Authenticate with a workspace API key. The response is 202 rather than 200, because a turn is durable and may wait days for an approval.

Last updated 2026-09-04.

Authentication

Every request carries a workspace API key as a bearer token. Create one in the console; the secret is shown once and is never stored in a form we can read back, so if you lose it, issue another and revoke the old one.

A key belongs to a workspace and can be pinned to a single employee. A pinned key that tries to address a different employee is refused, and no key ever reaches another workspace.

bash
Authorization: Bearer emp_<workspace>_<secret>

Giving it a task

One POST with the employee id and what you want done, in plain language. Omit the chat id to start a new thread, or pass one to continue an existing conversation, which is what you want when a system is reporting repeatedly about the same thing.

bash
curl -X POST https://employees.sanafai.com/api/v1/messages \
  -H "Authorization: Bearer $SANAF_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "employeeId": "…", "text": "Chase the three invoices that went past due today." }'

Why the answer is 202

A turn is durable. It can run for minutes, and it can pause for its manager approval for days. There is no honest way to return the finished reply on the same request, so the API does not pretend to.

You get back the chat id and the run id immediately. Read the reply with the MCP get_reply tool, or let the hire post the result where it normally would: the thread in Slack or Microsoft Teams, or the console.

json
{
  "employeeId": "…",
  "chatId": "…",
  "runId": "…",
  "status": "working"
}

Errors

A missing or invalid key is 401. A key that is pinned to one employee addressing another is 403. An employee id that does not exist in your workspace is 404, including a malformed id, because from the caller side those are the same thing. A body that is not JSON, or a request with no text, is 400 with a message that says which.

Endpoint reference

POST/api/v1/messages

Give an AI employee a task or a question, and start a durable turn.

  • Body: employeeId (optional when the key is pinned to one employee), text, and an optional chatId to continue a thread.
  • Answers 202 with employeeId, chatId, runId and status. It does not wait for the work to finish.
  • Read the reply with the MCP get_reply tool, or let the hire post it where it normally would.
Questions

Frequently asked

How do I read the reply?
Use the MCP get_reply tool, which returns every message in the chat, or let the hire post the result in the thread where it normally works. The HTTP endpoint starts work; it does not wait for it.
Can one key address every employee in my workspace?
A workspace key can, and a key pinned to a single employee cannot address any other. No key ever reaches another workspace.
What can I trigger this from?
Anything that can make an HTTP request: a cron job, a webhook from another system, a form handler, a shell script. That is the reason it exists alongside MCP.