Every B3OS product is reachable through the same four clients, all with the same key:

ClientInstallUse it for
TypeScript SDKnpm install @b3os/sdkCode on Node 20.16 or later, Bun and Cloudflare Workers
Python SDKpip install b3osPython 3.10 or later, sync or async
CLInpx b3osYour terminal, scripts and CI
MCP servernpx -y @b3os/mcp locally, or https://beta-api.b3os.org/mcpAgents in Claude, Cursor, Codex and other MCP clients

All of them read your key from B3OS_API_KEY. Inside a B3OS sandbox they find B3OS_API_URL (http://127.0.0.1:7700) and call the node directly, with no key.

One naming rule

The SDKs are generated from the OpenAPI document, so their names follow the API exactly. Each operation belongs to a namespace (the product, or for account operations keys, usage, limits, requests, webhooks, orgs or projects) and its method is the operation ID without the product prefix, starting lowercase:

Operation IDSDK method
visionScrapevision.scrape
sandboxesCreateSandboxsandboxes.createSandbox
routinesCreateRunroutines.createRun
platformListRequestsrequests.listRequests

The Python SDK uses the same namespaces with snake_case methods (sandboxes.create_sandbox). Compatibility paths (Firecrawl, and OpenAI's /v1/infer beyond these methods) are meant for their upstream SDKs, and dashboard-only operations are not in the SDKs.

Note

The SDKs, CLI and MCP server are version 0.1.0, built against the v0.1 API contract. The examples on this site are type-checked against the SDKs' source. Option names can still change before the packages are published.

Shared behavior

  • Jobs. Operations that start a job (crawls, batches, videos, routine runs) can wait for the finished job or stream its events: .wait() and .events() in TypeScript, wait=True and stream=True in Python. Event streams resume from the last event seen if the connection drops.
  • Errors. Failures raise B3OSError, carrying the problem's code, status, type and the request ID. Failures no server reported, such as a refused connection or a client timeout, carry client codes of their own.
  • Retries. Requests the server refused before doing any work (429, 503 unavailable) are retried with backoff; other retryable 5xx answers only when the call is safe to repeat. Operations that take an idempotency key get one per call, reused by every retry.
  • Timing. Every result's response carries the parsed Server-Timing phases.
  • Account operations from a sandbox. Keys, usage, limits, organizations, projects and the pack registry live at beta-api.b3os.org only; from inside a sandbox the SDK reports edge_only and says so.

Method index

MethodOperationNotes
vision.actPOST /v1/vision/sessions/{session_id}/act
vision.batchEventsGET /v1/vision/batches/{batch_id}/eventsevent stream
vision.cancelBatchPOST /v1/vision/batches/{batch_id}/cancel
vision.cancelCrawlPOST /v1/vision/crawls/{crawl_id}/cancel
vision.cancelExtractPOST /v1/vision/extracts/{job_id}/cancelplanned
vision.closeSessionDELETE /v1/vision/sessions/{session_id}
vision.connectCdpGET /v1/vision/sessions/{session_id}/cdpWebSocket
vision.crawlEventsGET /v1/vision/crawls/{crawl_id}/eventsevent stream
vision.createBatchPOST /v1/vision/batchesjob: .wait(), .events()
vision.createCrawlPOST /v1/vision/crawlsjob: .wait(), .events()
vision.createExtractPOST /v1/vision/extractsjob: .wait(), .events(); planned
vision.createProfilePOST /v1/vision/profiles
vision.createSessionPOST /v1/vision/sessions
vision.createSessionTicketPOST /v1/vision/sessions/{session_id}/ticket
vision.deleteProfileDELETE /v1/vision/profiles/{profile_id}
vision.exportProfileStateGET /v1/vision/profiles/{profile_id}/state
vision.extractEventsGET /v1/vision/extracts/{job_id}/eventsevent stream; planned
vision.getBatchGET /v1/vision/batches/{batch_id}
vision.getCrawlGET /v1/vision/crawls/{crawl_id}
vision.getExtractGET /v1/vision/extracts/{job_id}planned
vision.getProfileGET /v1/vision/profiles/{profile_id}
vision.getSessionGET /v1/vision/sessions/{session_id}
vision.listBatchesGET /v1/vision/batches
vision.listBatchPagesGET /v1/vision/batches/{batch_id}/pages
vision.listCrawlPagesGET /v1/vision/crawls/{crawl_id}/pages
vision.listCrawlsGET /v1/vision/crawls
vision.listProfilesGET /v1/vision/profiles
vision.listSessionsGET /v1/vision/sessions
vision.mapPOST /v1/vision/map
vision.readUrlGET /v1/vision/r/{url}
vision.saveSessionProfilePOST /v1/vision/sessions/{session_id}/profile
vision.scrapePOST /v1/vision/scrape
vision.updateProfilePATCH /v1/vision/profiles/{profile_id}
render.cancelVideoPOST /v1/render/videos/{video_id}/cancel
render.createScreenshotPOST /v1/render/screenshots
render.createVideoPOST /v1/render/videosjob: .wait(), .events()
render.deleteScreenshotDELETE /v1/render/screenshots/{screenshot_id}
render.deleteVideoDELETE /v1/render/videos/{video_id}
render.getArtifactGET /v1/render/artifacts/{artifact_id}
render.getScreenshotGET /v1/render/screenshots/{screenshot_id}
render.getVideoGET /v1/render/videos/{video_id}
render.getVideoTimelineGET /v1/render/videos/{video_id}/timeline
render.listPresetsGET /v1/render/presets
render.listScreenshotsGET /v1/render/screenshots
render.listVideosGET /v1/render/videos
render.restyleVideoPOST /v1/render/videos/{video_id}/restylejob: .wait(), .events()
render.videoEventsGET /v1/render/videos/{video_id}/eventsevent stream
sandboxes.createPortUrlPOST /v1/sandboxes/{sandbox_id}/ports/{port}/url
sandboxes.createSandboxPOST /v1/sandboxes
sandboxes.createSnapshotPOST /v1/sandboxes/{sandbox_id}/snapshot
sandboxes.createTicketPOST /v1/sandboxes/{sandbox_id}/ticket
sandboxes.deleteSandboxDELETE /v1/sandboxes/{sandbox_id}
sandboxes.deleteSnapshotDELETE /v1/sandboxes/snapshots/{snapshot_id}
sandboxes.execPOST /v1/sandboxes/{sandbox_id}/execevent stream
sandboxes.forkSandboxPOST /v1/sandboxes/{sandbox_id}/forkplanned
sandboxes.getSandboxGET /v1/sandboxes/{sandbox_id}
sandboxes.getSnapshotGET /v1/sandboxes/snapshots/{snapshot_id}
sandboxes.getTemplateGET /v1/sandboxes/templates/{template}
sandboxes.killProcessPOST /v1/sandboxes/{sandbox_id}/processes/{pid}/kill
sandboxes.listProcessesGET /v1/sandboxes/{sandbox_id}/processes
sandboxes.listSandboxesGET /v1/sandboxes
sandboxes.listSnapshotsGET /v1/sandboxes/snapshots
sandboxes.listTemplatesGET /v1/sandboxes/templates
sandboxes.openPtyGET /v1/sandboxes/{sandbox_id}/ptyWebSocket
sandboxes.pauseSandboxPOST /v1/sandboxes/{sandbox_id}/pause
sandboxes.readFileGET /v1/sandboxes/{sandbox_id}/files
sandboxes.resumeSandboxPOST /v1/sandboxes/{sandbox_id}/resume
sandboxes.runCodePOST /v1/sandboxes/{sandbox_id}/run_code
sandboxes.setTimeoutPOST /v1/sandboxes/{sandbox_id}/timeout
sandboxes.streamLogsGET /v1/sandboxes/{sandbox_id}/logsevent stream
sandboxes.writeFilePUT /v1/sandboxes/{sandbox_id}/files
routines.cancelRunPOST /v1/routines/runs/{run_id}/cancel
routines.createRoutinePOST /v1/routines
routines.createRunPOST /v1/routines/{routine}/runsjob: .wait(), .events()
routines.deleteRoutineDELETE /v1/routines/{routine}
routines.getRoutineGET /v1/routines/{routine}
routines.getRunGET /v1/routines/runs/{run_id}
routines.getVersionGET /v1/routines/{routine}/versions/{version}
routines.importRoutinePOST /v1/routines/import
routines.listRoutinesGET /v1/routines
routines.listRunsGET /v1/routines/{routine}/runs
routines.listRunStepsGET /v1/routines/runs/{run_id}/steps
routines.listVersionsGET /v1/routines/{routine}/versions
routines.publishRoutinePUT /v1/routines/{routine}
routines.rollbackRoutinePOST /v1/routines/{routine}/rollback
routines.rotateHookSecretPOST /v1/routines/{routine}/hooks/{hook_id}/rotate
routines.runEventsGET /v1/routines/runs/{run_id}/eventsevent stream
routines.signalRunPOST /v1/routines/runs/{run_id}/signal
routines.updateRoutinePATCH /v1/routines/{routine}
routines.validateRoutinePOST /v1/routines/validate
actions.callPOST /v1/actions/call
actions.describeGET /v1/actions/describe
actions.downloadPackGET /v1/actions/registry/packs/{namespace}/{name}/versions/{version}/download
actions.getPackGET /v1/actions/packs/{namespace}/{name}
actions.getPackManifestGET /v1/actions/packs/{namespace}/{name}/versions/{version}/manifest
actions.getRegistryPackGET /v1/actions/registry/packs/{namespace}/{name}
actions.getRegistryPackVersionGET /v1/actions/registry/packs/{namespace}/{name}/versions/{version}
actions.getSubscriptionGET /v1/actions/subscriptions/{subscription_id}
actions.listPacksGET /v1/actions/packs
actions.listRegistryPacksGET /v1/actions/registry/packs
actions.listSubscriptionsGET /v1/actions/subscriptions
actions.listTriggersGET /v1/actions/triggers
actions.publishPackPOST /v1/actions/registry/packs
actions.searchGET /v1/actions/search
vault.createConnectionPOST /v1/vault/connections
vault.deleteConnectionDELETE /v1/vault/connections/{connection_id}
vault.getConnectionGET /v1/vault/connections/{connection_id}
vault.listConnectionsGET /v1/vault/connections
vault.updateConnectionPATCH /v1/vault/connections/{connection_id}
infer.countMessageTokensPOST /v1/infer/v1/messages/count_tokensplanned
infer.createChatCompletionPOST /v1/infer/chat/completionsevent stream
infer.createEmbeddingsPOST /v1/infer/embeddingsplanned
infer.createMessagePOST /v1/infer/v1/messagesevent stream; planned
infer.createResponsePOST /v1/infer/responsesevent stream; planned
infer.createSpeechPOST /v1/infer/audio/speech
infer.getModelGET /v1/infer/models/{model}
infer.listModelsGET /v1/infer/models
infer.listVoicesGET /v1/infer/audio/voices
keys.createKeyPOST /v1/keys
keys.getCurrentKeyGET /v1/keys/current
keys.getKeyGET /v1/keys/{key_id}
keys.listKeysGET /v1/keys
keys.revokeKeyDELETE /v1/keys/{key_id}
keys.updateKeyPATCH /v1/keys/{key_id}
usage.getUsageGET /v1/usage
usage.listUsageRecordsGET /v1/usage/records
limits.getLimitsGET /v1/limits
requests.getRequestGET /v1/requests/{request_id}
requests.listRequestsGET /v1/requests
webhooks.getSecretPOST /v1/webhooks/secret
webhooks.listDeliveriesGET /v1/webhooks/deliveries
webhooks.rotateSecretPOST /v1/webhooks/secret/rotate
webhooks.sendTestPOST /v1/webhooks/test
orgs.getOrgGET /v1/orgs/{org_id}
orgs.listMembersGET /v1/orgs/{org_id}/members
orgs.listOrgsGET /v1/orgs
projects.createProjectPOST /v1/projects
projects.deleteProjectDELETE /v1/projects/{project_id}
projects.getProjectGET /v1/projects/{project_id}
projects.listProjectsGET /v1/projects
projects.updateProjectPATCH /v1/projects/{project_id}
Ask a question... ⌘I