Directory REST API
The Beam directory handles registration, discovery, relay, and operational visibility.
Base URL
https://api.beam.directoryCompatibility contract
The current directory family is beam/1.
- request and response additions must remain backward compatible inside
beam/1 - unknown top-level fields must be ignored rather than rejected
payloadis canonical for intent bodies; current SDKs still accept legacyparams- breaking request validation, signature input, or required-field changes require a new protocol family rather than a silent patch
For async handoffs, use the lifecycle terms consistently:
deliveredmeans the recipient accepted deliveryackedmeans the work reached terminal completion for that transport path
The recommended application payload for accepted-but-not-terminal async work is:
{
"accepted": true,
"acknowledgement": "accepted",
"terminal": false
}Organization namespace onboarding
Organization namespaces are claimed before an organization Beam ID can be issued:
POST /orgs
Content-Type: application/json
{
"name": "acme",
"displayName": "Acme GmbH",
"domain": "acme.com"
}domain is required. Beam canonicalizes it to the registrable domain and requires the namespace to match that domain label. For example, www.acme.com becomes acme.com and may claim acme; it cannot claim northwind. Brand names that do not match the legal domain need an administrator-reviewed override rather than automatic approval.
The 201 response is Cache-Control: no-store and returns the organization API key exactly once, together with verification.txtName, verification.txtValue, and claimExpiresAt. An unverified claim expires after 72 hours. Store the key outside source control, publish the TXT value, then call:
POST /orgs/acme/verify
x-api-key: beam_org_...Until verification succeeds, organization agent issuance and organization workspace creation return 403 ORG_VERIFICATION_REQUIRED. Organization claim, verification, and issuance endpoints share the public registration rate limit.
POST /register
In the current server implementation, agent registration is exposed as POST /agents/register.
Example request body:
{
"beamId": "assistant@demo.beam.directory",
"displayName": "Demo Assistant",
"capabilities": ["chat", "search"],
"publicKey": "<base64-ed25519-public-key>",
"org": "demo"
}Personal Beam IDs can be claimed without an organization credential. Organization IDs require a registered, DNS-verified organization and its API key:
x-api-key: beam_org_...organization-key...Registration is create-only. Reusing an existing Beam ID returns 409 BEAM_ID_ALREADY_REGISTERED; profile updates and key rotation use their authenticated endpoints instead.
Successful responses return the created agent record with trust and verification metadata. Registration responses also return an API key with the prefix bk_. Store it securely — it is only meant to be shown in plaintext at creation time. Successful registration responses are marked Cache-Control: no-store.
Detailed registration and lookup responses now also include keyState with:
activerevokedkeystotal
API key authentication
Agent-authenticated endpoints accept x-api-key: bk_... as a simpler alternative to Ed25519 request signing. The current SDK uses this header automatically when you construct BeamClient or BeamDirectory with an API key.
x-api-key: bk_...your-key...GET /agents
The current server exposes two listing styles:
GET /directory/agentsfor a full connected-status listingGET /agents/searchfor filtered discovery by org, capabilities, trust score, and limit
Typical search example:
GET /agents/search?org=demo&capabilities=chat,search&minTrustScore=0.5&limit=20Detailed lookup:
GET /agents/:beamIdGET /stats
Operational stats are currently exposed primarily through GET /health, with richer admin views for trust and recent intent activity.
Typical health response:
{
"status": "ok",
"protocol": "beam/1",
"connectedAgents": 12,
"timestamp": "2026-03-08T12:00:00.000Z",
"version": "1.4.0",
"gitSha": "abcdef1234567890abcdef1234567890abcdef12",
"deployedAt": "2026-04-01T19:00:00.000Z",
"release": {
"version": "1.4.0",
"gitSha": "abcdef1234567890abcdef1234567890abcdef12",
"gitShaShort": "abcdef1",
"deployedAt": "2026-04-01T19:00:00.000Z"
}
}If you publish a friendlier /stats endpoint in front of the directory, it should usually aggregate health, connection count, and relay metrics. The current built-in /stats endpoint now exposes the same release metadata, so health and stats can be compared for deploy-truth drift.
GET /release
For a small operator-facing release-truth check, the directory also exposes:
GET /releaseIt returns the current protocol family plus the live release metadata (version, gitSha, gitShaShort, deployedAt).
Admin auth
Admin and operator access is session-based.
POST /admin/auth/magic-linkPOST /admin/auth/verifyGET /admin/auth/sessionPOST /admin/auth/logout
Successful verification always sets an HttpOnly session cookie. The dashboard requests cookie-only transport and never stores the bearer token in browser storage. CLI and automation clients receive the short-lived bearer token by default; they can request cookie-only transport with {"sessionTransport":"cookie"}.
New magic-link secrets are stored only as SHA-256 hashes. Unused legacy plaintext rows remain consumable during the migration window and are deleted by the normal used/expired cleanup.
Workspace access and invitations
GET /admin/workspaces/:slug/access
GET /admin/workspaces/:slug/members
PATCH /admin/workspaces/:slug/members/:id
DELETE /admin/workspaces/:slug/members/:id
GET /admin/workspaces/:slug/invitations
POST /admin/workspaces/:slug/invitations
DELETE /admin/workspaces/:slug/invitations/:id
GET /admin/workspaces/invitations/:token
POST /admin/workspaces/invitations/:token/acceptMember and invitation administration requires the workspace owner role. Invitation preview is token-authenticated and deliberately redacted. Acceptance also requires an authenticated session for the exact invited email. Raw invitation secrets and token hashes are never returned by list endpoints.
Key lifecycle endpoints
GET /agents/:beamId/keys
POST /agents/:beamId/keys/rotate
POST /agents/:beamId/keys/revoke
GET /keys/revokedRotation accepts either:
x-api-key/ bearer API key auth- a signed key-management payload from the current active key
Revocation is intended for rotated-out historical keys. The active key must be replaced through rotation first.
Public Beam Shield policy
Operators can inspect and update public HTTP abuse controls with:
GET /shield/policies/public-endpoints
PATCH /shield/policies/public-endpointsThe policy covers registration, discovery, DID resolution, POST /intents/send, admin auth, and key mutation limits, plus trusted IP / trusted Beam ID overrides.
Hosted beta intake
Public hosted beta intake stays on the compatibility-safe POST /waitlist path.
Example request:
{
"email": "ops@northwind.systems",
"source": "hosted-beta-page",
"company": "Northwind Systems",
"agentCount": 6,
"workflowType": "hosted-beta-partner-handoff",
"workflowSummary": "Procurement asks partner operations for stock, then finance approves the async quote."
}Successful responses return:
status:registeredoralready_registeredrequest: the canonical hosted beta request recordnextStep: human-readable operator follow-up guidance
The canonical request payload now includes:
idemailsourcecompanyagentCountworkflowTypeworkflowSummaryrequestStatusstageowneroperatorNotesnextActionlastContactAtstalestaleReasonattentionFlagsnotificationIdnotificationStatuscreatedAtupdatedAt
Stable request statuses are:
newreviewingcontactedscheduledactiveclosed
Admin hosted beta workflow
Operators can work the hosted beta queue through:
GET /admin/beta-requests
GET /admin/beta-requests/:id
PATCH /admin/beta-requests/:id
GET /admin/beta-requests/export?format=json|csvList filtering currently supports:
qstatusownersourceworkflowTypeattention(unownedorstale)sort(attention,updated_desc,created_desc,stage,owner,last_contact_desc)limit
PATCH /admin/beta-requests/:id accepts:
{
"status": "reviewing",
"owner": "operator@beam.directory",
"operatorNotes": "Intro email sent, follow-up call pending.",
"nextAction": "Prepare a 30 minute buyer walkthrough.",
"lastContactAt": "2026-03-31T09:30:00.000Z",
"proofIntentNonce": "pilot-proof-123456"
}The response request record carries the same pipeline fields plus notification state and an optional proofIntentNonce, so operators can tell whether a request is still new, already acknowledged, or fully acted on.
GET /admin/beta-requests/:id also returns:
activity: the operator and follow-up timelineproofSummary: a buyer-friendly artifact generated from the linkedproofIntentNonce, including identity proof, delivery proof, operator visibility, and a recommended next step
Hosted beta export includes:
next_actionlast_contact_atnotification_statusstaleattention_flags
Operator notifications
Operator-visible intake and incident signals are exposed through:
GET /admin/operator-notifications
PATCH /admin/operator-notifications/:idGET /admin/operator-notifications supports:
qstatus(new,acknowledged,acted)source(beta_request,critical_alert)limithoursto control the critical-alert window that is synced before listing
Example patch:
{
"status": "acknowledged",
"owner": "ops@beam.directory",
"nextAction": "Open the latest failing trace, confirm the downstream condition, then update the runbook ticket."
}Notification payloads now include:
ownernextAction
Critical alerts from observability reuse the same notification path. The notificationStatus, notificationId, notificationOwner, and notificationNextAction fields also appear on critical alert payloads from GET /observability/overview and GET /observability/alerts.
First-party funnel analytics
The public Beam surfaces send privacy-conscious, first-party funnel events through:
POST /analytics/events
GET /admin/funnel?days=30Accepted public event categories are:
page_viewcta_clickrequestdemo_milestone
Example ingest payload:
{
"sessionId": "9f0f6f4f0f2f4c2da55f2f2d9f9b1e44",
"pageKey": "landing",
"eventCategory": "cta_click",
"ctaKey": "landing_guided_eval_hero",
"targetPage": "guided_evaluation"
}Request events use the same path, but require a compatible workflowType. Demo milestones require a compatible milestoneKey.
GET /admin/funnel returns:
- milestone progression across landing, guided evaluation, hosted beta, request, and demo proof
- partner motion metrics across hosted beta request, qualified, scheduled, pilot-complete, and next-step readiness
- stage aging, overdue follow-up counts, and a current stall list for weekly operator review
- entry pages
- CTA click summaries
- request workflow breakdown
- recent anonymous events for instrumentation validation
All hosted beta admin endpoints require an authenticated admin session and accept either:
Authorization: Bearer <admin-session-token>- the dashboard admin session cookie
DELETE /admin/waitlist
Clears waitlist and hosted beta intake entries from the legacy admin surface.
- Requires an authenticated admin session.
- Accepts
Authorization: Bearer <admin-session-token>for API clients or the dashboard session cookie. - Returns
{ deleted: <count> }on success.
WebSocket /ws
The real-time transport endpoint is /ws.
Agent sockets require the registered Beam-ID and a short-lived, single-use WebSocket ticket. Obtain the ticket with POST /agents/:beamId/ws-ticket and the agent API key. The API key therefore stays in the authenticated HTTPS request instead of appearing in a WebSocket URL. Transport authentication and per-frame Ed25519 signatures serve different purposes; both remain required.
wss://api.beam.directory/ws?beamId=assistant@demo.beam.directory&ticket=bwt_...single-use...Non-browser clients may authenticate the WebSocket upgrade itself with Authorization: Bearer <api-key> or X-API-Key, but tickets are the portable default. Query-string API keys are disabled unless the explicit temporary migration flag BEAM_ALLOW_LEGACY_WS_API_KEY_QUERY=true is set. Result Frames must be signed by the connected recipient's Ed25519 identity. The feed=intents operator feed requires an authenticated directory admin session and is not a public status feed.
Common message types:
connectedwhen the socket is acceptedintentwhen a remote agent sends a requestresultwhen a recipient replieserrorwhen validation or delivery fails