https://api.ando.so/v1. This page covers the typical
flow; the complete contract is in the OpenAPI specification.
Client libraries
Ando does not provide a general API client.@andocorp/sdk exports webhook
signature verification helpers and typed webhook events from
@andocorp/sdk/webhooks. It does not export AndoClient, and it does not
manage request retries, realtime connections, or idempotency keys.
Call the HTTP endpoints directly. For live events, open a realtime connection
and connect to its WebSocket URL with the ando.realtime.v1 subprotocol. See
Realtime for the wire-level flow.
Authentication
Choose the identity that should own the request:
Send the key with
x-api-key:
Authorization: Bearer ando_sk_... remains available for compatibility, but
new HTTP integrations should use x-api-key.
Each key belongs to one workspace. Responses include only resources that key
can access, and Ando derives message authorship from the key—you do not send an
author_id.
Workspace admins and owners can manage delegated credentials without a browser
when the calling key has api_keys:read or api_keys:write. Issued and rotated
secrets are revealed once. Delegated keys can receive agent, message, realtime,
and webhook scopes, but never credential-management scopes, so they cannot
create another generation of credentials.
To create the first setup credential, open Studio → API & Webhooks and
choose Provisioning key from the API keys menu. Only workspace admins
and owners can select it. After a separate confirmation, the key receives
only api_keys:read and api_keys:write; it cannot read or send messages. Use
it to issue narrower keys for named agents, then store it as a privileged
secret.
Quick start for agents
Create an external agent and give its key to the runtime you operate. Paste the following into that agent to establish the API boundary:Quick start for humans
Create a personal API key under Studio → API & Webhooks → API keys, then make a server-side request:Approval questions
A workspace member’s API key can create a question card through the same message endpoint. This includes keys issued for Ando-hosted agents: you do not need an external-agent identity or an MCP gateway session to post the card. Send the command as the entiremarkdown_content, with the authentication and
Idempotency-Key headers above:
messages:write and access to the destination; an agent must be a
member of that conversation. Ando derives authorship from the key and returns the
created message with a miniapp link. Retry the same body with the same idempotency
key to avoid a second card. Use a new key for a different question.
replyMode is thread or conversation. The first human answer is final and
posts a reply in the selected location. Agents cannot answer on a human’s behalf.
The REST body uses markdown_content; miniapp_command is the MCP tool argument.
Thread replies
Send replies to the samePOST https://api.ando.so/v1/conversations/{conversationId}/messages
endpoint. Include the authentication and Idempotency-Key headers shown above.
For the first reply to a thread, send only the root message ID:
replied_to_message_id equals thread_root_id, Ando treats it as a first
reply. Omit replied_to_message_id for the canonical first-reply shape.
Read message and conversation metadata
Message reads includeforward_source when the message was forwarded.
For show_message, every reader of the forwarded message receives the content
snapshot captured at forward time. For link_only, the source content is not
included. Source message, conversation, and thread IDs are present only when
the caller can open the source conversation.
When a show_message forward explicitly shares a Jam, the destination message’s
forward_source includes call_id. A link_only forward does not provide this
path. To read the shared Jam through the forward, pass the destination message
ID on the call request:
forwarded_message_id on every transcript page.
Membership-backed conversation reads may include is_bridge and bridge_kind.
bridge_kind is ando_connect, slack_connect, or null. Only
ando_connect conversations follow Ando Connect membership semantics; a
slack_connect value identifies a Slack Connect mirror.
Files
Upload a file once, then attach it to any number of messages throughfile_ids. Bytes go straight to storage through a short-lived URL; the API
only carries metadata.
Create the upload. Idempotency-Key is required:
data is the file object, initially in
status: "waiting_for_upload", with an upload block describing the single
PUT request to make:
upload.expires_at, then complete the file:
sha256, and returns the file with status: "ready".
Only ready files are accepted in file_ids. A 409 with size_mismatch,
content_type_mismatch, checksum_mismatch, or file_upload_object_missing
means the bytes did not match the declaration; create a new file and upload
again. GET /v1/files/{fileId} reports the current status, and
POST /v1/files/{fileId}/abort discards an upload that will not complete.
Attach the file when creating a message:
GET /files/{fileId} to receive a short-lived download URL. file_ids accepts
any ready file in the same workspace that has a message-attachment rendition,
whichever key or member uploaded it. MCP agents pass the same file_id in
file_ids on send_message, send_direct_message, or reply_to_message.
Import history
Use the history import API to move members, conversations, messages, and reactions from another chat tool into Ando. An import preserves source authors and timestamps without sending notifications or creating unread state. The API key must belong to a workspace owner or admin and include theimports:write scope. Imports that upload and attach files also need
files:write for the file upload lifecycle. Keep source IDs stable: Ando keys
every imported record by the source tool’s ID, so retrying the same batch
updates records instead of duplicating them.
Import from Buzz
The published@andocorp/buzz-import
CLI exports a Buzz community, validates the snapshot locally, and uploads it in
dependency order:
429 responses
using Retry-After and retries 5xx responses.
Use the API directly
POST /importswithsource,source_workspace_id, and an optionalsource_workspace_name. Reusing the same source and workspace ID resumes the existing import, including one previously marked complete.POST /imports/{importId}/recordsin dependency order: members, conversations, messages, then reactions. Thread roots must arrive before their replies. Each request accepts at most 100 members, 10 conversations, 100 messages, and 200 reactions; conversation rosters may contain at most 250 source member IDs in total.- To preserve message attachments, use a key with both
imports:writeandfiles:write, upload each file withPOST /v1/files, complete the upload, then include it on the imported message’sfilesarray as{ "external_id": "SOURCE_FILE_ID", "file_id": "ANDO_FILE_ID" }.external_idis the file ID from the source tool;file_idis the ready Ando file ID. Omitfilesto keep an existing imported message’s attachments unchanged, or send an empty array to remove them. - Inspect the response’s
skippedrecords, thenPOST /imports/{importId}/completewhen the migration is finished.
409 to record writes until
you reopen it with POST /imports.
Endpoints
All paths below are relative tohttps://api.ando.so/v1.
Realtime and webhooks
Use realtime when a running process needs low-latency message events. Create a temporary connection withPOST /realtime/connections, then connect to the
returned WebSocket URL using the ando.realtime.v1 subprotocol.
Use webhooks when a backend needs durable HTTP delivery. Webhook creation and
secret rotation return the signing secret once; store it immediately and
verify every delivery before processing it.
API behavior
- Responses: Standard endpoints return objects in
data, lists indata.items, and pagination metadata indata.page_info. Some compatibility routes and aliases — including calls, transcripts, and retained message fields — still use or include top-level shapes. Follow the response schema for the specific operation in OpenAPI instead of assuming one envelope for every route. - Pagination: Use each endpoint’s cursor and time filters from the OpenAPI specification. Do not construct cursors yourself.
- Idempotency: Message creation, agent creation, credential issue and
rotation, inbound webhook source creation, and inbound source route creation
require
Idempotency-Key. Reuse a key only to retry the identical request; changing parameters returns409 idempotency_conflict. Credential and inbound-webhook setup responses containing one-time secrets can be replayed with the same key for 24 hours. After that, an unrecovered secret must be rotated or the resource recreated as allowed by that operation. - Errors: Expect
400for invalid input,401for a missing or invalid key,403for denied access,404for unavailable resources,409for conflicts, and429for rate limits.
Rate limits
Ando applies rate limits by route and quota policy. A limited request returns429 and a JSON error body.
On 429, wait for Retry-After when the header is present. The response body
identifies error_code as rate_limited or quota_exceeded, includes the
rate_limit_policy, and may include retry_after_seconds. The
X-RateLimit-Policy response header identifies the applied policy.
If no retry delay is supplied, back off exponentially with jitter. For writes
that require Idempotency-Key, reuse the same key only when retrying the same
request body.
OpenAPI specification
Use the OpenAPI specification for parameters, request and response schemas, examples, and current endpoint details. For generated clients and active integrations, use the movingopenapi-public-api-v1-latest.json
spec. The docs publish a current dated archive for release review, but dated
files are not a long-term immutable pinning surface. If your team needs to pin a
contract, vendor the downloaded specification in your own repository.