Skip to Content
API

API

The Bee developer API serves your Bee data over HTTP under /v1/*. There are three ways to reach it:

  1. Public endpoint (default, recommended for experiments): https://api.developer.bee.amazon.dev, with a standard public TLS certificate.
  2. Local proxy: bee proxy serves the API on 127.0.0.1 and handles authentication for you.
  3. Raw TLS (advanced): TLS with attestation, straight to the API host. You verify Bee’s own certificate yourself.

Public endpoint (default)

This is the production Bee API, serving your real data.

This is the recommended way to experiment with the API. https://api.developer.bee.amazon.dev uses a certificate from a public CA, so any HTTP client works with its standard system trust store. Authenticate with a Bearer token:

curl -H "Authorization: Bearer $BEE_TOKEN" \ "https://api.developer.bee.amazon.dev/v1/me"

TLS for this endpoint ends at Bee’s public TLS front end, which forwards your requests to the API. To have TLS end at the API itself, with attestation, use raw TLS.

Local proxy

The bee proxy command starts a local HTTP API proxy server, allowing you to access your Bee data through standard HTTP requests. This is useful for building local applications, testing integrations, or accessing Bee data from tools that don’t support the Bee protocol directly.

The proxy server is intended for local development only. Do not expose it to the public internet as it provides unauthenticated access to your Bee data.

You must authenticate first with bee login, then start bee proxy.

Usage

# TCP listener (defaults to port 8787, auto-picking the next free port if taken) bee proxy bee proxy --port 8787

This starts a local HTTP server bound to 127.0.0.1, by default on port 8787. If 8787 is in use, the proxy auto-picks the next free port (unless you pin one with --port). Only paths under /v1/* are forwarded; any other path returns 404.

Options

FlagDescription
--port NListen on TCP port N on 127.0.0.1. Defaults to 8787 (auto-incrementing to the next free port when omitted). Cannot be combined with --socket.
--socket [path]Listen on a Unix domain socket instead of TCP. Defaults to ~/.bee/proxy.sock when no path is given. Stale socket files are removed before listening. Cannot be combined with --port.
--idle-timeout SECONDSServer idle request timeout. Defaults to 120. Increase it for large exports, or pass 0 to disable the idle timeout entirely.
# Unix socket listener (default path: ~/.bee/proxy.sock) bee proxy --socket bee proxy --socket /tmp/bee-proxy.sock # Raise the idle timeout for long-running exports (or 0 to disable) bee proxy --idle-timeout 300 bee proxy --idle-timeout 0

Proxy Authentication

When another trusted local process already handles Bee API authentication, point this CLI at it with bee login --proxy so requests are forwarded through that proxy instead of using a stored token directly:

# HTTP proxy bee login --proxy http://127.0.0.1:8787 # Unix socket proxy bee login --proxy ~/.bee/proxy.sock

This saves the proxy configuration to ~/.bee/proxy-{env}.json. When a proxy config exists, it takes precedence over stored token auth. Run bee logout to clear it before switching back to direct token auth.

Raw TLS (advanced)

This is also the production Bee API.

Raw TLS is TLS with attestation, for advanced use. Connect straight to https://app-api-developer.ce.bee.amazon.dev, the host the Bee CLI uses, so TLS ends at the API itself. Use the same /v1/* endpoints and authenticate with a Bearer token.

curl --cacert ./bee-ca.pem \ -H "Authorization: Bearer $BEE_TOKEN" \ "https://app-api-developer.ce.bee.amazon.dev/v1/me"

You must verify Bee’s certificate yourself. This host uses Bee’s private CA (not a public CA), so standard system trust stores alone are not enough: configure your client to trust Bee’s root CA, as --cacert does above.

Certificate source used by Bee CLI (PROD_ROOT_CA):

API Reference

These paths work the same with all three options: prefix them with the public endpoint, the raw TLS host, or your local proxy address. The proxy forwards any /v1/* path straight through to the Bee API. The list below is a representative subset, not an exhaustive catalog — additional developer endpoints (for example insights, locations, photos, todoSuggestions, conversations/:id/related, search/conversations, journals, and todayBrief) are forwarded the same way.

User

# Get user profile GET /v1/me

Changes

# Get changed entity ids since cursor (or default window when cursor is omitted) GET /v1/changes

Facts

# List all facts GET /v1/facts # Get a specific fact GET /v1/facts/:id # Create a new fact POST /v1/facts Content-Type: application/json {"text": "Your fact here"} # Update a fact PUT /v1/facts/:id Content-Type: application/json {"text": "Updated fact", "confirmed": true} # Delete a fact DELETE /v1/facts/:id

Todos

# List all todos GET /v1/todos # Get a specific todo GET /v1/todos/:id # Create a new todo POST /v1/todos Content-Type: application/json {"text": "New todo", "alarm_at": "2026-02-11T09:00:00Z"} # Update a todo PUT /v1/todos/:id Content-Type: application/json {"text": "Updated todo", "completed": true, "alarm_at": null} # Delete a todo DELETE /v1/todos/:id

alarm_at is provided as an ISO 8601 timestamp on input (e.g. "2026-02-11T09:00:00Z"), but is returned as epoch milliseconds in responses.

Journals

# List journals GET /v1/journals # Get a specific journal GET /v1/journals/:id

Conversations

# List conversations GET /v1/conversations # Get a specific conversation GET /v1/conversations/:id

Daily Summaries

# List daily summaries GET /v1/daily # Get a specific daily summary GET /v1/daily/:id
# BM25 keyword search POST /v1/search/conversations Content-Type: application/json {"query": "project roadmap", "limit": 20, "cursor": null} # Neural search POST /v1/search/conversations/neural Content-Type: application/json {"query": "project roadmap", "limit": 20}

Streaming

# SSE stream (optional: ?types=new-utterance,todo-created) GET /v1/stream # Common event types: # new-conversation, update-conversation, update-conversation-summary, delete-conversation # new-utterance, todo-created, todo-updated, todo-deleted # journal-created, journal-updated, journal-deleted, journal-text

Threads

Preview: test users only. Every /v1/threads endpoint answers 403 {"error": "test_user_required"} for other accounts, and the API may still change.

Threads are your chats with the Bee agent, the same ones you see in the app. Send a message, then wait until the agent finishes all its work on the thread, not just the next message. That wait also covers work started elsewhere, such as a message sent from the app. The bee threads commands wrap these endpoints.

# List threads, most recently active first (no paging) GET /v1/threads # Start a new thread with a first message POST /v1/threads Content-Type: application/json {"text": "Plan my trip", "file_ids": [], "wait_ms": 30000, "client_message_id": "trip-1"} # Send a message to a thread (same body) POST /v1/threads/:id/messages # Wait for the agent again, after a message of the thread GET /v1/threads/:id/wait?after=:message_id&wait_ms=30000 # Get all messages, oldest first (no paging) GET /v1/threads/:id/messages # Stop the agent's work on the thread POST /v1/threads/:id/abort # Upload an attachment for file_ids (multipart/form-data) POST /v1/threads/attachments

Send body

FieldDescription
textMessage text, up to 100,000 characters.
file_idsUp to 20 distinct ids from POST /v1/threads/attachments. Each must be your own upload that isn’t attached to a message yet.
wait_msHow long to wait for the agent, 0 to 120000. Defaults to 30000. Also a query parameter of /wait.
client_message_idOptional idempotency key, 1 to 128 characters from A-Z a-z 0-9 . _ : -. Retrying with the same key doesn’t send the message again.

A message needs non-blank text, at least one file id, or both. POST /v1/threads always picks the thread id. With a client_message_id the id is derived from that key, so a retried create lands on the same thread and message. Without a key, every create starts a new thread.

Send and wait responses

# 200: the agent finished {"status": "completed", "thread_id": "…", "message_id": "…", "text": "…", "messages": […]} # 202: the agent is still working ("pending") or has gone quiet ("stalled") {"status": "pending", "thread_id": "…", "message_id": "…"}
  • message_id is your message. Pass it as after to wait again.
  • messages holds the agent’s messages written after after, oldest first.
  • text is the last text part of the final agent message, which is the answer.
  • pending means wait_ms ran out. stalled means the thread is still marked running, but the agent has sent no update in the 5 minutes since the latest send, or in the last 30 minutes. Both can still finish, so you can keep waiting.

Other responses: the list returns {"threads": [{"thread_id", "name", "state", "created_at", "updated_at"}]} with state set to idle or running and times in epoch milliseconds. GET …/messages returns {"thread_id", "messages": […]}, and abort returns {"thread_id", "state": "idle"}.

Resume a send

BASE=http://127.0.0.1:8787 # bee proxy # Send without blocking. If this request fails, retry it with the same client_message_id. curl -s -X POST "$BASE/v1/threads" \ -H 'Content-Type: application/json' \ -d '{"text": "Summarize my week", "wait_ms": 0, "client_message_id": "week-summary-1"}' # 202 {"status":"pending","thread_id":"T","message_id":"M"} # Wait for the answer. Repeat while the status is "pending". curl -s "$BASE/v1/threads/T/wait?after=M&wait_ms=60000" # 200 {"status":"completed","thread_id":"T","message_id":"M","text":"…","messages":[…]}

A wait holds the request open. Through bee proxy, keep wait_ms below --idle-timeout (120 seconds by default), or raise that limit.

Attachments

# Optional fields (width, height, kind, filename, content_type) must come before the file part curl -s -X POST "$BASE/v1/threads/attachments" \ -F width=640 -F height=480 \ -F file=@photo.jpg # {"file_id":"F","kind":"image","filename":"photo.jpg","content_type":"image/jpeg","size_bytes":48213,"width":640,"height":480}

Files can be up to 25 MB. kind (image, audio or file) comes from the content type unless you set the kind field. width and height are only read when they come before the file part. Pass the file_id in file_ids. Each upload can be attached to one message.

Errors

StatuserrorWhen
400text_or_files_requiredBlank text and no file_ids.
400invalid_file_idsA file id is duplicated, unknown, not yours, or already attached.
400message_not_in_threadafter isn’t a message of this thread.
400No file uploaded, File too large (max 26214400 bytes), Uploaded file is emptyUpload problems.
403test_user_requiredThe account isn’t a test user.
403agent_vm_consent_requiredUpload only: you haven’t granted the agent consent.
404thread_not_foundThe thread doesn’t exist or belongs to someone else.
503agent_unavailableThe agent can’t be reached (send, abort). Nothing was sent.

Requests that fail schema validation, for example a wait_ms above 120000, also return 400.

Last updated on