# B3OS beta > Browsers, render, sandboxes, routines, actions and inference on the node that serves the model. Agents in a sandbox there, on that model, keep the loop on one machine. ## Pages - [Actions and triggers](https://docs.beta.b3os.org/actions): An open marketplace of signed packs whose actions any agent can search, describe and call, with credentials injected at the egress proxy instead of passed in. - [Call actions](https://docs.beta.b3os.org/actions/call): Find a marketplace action by describing what it should do, read its schemas, and call it with a stored connection, from code, a routine or an agent. - [Actions limits and FAQ](https://docs.beta.b3os.org/actions/limits): Rate and size limits for action calls in the beta, and answers to common questions about credentials, retries, effect classes and pack safety. - [Packs](https://docs.beta.b3os.org/actions/packs): What a B3OS pack contains, how a declarative HTTP action is written with CEL templates, and how packs are hashed, signed, published and verified. - [Pack triggers](https://docs.beta.b3os.org/actions/triggers): The webhook, poll and schedule triggers packs provide, how a routine subscribes to one, and how B3OS verifies, deduplicates and delivers their events. - [API reference](https://docs.beta.b3os.org/api/overview): Base URLs, authentication, conventions and error formats of the B3OS beta API, and how this reference is generated from the OpenAPI document. - [Benchmarks](https://docs.beta.b3os.org/benchmarks): How B3OS measures latency, the targets each product is held to, the dev baselines behind them, and what will be published as results. - [Changelog](https://docs.beta.b3os.org/changelog): Changes to the B3OS beta API, products and docs, newest first. Breaking changes are announced here 14 days before they ship. - [Firecrawl compatibility](https://docs.beta.b3os.org/compat/firecrawl): Point a Firecrawl SDK, the Firecrawl MCP server or LangChain's loader at B3OS by changing the base URL and key; which endpoints work and which do not. - [OpenAI compatibility](https://docs.beta.b3os.org/compat/openai): Use the OpenAI SDKs with the models served on the B3OS node by changing the base URL; supported endpoints, extensions and differences. - [Keys, scopes and principals](https://docs.beta.b3os.org/concepts/auth): How B3OS authenticates requests, what each scope allows, and how sandboxes, routines and streams get their own narrower identities. - [Beta contract](https://docs.beta.b3os.org/concepts/beta): What B3OS beta promises and what it does not, from availability and durability to data retention, isolation and how changes are announced. - [Glossary](https://docs.beta.b3os.org/concepts/glossary): The terms these docs use for B3OS objects, identities and measurements, with the two kinds of action always told apart. - [IDs and object shapes](https://docs.beta.b3os.org/concepts/ids): How B3OS IDs are built, which prefix belongs to which object, and the fields every object, list and credential shares. - [Jobs, streams and webhooks](https://docs.beta.b3os.org/concepts/jobs): The one contract every long-running B3OS operation follows, how to wait, stream or get a webhook, and how to retry writes safely. - [Same-host latency](https://docs.beta.b3os.org/concepts/latency): Why B3OS runs tools on the node that serves its model, which setups keep the loop on one machine, and which numbers are dev baselines or targets. - [Limits](https://docs.beta.b3os.org/concepts/limits): The beta's default limits per organization, how to read your current usage against them, and what the API returns when you hit one. - [The stack](https://docs.beta.b3os.org/concepts/stack): How B3OS sits on B3IQ, which hosts serve what, and the paths a request takes from your agent to the node and back. - [Timing and measurement](https://docs.beta.b3os.org/concepts/timing): How every B3OS response reports where its time went, how to read the request log, and the rules B3OS follows before it publishes a number. - [Usage and metering](https://docs.beta.b3os.org/concepts/usage): What B3OS meters, which unit each operation bills, and how to read your usage as totals or as the individual records behind them. - [Errors](https://docs.beta.b3os.org/errors): All 151 B3OS error codes with HTTP status, meaning, retry advice and the Firecrawl mapping, generated from errors.yaml. - [Infer](https://docs.beta.b3os.org/infer): OpenAI-compatible chat completions and speech from models served on the B3OS node, so an agent in a sandbox reaches its model without leaving the machine. - [Chat completions](https://docs.beta.b3os.org/infer/chat): Call the node's model with the OpenAI Chat Completions API, including tool calls, JSON Schema output, streaming and opting into the B3IQ gateway. - [Infer limits and FAQ](https://docs.beta.b3os.org/infer/limits): Per-model token and request limits, request sizes and stream lengths for inference in the beta, and answers to common questions about the node's models. - [Speech](https://docs.beta.b3os.org/infer/speech): Synthesize speech with the node's text-to-speech model through the OpenAI speech API, and get the start and end of every word for captions. - [Introduction](https://docs.beta.b3os.org/introduction): B3OS beta runs browsers, sandboxes and other agent tools on the node that serves its model. Agents in a sandbox there keep the whole loop on one machine. - [Platform](https://docs.beta.b3os.org/platform): The account side of B3OS beta, covering organizations, projects, keys, CLI login, usage, limits, webhook secrets and the per-request log. - [API keys](https://docs.beta.b3os.org/platform/keys): Create API keys with only the scopes an agent needs, a spend cap and an expiry; rotate them, revoke them, and check what a key can do. - [Platform limits and FAQ](https://docs.beta.b3os.org/platform/limits): Limits for keys, projects, CLI tokens, webhook secrets and the request log in the beta, and answers to common questions about the account side. - [Request log](https://docs.beta.b3os.org/platform/requests): Look up any request by its ID to see where its time went, or list recent requests by product, status, key, connection or sandbox, for 7 days. - [Webhooks](https://docs.beta.b3os.org/platform/webhooks): Get the signing secret for a webhook URL, send a test delivery, read the delivery history, and rotate secrets without dropping events. - [Quickstart](https://docs.beta.b3os.org/quickstart): Get a B3OS beta key, then scrape a page with curl, connect the MCP server, or run an agent in a sandbox next to the model. - [Install the MCP server](https://docs.beta.b3os.org/quickstart/mcp): Connect Claude, Cursor or Codex to the B3OS MCP server so your agent can scrape, run sandboxes and call marketplace actions. - [Run an agent in a sandbox next to the model](https://docs.beta.b3os.org/quickstart/sandbox-agent): Start a sandbox on the node, give it a scoped grant, and run a small tool-calling agent whose calls to the model and to B3OS never leave the machine. - [Scrape a page with curl](https://docs.beta.b3os.org/quickstart/scrape): Turn a URL into clean Markdown with one request to B3OS vision, then read the Server-Timing header to see where the time went. - [Render](https://docs.beta.b3os.org/render): Styled screenshots and scripted product videos rendered on the node, with narration, word-timed captions and restyling, served from signed URLs. - [Render limits and FAQ](https://docs.beta.b3os.org/render/limits): Concurrency and size limits for screenshots and videos in the beta, retention of artifacts, and answers to common questions about render. - [Screenshots](https://docs.beta.b3os.org/render/screenshots): Capture a page, the full page or one element from a warm browser and compose it with a background and window frame, as JSON with signed URLs or as image bytes. - [Videos](https://docs.beta.b3os.org/render/videos): Record a scripted, narrated product demo as MP4, GIF, poster and captions, follow it as a job, and restyle it later without recording again. - [Routines](https://docs.beta.b3os.org/routines): Durable workflows written like GitHub Actions with CEL expressions, started by API, cron, webhooks or pack triggers, next to the tools they call. - [Routine definitions](https://docs.beta.b3os.org/routines/definitions): Every field of a routine definition, how steps are ordered and connected, the CEL expressions between them, and how B3OS differs from GitHub Actions. - [Routine limits and FAQ](https://docs.beta.b3os.org/routines/limits): Step quotas, definition sizes and retention for routines in the beta, and answers to common questions about durability, retries and triggers. - [Runs](https://docs.beta.b3os.org/routines/runs): Start a routine run, wait for it or follow its steps live, send signals to waiting steps, cancel it, and read its steps and history. - [Triggers](https://docs.beta.b3os.org/routines/triggers): Start routine runs on a cron schedule, at an interval, from signed webhooks, or from pack triggers such as a new GitHub issue or a paid Stripe invoice. - [Sandboxes](https://docs.beta.b3os.org/sandboxes): Firecracker microVMs claimed from warm pools on the B3OS node, with commands, files, a terminal, ports, snapshots and a scoped API grant. - [Agents in sandboxes](https://docs.beta.b3os.org/sandboxes/agents): Run an agent inside a sandbox with a scoped grant to B3OS, call the model and tools without a key, inject vault credentials and start nested sandboxes safely. - [Commands, code and files](https://docs.beta.b3os.org/sandboxes/commands): Run commands in a sandbox buffered, streamed or in the background, run code in a Jupyter kernel, move files in and out, and open a terminal. - [Sandbox limits and FAQ](https://docs.beta.b3os.org/sandboxes/limits): Concurrency, size and lifetime limits for sandboxes in the beta, per-request caps for commands and files, retention, and common questions. - [Ports and previews](https://docs.beta.b3os.org/sandboxes/ports): Reach a web server running in a sandbox through a signed preview URL on usercontent.b3os.org, private by default or public, with base-path handling. - [Snapshots and pausing](https://docs.beta.b3os.org/sandboxes/snapshots): Pause and resume a sandbox in place, save its memory and disk as a snapshot, and start new sandboxes from the snapshot with fresh identities. - [SDKs and tools](https://docs.beta.b3os.org/sdks): One key, one SDK, one CLI and one MCP server for every B3OS product, with method names generated from the OpenAPI document. - [CLI](https://docs.beta.b3os.org/sdks/cli): The b3os command line for signing in, scraping, screenshots, sandboxes, routines, actions and the MCP server, built for scripts and agents too. - [MCP server](https://docs.beta.b3os.org/sdks/mcp): Connect any MCP client to B3OS through the local stdio server or the remote endpoint, which tools each one lists, and how agents reach marketplace actions. - [Python SDK](https://docs.beta.b3os.org/sdks/python): Install the b3os package and call every B3OS product from Python with a typed sync or async client, with jobs, streams, typed errors and timing. - [TypeScript SDK](https://docs.beta.b3os.org/sdks/typescript): Install @b3os/sdk, call every B3OS product from Node, Bun or Workers, wait on jobs, stream events, handle typed errors and read timing. - [Vault](https://docs.beta.b3os.org/vault): Store credentials as encrypted connections that B3OS injects into outbound requests at the egress proxy, so agents use them without ever seeing them. - [Vault limits and FAQ](https://docs.beta.b3os.org/vault/limits): Size limits for vault connections and secrets in the beta, and answers to common questions about how credentials are stored, injected and rotated. - [Vision](https://docs.beta.b3os.org/vision): Turn web pages into Markdown, map and crawl sites, and drive dedicated browsers over CDP, from browser pools that are already running on the node. - [Map, batch and crawl](https://docs.beta.b3os.org/vision/crawl): List a site's URLs, scrape up to 1,000 known URLs, or crawl a site by following its links, as jobs you can wait on, stream or get a webhook for. - [Vision limits and FAQ](https://docs.beta.b3os.org/vision/limits): Rate, concurrency and size limits for scrapes, crawls and browser sessions in the beta, and answers to common questions about vision. - [Profiles](https://docs.beta.b3os.org/vision/profiles): Save browser cookies and storage as an encrypted profile, load it into scrapes, sessions and screenshots, and keep it current without losing newer logins. - [Scrape a page](https://docs.beta.b3os.org/vision/scrape): Fetch one URL as Markdown, HTML, text, links, metadata or a screenshot, with main-content extraction, browser actions, profiles and caching. - [Browser sessions](https://docs.beta.b3os.org/vision/sessions): Claim a dedicated browser for your agent, drive it with batched browser actions in one round trip, or connect Playwright and Puppeteer over CDP. - [Scrape a page](https://docs.beta.b3os.org/api/post-v1-vision-scrape): Fetches one URL and returns the formats you ask for. With `engine: "auto"` (the default) vision answers from the cache when a fresh copy exists (`max_age_ms`, default 2 days), otherwise fetches over HTTP and switches to a warm browser only when the page needs JavaScript. Custom `headers`, a `profile` or `actions` bypass the cache; a page that sets cookies (by a response or a script) is cached for your organization only. The response's `cache.state` and `tier` say what served it. Synchronous: the response arrives when the page is done, within `timeout_ms` (at most 60 seconds). For many pages use a batch scrape or a crawl. - [Map a site's URLs](https://docs.beta.b3os.org/api/post-v1-vision-map): Lists URLs on a site from its sitemaps and from links on the start page, without scraping each page. Use it to choose what to scrape or crawl. `search` orders the results by relevance to a phrase. Bills one `vision.page` per call. - [Read a URL as Markdown](https://docs.beta.b3os.org/api/get-v1-vision-r-url-): The shortest way to read a page: put the target URL after `/v1/vision/r/`, unencoded, for example `GET /v1/vision/r/https://example.com/pricing`. Returns `text/markdown` by default. Options go in `X-B3OS-*` headers so the target URL stays untouched. Same tiers, cache and billing as `scrape`. - [List batch scrapes](https://docs.beta.b3os.org/api/get-v1-vision-batches): Lists batch scrapes in this project, newest first. Records are kept for 7 days after they finish. - [Scrape a list of URLs](https://docs.beta.b3os.org/api/post-v1-vision-batches): Starts a job that scrapes up to 1,000 URLs with the same options. Each page bills one `vision.page`. Results are listed with `GET /v1/vision/batches/{batch_id}/pages`; `?wait=`, the events stream and `webhook` report progress. - [Get a batch scrape](https://docs.beta.b3os.org/api/get-v1-vision-batches-batch-id-): Returns the batch job with its status, progress and summary result. Page contents are listed separately. - [List a batch's page results](https://docs.beta.b3os.org/api/get-v1-vision-batches-batch-id-pages): Lists the scraped pages of a batch in completion order, including failures. Available while the batch runs. - [Stream a batch's events](https://docs.beta.b3os.org/api/get-v1-vision-batches-batch-id-events): Server-sent events for the batch: lifecycle events plus `page.succeeded` and `page.failed` per URL. Ends after the terminal event. Reconnect with `Last-Event-ID` to resume. - [Cancel a batch scrape](https://docs.beta.b3os.org/api/post-v1-vision-batches-batch-id-cancel): Stops scraping new URLs. Pages already scraped stay listed and billed. Returns the batch with status `canceled`. - [List crawls](https://docs.beta.b3os.org/api/get-v1-vision-crawls): Lists crawls in this project, newest first. Records are kept for 7 days after they finish. - [Crawl a site](https://docs.beta.b3os.org/api/post-v1-vision-crawls): Starts a job that discovers pages from `url` (links and sitemaps), breadth first, and scrapes up to `limit` pages (at most 500). robots.txt is honored and requests to one host are spaced politely. One crawl runs at a time per organization. Each page bills one `vision.page`. - [Get a crawl](https://docs.beta.b3os.org/api/get-v1-vision-crawls-crawl-id-): Returns the crawl job with its status, progress and summary result. Page contents are listed separately. - [List a crawl's page results](https://docs.beta.b3os.org/api/get-v1-vision-crawls-crawl-id-pages): Lists crawled pages in completion order, including failures. Available while the crawl runs. - [Stream a crawl's events](https://docs.beta.b3os.org/api/get-v1-vision-crawls-crawl-id-events): Server-sent events for the crawl: lifecycle events plus `page.succeeded` and `page.failed` per page. Ends after the terminal event. Reconnect with `Last-Event-ID` to resume. - [Cancel a crawl](https://docs.beta.b3os.org/api/post-v1-vision-crawls-crawl-id-cancel): Stops discovering and scraping pages. Pages already scraped stay listed and billed. - [Extract structured data](https://docs.beta.b3os.org/api/post-v1-vision-extracts): Starts a job that scrapes up to 10 URLs and asks the node's model to fill your JSON Schema from their content (with `prompt` as guidance). The result is validated against the schema; an invalid result after retries fails the job with `extraction_failed`. Bills `vision.page` per page plus the model's tokens. - [Get an extraction](https://docs.beta.b3os.org/api/get-v1-vision-extracts-job-id-): Returns the extraction job; `result.data` holds the extracted JSON once it succeeded. - [Stream an extraction's events](https://docs.beta.b3os.org/api/get-v1-vision-extracts-job-id-events): Server-sent lifecycle events for the extraction job. Ends after the terminal event. - [Cancel an extraction](https://docs.beta.b3os.org/api/post-v1-vision-extracts-job-id-cancel): Stops the extraction. Pages already scraped and tokens already used stay billed. - [List browser sessions](https://docs.beta.b3os.org/api/get-v1-vision-sessions): Lists sessions in this project, newest first, including recently closed ones (kept for 7 days). - [Create a browser session](https://docs.beta.b3os.org/api/post-v1-vision-sessions): Claims a warm, dedicated browser for your organization and returns it ready to drive. Load a `profile` to start signed in; set `persist_profile` to save cookies and storage back when the session closes. The session closes after `timeout_s` (at most 1,800) or on `DELETE`. Bills `vision.browser_ms` from claim to close. - [Get a browser session](https://docs.beta.b3os.org/api/get-v1-vision-sessions-session-id-): Returns the session, its open pages and the browser time used so far. - [Close a browser session](https://docs.beta.b3os.org/api/delete-v1-vision-sessions-session-id-): Closes the session and destroys its browser. With `persist_profile`, cookies and storage are saved to the profile first (a newer revision saved by another session fails the save with `profile_conflict` unless `overwrite_profile` was set; the session still closes). Returns the closed session with the final browser time. Closing a closed session returns it unchanged. - [Run browser actions](https://docs.beta.b3os.org/api/post-v1-vision-sessions-session-id-act): Runs a batch of browser actions in order on one page and returns every result in one round trip: `navigate`, `click`, `hover`, `type`, `key`, `scroll`, `select` and `wait` (the same kinds and fields as render scripts), plus `evaluate`, `screenshot` and `markdown`. Execution stops at the first failed action unless `continue_on_error` is set; the failed action's result carries the error (for example `target_not_found`) and later actions are reported as `skipped`. The batch must finish within `timeout_ms`. - [Connect over CDP](https://docs.beta.b3os.org/api/get-v1-vision-sessions-session-id-cdp): Opens a WebSocket that speaks the Chrome DevTools Protocol for this session only, so Playwright (`chromium.connectOverCDP`), Puppeteer (`puppeteer.connect`) or any CDP client can drive the browser. The proxy exposes only the session's own targets. It refuses `SystemInfo.*`, `Tethering.*`, `Extensions.*`, `Cast.*`, and `Browser.*` except the methods Playwright and Puppeteer need to drive a browser (`getVersion`, the permission methods, window bounds, `setDownloadBehavior` and `cancelDownload`); host file access (`DOM.setFileInputFiles`, file drags); downloads to host paths (they land in the session's own directory, wiped with the browser); and navigation to anything but `http:`, `https:` and `about:blank` (`file:`, `chrome:`, `chrome-extension:`, `view-source:`, `devtools:`, `data:`). These answer `cdp_method_blocked` in the CDP error (`error.data.code`). `Target.createBrowserContext` with `proxyServer`, `proxyBypassList` or `originsWithUniversalNetworkAccess` answers `forbidden` (403): every context of a session uses the session's egress. Authenticate with the `Authorization` header or a ticket from `POST /v1/vision/sessions/{session_id}/ticket`. A client that falls more than a few MB behind is disconnected, and so is one that sends a message over 32 MiB. A message with a repeated member (two `method`s, say) answers the JSON-RPC parse error `-32700`. - [Create a stream ticket](https://docs.beta.b3os.org/api/post-v1-vision-sessions-session-id-ticket): Returns a single-use ticket, valid for 30 seconds, that opens the session's CDP socket without a bearer header (for browsers and CDP clients that cannot set headers). Pass it as `?ticket=` or in `Sec-WebSocket-Protocol: b3os.v1, b3os.ticket.`. The socket runs with this caller's scopes. - [Save a session to a profile](https://docs.beta.b3os.org/api/post-v1-vision-sessions-session-id-profile): Saves the session's current cookies and storage to a profile now: the named profile is created if it does not exist, otherwise a new revision replaces its state. Use it right after an agent or a person signs in. If another session saved the profile since this one loaded it, the save fails with `profile_conflict` unless `overwrite` is set. - [List profiles](https://docs.beta.b3os.org/api/get-v1-vision-profiles): Lists profiles in this project, newest first. - [Create a profile](https://docs.beta.b3os.org/api/post-v1-vision-profiles): Stores cookies and storage as a named profile, encrypted in the node's vault. `state` is Playwright's `storageState` JSON (`context.storageState({indexedDB: true})`) uploaded as is. Every cookie domain and origin must belong to `domains` (derived from the state when omitted). The API returns counts and domains, never cookie values; `GET /v1/vision/profiles/{profile_id}/state` exports the state. - [Get a profile](https://docs.beta.b3os.org/api/get-v1-vision-profiles-profile-id-): Returns a profile's metadata, revision and counts. Cookie values and storage contents are never returned here. - [Update a profile](https://docs.beta.b3os.org/api/patch-v1-vision-profiles-profile-id-): Renames a profile, changes its domains, expiry or metadata, or replaces its state (a new revision). Omitted fields are unchanged. - [Delete a profile](https://docs.beta.b3os.org/api/delete-v1-vision-profiles-profile-id-): Deletes the profile and every stored revision. Open sessions that loaded it keep their cookies until they close. - [Export a profile's state](https://docs.beta.b3os.org/api/get-v1-vision-profiles-profile-id-state): Returns the current revision's storage state (Playwright `storageState` JSON) so you can load it into your own browser or move it to another project. It contains live session cookies: treat the response like a password. Requires `vision:write`, the same scope that can replace the state. - [List screenshots](https://docs.beta.b3os.org/api/get-v1-render-screenshots): Lists screenshots in this project, newest first. Screenshots are kept for 7 days. - [Take a screenshot](https://docs.beta.b3os.org/api/post-v1-render-screenshots): Loads `url` (or renders `html`) in a warm browser, captures the viewport, the full page or one element, and composes it with a style (background, window frame, padding, shadow). Returns JSON with signed artifact URLs, or the image bytes directly when `Accept` is `image/png`, `image/jpeg` or `image/webp`. `variants` adds extra encodings of the same capture. Bills one `render.screenshot` per capture plus one per variant. - [Get a screenshot](https://docs.beta.b3os.org/api/get-v1-render-screenshots-screenshot-id-): Returns the screenshot with fresh signed URLs for its artifacts. - [Delete a screenshot](https://docs.beta.b3os.org/api/delete-v1-render-screenshots-screenshot-id-): Deletes the screenshot and its artifacts. Signed URLs stop working within a minute. - [List videos](https://docs.beta.b3os.org/api/get-v1-render-videos): Lists videos in this project, newest first. Videos and their artifacts are kept for 7 days. - [Record a video](https://docs.beta.b3os.org/api/post-v1-render-videos): Starts a job that records a scripted demo of `source.url`. Narration (`say`) is synthesized first with `/v1/infer/audio/speech`; the director then places each beat's steps on its narration, plans cursor and camera, records segments in parallel on a virtual clock, composes at the output frame rate and encodes MP4 (H.264, BT.709), GIF, poster and captions. Artifacts appear as they finish (`video.artifact` events, poster first). Bills `render.video_s` per second of output. - [Get a video](https://docs.beta.b3os.org/api/get-v1-render-videos-video-id-): Returns the video job; once it succeeded, `result.artifacts` lists its files with fresh signed URLs. - [Delete a video](https://docs.beta.b3os.org/api/delete-v1-render-videos-video-id-): Cancels the job if it is still running, then deletes the video, its artifacts and its archived capture. - [Stream a video's events](https://docs.beta.b3os.org/api/get-v1-render-videos-video-id-events): Server-sent events for the video job: lifecycle events, `video.phase` as the job moves through voice, plan, capture, compose, encode and upload, and `video.artifact` as each file becomes available. Ends after the terminal event; reconnect with `Last-Event-ID` to resume. - [Cancel a video](https://docs.beta.b3os.org/api/post-v1-render-videos-video-id-cancel): Stops the job. Artifacts already produced are kept; seconds already encoded are billed. - [Restyle a video](https://docs.beta.b3os.org/api/post-v1-render-videos-video-id-restyle): Starts a job that re-composes the source video's archived raw capture with a new style, captions, output size or formats. No browser runs and narration is reused, so it takes seconds. Camera moves are not changed. The result is a new video (`restyled_from` names the source). The raw capture is kept as long as the source video (7 days). - [Get a video's timeline](https://docs.beta.b3os.org/api/get-v1-render-videos-video-id-timeline): Returns the compiled timeline of a video that has finished planning: beats, narration with word timings, the timed action list the recorder replayed, cursor path, camera keyframes, captions and style (`timeline.schema.json`). `frames=1` adds the per-frame compositor state (large; for debugging). - [Get an artifact](https://docs.beta.b3os.org/api/get-v1-render-artifacts-artifact-id-): Returns an artifact's metadata with a fresh signed URL (valid for 24 hours). The URL needs no credentials and is safe to embed: it works for anyone who has it until `url_expires_at`, and the bytes are always served with `Content-Security-Policy: sandbox` (URL format: `renderGetArtifactContent`). - [Download an artifact's bytes](https://docs.beta.b3os.org/api/get-v1-render-artifacts-artifact-id-content-name-): The node side of artifact URLs. People and agents use the artifact's `url`, `https://usercontent.b3os.org/a//?node=&exp=&sig=`; the usercontent Worker checks the signature and serves the bytes from storage, or, until the upload has finished, from this route through the tunnel (with the same `node`, `exp` and `sig`). beta-api.b3os.org and beta.b3os.org never serve this route (`x-b3os-host: usercontent`). **Signature.** `sig` is the base64url (no padding) Ed25519 signature, made with the node key (the one that signs usage batches; the edge holds its public key), over the UTF-8 bytes of ``` "b3os-url-v1\n" + node + "\n" + method + "\n" + path + "\n" + exp ``` `node` is the signing node's ID (`n1`, also the `node` query parameter), `method` is `GET` (a `HEAD` request is checked as `GET`), `path` is this route's path, `/v1/render/artifacts//content/`, with the ID in `art_` form (not the host-safe `art-` form of the usercontent path), and `exp` is the expiry in Unix seconds, written in decimal without leading zeros. Other query parameters are not signed and are ignored. The Worker and the node both check the signature (`verify_strict`) and that `exp` has not passed; the node also checks that `node` is its own ID. A refused URL is `403 signed_url_invalid` with `reason`. `name` is the artifact's file name as it appears in `url`; any other name is `404 artifact_not_found`. **Response.** The artifact's bytes with its content type, `Content-Security-Policy: sandbox` (so a page or SVG never runs scripts or reads the origin) and `X-Content-Type-Options: nosniff`. One byte range per request (`Range: bytes=…`) is answered with `206`; an unsatisfiable or multi-part range is ignored and the whole artifact is returned. The response starts within 65 seconds; large videos then stream at the speed of the node's uplink. - [List style presets](https://docs.beta.b3os.org/api/get-v1-render-presets): Lists the style presets `style` can name (backgrounds, window frames, cursors, caption styles, click effects), with a preview image for each. - [List sandboxes](https://docs.beta.b3os.org/api/get-v1-sandboxes): Lists sandboxes in this project, newest first, including stopped ones from the last 7 days. - [Create a sandbox](https://docs.beta.b3os.org/api/post-v1-sandboxes): Claims a pre-warmed microVM from the template's pool (or restores a snapshot), binds a fresh identity to it (new entropy, machine ID and clock) and returns it running. The sandbox stops when `timeout_s` passes unless you extend it, and `on_idle: pause` pauses it instead. It bills `sandboxes.vcpu_ms` (CPU used) and `sandboxes.gib_ms` (memory allocated) while running. `api` grants code inside the sandbox access to B3OS (`http://127.0.0.1:7700`) with scopes that must be a subset of yours; `sandboxes:write`, every `vault:*` and every `platform:*` scope are never granted unless named explicitly. `api.spend_cap_usd` may not exceed your own spend cap, and `null` means your cap applies; scopes or a cap beyond yours are refused with `403 forbidden`, `reason: scope_escalation`. Inside the sandbox the environment also has `B3OS_API_URL=http://127.0.0.1:7700`, `B3OS_SANDBOX_ID`, `B3OS_PROJECT` and `B3OS_PORT_BASE_PATH=/sbx/`. `B3OS_PORT_BASE_PATH` is only the fixed start of every port preview path on `usercontent.b3os.org`, not a full base path: the full prefix of a request, `/sbx///`, arrives with it in `X-Forwarded-Prefix` (`sandboxesProxyPortGet`). `timing` phases: `validate_ms`, then `claim_ms` and `resume_ms` for a pre-warmed microVM from the pool, or `restore_ms` when none was parked (a restore on demand, or from a snapshot), then `bind_ms` (the identity and environment reach the guest agent), and `total_ms`. A create that has started finishes even if the client disconnects before the response: the sandbox then runs (and is billed) until its timeout or a delete, and `GET /v1/sandboxes` lists it with the `metadata` it was created with. After a disconnect, look for it there before you retry: a retry is a new create, also with the same `Idempotency-Key`, because the key is released when the client goes away before the response. Fork, snapshot, pause and resume also finish after a disconnect. - [Get a sandbox](https://docs.beta.b3os.org/api/get-v1-sandboxes-sandbox-id-): Returns the sandbox with its status, expiry, ports and usage so far. - [Delete a sandbox](https://docs.beta.b3os.org/api/delete-v1-sandboxes-sandbox-id-): Stops the sandbox and destroys its memory and disk. Snapshots taken from it are kept. Returns the stopped sandbox with its final usage. - [Extend a sandbox's timeout](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-timeout): Sets the sandbox to expire `timeout_s` seconds from now (up to your plan's maximum lifetime). Works on running and paused sandboxes. A longer life is billed (`sandboxes.vcpu_ms`, `sandboxes.gib_ms`), so the call is admitted like a create (credits, spend cap). - [Pause a sandbox](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-pause): Freezes the sandbox's vCPUs and keeps its memory and disk on the node. A paused sandbox bills no CPU time and still counts allocated memory; it still expires at `expires_at`. Resume continues exactly where it stopped. Pausing a paused sandbox returns it unchanged. - [Resume a sandbox](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-resume): Resumes a paused sandbox. Processes continue where they were, and the guest clock is corrected. Resuming a running sandbox returns it unchanged. A resumed sandbox is billed again (`sandboxes.gib_ms`), so a resume is admitted like a create (credits, spend cap). - [Snapshot a sandbox](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-snapshot): Saves the sandbox's memory and disk as a snapshot you can create new sandboxes from. The sandbox keeps running (it pauses for the copy). New sandboxes restored from a snapshot get a fresh identity, so two of them never share random state. Writing the snapshot resets the sandbox's open connections to the outside (open PTY sessions, streaming execs and log streams, port preview connections, outbound TCP connections); new ones work as soon as the call returns. Snapshots are kept 7 days. An organization keeps at most `sandboxes.snapshots_max` snapshots (beta: 20) per node, counting at most `sandboxes.snapshot_storage_max` (beta: 40 GiB). Each snapshot counts its sandbox's memory plus its disk size: the memory is stored whole, and the disk copy comes to hold every block the sandbox rewrites after the snapshot. Past either limit the snapshot is refused with `422 limit_exceeded` until you delete some. While the node's snapshot store is nearly full, snapshots and forks are refused with `503 capacity_unavailable`. - [Fork a sandbox](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-fork): Creates `count` new running sandboxes that share the source's memory and disk copy-on-write, each with a fresh identity (its own id, entropy, machine ID and clock; the source's environment, secrets, files and running processes carry over). The source must have been created with `forkable: true` (forkable sandboxes are restored for themselves rather than claimed from a pool, and track the pages they change); forks are forkable too. The source pauses while its changed memory is written (`pause`, `base`, `snapshot`, `export` phases in `Server-Timing`), then runs on; like a snapshot this resets its open connections to the outside. Each fork counts against your sandbox concurrency. - [Run a command](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-exec): Runs a command in the sandbox. By default the response waits for it to exit (at most `timeout_ms`, up to 60 seconds) and returns its exit code and output. With `?stream=true` (or `Accept: text/event-stream`) output arrives as `exec.stdout` and `exec.stderr` events while it runs, ending with `exec.exit`; streamed commands may run up to an hour. With `background: true` the response returns at once with the process, whose output you read from `GET /v1/sandboxes/{sandbox_id}/logs`. `cmd` as a string runs through `/bin/sh -c`; as an array it is executed directly. Output is UTF-8 (invalid bytes become U+FFFD) and each stream is capped at 1 MiB in a buffered response. - [Run code in a kernel](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-run-code): Runs code in the sandbox's Jupyter kernel and returns its rich results (text, images, HTML, JSON), output and any error. State persists between calls, like cells in a notebook. Needs a sandbox created from the `code-interpreter` template. - [List background processes](https://docs.beta.b3os.org/api/get-v1-sandboxes-sandbox-id-processes): Lists processes started with `background: true`, running or exited, newest first. - [Signal a background process](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-processes-pid-kill): Sends a signal (default `TERM`) to a background process and its process group, and returns the process. - [Stream process logs](https://docs.beta.b3os.org/api/get-v1-sandboxes-sandbox-id-logs): Server-sent events with the output of background processes: `log.stdout` and `log.stderr` per chunk and `process.exited` when one ends. Starts with up to 1 MiB of buffered output per process, then follows new output until the sandbox stops (or immediately ends with `follow=false`). Filter to one process with `pid`. Authenticate with the `Authorization` header or a ticket from `POST /v1/sandboxes/{sandbox_id}/ticket` (`?ticket=`, for `EventSource`). - [Read a file or list a directory](https://docs.beta.b3os.org/api/get-v1-sandboxes-sandbox-id-files): Returns the file at `path` as bytes. With `list=1` returns the directory's entries (or the single entry when `path` is a file) as JSON instead. Transfers are capped at 64 MiB. - [Write a file](https://docs.beta.b3os.org/api/put-v1-sandboxes-sandbox-id-files): Writes the request body to `path`, replacing any existing file, creating parent directories with `mkdir=1`. Returns the file's entry. Up to 64 MiB per request. - [Open a terminal](https://docs.beta.b3os.org/api/get-v1-sandboxes-sandbox-id-pty): Opens a WebSocket attached to a new pseudo-terminal running the user's login shell (or `cmd`). Binary frames carry terminal bytes in both directions. Text frames carry JSON control messages: send `{"type": "resize", "cols": 120, "rows": 40}`; the server sends `{"type": "exit", "code": 0}` before it closes. Authenticate with the `Authorization` header or a ticket from `POST /v1/sandboxes/{sandbox_id}/ticket`. - [Create a stream ticket](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-ticket): Returns a single-use ticket, valid for 30 seconds, that opens one stream under this sandbox (the terminal WebSocket or the logs event stream) without a bearer header. Pass it as `?ticket=` or in `Sec-WebSocket-Protocol: b3os.v1, b3os.ticket.`. The stream runs with this caller's scopes. - [Get a URL for a port](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-ports-port-url): Returns a URL that reaches `port` inside the sandbox: `https://usercontent.b3os.org/sbx////`. The token in the path is signed by the node and expires after `ttl_s` (10 minutes by default, at most 24 hours); anyone with the URL reaches the port until then, with no cookie or other credential. For a public port the response is the sandbox's long-lived URL (`ports[].url`) and `ttl_s` is ignored. The port must be declared in `ports` when the sandbox is created. The app sees the URL's base path in `X-Forwarded-Prefix` on every request (token format and forwarding: `sandboxesProxyPortGet`). - [Proxy a request to a sandbox port](https://docs.beta.b3os.org/api/get-v1-sandboxes-sandbox-id-ports-port-proxy-rest-): The node side of sandbox port previews. People and agents do not call it directly: they open `https://usercontent.b3os.org/sbx////`, and the usercontent Worker checks the token, then forwards the request here (through the tunnel, like the edge) with the token in `x-b3os-port-token`. A path that ends at the token is redirected to the same path plus `/`, so relative URLs resolve under it. beta-api.b3os.org and beta.b3os.org never serve this route (`x-b3os-host: usercontent`). **Port token** (from `POST /v1/sandboxes/{sandbox_id}/ports/{port}/url`, or a public port's `ports[].url`): `pt1...`. `node` is the signing node's ID (`n1`), `exp` the expiry in Unix seconds (decimal, no leading zeros) and `sig` the base64url (no padding) Ed25519 signature, made with the node key (the one that signs usage batches) over the UTF-8 bytes of ``` "b3os-port-v1\n" + node + "\n" + sandbox_id + "\n" + port + "\n" + exp ``` with `sandbox_id` in `sbx_` form (not the host-safe form) and `port` in decimal. A token is good for that sandbox and port only, until `exp`. The Worker checks the signature with the public key it holds for `node` (`verify_strict`) and the expiry before forwarding; the node checks both again, that `node` is its own ID, that the sandbox is running and that the port is declared, then connects to the port inside the sandbox over vsock. A refused token is `403 signed_url_invalid` with `reason`. **Forwarding.** The proxy forwards exactly seven methods, each declared here as its own operation: `GET` (WebSocket upgrades included), `HEAD`, `POST`, `PUT`, `PATCH`, `DELETE` and `OPTIONS` (`sandboxesProxyPortGet` … `sandboxesProxyPortOptions`). Every other method, `TRACE` and `CONNECT` included, is refused with `405 method_not_allowed` and an `Allow` header naming the seven. The app receives the request at `/`, without the `/sbx///` prefix; `rest` may be empty (`…/proxy/` reaches the app's root), and it and the query string are passed byte for byte. The request carries `X-Forwarded-Proto: https`, `X-Forwarded-Host: usercontent.b3os.org` and `X-Forwarded-Prefix: /sbx///`. The response comes back as the app sends it (status, headers, streamed body) minus hop-by-hop headers, `Set-Cookie`, and the two headers that would reach past the preview's own path on the shared origin, `Service-Worker-Allowed` and `Clear-Site-Data`; `Cookie` is removed from requests too (no cookies on usercontent in either direction). Unless the app sets `Referrer-Policy`, the proxy adds `Referrer-Policy: strict-origin`, so the token in the path is not sent to other sites. A response starts within 65 seconds; a WebSocket or a streamed body stays open up to an hour. **Base path.** All previews share the `usercontent.b3os.org` origin in v0.1 (per-port hostnames are planned): a page served from one port can send same-origin requests to any other usercontent URL it knows, so keep secrets out of previews. Apps should emit relative URLs. Two values describe the base path: - `X-Forwarded-Prefix` (on every forwarded request) is the request's full base path, `/sbx///`. Build absolute paths from it. - `B3OS_PORT_BASE_PATH` (in the sandbox's environment) is only the fixed start of that path, `/sbx/`, the same for every port and URL of the sandbox. It is not a full base path: the port and the token follow it, and the token differs per minted URL, so no value set when the sandbox starts can hold it. A public port's token lasts 7 days from sandbox creation, so its URL and base path (`ports[].url`) stay fixed; a sandbox that runs longer gets a new one. - [Proxy a POST request to a sandbox port](https://docs.beta.b3os.org/api/post-v1-sandboxes-sandbox-id-ports-port-proxy-rest-): `POST` to an app listening on a sandbox port, reached only through `usercontent.b3os.org` port previews. Token check, forwarding and limits are the same as for `GET` (`sandboxesProxyPortGet`). - [Proxy a PUT request to a sandbox port](https://docs.beta.b3os.org/api/put-v1-sandboxes-sandbox-id-ports-port-proxy-rest-): `PUT` to an app listening on a sandbox port, reached only through `usercontent.b3os.org` port previews. Token check, forwarding and limits are the same as for `GET` (`sandboxesProxyPortGet`). - [Proxy a PATCH request to a sandbox port](https://docs.beta.b3os.org/api/patch-v1-sandboxes-sandbox-id-ports-port-proxy-rest-): `PATCH` to an app listening on a sandbox port, reached only through `usercontent.b3os.org` port previews. Token check, forwarding and limits are the same as for `GET` (`sandboxesProxyPortGet`). - [Proxy a DELETE request to a sandbox port](https://docs.beta.b3os.org/api/delete-v1-sandboxes-sandbox-id-ports-port-proxy-rest-): `DELETE` to an app listening on a sandbox port, reached only through `usercontent.b3os.org` port previews. Token check, forwarding and limits are the same as for `GET` (`sandboxesProxyPortGet`). - [Proxy a HEAD request to a sandbox port](https://docs.beta.b3os.org/api/head-v1-sandboxes-sandbox-id-ports-port-proxy-rest-): `HEAD` to an app listening on a sandbox port, reached only through `usercontent.b3os.org` port previews. Token check, forwarding and limits are the same as for `GET` (`sandboxesProxyPortGet`). - [Proxy a OPTIONS request to a sandbox port](https://docs.beta.b3os.org/api/options-v1-sandboxes-sandbox-id-ports-port-proxy-rest-): `OPTIONS` to an app listening on a sandbox port, reached only through `usercontent.b3os.org` port previews. Token check, forwarding and limits are the same as for `GET` (`sandboxesProxyPortGet`). - [List snapshots](https://docs.beta.b3os.org/api/get-v1-sandboxes-snapshots): Lists snapshots in this project, newest first. - [Get a snapshot](https://docs.beta.b3os.org/api/get-v1-sandboxes-snapshots-snapshot-id-): Returns a snapshot's metadata and status. - [Delete a snapshot](https://docs.beta.b3os.org/api/delete-v1-sandboxes-snapshots-snapshot-id-): Deletes the snapshot. Sandboxes already restored from it keep running. - [List templates](https://docs.beta.b3os.org/api/get-v1-sandboxes-templates): Lists the templates sandboxes can start from (`base`, `code-interpreter`, `agent`, and on nodes that build it `browser`: Chrome already running in the snapshot, a VM-isolated browser with DevTools on port 9222) with their contents and defaults. - [Get a template](https://docs.beta.b3os.org/api/get-v1-sandboxes-templates-template-): Returns one template by name (`base`) or ID (`tpl_…`). - [List routines](https://docs.beta.b3os.org/api/get-v1-routines): Lists routines in this project, most recently updated first. - [Create a routine](https://docs.beta.b3os.org/api/post-v1-routines): Compiles and publishes a new routine as version 1. The body is the routine definition, as JSON or as YAML (`Content-Type: application/yaml`). Fails with `routine_invalid` (pointers into the definition) when it does not compile, and with `routine_name_taken` when the name exists; `PUT /v1/routines/{routine}` creates or updates by name instead. Webhook triggers verified with the `b3os` scheme get a signing secret that is returned in this response only. - [Validate a definition](https://docs.beta.b3os.org/api/post-v1-routines-validate): Compiles a definition without publishing it and returns every diagnostic with a JSON pointer: schema errors, unknown callables and step references, dependency cycles, CEL type errors and input mismatches against the callables' schemas. Always answers 200; check `valid`. Use it while an agent writes a routine. - [Convert a B3OS workflow](https://docs.beta.b3os.org/api/post-v1-routines-import): Converts a workflow from the original B3OS JSON node tree into a routine definition and returns it with diagnostics for anything that did not map (unsupported nodes, actions without a pack, connectors to bind). Nothing is created; publish the result with `PUT /v1/routines/{routine}`. - [Get a routine](https://docs.beta.b3os.org/api/get-v1-routines-routine-): Returns the routine by ID or name, with its active version, triggers and the identity its runs use. - [Publish a routine version](https://docs.beta.b3os.org/api/put-v1-routines-routine-): Compiles the definition and publishes it as a new immutable version that becomes active at once: triggers switch atomically, runs already in progress keep the version they started with. `{routine}` is an ID or a name; a name that does not exist creates the routine (`201`), which makes `b3os routine deploy` idempotent. The definition's `name` must match a name in the path. The publishing key becomes the routine's `run_as` identity and its scopes are snapshotted. Hook IDs stay the same across versions for the same trigger ID. Pack triggers (`type: action`) are subscriptions: publishing creates or updates one trigger subscription (`tsub_`, read-only at `GET /v1/actions/subscriptions`) per action trigger, and removes the subscriptions of action triggers the new version no longer has. - [Pause, resume or label a routine](https://docs.beta.b3os.org/api/patch-v1-routines-routine-): `paused: true` stops every trigger of the routine (API runs still work); `false` resumes them. Resuming a routine paused because its publishing key was revoked fails until a new version is published with a valid key. Also replaces `metadata`. - [Delete a routine](https://docs.beta.b3os.org/api/delete-v1-routines-routine-): Deletes the routine, removes its triggers, hooks and trigger subscriptions, and cancels its active runs. Run history stays readable for 30 days. - [Roll back to a version](https://docs.beta.b3os.org/api/post-v1-routines-routine-rollback): Makes an earlier version active again (triggers switch atomically). Running runs keep their version. The rollback is recorded as the routine's update; no new version is created. Trigger subscriptions follow the version: those of action triggers the earlier version does not have are removed, and the others are updated to its definition. - [List versions](https://docs.beta.b3os.org/api/get-v1-routines-routine-versions): Lists the routine's versions, newest first, without their definitions. - [Get a version](https://docs.beta.b3os.org/api/get-v1-routines-routine-versions-version-): Returns one version, by `ver_` ID or number, with its full definition. - [Rotate a hook's signing secret](https://docs.beta.b3os.org/api/post-v1-routines-routine-hooks-hook-id-rotate): Issues a new signing secret for a webhook trigger verified with the `b3os` scheme and returns it once. The previous secret keeps verifying deliveries for `grace_s` seconds (default one day) so senders can switch. - [List a routine's runs](https://docs.beta.b3os.org/api/get-v1-routines-routine-runs): Lists runs of the routine, newest first. Run history is kept for 30 days. - [Run a routine](https://docs.beta.b3os.org/api/post-v1-routines-routine-runs): Starts a run of the active version (or `version`) with `input`, validated against the routine's `inputs` schema. Use `?wait=` for tool-call style use (an `ephemeral` run that finishes within the wait never touches the journal), `Accept: text/event-stream` to follow steps live, or `webhook`. Effect steps without a product meter of their own bill `routines.effect_step`; product steps bill their product's unit. - [Get a run](https://docs.beta.b3os.org/api/get-v1-routines-runs-run-id-): Returns the run with its status, input, result and the state of every top-level step (map items are summarized; list them with `…/steps`). - [List a run's steps](https://docs.beta.b3os.org/api/get-v1-routines-runs-run-id-steps): Lists every step execution of the run in start order, including each map item (`item_index`) and retries (`attempt`), with outputs and errors. - [Stream a run's events](https://docs.beta.b3os.org/api/get-v1-routines-runs-run-id-events): Server-sent events for the run: lifecycle events, `step.*` events as steps start, retry, wait and finish, and `run.log` from `core/log` steps. Ends after the terminal event; reconnect with `Last-Event-ID` to resume (events are kept with the run history). - [Cancel a run](https://docs.beta.b3os.org/api/post-v1-routines-runs-run-id-cancel): Cancels the run. In-flight steps are told to stop; steps that already had effects are not undone. The run ends `canceled` with `job_canceled`. - [Send a signal to a run](https://docs.beta.b3os.org/api/post-v1-routines-runs-run-id-signal): Delivers a named signal to the run. A `wait` step waiting for it completes with `payload` as its outputs; a signal sent before its step starts waiting is buffered (up to 16 per name) and consumed in order. Fails with `run_not_waiting` when the run already finished or the buffer for this name is full. - [Deliver an inbound webhook](https://docs.beta.b3os.org/api/post-v1-routines-hooks-hook-id-): The URL you give a provider for a routine's webhook trigger. The request is verified with the trigger's `verify` scheme (B3OS HMAC `B3OS-Signature: t=,v1=`, or the GitHub, Stripe, Slack or Standard Webhooks signature, or a generic HMAC header) with a ±5 minute timestamp window where the scheme has one, and deduplicated for 24 hours by the trigger's `dedupe` key (by default the provider's delivery ID: `X-GitHub-Delivery`, the Stripe event `id`, the Slack `event_id`, `webhook-id`, or for `b3os` the `Idempotency-Key` header, else the signature; `hmac_sha256` triggers must set `dedupe`); a duplicate answers 202 with `deduplicated: true` and the first delivery's run. No API key is used: the unguessable hook ID plus the signature authenticate it. When the trigger's `if` is false the delivery is acknowledged and starts nothing. If the node is down, the edge stores the delivery durably and replays it in order. On a replay the signed timestamp is checked against the time the edge received the delivery (the edge signs that time), so a delivery queued during an outage is not refused as stale. A 5xx answer means "retry later" and the edge keeps the delivery; 2xx and 4xx answers are final. - [Search actions](https://docs.beta.b3os.org/api/get-v1-actions-search): Full-text search over action titles, descriptions and pack names, ranked for agents. Returns references you can pass to describe and call. The same results back the `actions_search` MCP tool. - [Describe an action](https://docs.beta.b3os.org/api/get-v1-actions-describe): Returns everything needed to call one action: input and output JSON Schemas, effect class, MCP annotations and tool definition, and the connections it needs. A reference with `@` resolves to the newest matching release; the response shows the exact version. - [Call an action](https://docs.beta.b3os.org/api/post-v1-actions-call): Validates `input` against the action's schema, runs it, validates the result against its output schema and returns it. Credentials come from `connections` (pack connection key to `conn_` ID), or else from your project's most recently created connection for that pack and key; when that connection belongs to an end user (it has a `subject`), the call is refused with `422 connection_required` instead, so an unnamed key never uses one end user's credential for another: name end-user connections explicitly. Using a stored connection, named or not, also needs `vault:run`. Only `pure` and `read` actions are retried automatically; send `Idempotency-Key` with `write` actions so a retry of your own does not repeat the effect (packs that declare an idempotency header pass it upstream). `timing` phases: `validate` (input schema), `inject` (connections), `render` (request templates), `upstream` (every HTTP exchange, retries and redirects included), `map` (response mapping and output schema) for declarative HTTP actions; `sidecar` for JavaScript actions. Bills one `actions.call` once the action ran. - [List triggers](https://docs.beta.b3os.org/api/get-v1-actions-triggers): Lists the triggers packs provide (webhook, poll and schedule), with their configuration and event schemas. Routines subscribe to them from their definition with a `type: action` trigger; each published one becomes a trigger subscription (`GET /v1/actions/subscriptions`). - [List trigger subscriptions](https://docs.beta.b3os.org/api/get-v1-actions-subscriptions): Lists the trigger subscriptions in your project, newest first. A subscription connects one `type: action` trigger of a published routine version to a pack trigger: publishing the version creates or updates it, and a rollback to a version without that trigger, a version that drops it, or deleting the routine removes it. Subscriptions are read-only here; change them by publishing the routine. Filter by routine or pack. - [Get a trigger subscription](https://docs.beta.b3os.org/api/get-v1-actions-subscriptions-subscription-id-): Returns one trigger subscription: the routine trigger it serves, the exact pack trigger version, the configuration and connections bound at publish, and its status (`failed` with `error` when subscribing at the provider failed; B3OS retries). - [Deliver a pack trigger webhook](https://docs.beta.b3os.org/api/post-v1-actions-hooks-hook-id-): The URL B3OS registers with a provider for a webhook trigger subscription (`tsub_…`). The delivery is verified with the trigger's `verify` scheme from its pack manifest, deduplicated by its dedupe key, filtered, and turned into events for the subscription's consumers. Timestamped schemes (`stripe`, `slack`, `standard_webhooks`, and `hmac_sha256`, which always is) refuse a delivery whose timestamp is more than `verify.toleranceS` seconds (at most 300) from the node clock: `401 webhook_signature_invalid` with `reason: timestamp`, so a captured delivery cannot be replayed later; inside the window a repeat is a duplicate (the dedupe key is remembered for 73 hours, up to 10,000 keys per subscription). Providers that send a verification handshake (Slack's `url_verification`) get the answer the manifest's `handshake` defines. A paused subscription, a filtered delivery and an authentic delivery whose event does not match the trigger's `eventSchema` are acknowledged with `202` and emit nothing. No API key is used: the unguessable hook ID plus the provider signature authenticate it. The verified signature is remembered with the dedupe key, so a captured delivery replayed with a new value in an unsigned header (GitHub's `X-GitHub-Delivery`) is still a duplicate; `github` signs no timestamp, so such a replay is refused only while the signature is remembered (73 hours, up to 10,000 per subscription). While the node is unreachable the edge queues deliveries (`202` with `x-b3os-queued: true`) and replays them in order, attesting when it received each one: `x-b3os-hook-received-at` (Unix seconds), `x-b3os-edge-kid` and `x-b3os-edge-sig`, an Ed25519 signature by the edge key over `b3os-hook-v1\n\n\n\n`, plus `x-b3os-hook-replay` (the attempt, 0 first). The node verifies the attestation when it is present (`401 webhook_signature_invalid`, `reason: signature` or `timestamp`, when it does not verify or the receive time is more than 300 seconds ahead or 72 hours plus 300 seconds behind the node clock) and, on a replay (`x-b3os-hook-replay` ≥ 1), applies the provider's timestamp tolerance to the edge's receive time instead of its own clock, so a delivery queued during an outage is not refused as stale. The provider signature is required either way. A replay signed by an edge key id this node does not trust yet, whose provider timestamp is outside the tolerance of the node clock, answers `503 hook_attestation_unverifiable` with `Retry-After: 60` (the same rule as the routines hook route). The node answers 5xx only when a later attempt can succeed (also: the vault, the routine engine or the pinned pack version is not available right now, `503 product_unavailable` or `503 pack_unavailable`); the edge keeps those deliveries and retries them. A subscription whose signing secret cannot be used answers `422 connection_required` or `422 connection_mismatch`. - [List packs](https://docs.beta.b3os.org/api/get-v1-actions-packs): Lists the packs available on the node, alphabetically by ID, optionally filtered by a search phrase. - [Get a pack](https://docs.beta.b3os.org/api/get-v1-actions-packs-namespace-name-): Returns a pack version (the latest unless `version` is given) with its actions, triggers, connections and egress hosts. - [Get a pack manifest](https://docs.beta.b3os.org/api/get-v1-actions-packs-namespace-name-versions-version-manifest): Returns the exact `b3pack.json` of one pack version, as published and signed. - [List connections](https://docs.beta.b3os.org/api/get-v1-vault-connections): Lists connections in this project, newest first, optionally only one pack's or one subject's. - [Create a connection](https://docs.beta.b3os.org/api/post-v1-vault-connections): Stores a credential. For a pack connection give `pack` and `key` (the connection key in the pack); the type and bound hosts come from the pack and `type`, if given, must match. For a credential used by your own HTTP steps give `type` and `hosts`. For a verification-only connection give `type` and no `hosts` (or `[]`): it is never injected into any request and holds a secret B3OS itself uses, such as a routine webhook's signing secret (`verify.secret`). `secret` holds the fields of the type: `api_key` {api_key}, `basic` {username, password}, `bearer` {token}, `oauth2` {access_token, refresh_token?, expires_at?, client_id?, client_secret?}, `none` {}. An `oauth2` pack connection with `refresh_token` and `expires_at` is refreshed in the background, always against the token endpoint (`tokenUrl`) its pack declared when the connection was created. A project holds at most 1,000 connections (limit `vault.connections`; more is 422 `limit_exceeded`). - [Get a connection](https://docs.beta.b3os.org/api/get-v1-vault-connections-connection-id-): Returns a connection's metadata, bound hosts and the names of its stored secret fields. Values are never returned. - [Update a connection](https://docs.beta.b3os.org/api/patch-v1-vault-connections-connection-id-): Changes a connection's label, subject, params, bound hosts (custom connections only) or metadata, or replaces its secret (all fields at once, for rotation). Omitted fields are unchanged. In-flight calls finish with the old secret; new calls use the new one. Concurrent updates of one connection apply one after another; 409 `conflict` means the connection kept changing while this update ran (read it and try again). - [Delete a connection](https://docs.beta.b3os.org/api/delete-v1-vault-connections-connection-id-): Deletes the connection and its encrypted secret. Routine versions that bind it fail their next step that needs it with `connection_required`; sandboxes granted it lose access. - [Create a chat completion](https://docs.beta.b3os.org/api/post-v1-infer-chat-completions): The OpenAI Chat Completions API: messages (text and, on models with `image_input`, images), tools and tool choice, `response_format` with JSON Schema, sampling parameters and streaming. With `stream: true` the response is server-sent events of `chat.completion.chunk` objects ending with `data: [DONE]`, exactly as OpenAI sends them; `stream_options.include_usage` adds a final usage chunk (and `"usage": null` on the others). A stream that fails after it started ends with an OpenAI error event (`data: {"error": {...}}`); one that fails before the first token is a plain HTTP error. The response head of a stream waits for the first generated token, so `Server-Timing` can carry `ttft`. Parameters this node does not take return `400 unsupported_parameter` naming the parameter. Besides the OpenAI parameters below, it takes the sampling extensions `top_k`, `min_p`, `repetition_penalty` and `logit_bias`, and `chat_template_kwargs.enable_thinking` (the model answers without a reasoning phase unless it is `true`; the reasoning then arrives in `reasoning_content`). `metadata`, `store` and `service_tier` are accepted and ignored. `null` means unset for every optional parameter. Image URLs are `https://` (fetched by the node through its egress guard, which refuses private, loopback and metadata addresses with `403 egress_denied`) or `data:image/{png,jpeg,webp,gif};base64,`. JSON Schemas (tool `parameters`, `response_format.json_schema.schema`) larger than 64 KiB or nested deeper than 32 levels are `400 unsupported_parameter`. Bills input and output tokens. Requests are admitted against your organization's per-minute limits on the model: one request, and the estimated prompt plus `max_completion_tokens` (or `max_tokens`, else 512 tokens), settled with the real counts when the request ends. - [Create a response (OpenAI Responses API)](https://docs.beta.b3os.org/api/post-v1-infer-responses): A stateless subset of the OpenAI Responses API on the node's own models, for SDKs and agent frameworks that speak Responses (the OpenAI Agents SDK among them) with only the base URL changed: `input` as a string or as items (`message` with `input_text` and `input_image` parts, or `output_text` for assistant turns; `function_call`, `function_call_output` and `reasoning` items), `instructions`, function tools with `tool_choice` and `parallel_tool_calls`, structured output through `text.format` (`json_schema`, `json_object`), `reasoning.effort` (`low` and above turn the model's reasoning phase on; its text arrives in `reasoning` items), `max_output_tokens`, `temperature`, `top_p`, and the Responses event stream (`response.created` ... `response.completed`, as OpenAI sends them). Nothing is stored: send the whole conversation as `input` items each turn. `previous_response_id`, `conversation`, `prompt`, `background: true` and `truncation: "auto"` are `400 unsupported_parameter`; `store`, `metadata` (echoed), `user`, `safety_identifier`, `prompt_cache_key`, `service_tier`, `text.verbosity`, `reasoning.summary` and `include: ["reasoning.encrypted_content"]` are accepted and ignored, and every response reports `store: false`. Tools other than `function` (web search, file search, computer use, code interpreter, MCP, image generation, shell) run on OpenAI's side and are `400 unsupported_parameter`. `null` means unset for every optional parameter. Images and JSON Schemas have the limits of chat completions. A stream that fails after it started ends with an `error` event; one that fails before the first token is a plain HTTP error. The response head of a stream waits for the first generated token, so `Server-Timing` can carry `ttft`. Bills input and output tokens, with the admission and limits of chat completions (the estimated prompt plus `max_output_tokens`, else 512 tokens, settled with the real counts; an abandoned stream is billed to its last token). - [List models](https://docs.beta.b3os.org/api/get-v1-infer-models): The OpenAI model list for the models this node serves, each with a `b3os` object: context length, quantization, whether it supports tools, JSON Schema output and image input, the largest accepted request, and your per-model token and request limits. Chat models are listed while the node's model runtime is configured (one that is restarting is still listed; requests get `503` with `Retry-After`); speech models while the voice service answers. - [Get a model](https://docs.beta.b3os.org/api/get-v1-infer-models-model-): One model from the list, by ID. IDs may contain a slash (`b3os/qwen3.5-9b`); send it unencoded. - [Create embeddings](https://docs.beta.b3os.org/api/post-v1-infer-embeddings): The OpenAI Embeddings API, for embedding models the node serves (`b3os.kind` is `embedding`). Other models return `404 model_not_available`; the beta node serves no embedding model yet. Bills input tokens. - [Create speech](https://docs.beta.b3os.org/api/post-v1-infer-audio-speech): The OpenAI speech API: synthesizes `input` with a voice and returns the audio bytes. B3OS extension: `timestamps: "word"` returns JSON instead, with the audio base64-encoded and the start and end time of every word, which render uses to place clicks on words and cut captions. Every `response_format` is produced: `mp3`, `opus` (Ogg), `aac` (ADTS), `flac`, `wav` and `pcm` (16-bit mono at `sample_rate`, 24 kHz for `kokoro-82m`). `kokoro-82m` speaks at `speed` 0.5 to 2 and takes no `instructions`; other values return `400 unsupported_parameter`. While the node's voice service is down the answer is `503 infer_backend_unavailable` with `Retry-After`. `Server-Timing` carries the voice service's own `voice_queue` and `voice_run` beside b3osd's `synthesize` and `encode`. Bills `infer.audio_chars` (characters of `input`). - [List voices](https://docs.beta.b3os.org/api/get-v1-infer-audio-voices): Lists the voices each speech model offers, with language and an audio sample. A B3OS endpoint (not part of the OpenAI API), so it uses B3OS lists and errors: `503 infer_backend_unavailable` with `Retry-After` while the voice service is down. All voices arrive in one page (`next_cursor` is always `null`). - [Create a message (Anthropic Messages API)](https://docs.beta.b3os.org/api/post-v1-infer-v1-messages): The Anthropic Messages API on the node's own model, so Anthropic SDKs and agents built on them run against it with only the base URL and the credential changed: set `ANTHROPIC_BASE_URL` (or `base_url`) to `https://beta-api.b3os.org/v1/infer`, the same base URL as the OpenAI SDKs (`http://127.0.0.1:7700/v1/infer` inside a sandbox; the SDKs add `/v1/messages`), and send the B3OS key as a bearer token (`ANTHROPIC_AUTH_TOKEN`, or `auth_token` in the SDKs). Text, images (`base64`, or `url` sources fetched by the node through its egress guard), custom tools with `tool_use` and `tool_result` blocks, `tool_choice`, `thinking` (the reasoning arrives in `thinking` blocks; `budget_tokens` caps it), JSON Schema output through `output_config.format`, stop sequences, a trailing assistant turn that the model continues, and streaming events (`message_start` ... `message_stop`, exactly as Anthropic sends them). Models are those of `GET /v1/infer/models`; there is no gateway route here. Parameters this node does not take return `400 unsupported_parameter` (tools Anthropic defines or runs, such as `web_search` or `bash`, `container`, `mcp_servers`, document and file sources). `cache_control`, `citations`, `metadata`, `service_tier`, `output_config.effort` and `thinking.display` are accepted and ignored (the runtime caches prompt prefixes on its own). Errors use the Anthropic shape (`{"type": "error", "error": {...}}`, with the B3OS code under `b3os`), except those raised before the request reaches the infer service (authentication, scopes, body size), which use the OpenAI shape of the rest of `/v1/infer`; Anthropic SDKs map both by HTTP status. A stream that fails after it started ends with an `error` event; one that fails before the first token is a plain HTTP error. The response head of a stream waits for the first generated token, so `Server-Timing` can carry `ttft`. Bills input and output tokens, with the admission and limits of chat completions (the estimated prompt plus `max_tokens`, settled with the real counts; an abandoned stream is billed to its last token). - [Count the tokens of a message request](https://docs.beta.b3os.org/api/post-v1-infer-v1-messages-count-tokens): The Anthropic token-counting API: the input tokens a Messages request with the same `messages`, `system`, `tools`, `tool_choice` and `thinking` would use, counted by the model runtime with the model's own chat template (images included). Free: it counts against your requests per minute, not your tokens. - [Get an endpoint's signing secret](https://docs.beta.b3os.org/api/post-v1-webhooks-secret): Returns the signing secret for one endpoint URL in this project, creating it on first use. Call it when you set up your receiver; the same URL always gets the same secret until you rotate it. URLs are compared after lowercasing the scheme and host and removing a default port. - [Rotate an endpoint's signing secret](https://docs.beta.b3os.org/api/post-v1-webhooks-secret-rotate): Replaces the endpoint's secret. For `grace_s` seconds (default one day) deliveries carry two `v1` signatures, one per secret, so receivers can switch without dropping events. - [List webhook deliveries](https://docs.beta.b3os.org/api/get-v1-webhooks-deliveries): Lists recent deliveries (7 days), newest first, with attempts and the last response status. Filter by endpoint, job or status. - [Send a test delivery](https://docs.beta.b3os.org/api/post-v1-webhooks-test): Sends one signed `webhook.test` event to the URL now and returns the delivery with the outcome of the first attempt. It is not retried. - [List API keys](https://docs.beta.b3os.org/api/get-v1-keys): Lists the organization's API keys and CLI tokens (secrets are never returned), newest first. `kind` tells them apart; revoke a lost CLI token like any key. - [Create an API key](https://docs.beta.b3os.org/api/post-v1-keys): Creates a key in your project (or `project`, in the same organization). `scopes` and `spend_cap_usd` may not exceed the caller's own, and when the caller expires, `expires_at` must be set and no later than the caller's expiry (`forbidden`, reason `scope_escalation`). The response is the only time `secret` is returned. - [Describe the calling credential](https://docs.beta.b3os.org/api/get-v1-keys-current): Returns who is calling: the key or CLI token (or dashboard session, or sandbox), its organization and project, scopes, spend cap and expiry. Any valid credential may call it, whatever its scopes. - [Get an API key](https://docs.beta.b3os.org/api/get-v1-keys-key-id-): Returns one key's metadata, spend this period and last use. The secret is never returned. - [Update an API key](https://docs.beta.b3os.org/api/patch-v1-keys-key-id-): Renames a key or changes its spend cap, expiry or metadata. Scopes cannot change; create a new key instead. A caller with a spend cap or an expiry cannot set a larger cap or a later (or no) expiry than its own (`forbidden`, reason `scope_escalation`). - [Revoke an API key](https://docs.beta.b3os.org/api/delete-v1-keys-key-id-): Revokes the key. The operations the edge answers itself refuse it at once; every other request refuses it within 10 seconds (the edge keeps a key's record at most 10 seconds after reading it from its primary database, and never reads keys from a replica). The edge also pushes the revocation to nodes, so open streams authenticated by it close within 60 seconds. Routines published with it pause their triggers. Returns the revoked key; it stays listed for audit. Changes made with `PATCH /v1/keys/{key_id}` take effect within the same 10 seconds. - [Summarize usage](https://docs.beta.b3os.org/api/get-v1-usage): Totals usage between `start` and `end` (default: this calendar month so far), grouped by any of `product`, `unit`, `key`, `project` and `day`. Nodes report usage within seconds; the last minute may still change. - [List usage records](https://docs.beta.b3os.org/api/get-v1-usage-records): Lists individual usage records as nodes reported them, newest first, filterable by product, unit, key and request. - [Get your limits](https://docs.beta.b3os.org/api/get-v1-limits): Returns every limit that applies to the caller with its current usage: concurrency, rates, quotas and size caps per product, plus the key's spend cap. Any valid credential may call it. The IDs match the `limit` member of `429` and `422` problems. - [List organizations](https://docs.beta.b3os.org/api/get-v1-orgs): Lists the organizations the caller belongs to (an API key belongs to exactly one). - [Get an organization](https://docs.beta.b3os.org/api/get-v1-orgs-org-id-): Returns one organization the caller belongs to, with the caller's role in it. - [Update an organization](https://docs.beta.b3os.org/api/patch-v1-orgs-org-id-): Renames the organization or replaces its metadata. Owners and admins only, from the dashboard. - [List members](https://docs.beta.b3os.org/api/get-v1-orgs-org-id-members): Lists the organization's members and their roles. - [List projects](https://docs.beta.b3os.org/api/get-v1-projects): Lists the projects of the caller's organization. - [Create a project](https://docs.beta.b3os.org/api/post-v1-projects): Creates a project in the caller's organization. Objects, keys, connections and usage are separated per project. - [Get a project](https://docs.beta.b3os.org/api/get-v1-projects-project-id-): Returns one project of the caller's organization. - [Update a project](https://docs.beta.b3os.org/api/patch-v1-projects-project-id-): Renames a project or replaces its metadata. - [Delete a project](https://docs.beta.b3os.org/api/delete-v1-projects-project-id-): Deletes an empty project: it must have no running sandboxes, open browser sessions or active routines (`project_not_empty`), and may not be the organization's last project (`last_project`). Its keys are revoked. - [Send a sign-in code](https://docs.beta.b3os.org/api/post-v1-auth-email-start): Emails a 6-digit sign-in code, valid for 10 minutes. Always answers 202, whether or not the address has an account. - [Sign in with an email code](https://docs.beta.b3os.org/api/post-v1-auth-email-verify): Exchanges the emailed code for a dashboard session, set as the `__Host-b3os_session` cookie. Creates the user on first sign-in. - [Sign in with GitHub](https://docs.beta.b3os.org/api/get-v1-auth-github): Redirects to GitHub to authorize B3OS, then back to the callback. `redirect_to` is a dashboard path to land on afterwards. - [GitHub sign-in callback](https://docs.beta.b3os.org/api/get-v1-auth-github-callback): Where GitHub sends the browser back. Sets the session cookie and redirects to `redirect_to`; on failure redirects to `/app/sign-in?error=`. - [Get the dashboard session](https://docs.beta.b3os.org/api/get-v1-auth-session): Returns the signed-in user, the active organization and project, the user's organizations and the CSRF token to send as `x-b3os-csrf` on writes. - [Switch organization or project](https://docs.beta.b3os.org/api/patch-v1-auth-session): Sets the session's active organization and project; dashboard requests then act in that project. - [Sign out](https://docs.beta.b3os.org/api/delete-v1-auth-session): Ends the dashboard session and clears its cookie. - [Redeem an invite code](https://docs.beta.b3os.org/api/post-v1-auth-invites-redeem): Turns a beta invite code into an organization with a first project and a first API key (shown once), and makes them the session's active organization and project. The key gets the default key scopes (`x-b3os-default-key-scopes` in common.yaml): read, write and run on vision, render, sandboxes, routines, actions and infer, plus `vault:read`, `vault:run` and `platform:read`; never `*`, `vault:write` or `platform:write`. `setup.shell` is the line to paste (`export B3OS_API_KEY=…`) and `setup.prompt` the text for the dashboard's "Copy setup prompt" button. - [Start a device login](https://docs.beta.b3os.org/api/post-v1-auth-device-code): RFC 8628 device authorization request, used by `b3os login`. Show the user `user_code` and send them to `verification_uri` (or `verification_uri_complete`), then poll the token endpoint every `interval` seconds. `scope` is a space-separated list of the scopes the token should have (default `*`, limited at approval to the approver's). Too many device logins from one address get `429` with `error: rate_limited`. - [Poll for a device login token](https://docs.beta.b3os.org/api/post-v1-auth-device-token): RFC 8628 device access token request. Until the user approves, answers `400` with `authorization_pending` (or `slow_down` when you poll faster than `interval`: add 5 seconds to it). After approval returns a `b3os_pat_` token once; the device code then stops working. Errors use the OAuth shape `{error, error_description}`; too many polls from one address get `429` with `error: rate_limited`. - [Look up a device login](https://docs.beta.b3os.org/api/get-v1-auth-device-user-code-): Returns the pending device login for a user code, so the dashboard can show what is asking (client, scopes, when) before the user approves. - [Approve a device login](https://docs.beta.b3os.org/api/post-v1-auth-device-user-code-approve): Approves the device login for one organization and project, with scopes no wider than your own. The CLI's next poll receives the token. - [Deny a device login](https://docs.beta.b3os.org/api/post-v1-auth-device-user-code-deny): Denies the device login; the CLI's next poll receives `access_denied`. - [List registry packs](https://docs.beta.b3os.org/api/get-v1-actions-registry-packs): Lists packs in the registry with their latest version. Nodes use it to keep their local index current. - [Publish a pack version](https://docs.beta.b3os.org/api/post-v1-actions-registry-packs): Uploads a pack bundle: a gzip-compressed tar with `b3pack.json` at its root plus the files it references (at most 2,000 files and 16 MiB once decompressed; other organizations are refused before the upload is read). The manifest's `signature` must verify: `sig` is Ed25519 over `b3pack-sig-v1\n\n\n` with the publisher key `kid`, and `contentHash` covers the bundle with the signature removed. Versions are immutable. In the beta only first-party publishers (`io.b3os`) may publish. - [Get a registry pack](https://docs.beta.b3os.org/api/get-v1-actions-registry-packs-namespace-name-): Returns one pack's registry record with every published version. - [Get a registry pack version](https://docs.beta.b3os.org/api/get-v1-actions-registry-packs-namespace-name-versions-version-): Returns the record nodes verify before loading a pack version (content hash, signature, publisher key) and its download URL. - [Download a pack version](https://docs.beta.b3os.org/api/get-v1-actions-registry-packs-namespace-name-versions-version-download): Redirects to a short-lived signed URL for the bundle. Verify `content_hash` and the signature before loading it. - [List requests](https://docs.beta.b3os.org/api/get-v1-requests): Lists the requests the node served for your project in the last 7 days, newest first, over every connection kind, filterable by product, operation, status, key, connection kind and sandbox. Requests the edge answered without forwarding them (edge-served operations, or requests refused before forwarding) are not listed; get those by ID. The edge forwards this operation and merges its `edge_*` phases into each record. - [Get a request](https://docs.beta.b3os.org/api/get-v1-requests-request-id-): Returns one request with its full phase breakdown: the node's phases (its `Server-Timing` phases, or the final phases of a stream) and the edge's `edge_auth` and `edge_upstream`, which the edge merges in under the same request ID. Use the `x-request-id` of any response, or a problem's `instance`. For a request the edge answered itself (an edge-served operation, or one refused before forwarding), the edge returns its own record: `node` is `null` and only edge phases are listed. - [Scrape a URL (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-scrape): Firecrawl's `POST /v2/scrape`, served by vision. Same request and response fields as Firecrawl; B3OS extras are in `data.metadata.b3os` and the `Server-Timing` header. `timeout` above 60000 is treated as 60000 (no request is held longer). Options B3OS cannot honor return `400` with code `unsupported_option` instead of being ignored. Bills one `vision.page`. - [Start a batch scrape (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-batch-scrape): Firecrawl's `POST /v2/batch/scrape`, served by a vision batch scrape (`batch_` job). The scrape options are at the top level of the body, as Firecrawl takes them. `webhook` deliveries use Firecrawl's payload and `X-Firecrawl-Signature`. Each page bills one `vision.page`. - [Get a batch scrape (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-batch-scrape-id-): Status and documents of a batch scrape, 10 MB per page of results. `next` is an absolute URL under `https://beta-api.b3os.org/compat/firecrawl` while more documents exist; the SDKs follow it. Opened as a WebSocket instead (firecrawl-js `watcher()`), the same URL streams Firecrawl's watcher protocol: one `catchup` message with this body, a `document` message per page as it finishes, then a close with code 1000 and reason `{"type":"done"}`. - [Cancel a batch scrape (Firecrawl)](https://docs.beta.b3os.org/api/delete-compat-firecrawl-v2-batch-scrape-id-): Cancels the batch. Answers `409` when it already finished, which the SDKs treat as nothing to cancel. - [Get batch scrape errors (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-batch-scrape-id-errors): The pages of the batch that failed, and URLs robots.txt blocked. - [Start a crawl (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-crawl): Firecrawl's `POST /v2/crawl`, served by a vision crawl (`crawl_` job). robots.txt is always honored (`ignoreRobotsTxt: true` returns `unsupported_option`). `limit` above your plan's crawl limit (500 pages in the beta) is treated as that limit. Each page bills one `vision.page`. - [List active crawls (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-crawl-active): Crawls of your project that are still running. `teamId` is your B3OS project ID. - [Get a crawl (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-crawl-id-): Status and documents of a crawl, 10 MB per page of results; follow `next` for the rest. Opened as a WebSocket instead (firecrawl-js `watcher()`), the same URL streams Firecrawl's watcher protocol: one `catchup` message with this body, a `document` message per page as it finishes, then a close with code 1000 and reason `{"type":"done"}`. - [Cancel a crawl (Firecrawl)](https://docs.beta.b3os.org/api/delete-compat-firecrawl-v2-crawl-id-): Cancels the crawl. Answers `409` when it already finished. - [Get crawl errors (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-crawl-id-errors): The pages of the crawl that failed, and URLs robots.txt blocked. - [Map a site (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-map): Firecrawl's `POST /v2/map`, served by vision map. `links` are objects with `url`, `title` and `description`. `limit` above 5000 is treated as 5000. Bills one `vision.page`. - [Start an extraction (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-extract): Firecrawl's `POST /v2/extract`, served by vision extract (a `job_` job) with the node's model. URL globs and `enableWebSearch` are not supported (`unsupported_option`). Bills `vision.page` per page plus the model's tokens. - [Get an extraction (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-extract-id-): Status and, once `completed`, the extracted `data`. - [Get credit usage (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-team-credit-usage): B3OS counts one Firecrawl credit per `vision.page`. `planCredits` is your organization's monthly page allowance (`GET /v1/limits` lists it as `vision.pages.monthly`) and `remainingCredits` the allowance minus the pages billed this period; the period is the billing period of `GET /v1/limits` (the UTC calendar month). Both are `null` when the organization has no page allowance. The free beta reports the allowance but does not stop scraping when it reaches 0. - [Scrape a URL (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v1-scrape): Firecrawl's `POST /v1/scrape`, served by vision. Same request and response fields as Firecrawl; B3OS extras are in `data.metadata.b3os` and the `Server-Timing` header. `timeout` above 60000 is treated as 60000 (no request is held longer). Options B3OS cannot honor return `400` with code `unsupported_option` instead of being ignored. Bills one `vision.page`. - [Start a batch scrape (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v1-batch-scrape): Firecrawl's `POST /v1/batch/scrape`, served by a vision batch scrape (`batch_` job). The scrape options are at the top level of the body, as Firecrawl takes them. `webhook` deliveries use Firecrawl's payload and `X-Firecrawl-Signature`. Each page bills one `vision.page`. - [Get a batch scrape (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-batch-scrape-id-): Status and documents of a batch scrape, 10 MB per page of results. `next` is an absolute URL under `https://beta-api.b3os.org/compat/firecrawl` while more documents exist; the SDKs follow it. Opened as a WebSocket instead (firecrawl-js `watcher()`), the same URL streams Firecrawl's watcher protocol: one `catchup` message with this body, a `document` message per page as it finishes, then a close with code 1000 and reason `{"type":"done"}`. - [Cancel a batch scrape (Firecrawl)](https://docs.beta.b3os.org/api/delete-compat-firecrawl-v1-batch-scrape-id-): Cancels the batch. Answers `409` when it already finished, which the SDKs treat as nothing to cancel. - [Get batch scrape errors (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-batch-scrape-id-errors): The pages of the batch that failed, and URLs robots.txt blocked. - [Start a crawl (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v1-crawl): Firecrawl's `POST /v1/crawl`, served by a vision crawl (`crawl_` job). robots.txt is always honored (`ignoreRobotsTxt: true` returns `unsupported_option`). `limit` above your plan's crawl limit (500 pages in the beta) is treated as that limit. Each page bills one `vision.page`. - [List active crawls (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-crawl-active): Crawls of your project that are still running. `teamId` is your B3OS project ID. - [Get a crawl (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-crawl-id-): Status and documents of a crawl, 10 MB per page of results; follow `next` for the rest. Opened as a WebSocket instead (firecrawl-js `watcher()`), the same URL streams Firecrawl's watcher protocol: one `catchup` message with this body, a `document` message per page as it finishes, then a close with code 1000 and reason `{"type":"done"}`. - [Cancel a crawl (Firecrawl)](https://docs.beta.b3os.org/api/delete-compat-firecrawl-v1-crawl-id-): Cancels the crawl. Answers `409` when it already finished. - [Get crawl errors (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-crawl-id-errors): The pages of the crawl that failed, and URLs robots.txt blocked. - [Map a site (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v1-map): Firecrawl's `POST /v1/map`, served by vision map. `links` are URL strings, as in Firecrawl v1. `limit` above 5000 is treated as 5000. Bills one `vision.page`. - [Start an extraction (Firecrawl)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v1-extract): Firecrawl's `POST /v1/extract`, served by vision extract (a `job_` job) with the node's model. URL globs and `enableWebSearch` are not supported (`unsupported_option`). Bills `vision.page` per page plus the model's tokens. - [Get an extraction (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-extract-id-): Status and, once `completed`, the extracted `data`. - [Get credit usage (Firecrawl)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-team-credit-usage): B3OS counts one Firecrawl credit per `vision.page`. `plan_credits` is your organization's monthly page allowance (`GET /v1/limits` lists it as `vision.pages.monthly`) and `remaining_credits` the allowance minus the pages billed this period; the period is the billing period of `GET /v1/limits` (the UTC calendar month). Both are `null` when the organization has no page allowance. The free beta reports the allowance but does not stop scraping when it reaches 0. Field names are snake_case, as in Firecrawl v1. - [Search (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-search): Firecrawl's `POST /v2/search` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: B3OS has no search index in the beta. Search with your provider, then scrape the results with POST /v2/batch/scrape. - [Agent (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-agent): Firecrawl's `POST /v2/agent` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Run your agent in a B3OS sandbox (POST /v1/sandboxes) and let it call /v2/scrape or vision sessions. - [Interact (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-interact): Firecrawl's `POST /v2/interact` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use B3OS browser sessions: POST /v1/vision/sessions, then POST /v1/vision/sessions/{session_id}/act or CDP. - [Scrape interact (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-scrape-job-id-interact): Firecrawl's `POST /v2/scrape/{jobId}/interact` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use B3OS browser sessions: POST /v1/vision/sessions, then POST /v1/vision/sessions/{session_id}/act or CDP. - [Scrape status (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-scrape-job-id-): Firecrawl's `GET /v2/scrape/{jobId}` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: B3OS scrapes are synchronous; the document is in the POST /v2/scrape response. - [Parse (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-parse): Firecrawl's `POST /v2/parse` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: File upload parsing is not available. Scrape the file's URL with POST /v2/scrape. - [Crawl params preview (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-crawl-params-preview): Firecrawl's `POST /v2/crawl/params-preview` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Set crawl parameters explicitly in POST /v2/crawl. - [Monitor (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v2-monitor): Firecrawl's `POST /v2/monitor` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Create a B3OS routine with a cron trigger and a vision/scrape@1 step (PUT /v1/routines/{routine}). - [Token usage (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-team-token-usage): Firecrawl's `GET /v2/team/token-usage` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use GET /v1/usage, which reports infer tokens per day. - [Historical credit usage (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-team-credit-usage-historical): Firecrawl's `GET /v2/team/credit-usage/historical` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use GET /v1/usage with group_by=day. - [Queue status (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-team-queue-status): Firecrawl's `GET /v2/team/queue-status` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use GET /v1/limits, which shows current concurrency against each limit. - [Concurrency check (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v2-concurrency-check): Firecrawl's `GET /v2/concurrency-check` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use GET /v1/limits, which shows current concurrency against each limit. - [Search (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v1-search): Firecrawl's `POST /v1/search` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: B3OS has no search index in the beta. Search with your provider, then scrape the results with POST /v1/batch/scrape. - [Deep research (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v1-deep-research): Firecrawl's `POST /v1/deep-research` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Run your research agent in a B3OS sandbox and let it scrape with /v1/scrape. - [LLMs.txt generation (not supported)](https://docs.beta.b3os.org/api/post-compat-firecrawl-v1-llmstxt): Firecrawl's `POST /v1/llmstxt` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Map the site with POST /v1/map and scrape the pages you need. - [Token usage (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-team-token-usage): Firecrawl's `GET /v1/team/token-usage` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use GET /v1/usage, which reports infer tokens per day. - [Historical token usage (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-team-token-usage-historical): Firecrawl's `GET /v1/team/token-usage/historical` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use GET /v1/usage with group_by=day. - [Historical credit usage (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-team-credit-usage-historical): Firecrawl's `GET /v1/team/credit-usage/historical` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use GET /v1/usage with group_by=day. - [Queue status (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-team-queue-status): Firecrawl's `GET /v1/team/queue-status` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: Use GET /v1/limits, which shows current concurrency against each limit. - [Crawl parameters (not supported)](https://docs.beta.b3os.org/api/get-compat-firecrawl-v1-crawl-id-params): Firecrawl's `GET /v1/crawl/{id}/params` is not implemented by B3OS. It answers `404` with code `unsupported_endpoint` and this alternative, with or without credentials: GET /v1/vision/crawls/{crawl_id} returns the crawl as B3OS ran it. ## Optional - [Full documentation](https://docs.beta.b3os.org/llms-full.txt): Complete content of all pages