# Beam for Agents (/docs/agent) Use this guide to assess a client's architecture, discover opportunities for Beam, and turn them into a credible technical or commercial proposal. It is both a capability model and an architecture/sales-assistance playbook: identify where Beam helps, explain why, and name what must be confirmed before a client commits. Last reviewed: 25 September 2026. Support varies by interface, provider and client version. Before committing to an integration, confirm the required operations in the current documentation and test them against the client's workload. A capability description is not a service-level guarantee. This page is deliberately conceptual. It carries almost no code. When you need an exact signature, a field name, or a working example, fetch it: | Need | Fetch | | -------------------------------------------------- | ------------------------------------ | | Documentation as a plain-text corpus | [Full documentation](/llms-full.txt) | | The index of pages, for choosing what to read | [Documentation index](/llms.txt) | | One page as raw Markdown | `https://docs.b1m.ai/docs/.md` | | REST documentation and interactive reference links | [API reference](/docs/api-reference) | Read this page for judgement. Fetch those for syntax. *** ## 1. What Beam is [#1-what-beam-is] Beam is an open coordination layer for bandwidth. A client expresses **intent** — move these bytes, from here, to there, under these conditions — and a network of independent operators competes to deliver it. Beam coordinates delivery using measured performance. It addresses problems such as slow or duplicated transfers, fragmented connectivity, and bandwidth that applications cannot easily discover or use. Cloud egress can be a significant cost, but rates vary by provider, region, volume and route. Beam does not automatically remove a source provider's charges. Assess the client's actual bill and workload before promising savings. Five roles separate coordination, execution and verification: | Role | Does | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | **Client** | Expresses intent through an application, service, enterprise integration or AI agent. Client use does not require a Bittensor wallet. | | **BeamCore** | Coordinates requests, delivery and lifecycle tracking. | | **Orchestrator** | Operates a worker pool and competes for work. | | **Worker** | Carries out data delivery. | | **Validator** | Checks evidence and contributes to network evaluation. | Beam runs as **Bittensor subnet 105**. This is useful context for questions about the underlying network; most client integrations use Beam's client interfaces without operating a subnet participant. The structural fact to carry into a design conversation is that clients do not have to select or manage delivery workers themselves. They use Beam's APIs, SDKs and agents. Client-operated agents can connect directly to assigned delivery infrastructure, so distinguish this programming abstraction from the actual data path described in [section 4](#4-where-the-bytes-actually-go). *** ## 2. The five primitives [#2-the-five-primitives] Beam can be understood through five primitives. Each has a distinct interface, trust model and set of limits. Select the one that fits the job, then confirm support for the chosen client and release. ### Transfer — move bytes between endpoints [#transfer--move-bytes-between-endpoints] ```text Source ──▶ Destination ``` A transfer names one or more sources and destinations, with a known, finite source size before planning. Depending on the interface, the caller supplies size information or the SDK obtains it from the source. Beam plans chunks and can distribute delivery across workers. Parallel delivery can improve completion time when the object, endpoints and available network capacity permit it. Interfaces: server SDKs (Python, TypeScript, Go, Rust), HTTP API, CLI and Studio. The browser SDK exposes transfers through its broker integration; it does not require storage secrets in frontend code. ### Fan-out — the same bytes to many destinations [#fan-out--the-same-bytes-to-many-destinations] ```text ┌──▶ Destination A Source ───────┼──▶ Destination B ├──▶ Destination C └──▶ Destination D ``` Fan-out is the transfer API with more than one entry in `destinations`. It is particularly relevant to a client running N sequential copies of the same dataset. Validate the combined source and destination capacity, completion requirements and cost against the existing process. Multiple entries in `sources` represent multiple source objects. They do not implicitly merge files, calculate deltas or synchronize directories. Provider combinations have limits; for example, the reviewed Hugging Face destination path requires a single source object. ### Room — a private group of machines and buckets [#room--a-private-group-of-machines-and-buckets] ```text ROOM Agent ───────────────── Bucket │ │ │ │ Agent ──────────────── Web Agent ``` A Room is a permissioned group for exchanging messages, streams, media and objects. Members include enrolled machines running the Beam agent and object-storage buckets attached through an organization-scoped credential. Browsers can participate through a Web Agent and share that instance's identity and grants. A Room has roles, per-channel grants, bounded invitations, and channels of six kinds: `message`, `stream`, `datagram`, `request-reply`, `media`, `object`. Not every client exposes every channel kind. Two properties make Rooms useful for integration: * Invitation-based joining can avoid a personal Beam account. An invitation can bootstrap a machine identity with granted roles and channels. That invitation-only identity cannot create Rooms. The Room still needs a payer. * A bucket can participate without sharing its storage secret with other members. The configured Studio service resolves and uses the credential. Treat that signing service as a trusted part of the client's deployment. Interfaces: CLI (`beam room …`), the local agent API, the browser Web Agent for supported operations, and Studio, including bucket membership management. The protection of an object publication depends on its source and recipients; see [section 4](#4-where-the-bytes-actually-go). ### Tunnel — reach a private resource from outside [#tunnel--reach-a-private-resource-from-outside] ```text Private resource ──▶ Beam Tunnel ──▶ Remote consumer ``` The machine holding the resource establishes an outbound connection. An inbound port on that origin does not need to be opened. This helps machines behind NAT participate, provided the network permits the required outbound connections. A tunnel can expose a **file**, an **HTTP service**, a **stream**, a **WebRTC endpoint**, a **TCP address**, or a **receive directory** for inbound files. For a public HTTPS endpoint, use the URL returned by Beam when the tunnel is created. Copy that URL exactly rather than constructing a hostname. Consumers do not need a Beam installation to use the endpoint, but access still depends on its authentication policy and the application behind it. Closing the tunnel stops serving the resource through that endpoint. A file source or receive directory can also expose an authenticated **S3-compatible interface** for supported object operations. This lets compatible clients, including Beam's SDK, use a local resource as a transfer endpoint. It is not a promise of every S3 bucket operation or arbitrary directory-source support. Native public TCP is separate from hostname-based HTTPS ingress. Interface: CLI (`beam tunnel …`) driving the local agent. ### Stream — live and continuously produced data [#stream--live-and-continuously-produced-data] ```text Source ~~~~~~▶ Consumers ``` Rooms provide live-data facilities: * `stream` channels carry byte streams between compatible agents. * `datagram` channels carry bounded individual payloads, suited to workloads that accept the selected delivery and loss behavior. * `media` channels expose **WHIP** ingest for an encoder such as OBS and **WHEP** playback for viewers. Named publishers can share a channel; subscribers can select publishers through the supported client interface. * A tunnel can also expose a stream or WebRTC endpoint without a Room. Live data does not need a declared total byte length. Session lifetimes, idle limits, backpressure and reconnect behavior still apply. A producer that does not know its final size may fit a stream or media channel, provided those limits meet the client's needs. Do not promise the completion, durability or verification contract of an object transfer for a live stream. *** ## 3. Room vs Tunnel [#3-room-vs-tunnel] **Tunnel = make a resource reachable.** Consumers use an endpoint. They do not need Room membership; endpoint authentication and application permissions still apply. **Room = organize ongoing exchange.** Members have identities, roles and channel grants, and can exchange several kinds of data. ```text Tunnel: A ──▶ endpoint ──▶ allowed consumer Room: A ↙ ↘ B C ↘ ↙ D ``` If the client's problem is "somebody outside needs to get at this one thing", consider a tunnel. If it is "these parties keep exchanging data and need shared membership and permissions", consider a Room. Some architectures benefit from both: a Room for ongoing collaboration and tunnels for specific resources. Participant count is a useful discovery signal, not a rule. Two participants can benefit from a Room, and many destinations can be served by a fan-out without creating one. *** ## 4. Where the bytes actually go [#4-where-the-bytes-actually-go] Separate coordination from delivery, and identify the trust boundary for the chosen path. In provider transfers, workers move bulk data between source and destination endpoints. Room agents connect to delivery infrastructure; tunnels and media can use gateways or relays. Do not describe every Beam primitive as having the same direct path or promise that payload never traverses Beam-operated infrastructure. Workers are third parties. What they can read depends on the selected mode: | Path | What intermediaries handle | Confidentiality boundary | | --------------------------------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | Provider transfer | Prepared source and destination routes, payload bytes and delivery metadata | Workers can see transferred plaintext unless the client encrypts it before delivery. Access scope depends on the provider and route. | | Protected Room object publication between agents only | Encrypted payloads and operational metadata | Object content is end-to-end encrypted between the participating agents using MLS-based protection. | | Room object publication with a bucket source or recipient | Storage access routes and payload bytes, including on agent-recipient paths | Transport encryption protects connections, but delivery workers can see plaintext. | | Browser participation through a Web Agent | The Web Agent acts for the browser using its own identity and grants | Protected data is decrypted at the trusted Web Agent. This is not independent browser-to-browser E2EE. | | Tunnel or media | Protocol-specific data through the selected endpoint, gateway or relay | Confirm endpoint authentication and encryption termination for that mode; do not inherit the Room object guarantee. | Three consequences matter to a client: 1. **Keep long-lived storage secrets in the trusted signing application.** Supported provider adapters sign through the client's SDK process or configured Studio service. Workers receive prepared access routes rather than those signing secrets. Client-supplied HTTP headers and URLs need their own access review. 2. **Signed URLs are access capabilities, not content encryption.** Their scope, expiry and reuse behavior depend on the provider. An assigned chunk does not establish a universal one-chunk access restriction, and a small chunk may be the whole object. Keep usable URLs and tokens out of public examples and logs. If unknown intermediaries must not read the content, use client-side encryption or an appropriate protected agent-only object publication. 3. **Check protection per publication.** A bucket source or recipient selects transport protection for that object publication, including its agent recipients. The presence of a bucket elsewhere in the Room does not by itself determine every channel's protection. Check the reported protection mode before sending sensitive content. Completion and integrity verification also depend on the provider and operation. Confirm the required checks and final object availability instead of assuming one multipart-completion mechanism or one verification guarantee for all paths. *** ## 5. What Beam can connect to [#5-what-beam-can-connect-to] Start with the client's real endpoints and required operations. A provider name, credential form or SDK type is not proof that every operation is supported. | Surface | What to plan around | | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | S3, Cloudflare R2 and configured S3-compatible storage | SDK signing and object delivery, subject to the provider's supported operations and endpoint configuration. | | Hippius | Supported provider paths have different completion and verification behavior from S3 multipart. Confirm final-object verification against the selected adapter before relying on it. | | Hugging Face | Supported source and destination flows have Hub-specific constraints. The reviewed destination path requires one source; multiple targets must have compatible upload requirements. | | Google Cloud Storage and Azure Blob SDK models | Native provider signing is not implemented in the reviewed SDK paths and may fail explicitly. Do not treat the models as working connectors or assume Studio supplies a native GCS workaround. | | Prepared HTTP endpoints | Potential sources or destinations when authentication, known size, required range reads, write semantics and reachability are compatible. | A service lacking a native adapter may still be usable through a properly authorized HTTP endpoint or a compatible storage interface. Validate that specific route before promising GCS, Azure or any other provider. Studio's storage profiles simplify configuration for services such as MinIO/AIStor, Wasabi, Backblaze B2, DigitalOcean Spaces and other S3-compatible systems. Many profiles use the same driver and require an endpoint. They are configuration options, not independent compatibility certifications. Studio workflow actions extend beyond data movement. Concrete examples include Slack messaging, Salesforce queries and record operations, HTTP requests, and Zapier tool calls. Studio also has credential definitions for services including Adobe AEP, Snowflake and Databricks; credential support alone does not establish a ready-to-run operational connector. Identify the actual action or API call the workflow will execute. Local resources can participate through tunnel file-source or receive-directory endpoints, including supported S3-compatible operations. Check the required read/write direction and operations rather than assuming a local directory behaves like a complete cloud bucket. Use the [connector documentation](/docs/connectors) to choose a candidate, then confirm operation support in the selected interface and release. A small end-to-end test is the final check. *** ## 6. How a client drives Beam [#6-how-a-client-drives-beam] Pick per job, not once. A client can use the SDK inside a service and Studio for scheduled workflows. The Console provides account, credit, API-key and transfer views; local Studio run history and other surfaces should be checked in their respective interfaces. | Interface | Reach for it when | | ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | [Server SDK](/docs/sdk) — Python, TypeScript, Go, Rust | A transfer is one step inside an application. The SDK handles supported preparation, signing and lifecycle operations. | | Browser SDK | A web application needs supported Rooms/media or transfer operations through a broker, or supported Web Agent operations. These are distinct clients. | | [HTTP API](/docs/api-reference) | No suitable SDK exists for the client's language, or they need direct lifecycle control. | | [CLI](/docs/cli) | Move data from a terminal, script shell operations, or operate Rooms and tunnels. Follow the official installation guide. | | [Studio](/docs/studio) | The work includes steps, branches, retries, schedules and inspectable run history. A self-hosted deployment keeps its credential store under the client's control. | | MCP server | An AI agent should operate supported Studio tools within an assigned scope. | | Zapier | The workflow needs supported Zapier triggers or tools. Check the exact integration direction. | | Registry | The client wants to package or use a reusable action. Confirm runtime compatibility and the action's requested permissions before execution. | ### The agent-native surface [#the-agent-native-surface] Studio's MCP server exposes capability-scoped tools, including `read:transfers`, `write:transfers`, `run:transfers`, `read:runs`, `cancel:runs`, `write:schedules`, `read:credentials` and `read:api_keys`. The reviewed tools cover Room discovery and bucket membership, workflow creation and updates, execution/retry/cancellation, transfers, schedules and status. The read-credential and read-key surfaces expose safe previews or metadata, not a general ability to retrieve raw secrets. The service binds to loopback by default; deployment configuration can change that. An agent can automate supported operations using configured credential references without receiving storage secrets itself. Grant only the tools needed for the intended work and follow the client's authorization policy for spending, publishing endpoints and executing actions. Do not assume MCP exposes every Room channel operation. The browser Web SDK has two different trust models: * The **Beam broker client** obtains short-lived scoped access tokens through a publishable client key, a backend token endpoint or a supplied token callback. Keep long-lived Beam API keys and storage secrets on the trusted server. * The **WebAgent client** authenticates to a Web Agent instance, and browsers using that instance share its identity and grants. Its instance credential belongs in a trusted application flow, not a public bundle. The SDK rejects long-lived Beam API keys, agent credentials and Studio delegations as substitutes. ### From a proposal to a first test [#from-a-proposal-to-a-first-test] | Job | Prepare and read | Establish success | | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | | Transfer or fan-out | Account/key and credits; compatible endpoints and finite source sizes. [Quickstart](/docs/developer-quickstart), [SDK](/docs/sdk), [transfers](/docs/transfers). | Inspect terminal status and each requested destination; verify final object availability and the client's required integrity checks. | | Room object exchange | Enroll agents or use invitations; configure channels, grants, payer and publication protection. [CLI](/docs/cli), [Studio](/docs/studio). | Confirm the intended recipient set, protection mode and delivery outcome, including any explicitly allowed partial failure. | | Private-resource access | Install the origin agent, allow required outbound connectivity, and choose public access or authentication. [CLI](/docs/cli). | Test from the intended consumer and close the endpoint when access is no longer needed. | | Live data or media | Choose compatible publisher/subscriber interfaces, transport and session limits. [SDK](/docs/sdk), [CLI](/docs/cli). | Test the required duration, loss/backpressure behavior and reconnect path with real consumers. | | Scheduled or agent-driven workflow | Configure credential references, action permissions, schedule or MCP scope. [Studio](/docs/studio), [billing](/docs/billing). | Inspect run history and outputs; confirm retry and cancellation behavior for the actual actions. | Retain the operation identifiers needed to inspect progress. Request acceptance is not delivery completion. Check partial results before retrying, especially when a workflow action has external side effects. *** ## 7. Hard limits, and what Beam is not [#7-hard-limits-and-what-beam-is-not] Check constraints before recommending a fit. Distinguish the selected interface's current limits from a statement about all of Beam. ### Size: a transfer constraint, not a Beam constraint [#size-a-transfer-constraint-not-a-beam-constraint] Sized delivery and live streaming are separate paths. | Surface | Size rule | | --------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | | Transfer — SDK, HTTP, Studio, CLI | A known, finite source size is needed before planning. The caller supplies it or the SDK derives it from source metadata. | | Room object publication | The file path requires a regular, nonempty file; its size is derived from the file. A bucket source uses object metadata. | | Room `stream` channel | No declared total; session and stream lifecycle limits still apply. | | Room `media` channel | No declared total; WHIP ingest and WHEP playback operate within the selected session's limits. | | Room `datagram` channel | No total, but the reviewed agent path permits at most 1,008 plaintext bytes per datagram. | | Tunnel stream / WebRTC exposure | No declared total; endpoint and protocol limits apply. | Unknown-length video, audio or sensor output may fit live channels. For an append-only log or event feed, also establish whether loss, replay, ordering and reconnect behavior meet the application's requirements. If a client needs transfer-style chunked delivery and object completion checks but cannot know the source length, finalize finite objects first or choose a live path with a different completion contract. Do not promise that the two paths provide identical verification. ### Other constraints on transfers [#other-constraints-on-transfers] * **Parallelism is workload-dependent.** Small objects may provide little scope for parallel delivery. Measure them in the intended workflow; aggregation can help when per-object overhead dominates. Chunk selection and supported limits depend on the service, provider and release. * **Object transfer is not automatic delta synchronization.** For "only what changed", directory synchronization or deduplication requirements, identify which client or workflow computes the changes and submits the resulting objects. * **Confirm billing authorization.** Account-backed operations need an authorized account or API key and sufficient credits. Invitation-only Room members use the Room's configured payer. * **R2 range-read compatibility — observed 24 September 2026.** Some R2 multipart objects with nonconsecutive part numbers returned incomplete partial reads crossing an upload boundary, even though full-object reads succeeded. Validate range reads on the actual source objects; a full-file checksum alone does not establish this behavior. Confirm the current limitation and workaround with Beam before relying on affected objects. * **Support is operation-specific.** SDK types and Studio profiles do not prove a working adapter. Check [section 5](#5-what-beam-can-connect-to) and the actual release before naming a provider in a proposal. ### Constraints on Rooms, tunnels and browsers [#constraints-on-rooms-tunnels-and-browsers] | Browser client | Supported surface in this review | Limit | | ----------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------- | | WebAgent SDK connected to a standalone instance | Room admission, channel discovery, messages and media publish/view | No SDK byte-stream methods or Room/channel administration. Browsers share the instance's identity and grants. | | Beam broker client | Supported media Rooms, broadcast and transfers | No protected Room data-channel API. These media Rooms are not the full agent Room administration surface. | The current direct browser interface does not provide a supported MLS enrollment path. The Web Agent handles protected data on the browser's behalf, so that server is part of the trust boundary. Do not recommend a general browser byte-stream integration without a documented, supported client path. Live-channel duration, idle limits, backpressure and reconnect behavior vary by interface. "No declared size" never means unlimited duration or durable replay. Additional limits: * Exposing a machine's private resource requires an agent process on that machine; a browser-only application cannot perform that role. A browser can consume a compatible public endpoint. * Native public TCP is not supported by hostname-based HTTPS ingress. Use the supported relay path for TCP and validate its client requirements. * Creating a Room requires billing authorization. Member identity and grants determine access; the configured API key determines the payer. * Object publication requires all selected recipients to finish by default. Partial delivery must be explicitly allowed and inspected. * A grant, signed route or session can expire or be revoked. Design status, cancellation and reconnect handling for the selected interface. ### What Beam is not [#what-beam-is-not] * A substitute for general-purpose compute. Studio can execute supported workflow actions, but moving training data does not provide a training cluster. * A long-term storage service. Destinations, agent inboxes and workflow artifacts can retain data; confirm their storage and retention policies. * A guarantee of durable messaging, replay or exactly-once external effects. Evaluate channel and workflow behavior against the client's requirements. * A promise of CDN edge caching. * Unlimited capacity. Validate volume, concurrency and geography against the current service and workload. ### Claims never to make [#claims-never-to-make] Do not promise that no intermediary can see plaintext, that no component retains data, or that all Beam paths share one encryption or routing model. Do not quote throughput, capacity, availability or savings without supporting evidence and scope. Do not treat acknowledgement as delivery or promise an undocumented delivery guarantee. Explain the overlap and differences when comparing Rooms, tunnels or Studio with existing products. Recommend only the capabilities that materially improve the client's architecture. *** ## 8. Finding where Beam fits [#8-finding-where-beam-fits] Start by mapping where data moves, gets duplicated, gets staged, or waits. A client may describe a slow business process, an integration burden or a cloud bill before describing a transfer problem. Look for these signals. **Signals for Transfer or Fan-out** * The same dataset is copied to several destinations, one after another. * A dataset crosses cloud providers, or moves between cloud and on-premise. * Models, checkpoints, embeddings, container images or media masters are distributed to multiple regions or teams. * Someone waits on a transfer before a business process or a compute job starts. * Cloud egress cost is a line item people complain about. * Data is staged into temporary storage purely to move it somewhere else. * Teams download and re-upload the same datasets repeatedly. **Signals for a Room** * Several parties exchange data on a recurring basis. * Separate point-to-point integrations exist between pairs of participants. * Different participants need different permissions over the same data. * Partners or customers need onboarding without accounts in the client's systems. * A bespoke central relay is maintained primarily to coordinate data exchange. * A bucket needs to participate in ongoing exchange, beyond one delivery. **Signals for a Tunnel** * A private service must be reachable by something outside the network. * Developers expose services through temporary public infrastructure, or through a VPN that exists only for that. * A machine cannot accept inbound connections — NAT, restrictive network, edge device — but can establish the required outbound connection. * One file on one machine needs to reach one person, once. **Signals for a Stream** * Continuously produced data is currently handled by polling, by writing a series of small files, or by a bespoke central relay. * Several consumers need the same live feed at the same time. * Live media has to reach viewers with a real encoder in front of it. * The producer does not know how many bytes it will emit. Audio, video, sensor output, an append-only log, a tail of events. Consider a live channel, then verify its delivery and lifecycle behavior. The known-size requirement applies to transfers, not every Beam primitive. **Signals for Studio** * The work is a pipeline, with conditions, retries, schedules and several steps. * The client needs a run history a non-engineer can read. * Non-storage systems are in the loop, such as Salesforce or Slack, through a supported action or a verified API integration. *** ## 9. How to reason about a client [#9-how-to-reason-about-a-client] ### Step 1 — Map the movement [#step-1--map-the-movement] Sources, destinations, volume per transfer and per month, frequency, direction, and number of participants. Write the current path down before proposing anything. ### Step 2 — Separate movement from connectivity [#step-2--separate-movement-from-connectivity] "We cannot move this fast enough" suggests transfer or fan-out. "We cannot reach that system at all" suggests a tunnel. Many clients have both problems and describe only one. ### Step 3 — Understand the relationships [#step-3--understand-the-relationships] A one-off delivery may need only a transfer or fan-out. Ongoing exchange with shared membership, channels and permissions suggests a Room, even with two participants. Count the integrations and permissions being maintained, as well as the parties. ### Step 4 — Find the inefficiency [#step-4--find-the-inefficiency] Sequential transfers, duplicated transfers, staging servers, unnecessary copies, centralised bottlenecks, slow WAN movement, expensive egress, manual file exchange, polling, and separately maintained point-to-point integrations. ### Step 5 — Check the constraints before the fit [#step-5--check-the-constraints-before-the-fit] Run [section 7](#7-hard-limits-and-what-beam-is-not) against the candidate. For a transfer, is source size known or derivable before planning? Is whole-object movement acceptable, or are deltas needed? Are the required provider operations supported? Can the chosen intermediaries see plaintext under the client's policy? Are endpoints reachable with the required authentication? For live data, do session, loss and reconnect limits meet the application's needs? A design that fails here fails regardless of how good the fit looked. ### Step 6 — Match the smallest sufficient set of primitives [#step-6--match-the-smallest-sufficient-set-of-primitives] Use only what materially improves the workflow. One transfer with four destinations can be the complete proposal when shared membership adds no value. ### Step 7 — Quantify what you can, and mark what you cannot [#step-7--quantify-what-you-can-and-mark-what-you-cannot] Data volume, destination count, frequency, current duration, redundant copies, integration paths and participating systems. Where a number is missing, say it is missing and name who can supply it. Label estimates and assumptions clearly; do not present them as measurements. For a cost comparison, include applicable source egress and request charges, Beam charges, destination charges and retries. Measure representative workloads before promising faster completion or lower total cost. ### Step 8 — Propose the smallest proof [#step-8--propose-the-smallest-proof] The test should be small enough to run this week and decisive enough to settle the question: * One large object to three destinations in a single fan-out, against the client's real endpoints, checking each destination. * One bucket-to-bucket transfer across two providers they already use. * One private API reached through an authenticated tunnel, consumed by the system that needs it. * One Room with a bucket, two machines and one partner joining from an invitation, checking grants and the selected publication's protection mode. * One live channel with a real encoder and two viewers, for the required duration. * One recurring job in Studio, replacing a script somebody maintains by hand. Agree the success criteria before running the proof. *** ## 10. Integration patterns [#10-integration-patterns] Each pattern names the primitive, the interface, and what must be validated. **A — Sequential copies become one fan-out.** Source writes to N destinations one at a time. Replace with one transfer carrying N destinations. *Primitive:* transfer with multiple destinations through the SDK, API or Studio. *Validate:* source and destination capacity, each destination's completion and integrity, provider compatibility, elapsed time and combined cost. **B — Multi-cloud distribution.** One dataset to S3, R2, a self-hosted S3-compatible store and private infrastructure at once. *Primitive:* fan-out through the SDK, API or Studio. *Validate:* every target's required operations through a supported adapter or compatible, authorized HTTP endpoint. Check [section 5](#5-what-beam-can-connect-to) before naming a cloud, and identify the trusted SDK process or Studio service that holds the signing credentials. **C — Dataset to distributed compute.** Training or batch data reaching several GPU hosts. *Primitive:* fan-out through the SDK or Studio; or a Room if the hosts also exchange results. *Validate:* integration with the client's compute system and the point at which the data is usable. Do not assume a job can start before the full object lands. The training or batch compute remains a separate service. **D — Multi-party data room.** Enterprise, partners, analysts, buckets and agents around one dataset. *Primitive:* Room with roles, grants, invitations and object channels, using agent/CLI interfaces and Studio for bucket configuration. *Validate:* each participant's permissions and the protection of each publication. A bucket source or recipient changes that publication's confidentiality boundary. **E — Agent data exchange.** Agents request datasets, deliver outputs, exchange live information and reach services. *Primitive:* supported Room channels through agent or Web Agent interfaces, and transfers or workflows through Studio MCP. *Validate:* actual tool and channel support, identities, scopes, spending authorization and credential references. MCP access is not a universal Room channel API. **F — Broadcast from storage.** A bucket object distributed to several regions at once. *Primitive:* fan-out from an object-storage source through SDK/API/Studio; or a Room object publication to bucket members. *Validate:* the dated R2 range-read caveat in [section 7](#7-hard-limits-and-what-beam-is-not) if R2 is the source, publication protection, and whether recipients need durable membership or one-off destinations. **G — Event-driven movement.** An application event produces data that must reach several systems. *Primitive:* transfer or fan-out from the SDK, or a Studio workflow using a supported external trigger. *Validate:* that source size can be supplied or derived before planning, action retry behavior, and whether the client wants an inspectable run history. **H — Private service connectivity.** A service currently exposed through public infrastructure or a VPN that exists only for it. *Primitive:* tunnel through CLI/local agent. *Validate:* protocol, outbound connectivity, endpoint authentication and encryption termination. TCP uses a supported relay path, rather than native public hostname ingress. **I — Partner data exchange.** Separate transfer workflows per partner. *Primitive:* Room with per-partner roles and invitation-based joining through the CLI/agent, or a supported Web Agent flow. *Validate:* partners' available clients and supported operations, grants, payer, revocation and trust boundary. Browser participants using one Web Agent share that instance's identity. **J — Live distribution.** One live source, several consumers. *Primitive:* Room media channel with WHIP ingest and WHEP playback, or a Room stream channel through compatible agents. *Validate:* encoder, consumer count, duration, backpressure/loss and reconnect behavior. For browsers, the reviewed Web Agent SDK exposes messages and media; the Beam broker client exposes media paths. Neither is a general browser byte-stream API. *** ## 11. Decision tree [#11-decision-tree] ```text Bytes need to move? | +-- Finite size known or derivable before planning? +-- yes, one destination ------> Transfer +-- yes, several destinations --> Fan-out +-- no, open-ended producer ----> Assess a live channel below Ongoing exchange needs shared membership and permissions? +-----------------------------------> Room (roles, grants, invitations) Data is live or continuous? +-- between compatible agents ------> Room stream / datagram channel +-- audio/video with an encoder -----> Room media (WHIP in, WHEP out) +-- browser participation -----------> Web Agent SDK: messages + media; | Beam broker client: media paths +-- expose a source to consumers ----> Tunnel stream / WebRTC endpoint with the chosen access policy Check duration, delivery behavior and reconnect needs for every path. Something private must be reachable from outside? +-----------------------------------> Tunnel; confirm mode and access policy The process around movement needs steps, retries or scheduling? +-----------------------------------> Studio workflow An AI agent should drive it? +-- supported Studio operations -----> Studio MCP server +-- other supported operations ------> Their SDK, CLI or agent interface Several of these at once? +-----------------------------------> Combine where each adds value ``` The tree suggests a starting point. Apply the provider, interface and security constraints in sections 4–7 before recommending a design. *** ## 12. Shape of a good answer [#12-shape-of-a-good-answer] When asked how Beam could help a company, answer in this shape. Keep it short enough to be read and specific enough to be acted on. **Existing process** — how data moves today and how the systems reach each other. Use their words and their numbers. **Where Beam fits** — the specific points of introduction, supported by the client's problem. **Primitives and interfaces used** — the capabilities and clients needed for the workflow. Record the client versions used for validation. **Proposed flow** — a simple diagram, showing which parts Beam coordinates, where payload travels, and which components are trusted with plaintext or credentials. **Why it helps** — the technical or operational reason: parallel delivery, fewer duplicated copies, reusable membership, controlled reachability or automation of repeatable steps. Quantify benefits only where supported by measurements or clearly labeled estimates. **What must be confirmed** — open questions with who can answer them. Include unverified constraints from [section 7](#7-hard-limits-and-what-beam-is-not), support/availability, security requirements and the full cost assumptions. **Smallest proof** — one test, with agreed success criteria and the relevant getting-started links from [section 6](#6-how-a-client-drives-beam). *** ## 13. Final mental model [#13-final-mental-model] A useful architecture or sales conversation starts with: > Where is data moving, being duplicated, distributed, streamed, or waiting to > move? And which systems need to reach each other but currently cannot? Then ask whether Beam makes that part of the process more programmable, more concurrent or easier to automate. Find where data movement or connectivity creates avoidable delay, duplication, cost or infrastructure overhead. Explain the specific value Beam can offer, the evidence for it and the conditions required to deliver it. A credible proposal is also clear when the existing architecture already meets the need. *** ## 14. Reference map [#14-reference-map] | Surface | Where | | ----------------------------------------------------- | ----------------------------------------------------------------------------------------------- | | Documentation, human-readable | [Beam docs](/docs/intro) | | Documentation, agent-readable | [Index](/llms.txt), [full corpus](/llms-full.txt), and `https://docs.b1m.ai/docs/.md` | | Console — organizations, credits, API keys, transfers | [Console](https://console.b1m.ai) | | Transfer HTTP API | `https://beamcore.b1m.ai` — [API reference](/docs/api-reference) | | Organization, API-key and billing management API | `https://api.b1m.ai` — [Management API](/docs/management-api) | | Authentication | `https://auth.b1m.ai` | | Action registry | `https://api.b1m.ai/registry` | | CLI and Studio installers | `https://cdn.b1m.ai` — follow the [CLI](/docs/cli) or [Studio](/docs/studio) installation guide | | Public tunnel endpoint | Use the HTTPS URL returned by Beam when the tunnel is created. | Pages worth fetching as Markdown when you need detail: [intro](/docs/intro), [architecture](/docs/architecture), [clients](/docs/clients), [developer-quickstart](/docs/developer-quickstart), [sdk](/docs/sdk), [cli](/docs/cli), [studio](/docs/studio), [transfers](/docs/transfers), [connectors](/docs/connectors), [billing](/docs/billing), [management-api](/docs/management-api), [api-reference](/docs/api-reference). # /auth/challenge (/docs/api/auth/auth/challenge/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /auth/keys (/docs/api/auth/auth/keys/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /auth/keys/{key_prefix} (/docs/api/auth/auth/keys/key_prefix/delete) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /auth/keys (/docs/api/auth/auth/keys/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /auth/me (/docs/api/auth/auth/me/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /auth/verify (/docs/api/auth/auth/verify/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /clients/{client_id} (/docs/api/clients/clients/client_id/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /clients (/docs/api/clients/clients/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /clients/register (/docs/api/clients/clients/register/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /destinations/{destination_id} (/docs/api/destinations/destinations/destination_id/delete) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /destinations/{destination_id} (/docs/api/destinations/destinations/destination_id/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /destinations/{destination_id} (/docs/api/destinations/destinations/destination_id/put) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /destinations (/docs/api/destinations/destinations/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /destinations (/docs/api/destinations/destinations/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /docs/ (/docs/api/docs/docs/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /docs/json (/docs/api/docs/docs/json/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /docs/static/index.html (/docs/api/docs/docs/static/index-html/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /docs/static/swagger-initializer.js (/docs/api/docs/docs/static/swagger-initializer-js/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /docs/static/{*} (/docs/api/docs/docs/static/wildcard/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /docs/static/{*} (/docs/api/docs/docs/static/wildcard/head) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /docs/yaml (/docs/api/docs/docs/yaml/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /health (/docs/api/health/health/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # Overview (/docs/api) This reference is generated from the versioned BeamCore OpenAPI snapshot. It documents the methods, parameters, request bodies, responses, schemas, and schema-provided examples without requiring network access during a build. Endpoints are grouped in the sidebar under the role that calls them, so the client surface stays separate from the orchestrator, worker, and validator routes. Select a resource group to browse its endpoints. Each operation lists the credential it needs, and the request panel builds a sample in cURL, JavaScript, Go, Python, Java, C#, and Rust. **Samples omit the key itself until you enter one.** They mirror the request panel above them, so an authenticated operation shows the header with an empty value — `-H "X-Api-Key: "` — and copying it as-is returns `401 authentication required`. Enter a key in the panel and the samples fill it in across every language, or paste your own value into the header. Authenticated operations use the `X-Api-Key` request header. Enter only a test or scoped key in an interactive client; this documentation never stores or embeds API keys. # /jobs (/docs/api/jobs/jobs/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /jobs/{job_id} (/docs/api/jobs/jobs/job_id/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /openapi.json (/docs/api/openapi.json/openapi-json/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /redoc (/docs/api/redoc/redoc/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /transfers (/docs/api/transfers/transfers/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /transfers/{transfer_id} (/docs/api/transfers/transfers/transfer_id/get) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # /webhooks/sentry (/docs/api/webhooks/webhooks/sentry/post) {/* This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again. */} # API Reference (/docs/api-reference) The BeamCore API is the REST API served at [beamcore.b1m.ai](https://beamcore.b1m.ai). It runs transfers, and authenticates with an API key (`b1m_…`) in `X-Api-Key`. It is what every [SDK](/docs/sdk), the [CLI](/docs/cli) and [Studio](/docs/studio) call underneath. Administering the account — creating, rotating and revoking those keys, and reading credits and usage — is a separate API on a separate host. See the [Account Management API](/docs/management-api). New to Beam? Start with the [Developer Quickstart](/docs/developer-quickstart) to create an API key and send your first transfer. ## Interactive Documentation [#interactive-documentation]
Integrated API Reference Browse methods, parameters, request bodies, responses, schemas, and examples generated from BeamCore's OpenAPI schema. Swagger UI ↗ Try requests directly in the browser. Explore all endpoints with an interactive playground. ReDoc ↗ Clean, readable API documentation with a three-panel layout. Great for browsing schemas.
## Authentication [#authentication] All non-public endpoints require an `X-Api-Key` header. ```http X-Api-Key: your_api_key ``` A client API key reaches the client routes documented here. Keys issued for other purposes do not, and a key that lacks a route's permission is refused rather than falling back. ## Base URL [#base-url] ```text https://beamcore.b1m.ai ``` The OpenAPI schema is also available as JSON at /openapi.json. ## Transfer Metadata Privacy [#transfer-metadata-privacy] Public transfer-list and dashboard transfer responses redact transfer display names, so the name you give a transfer is not exposed to the network moving it. `transfer_name` stays present as `null`, and returned transfer metadata omits `metadata.name`. # Architecture (/docs/architecture) Beam is composed of four distinct layers: the client-facing **Core Server**, the network's **Orchestrators** and **Workers**, and the metagraph-level **Validators**. This page describes how they connect and communicate. *** ## Network Topology [#network-topology] Control traffic and data traffic are separate. The Core Server assigns work but never carries payload: bytes move directly between the worker and your storage. Orchestrators and workers are paid in `$TAO` through metagraph weights set by validators, which is what keeps them competing for your transfers. *** ## Component Roles [#component-roles] | Component | Runs at | Responsibility | | ------------------ | ------------------- | ----------------------------------------------------------- | | **Core Server** | Beam-operated | API, task orchestration, transfer tracking, PRISM data | | **Orchestrator** | Operator-run | Worker pool management, task routing, task result reporting | | **Worker Gateway** | Orchestrator-run | WebSocket session hub for workers | | **Worker** | Operator-run | Data movement, chunk execution, task result reporting | | **Validator** | Bittensor validator | Reads BeamCore epoch summaries and sets metagraph weights | *** ## Communication Paths [#communication-paths] ### Client → Core Server [#client--core-server] Clients interact exclusively via the REST API. They submit transfer requests, poll status, and retrieve metadata. Authentication uses API keys. ```http POST /transfers/create POST /transfers/distribute GET /transfers/:transfer_id/status ``` ### Core Server → Orchestrators [#core-server--orchestrators] The Core Server and each orchestrator communicate over an authenticated **NATS control session**. Task assignments, recovery offers, readiness, and task results travel on this channel in real time. ### Orchestrators → Workers [#orchestrators--workers] Orchestrators operate a **Worker Gateway** — a WebSocket server that workers connect to. ### Workers to Orchestrators [#workers-to-orchestrators] After completing or failing a chunk, workers send `task_result` through the orchestrator-owned worker gateway. *** ## Control Plane [#control-plane] BeamCore keeps active transfers moving by watching task-offer batches and authoritative task results. When work stalls or fails, BeamCore issues replacement offers to eligible ready orchestrators in the transfer pool. Participants keep their sessions healthy and relay results promptly. *** ## Data Plane [#data-plane] Data never passes through the Core Server. Chunks are transferred directly from the origin (or client) to the worker, which writes to the destination storage. This keeps the Core Server lightweight and prevents it from becoming a bandwidth bottleneck. # Billing & Payments (/docs/billing) Beam usage is denominated in **credits**. Credits are bought in packs, or included in a plan, and are consumed as transfers run. This page describes how a payment becomes credits. Which settlement rail a payment takes is decided entirely by the currency: | Currency | Rail | Settles through | Status | | ---------- | ------------------------ | ------------------------------------------- | --------------------- | | USD | Card | Stripe, embedded in the console | **Available** | | TAO | On-chain deposit address | Beam's own chain watcher | **Available** | | Alpha Beam | On-chain deposit address | Beam's own chain watcher | **Available** | | USDC | Hosted crypto checkout | Coinbase Commerce (Ethereum, Base, Polygon) | Not currently offered | No payment processor settles Beam subnet alpha, which exists only on the Bittensor chain. That is why the two Bittensor assets are settled by Beam directly rather than by a provider. A method is never selectable before its rail can actually settle, so no one picks a payment that would fail at checkout. *** ## Every rail, one ledger [#every-rail-one-ledger] Whichever rail a payment takes, it converges on the same idempotent credit grant. Credits are written **only** once settlement is confirmed. The uniqueness constraint on the credit ledger is what makes every path safe to retry. A webhook delivered twice, a block scanned twice, or a page reloaded twice all produce exactly one credit grant. *** ## Referral rewards [#referral-rewards] Every account has a referral link, on **Settings → Referrals**. Share it, and anyone who creates their account through it is recorded as your referral. When a referral's organization has purchased **$500** of credits in total, that referral qualifies and earns you **+10% bonus credits on your next credit purchase**. The purchase is charged in full; the bonus arrives as extra credits beside it. * Qualifying spend is counted across every rail — card, USDC, TAO and Alpha Beam — from the point the referred account joined its organization, net of refunds. There is no deadline. * Each referral earns **one** reward. Rewards queue up, and exactly one is applied per purchase, so a purchase is never discounted twice. * Rewards do not expire, and they apply to automatic top-ups as well as purchases you make yourself. * The bonus appears in payment history as its own line, so you can always see what was granted and which referral paid it. * Your code never changes, so a link you have already shared keeps working. Your referrals page shows whether each referral has qualified, and nothing else about them. It does not report their spending, their name or their email — how much another organization buys is their business, not the referrer's. *** ## Paying by card [#paying-by-card] Stripe's payment form is mounted directly in the billing page — paying does not send you to another site. Card details are entered in Stripe-hosted fields and never reach Beam's servers. Credits are granted when Stripe confirms the payment, via the same webhook and idempotent ledger write every other rail uses. *** ## Paying with USDC [#paying-with-usdc] Coinbase Commerce hosts the checkout, quotes the exchange rate, and guarantees it for the life of the charge. Beam names a price in **US dollars** and never computes an exchange rate itself. **If a payment goes wrong.** An underpaid charge is never credited automatically — it is held for review, and resolving it grants the originally purchased pack. An overpaid charge is credited for what was purchased, with the surplus recorded so support can refund it. A charge that expires unpaid is closed, but is revived if funds arrive later. **If a webhook is missed.** The console reconciles on its own: it re-checks any pending payment when you return from checkout, polls while a payment is in flight, and sweeps stale payments whenever the billing page loads. Coinbase also retries delivery for up to three days. *** ## Paying with TAO or Alpha Beam [#paying-with-tao-or-alpha-beam] Bittensor assets settle directly on chain. Every organization gets its **own** deposit address, generated the first time you open the crypto tab in Billing. Funds are never pooled with another customer's. Because the address identifies you, there is nothing else to get right: no memo, no exact amount to match, and no time limit. Send whatever you like, whenever you like. Beam **holds no private key for these addresses on any server**. Each address is derived from a master *public* key, so the console can create addresses but cannot spend from them. The matching spending key is derived offline by an operator, which is also how deposited funds are later moved. ### How a deposit is priced [#how-a-deposit-is-priced] Credits are granted at the value **received**, using the rate observed when the deposit confirmed — not a rate quoted earlier, because a deposit address has no checkout to quote at. * **TAO** is valued against its USD price. * **Alpha Beam** is valued through the subnet's own AMM reserves, then to USD. The subnet is its own price oracle; no third-party feed is involved for alpha. Credits always round **down**. Any remainder stays as value received but ungranted, and a deposit worth less than a single credit is recorded but grants nothing until topped up. The rate shown in the console is explicitly indicative and may differ from the one applied. If the price feed is unavailable, a deposit is held rather than credited at a guessed or stale rate. ### What "confirmed" means [#what-confirmed-means] Bittensor uses GRANDPA finality, which is absolute — a finalized block cannot be reorganised. Beam scans only finalized blocks and treats finality itself as the confirmation. There is no confirmation counter to wait through; detection typically takes under a minute. Every deposit is recorded once, keyed by its exact position on chain, so a re-scan can never grant credits twice. ### Sending alpha [#sending-alpha] Alpha moves as a **stake transfer** between coldkeys on the same subnet, which is what `btcli stake transfer` performs. It arrives as stake owned by your organization's deposit coldkey while remaining delegated to the hotkey you were using. A transfer between *different* subnets is not accepted as a deposit: its amount is denominated in another subnet's alpha and cannot be priced against ours. ### Refunds [#refunds] Because no spending key is held on a server, Beam cannot issue an automatic on-chain refund. Contact support; refunds are performed manually by an operator. *** ## Plans [#plans] Plan subscriptions are card-only. Crypto buys credits, which are consumed as transfers run. *** ## Credit consumption [#credit-consumption] Credits are consumed as transfers run, and every grant and deduction is recorded in the organization's credit ledger. **Auto top-up is card-only.** It works by charging a saved payment method when the balance falls below a threshold, which requires a mandate that no crypto rail can provide. Once a card is saved, the threshold and pack can also be set over HTTP — see the [Account Management API](/docs/management-api). *** ## Payment history [#payment-history] **Billing → Payment history** is the record of what an organization has paid, over any month or year rather than a rolling window of recent days. It merges three things into one date-ordered list: * Credit purchases and on-chain deposits, from the credit ledger. * Refunds, bonuses and manual adjustments. * Plan and subscription invoices, read directly from Stripe. These never enter the credit ledger, so without them the totals would understate what a paid plan has cost. Each settled payment expands to its receipt: the amount, the method, who initiated it, and either the Stripe-hosted receipt or the Subscan link for the extrinsic that paid it. A deposit worth less than one credit is listed as **needs attention**, with the reason it granted nothing — it is recorded, so it is shown. Plan charges are the one part that depends on a live Stripe call. If Stripe cannot be reached, the page says so and still reports credit purchases and deposits rather than failing. ### Exports [#exports] Two formats, both scoped to the selected period: * **Export CSV** — one row per payment, for reconciliation. * **Statement** — a one-page summary with per-method subtotals and line items, laid out for printing or saving as a PDF. Payment history and usage are also readable over HTTP. See the [Account Management API](/docs/management-api). *** ## Usage breakdowns [#usage-breakdowns] **Usage** answers where credits went, for the same kind of period. Spend is broken down three ways: * **By project** — attributed to the project the spending key belonged to at the time. * **By API key** * **By action** — the billable action the credits were spent on, such as `transfer.run`. AI spend settles in aggregate and is reported as `ai.completion`. Each of these is a snapshot taken when the credits were spent, not a live lookup. Moving a key to another project, or deleting a project, does not rewrite what earlier periods reported. Usage recorded before project attribution existed is attributed to each key's current project, which the page states. A member whose access is scoped to particular projects sees only those projects' spend. The same breakdowns are available programmatically at `GET /v1/usage`, for pulling spend into your own reporting. See the [Account Management API](/docs/management-api). # Beam CLI (/docs/cli) The **Beam CLI** moves data from a terminal without writing code. It is deliberately a thin client: the binary contains no transfer engine, Registry server, or daemon of its own. Every command calls the same public APIs the SDK uses, so anything you do here is visible in the Console alongside your other transfers. *** ## Install [#install] The CLI ships as a compiled bundle from the release CDN, on macOS (`arm64`, `amd64`), Linux (`arm64`, `amd64`), and Windows (`amd64`). Each archive carries matching CLI and tunnel-agent binaries plus SHA-256 verification. ```bash curl -fsSL https://cdn.b1m.ai/cli/install.sh | sh ``` This installs the `beam` command. On Windows, use the bundled `install.ps1` instead of the shell one-liner. A first interactive install launches `beam setup`, which can connect your Beam account, select an organization, name the machine, join a Room from an invitation, and install shell completion. For unattended installs, set `BEAM_SKIP_ONBOARDING=1` and run setup later. Keep the CLI current with `beam update`, or check without installing: ```bash beam update --check ``` *** ## Sign in [#sign-in] ```bash beam login beam whoami ``` `beam setup` is the guided path and is resumable. For automation it needs an explicit mode: ```bash beam setup --mode account --no-interactive ``` Modes are `account`, `room`, or `skip`. The mode is mandatory when non-interactive — setup will not guess. *** ## Contexts [#contexts] `beam` talks to the production authentication, API, and Registry services. Contexts let one installation hold several organizations or machines: ```bash beam context list beam context current beam context use ``` `BEAM_*_URL` environment variables override the embedded defaults when you need to point at a private environment. *** ## Moving data [#moving-data] The quickest path is sharing and receiving, which needs no configuration beyond being signed in: ```bash beam share file ./dataset.tar beam receive ./incoming beam unshare --last ``` For the full transfer lifecycle — creating a transfer, distributing it, and reading status — use the transfer commands: ```bash beam transfer --help ``` *** ## Checking your setup [#checking-your-setup] ```bash beam status beam doctor --fix ``` `beam status` reports what the CLI is connected to. `beam doctor` diagnoses a broken install and, with `--fix`, repairs what it can. *** ## The rest of the surface [#the-rest-of-the-surface] The CLI reaches beyond client transfers. These are available but belong to other parts of Beam: | Command group | What it covers | | --------------- | ------------------------------------------------------------- | | `beam studio` | Drive a [Beam Studio](/docs/studio) installation. | | `beam room` | Create and join Rooms, manage members, roles, and channels. | | `beam tunnel` | Expose files, HTTP, streams, or TCP through the tunnel agent. | | `beam registry` | Inspect, pack, publish, and resolve Registry packages. | | `beam action` | Run an action bundle locally. | | `beam agent` | Enrol, rename, and revoke this machine. | Run `beam help`, or `beam --help`, for the complete command tree on the version you have installed. *** ## Source code [#source-code] | Repository | Status | | ------------------------------ | --------------------------------------------------- | | `Beam-Network/beam-cli-public` | Being prepared for publication — not yet reachable. | Until it is published, install from the release CDN above. See [Build with Beam](/docs/clients#source-code) for the SDK and Studio repositories. *** ## Next steps [#next-steps] * [Developer Quickstart](/docs/developer-quickstart) — The same first transfer with the SDK. * [Connectors](/docs/connectors) — Configure the storage you move data between. * [Beam Studio](/docs/studio) — Build pipelines rather than single commands. * [API Reference](/docs/api-reference) — The HTTP API underneath every command. # Build with Beam (/docs/clients) You are a **client** if you want Beam to move your data. You describe intent — these bytes, from here, to there — and the network competes to deliver it. You never talk to orchestrators or workers directly, and you do not need a Bittensor wallet. This page is the map. Everything a client needs falls into two halves: **implementation** guides that get bytes moving, and **reference** material you return to once they are. *** ## Set up [#set-up] Three things, in this order. The [Developer Quickstart](/docs/developer-quickstart) runs through them end to end. | # | Step | Where | | - | -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | | 1 | Add credits and create an API key | [console.b1m.ai](https://console.b1m.ai) | | 2 | **Install [Beam Studio](/docs/studio)** — the application you build and run data movement in | `curl -fsSL https://cdn.b1m.ai/studio/install.sh \| sudo sh` | | 3 | **Install the [Beam CLI](/docs/cli)** — your account, your machines, and transfers from a terminal | `curl -fsSL https://cdn.b1m.ai/cli/install.sh \| sh` | Studio is self-hosted, so step 2 is a real install on a Linux host with Docker, not a signup. It is how most teams operate Beam day to day — see [Beam Studio](/docs/studio) for requirements and the connect flow. *** ## Implementation [#implementation] *** ## Reference [#reference] The sidebar lists the client surface under **API reference** — auth, clients, destinations, transfers, webhooks, and jobs. *** ## What you need before you start [#what-you-need-before-you-start] | Requirement | Where it comes from | | ---------------------------- | ----------------------------------------------------------------------------------------------------------- | | An organization with credits | [console.b1m.ai](https://console.b1m.ai) → **Settings → Billing**. See [Billing & Payments](/docs/billing). | | An API key | [console.b1m.ai](https://console.b1m.ai) → **API Keys**. | | A reachable source | Signed URL or endpoint the workers can read. See [Connectors](/docs/connectors). | | A reachable destination | Endpoint the workers can write to, with the exact byte size known up front. | The [Developer Quickstart](/docs/developer-quickstart) walks through all of it in order, including installing Studio and the CLI. *** ## Choosing an interface [#choosing-an-interface] | Interface | Use it when | | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **[SDK](/docs/sdk)** | A transfer is one step inside an application you maintain. Chunking, distribution, and completion polling are handled for you. Available for Python, TypeScript, Go, Rust, and the browser. | | **[Beam Studio](/docs/studio)** | The work is a pipeline rather than a single transfer — several steps, conditions, retries, or a schedule — and you want to see runs rather than tail logs. | | **HTTP API** | Your language has no SDK, or you need to drive the transfer lifecycle yourself. | | **[CLI](/docs/cli)** | You want to move data from a terminal without writing code, or script it from a shell. | All four reach the same network and spend the same organization credits, and every transfer they create shows up together in the Console. Pick per job, not once: using the SDK in your service and Studio for scheduled syncs is normal. *** ## Source code [#source-code] The client-facing parts of Beam are open source: | Component | Repository | Status | | ---------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------- | | [SDK](/docs/sdk) | [`Beam-Network/beam-sdk-public`](https://github.com/Beam-Network/beam-sdk-public) | Public. | | [CLI](/docs/cli) | `Beam-Network/beam-cli-public` | Being prepared for publication — not yet reachable. | | [Studio](/docs/studio) | `Beam-Network/beam-studio-public` | Being prepared for publication — not yet reachable. | The two unpublished repositories are listed so you know where they will appear. Until then, install the CLI and Studio from the release CDN as their pages describe. Everything else lives under [github.com/Beam-Network](https://github.com/Beam-Network). *** ## Next steps [#next-steps] * [Developer Quickstart](/docs/developer-quickstart) — Send your first transfer. * [Beam CLI](/docs/cli) — Move data from a terminal. * [Beam Studio](/docs/studio) — Build the pipeline around the transfer. * [Connectors](/docs/connectors) — Configure your storage provider. * [API Reference](/docs/api-reference) — Authentication and base URLs. * [Architecture](/docs/architecture) — What sits behind the API, if you are curious. # Google Cloud Storage (/docs/connectors/gcs) Google Cloud Storage support is exposed in the Python SDK provider models as `GCSProviderSource` and `GCSProviderDestination`. The current TypeScript SDK provider list does not expose a `GCSProviderConfig`; use the Python SDK or raw HTTP transfer configs until TypeScript GCS support is added. Participant workers do not use GCS credentials directly. They receive signed URLs or prepared task routes from BeamCore. ## Python [#python] ```python from beam_network_sdk.models import GCSProviderDestination, GCSProviderSource source = GCSProviderSource( bucket="gcp-data-lake", key="exports/2026/report.parquet", project_id="my-gcp-project", credentials_path="/path/to/service-account.json", ) destination = GCSProviderDestination( bucket="gcp-archive", key="imports/2026/report.parquet", project_id="my-gcp-project", credentials_path="/path/to/service-account.json", ) ``` You may pass `service_account_json` instead of `credentials_path` when the SDK process receives credentials from a secret manager. ## Service Account Permissions [#service-account-permissions] For a source bucket, grant read access: ```text roles/storage.objectViewer ``` For a destination bucket, grant write access: ```text roles/storage.objectCreator ``` Grant permissions at the bucket level for least privilege. # Hippius (/docs/connectors/hippius) Hippius support is exposed through SDK provider configs. The SDK process uses the Hippius API token to prepare source/destination access; workers receive executable URLs/routes and never receive the token. ## Python SDK [#python-sdk] ```python import asyncio from beam_network_sdk import BeamSDK from beam_network_sdk.models import HippiusProviderDestination, HippiusProviderSource async def main() -> None: async with BeamSDK(api_key="b1m_...", environment="prod") as beam: result = await beam.transfers.prepare_provider_transfer( sources=[ HippiusProviderSource( bucket="source-bucket", key="datasets/file.bin", api_token="YOUR_HIPPIUS_TOKEN", ) ], destinations=[ HippiusProviderDestination( bucket="dest-bucket", key="archive/file.bin", api_token="YOUR_HIPPIUS_TOKEN", ) ], distribute=True, ) print(result.transfer_id) asyncio.run(main()) ``` ## TypeScript SDK [#typescript-sdk] ```typescript import { BeamClient, HippiusProviderConfig } from "@beam-network/sdk"; const beam = new BeamClient({ apiKey: process.env.BEAM_API_KEY! }); const transfer = await beam.createTransfer({ sources: [ HippiusProviderConfig.create({ bucket: "source-bucket", key: "datasets/file.bin", api_token: process.env.HIPPIUS_API_TOKEN!, }), ], destinations: [ HippiusProviderConfig.create({ bucket: "dest-bucket", key: "archive/file.bin", api_token: process.env.HIPPIUS_API_TOKEN!, }), ], name: "hippius-transfer", }); console.log(transfer.transfer_id); ``` ## Configuration [#configuration] | Field | Required | Description | | ------------------------------ | -------- | ------------------------------------------------------- | | `bucket` | yes | Hippius bucket name | | `key` | yes | Object key | | `api_token` | yes | Hippius API token used only by the SDK process | | `base_url` | no | Hippius API base URL, default `https://api.hippius.com` | | `source_id` / `destination_id` | no | Optional Python SDK labels | ## Notes [#notes] * The current SDK surface uses `beam_network_sdk` for Python and `@beam-network/sdk` for TypeScript. * Sink-mode helpers are not documented here because they are not present in the current SDK package. * Participant workers execute prepared task URLs; they do not call Hippius directly with your token. # HTTP Connector (/docs/connectors/http) HTTP transfers use raw BeamCore transfer configs or Python SDK `SourceConfig` / `DestConfig` models. They are useful when the source and destination are already exposed through HTTPS URLs. ## BeamCore API Shape [#beamcore-api-shape] ```http POST /transfers/create Content-Type: application/json X-Api-Key: b1m_... { "sources": [ { "type": "http", "url": "https://downloads.example.com/dataset.bin", "headers": { "Authorization": "Bearer SOURCE_TOKEN" } } ], "destinations": [ { "type": "http", "url": "https://uploads.example.com/ingest/dataset.bin", "headers": { "Authorization": "Bearer DEST_TOKEN" } } ], "total_size": 104857600, "name": "http-to-http" } ``` Then start assignment: ```http POST /transfers/distribute Content-Type: application/json X-Api-Key: b1m_... { "transfer_id": "uuid" } ``` ## Python SDK [#python-sdk] ```python from beam_network_sdk.models import DestConfig, SourceConfig source = SourceConfig( type="http", url="https://downloads.example.com/report.parquet", headers={"Authorization": "Bearer SOURCE_TOKEN"}, ) destination = DestConfig( type="http", url="https://uploads.example.com/ingest/report.parquet", headers={"Authorization": "Bearer DEST_TOKEN"}, ) ``` ## Worker Requirements [#worker-requirements] Workers receive signed or direct HTTP URLs in `task_offer` messages. They must be able to reach both endpoints from their host network. For efficient parallel transfers, HTTP sources should support byte ranges: ```text Accept-Ranges: bytes ``` If a source does not support range requests, large transfers may fall back to less efficient execution depending on the prepared task route. # Connectors (/docs/connectors) Connectors are client SDK helpers for preparing transfers from storage providers. They run in the SDK process, keep provider credentials local, create task-scoped source and destination access, and submit the prepared transfer to BeamCore. Participant workers do not load connector plugins or provider credentials. Workers receive executable `task_offer` messages with source/destination URLs and headers, then move bytes directly between storage endpoints. ## TypeScript SDK [#typescript-sdk] Install: ```bash npm install @beam-network/sdk ``` Example: ```typescript import { BeamClient, R2ProviderConfig, S3ProviderConfig } from "@beam-network/sdk"; const beam = new BeamClient({ apiKey: process.env.BEAM_API_KEY! }); const transfer = await beam.createTransfer({ sources: [ R2ProviderConfig.create({ bucket: "source-bucket", key: "exports/report.parquet", account_id: process.env.R2_ACCOUNT_ID, access_key_id: process.env.R2_ACCESS_KEY_ID!, secret_access_key: process.env.R2_SECRET_ACCESS_KEY!, }), ], destinations: [ S3ProviderConfig.create({ bucket: "destination-bucket", key: "imports/report.parquet", region: "us-east-1", access_key_id: process.env.AWS_ACCESS_KEY_ID!, secret_access_key: process.env.AWS_SECRET_ACCESS_KEY!, }), ], name: "r2-to-s3-report", }); const status = await beam.waitForTransfer(transfer.transfer_id); console.log(status.status); ``` ## Python SDK [#python-sdk] Install: ```bash pip install beam-network-sdk ``` Example: ```python import asyncio from beam_network_sdk import BeamSDK from beam_network_sdk.models import S3ProviderDestination, S3ProviderSource async def main() -> None: async with BeamSDK(api_key="b1m_...", environment="prod") as beam: transfer = await beam.transfers.prepare_provider_transfer( sources=[ S3ProviderSource( bucket="source-bucket", key="exports/report.parquet", region="us-east-1", access_key_id="...", secret_access_key="...", ) ], destinations=[ S3ProviderDestination( bucket="dest-bucket", key="imports/report.parquet", region="us-east-1", access_key_id="...", secret_access_key="...", ) ], distribute=True, ) print(transfer.transfer_id) asyncio.run(main()) ``` ## Supported Provider Models [#supported-provider-models] | Provider | TypeScript | Python | | -------------------- | --------------------------------------------------- | ------------------------------------------------------ | | Amazon S3 | `S3ProviderConfig` | `S3ProviderSource`, `S3ProviderDestination` | | Cloudflare R2 | `R2ProviderConfig` | `R2ProviderSource`, `R2ProviderDestination` | | S3-compatible | `S3CompatibleProviderConfig` | `S3ProviderSource` / `Destination` with `endpoint_url` | | Google Cloud Storage | See SDK support status | `GCSProviderSource`, `GCSProviderDestination` | | Hippius | `HippiusProviderConfig` | `HippiusProviderSource`, `HippiusProviderDestination` | | HTTP | Raw `sources[]` / `destinations[]` transfer configs | `SourceConfig`, `DestConfig` | # Cloudflare R2 (/docs/connectors/r2) Cloudflare R2 is supported through SDK provider configs. The SDK signs R2 access locally and Beam workers receive only prepared URLs/routes. ## TypeScript [#typescript] ```typescript import { BeamClient, R2ProviderConfig, S3ProviderConfig } from "@beam-network/sdk"; const beam = new BeamClient({ apiKey: process.env.BEAM_API_KEY! }); const transfer = await beam.createTransfer({ sources: [ S3ProviderConfig.create({ bucket: "aws-source", key: "ml-models/model.tar.gz", region: "us-east-1", access_key_id: process.env.AWS_ACCESS_KEY_ID!, secret_access_key: process.env.AWS_SECRET_ACCESS_KEY!, }), ], destinations: [ R2ProviderConfig.create({ bucket: "cf-dest", key: "ml-models/model.tar.gz", account_id: process.env.R2_ACCOUNT_ID, access_key_id: process.env.R2_ACCESS_KEY_ID!, secret_access_key: process.env.R2_SECRET_ACCESS_KEY!, }), ], name: "s3-to-r2", }); console.log(transfer.transfer_id); ``` ## Python [#python] ```python from beam_network_sdk.models import R2ProviderDestination, R2ProviderSource source = R2ProviderSource( bucket="source-bucket", key="exports/file.bin", account_id="cloudflare-account-id", access_key_id="...", secret_access_key="...", ) destination = R2ProviderDestination( bucket="dest-bucket", key="imports/file.bin", account_id="cloudflare-account-id", access_key_id="...", secret_access_key="...", ) ``` ## R2 Token Requirements [#r2-token-requirements] Create an R2 API token with object read permission for sources and object write/multipart permissions for destinations. R2 uses S3-compatible access key and secret key credentials. The endpoint is derived from the account ID unless you provide an explicit `endpoint_url`: ```text https://.r2.cloudflarestorage.com ``` # Amazon S3 (/docs/connectors/s3) The S3 connector is a client SDK provider config. It signs source reads and destination writes in the SDK process, then gives BeamCore prepared URLs/routes for workers to execute. Workers never receive AWS credentials. ## TypeScript [#typescript] ```typescript import { BeamClient, R2ProviderConfig, S3CompatibleProviderConfig, S3ProviderConfig, } from "@beam-network/sdk"; const beam = new BeamClient({ apiKey: process.env.BEAM_API_KEY! }); const transfer = await beam.createTransfer({ sources: [ S3ProviderConfig.create({ bucket: "source-bucket", key: "datasets/2026/data.parquet", region: "us-east-1", access_key_id: process.env.AWS_ACCESS_KEY_ID!, secret_access_key: process.env.AWS_SECRET_ACCESS_KEY!, }), ], destinations: [ R2ProviderConfig.create({ bucket: "dest-bucket", key: "datasets/2026/data.parquet", account_id: process.env.R2_ACCOUNT_ID, access_key_id: process.env.R2_ACCESS_KEY_ID!, secret_access_key: process.env.R2_SECRET_ACCESS_KEY!, }), ], name: "s3-to-r2", }); console.log(transfer.transfer_id); ``` ## S3-Compatible Providers [#s3-compatible-providers] Use `S3CompatibleProviderConfig` for Wasabi, MinIO, Backblaze B2 S3 API, DigitalOcean Spaces, or any provider that needs a custom endpoint. ```typescript await beam.prepareProviderTransfer({ sources: [ S3CompatibleProviderConfig.create({ provider: "wasabi", bucket: "my-bucket", key: "input/file.bin", region: "us-east-1", endpoint_url: "https://s3.us-east-1.wasabisys.com", access_key_id: process.env.WASABI_ACCESS_KEY_ID!, secret_access_key: process.env.WASABI_SECRET_ACCESS_KEY!, }), ], destinations: [ S3CompatibleProviderConfig.create({ provider: "minio", bucket: "archive", key: "file.bin", endpoint_url: "https://minio.example.com", force_path_style: true, access_key_id: process.env.MINIO_ACCESS_KEY_ID!, secret_access_key: process.env.MINIO_SECRET_ACCESS_KEY!, }), ], name: "S3-compatible transfer", }); ``` ## Python [#python] ```python from beam_network_sdk.models import S3ProviderDestination, S3ProviderSource source = S3ProviderSource( bucket="source-bucket", key="datasets/2026/data.parquet", region="us-east-1", access_key_id="...", secret_access_key="...", ) destination = S3ProviderDestination( bucket="dest-bucket", key="datasets/2026/data.parquet", region="us-east-1", access_key_id="...", secret_access_key="...", ) ``` ## IAM Permissions [#iam-permissions] For a source bucket, the SDK needs read permission: ```json { "Effect": "Allow", "Action": ["s3:GetObject", "s3:HeadObject"], "Resource": "arn:aws:s3:::my-bucket/*" } ``` For a destination bucket, the SDK needs write and multipart permissions: ```json { "Effect": "Allow", "Action": ["s3:PutObject", "s3:CreateMultipartUpload", "s3:CompleteMultipartUpload", "s3:ListMultipartUploadParts", "s3:AbortMultipartUpload"], "Resource": "arn:aws:s3:::my-bucket/*" } ``` # Developer Quickstart (/docs/developer-quickstart) Getting set up on Beam is four steps, in this order: 1. **Create an API key** in the [Console](https://console.b1m.ai) — everything else authenticates against your organization. 2. **Install [Beam Studio](/docs/studio)** — the application you design and operate data movement in. 3. **Install the [Beam CLI](/docs/cli)** — the terminal client for your account, your machines, and ad hoc transfers. 4. **Send a transfer** — here, with the Python SDK. Steps 2 and 3 are independent of each other. Install both: Studio is where pipelines live, the CLI is how you drive your account and move data from a shell. Beam has one public environment: production, at [console.b1m.ai](https://console.b1m.ai). Keys, installers, and transfers all target it. *** ## 1. Create an API key [#1-create-an-api-key] Open [console.b1m.ai](https://console.b1m.ai) and follow the **Get started** checklist: | Step | Where | | ------------------------ | ---------------------- | | Select your organization | Organization switcher | | Add credits | **Settings → Billing** | | Create an API key | **API Keys** | Copy the key (`b1m_…`) when it is shown — it is not displayed again. Ask an organization administrator if you cannot manage billing or create keys. Keys can also be created and rotated without the Console, which is what you want once you are automating deployments. See the [Account Management API](/docs/management-api). API keys spend organization credits. Keep them server-side and out of source control. *** ## 2. Install Beam Studio [#2-install-beam-studio] [Beam Studio](/docs/studio) is a self-hosted application for building data movement as a graph — transfers, transforms, checks, branching, and schedules — and then watching it run. It runs on your own infrastructure, which is what lets it hold your storage credentials locally. You need a Linux host with Docker Engine and Docker Compose v2, plus `curl`, `jq`, OpenSSL, and systemd. The installer does not install Docker for you. ```bash curl -fsSL https://cdn.b1m.ai/studio/install.sh | sudo sh ``` Then connect Studio to your organization. Studio does not take a pasted API key: it shows a short user code, and you approve that code at [console.b1m.ai/studio/connect](https://console.b1m.ai/studio/connect) while signed in. Studio receives its own credentials on approval. See [Beam Studio](/docs/studio) for the public-URL setting, the from-source Compose path, and how updates are signed and verified. *** ## 3. Install the Beam CLI [#3-install-the-beam-cli] The [Beam CLI](/docs/cli) moves data from a terminal and manages your account and machines. It ships as a signed bundle for macOS, Linux, and Windows: ```bash curl -fsSL https://cdn.b1m.ai/cli/install.sh | sh ``` On Windows, use the bundled `install.ps1` instead. A first interactive install launches `beam setup`, which connects your Beam account, selects an organization, names the machine, and installs shell completion. Then confirm it: ```bash beam login beam whoami beam status ``` *** ## 4. Send your first transfer [#4-send-your-first-transfer] The example below transfers a file between HTTP endpoints using the Python SDK. Python 3.10 or newer: ```bash python -m pip install beam-network-sdk ``` Set these environment variables before running it: * `BEAM_API_KEY`: the key you created in step 1. * `BEAM_SOURCE_URL`: a reachable HTTPS download URL for your file. * `BEAM_DESTINATION_URL`: an HTTPS upload endpoint configured to accept the transfer. * `BEAM_TOTAL_SIZE`: the exact file size in bytes. Both endpoints must be reachable by the workers. See the [HTTP Connector](/docs/connectors/http) for endpoint requirements. For S3, R2, or other storage providers, use the corresponding [connector](/docs/connectors) to prepare signed access. Save this as `first_transfer.py`: ```python import asyncio import os from beam_network_sdk import BeamSDK from beam_network_sdk.models import DestConfig, SourceConfig async def main() -> None: async with BeamSDK(api_key=os.environ["BEAM_API_KEY"]) as beam: transfer = await beam.transfers.create( sources=[SourceConfig(type="http", url=os.environ["BEAM_SOURCE_URL"])], destinations=[DestConfig(type="http", url=os.environ["BEAM_DESTINATION_URL"])], total_size=int(os.environ["BEAM_TOTAL_SIZE"]), name="my-first-transfer", progressive_mode=True, ) print("Transfer:", transfer.transfer_id) await beam.transfers.distribute(transfer.transfer_id) status = await beam.transfers.wait_complete(transfer.transfer_id) print("Status:", status.status) asyncio.run(main()) ``` ```bash python first_transfer.py ``` The SDK is not Python-only — TypeScript, Go, Rust, and browser clients create the same transfer. See [Beam SDK](/docs/sdk). *** ## 5. Check the result [#5-check-the-result] Find the printed transfer ID under **Transfers** in the Console. Confirm that the transfer completed and that the destination contains your file. If it failed, check your key, your organization's credits, and source and destination access. *** ## Next steps [#next-steps] * [Beam Studio](/docs/studio) — Build the pipeline around the transfer. * [Beam CLI](/docs/cli) — The full command surface. * [Beam SDK](/docs/sdk) — The same transfer in TypeScript, Go, Rust, or a browser. * [Connectors](/docs/connectors) — Configure your storage provider. * [API Reference](/docs/api-reference) — Browse HTTP endpoints and authentication. * [Billing & Payments](/docs/billing) — Manage the credits transfers consume. # What is Beam? (/docs/intro) **Beam** is an open coordination layer for bandwidth. It enables data to move across a distributed network of participants where routing decisions are not fixed or centrally controlled, but dynamically determined based on real-time performance. Instead of relying on predefined infrastructure such as cloud providers or CDNs, Beam coordinates a network of independent operators who contribute bandwidth and compete to deliver data efficiently. At its core, Beam transforms bandwidth into a **measurable, verifiable, and incentivized resource** — turning data transfer into a performance-driven market. *** ## Get started [#get-started] If you want to move data, this is the path. It takes three steps, in this order, and the [Developer Quickstart](/docs/developer-quickstart) walks through all of them. | # | Step | What it is | | - | ----------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | 1 | **Create an API key** at [console.b1m.ai](https://console.b1m.ai) | Add credits and issue the key everything else authenticates with. | | 2 | **Install [Beam Studio](/docs/studio)** | The self-hosted application where you build data movement as a graph — transfers, transforms, checks, branching, schedules — and watch it run. Most teams operate Beam from here. | | 3 | **Install the [Beam CLI](/docs/cli)** | The terminal client for your account, your machines, and ad hoc transfers. | ```bash # 2. Beam Studio — needs a Linux host with Docker Engine and Compose v2 curl -fsSL https://cdn.b1m.ai/studio/install.sh | sudo sh # 3. Beam CLI — macOS, Linux, Windows curl -fsSL https://cdn.b1m.ai/cli/install.sh | sh ``` Building Beam into an application you already maintain instead? Use the [SDK](/docs/sdk) — Python, TypeScript, Go, Rust, or the browser — or call the [HTTP API](/docs/api-reference) directly. All of them reach the same network and spend the same organization credits. Beam has one public environment: production, at [console.b1m.ai](https://console.b1m.ai). The rest of this page explains what the network is and why it works that way. *** ## The Problem with Data Movement Today [#the-problem-with-data-movement-today] Data transfer today is not a single system, but a stack of infrastructure layers — cloud networks (AWS, GCP, Azure), CDNs, and the underlying web of transit providers and peering agreements. These systems are powerful but operate as closed environments. Routing decisions are driven by provider policies, BGP, and pre-negotiated relationships — not by real-time application needs or measured end-to-end performance. What's missing is an open mechanism where paths compete based on latency, throughput, or reliability. Applications cannot express intent, and networks do not dynamically optimize for delivery outcomes. This limitation is becoming more critical as data movement scales. AI training and distributed workloads are rapidly increasing transfer volumes, and data movement can represent a significant share of total system cost. Cloud providers charge substantial egress fees — typically **$0.08–$0.12 per GB** — reflecting both infrastructure costs and closed ecosystem incentives. ### Structural limitations [#structural-limitations] | Limitation | Detail | | ----------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Pricing disconnected from performance** | Bandwidth is priced per GB regardless of delivery quality. No mechanism adapts pricing or routing to real-time conditions. | | **Routing is not programmable** | Applications cannot dynamically select paths, leverage multiple networks in parallel, or adapt in real time. | | **Infrastructure is permissioned** | Data delivery is controlled by large providers. Independent operators cannot contribute bandwidth or be rewarded based on performance. | | **Idle capacity cannot participate** | Significant unused bandwidth exists across data centers, ISPs, and edge networks, but it cannot be programmatically discovered, allocated, or monetized. | Beam introduces the missing layer — a coordination system where bandwidth becomes **measurable, competitive, and programmable**. *** ## How Beam Works [#how-beam-works] Beam operates as a real-time coordination layer that orchestrates how data moves across a distributed network of participants. Rather than relying on fixed infrastructure or predefined routes, Beam dynamically selects how data is transferred based on performance, availability, and economic incentives. *** ## Core Roles [#core-roles] Beam is composed of five roles that coordinate to move data across a distributed network. Each role is intentionally separated so that coordination, execution, and verification remain independent — creating a system where performance drives outcomes.

Clients

Originators of transfer requests — applications, services, enterprises, or AI agents. Clients express intent (move data from A to B under these conditions) and delegate execution to the network.

BeamCore

The coordination layer. Assigns work, tracks transfers, handles retries, and ensures observable, accountable execution. Does not touch the data itself.

Orchestrators

Turn transfer requests into execution strategies. Manage pools of workers, decide chunking and parallelism, and are evaluated on their entire pool's aggregate performance.

Workers

The off-chain execution layer. Move data from source to destination, report completed chunks, and compete to remain in high-performing pools.

Validators

Verify delivery integrity and enforce economic fairness. Confirm that work was real, performance is measurable, and rewards reflect actual contribution.

*** ## The Competitive Market [#the-competitive-market] Beam creates a fluid, performance-driven marketplace with aligned incentives at every layer: **Orchestrators** compete to build and maintain the most reliable worker pools. Better performance -> higher PRISM score -> more transfer assignments, while completed qualified production work drives validator weight and $TAO emissions. Orchestrators are evaluated at the *pool level*, so even a small number of weak workers degrades their score. They must also compensate workers fairly - validators enforce this, and failure to pay appropriately reduces future assignments. **Workers** compete to remain in high-performing pools. They are continuously evaluated on delivery success, throughput, and latency consistency. Workers are not locked into a single orchestrator — they migrate toward orchestrators offering the most reliable work and the best rewards, reinforcing a system where fairness is enforced by market dynamics, not policy alone. **Validators** bridge off-chain execution with on-chain incentives. They consume BeamCore performance metrics and set weights so orchestrators with stronger delivery receive more emissions over time. *** ## What Beam Enables [#what-beam-enables] * **High-performance transfer** — Data moves in parallel across multiple paths, dynamically optimized for real-time conditions. Particularly valuable for large datasets, AI pipelines, and cross-region systems. * **Resilient delivery** — Distributed across multiple workers and orchestrators, with automatic recovery from network issues. * **Programmable routing** — Define intent (source, destination, constraints) and the network determines the best execution strategy. * **Cost efficiency through competition** — Participants compete to deliver data, aligning cost more closely with actual performance. *** ## Bittensor Subnet 105 [#bittensor-subnet-105] Beam operates as **subnet 105** on the Bittensor network. Performance scores shape production routing, and validators submit verified-uploaded-byte epoch weights for $TAO emissions. That is what pays orchestrators to keep high-quality workers and to complete real production work — the competition you benefit from as a client. You do not need to interact with Bittensor directly to use Beam as a client. Connectors (S3, R2, GCS, HTTP) abstract all network details. *** ## Key Concepts [#key-concepts] * **Transfer** — A request to move data from source to destination, split into chunks and distributed across workers. * **Task** — A single chunk-level work unit assigned to a specific worker. * **Epoch** — A Bittensor time unit (\~12 minutes) after which weights are updated and emissions are distributed. *** ## Where To Go Next [#where-to-go-next] This site documents Beam for **clients** — everything needed to move data over the network. If you only want to send bytes, go straight to the [Developer Quickstart](/docs/developer-quickstart) — API key, then [Beam Studio](/docs/studio), then the [Beam CLI](/docs/cli). If you want the whole picture first, read [Architecture](/docs/architecture) and then [How Transfers Work](/docs/transfers). The SDK, CLI, and Studio source lives on GitHub — see [Source code](/docs/clients#source-code). Running an orchestrator, a worker, or a validator is documented separately; ask the Beam team for the participant documentation. # Account Management API (/docs/management-api) Everything the console does to an organization's API keys and billing can also be done over HTTP, at [api.b1m.ai](https://api.b1m.ai). Mint a key from CI, freeze a leaked one from a script, or pull usage into your own billing system. ## Two APIs, two credentials [#two-apis-two-credentials] This is the part worth reading twice. Beam has two HTTP APIs and they do not share a credential. | | Transfer API | Management API | | ---------- | ------------------- | ------------------------------------------- | | Host | `beamcore.b1m.ai` | `api.b1m.ai` | | Does | Runs transfers | Administers keys and billing | | Credential | An API key, `b1m_…` | A **service account credential**, `bm_sa_…` | | Header | `X-Api-Key` | `Authorization: Bearer` | A transfer key cannot manage keys, deliberately. A transfer key is handed to whatever runs a job — CI, a container, a colleague's laptop. If it could also mint keys, one leaked credential could issue successors that outlive revoking the original, and revoking it would not end the compromise. So the two capabilities are held by different credentials, and a service account is created and revoked from the console, separately from the keys it administers. A service account credential also cannot run transfers. Each does one job. *** ## Getting a credential [#getting-a-credential] In the console, go to **Organization → Service accounts** and create one. A service account is a machine identity: it has a name, a role, and optionally a project, and it holds one or more credentials. Creating a credential shows the `bm_sa_…` secret **once**. It is stored hashed and cannot be shown again — if you lose it, issue another. You need the **Manage service accounts** permission to create one. If you do not have it, an organization owner or admin does. ### What a credential is allowed to do [#what-a-credential-is-allowed-to-do] A credential's permissions come from its service account's role, plus any permissions granted to that service account directly: | Role | Can read keys and billing | Can create and rotate keys | Can revoke keys | Can change billing | | ------------ | ----------------------------- | -------------------------- | --------------- | ------------------ | | Owner, Admin | Yes | Yes | Yes | Yes | | Developer | Yes | Yes | No | No | | Billing | Yes | Yes | No | Yes | | Viewer | Yes | No | No | No | | Custom | Only what is granted directly | | | | Give a service account the least that its job needs. A deployment pipeline that only rotates keys does not need billing access. Disabling the service account disables every credential it holds, at once. That is the fastest way to cut off an integration. *** ## Authentication [#authentication] Send the credential as a bearer token: ```bash curl https://api.b1m.ai/v1/keys \ -H "Authorization: Bearer bm_sa_your_credential" ``` `X-Api-Key: bm_sa_…` is accepted as well, if that is easier for your client. Every route answers for exactly one organization — the one its credential belongs to. There is no organization parameter, and a credential cannot read or change another organization. *** ## Managing API keys [#managing-api-keys] | Method | Path | Permission | | -------- | --------------------- | ----------------------- | | `GET` | `/v1/keys` | Read API keys | | `POST` | `/v1/keys` | Create API keys | | `GET` | `/v1/keys/:id` | Read API keys | | `PATCH` | `/v1/keys/:id` | Create API keys | | `POST` | `/v1/keys/:id/rotate` | Create API keys | | `DELETE` | `/v1/keys/:id` | Manage service accounts | These manage **transfer keys** (`b1m_…`). Service account credentials are not listed here and are managed from the console. ### Create a key [#create-a-key] ```bash curl -X POST https://api.b1m.ai/v1/keys \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" \ -H "Content-Type: application/json" \ -d '{"name": "production ingest", "creditLimit": 5000}' ``` | Field | | | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | | `name` | Required. | | `expiresAt` | ISO date or timestamp. A bare date expires at the end of that day, UTC. Omit for a key that does not expire. | | `creditLimit` | Credits this key may spend, on top of the organization's balance. Omit for no per-key cap. | | `projectId` | Scope the key to a project, so its spend is attributed there. | | `monthlyBudgetCredits`, `budgetWarningThresholds`, `budgetBlockOnExceed` | Budget controls. Sending any of these also requires **Manage billing**. | The response carries `rawKey` — the only time the secret is returned. Store it before you do anything else. ```json { "key": { "id": "cmud1y0pl0001qr018c338s2g", "name": "production ingest", "prefix": "b1m_p6e-1LXE", "status": "ACTIVE", "creditLimit": 5000, "rawKey": "b1m_p6e-1LXE…" } } ``` Your organization must have passed KYC before it can create keys, and a restricted organization cannot create them at all. ### Freeze a key [#freeze-a-key] Freezing stops a key working while keeping it, its budget and its usage history. Use it when you suspect a key is compromised but are not ready to throw it away. ```bash curl -X PATCH https://api.b1m.ai/v1/keys/$KEY_ID \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" \ -H "Content-Type: application/json" \ -d '{"status": "DISABLED"}' ``` `status` accepts `ACTIVE`, `DISABLED` and `REVOKED`. Freezing is reversible; revoking is not. The same call changes `name`, `creditLimit`, `expiresAt`, `projectId` and the budget fields. A frozen key stops authenticating transfers immediately, including any secret still inside a rotation grace period. ### Move a key between projects [#move-a-key-between-projects] A key's scope is not fixed at creation. `PATCH` it with a different `projectId` to move it, or with `null` to return it to organization scope: ```bash # scope it to a project curl -X PATCH https://api.b1m.ai/v1/keys/$KEY_ID \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" \ -H "Content-Type: application/json" \ -d '{"projectId": "cmuel5roi000zop016h40hpi3"}' # back to organization-wide -d '{"projectId": null}' ``` Moving a key changes where its **future** spend is attributed. Usage already recorded stays under the project it was spent in, so past periods do not move with the key. **An organization-wide credential can move a key anywhere in its organization**, including back to organization scope. **A project-scoped credential can only move keys between the projects it holds** — sending a key to a project it cannot reach, or to organization scope, would put that key beyond the caller on the very next request. Either returns `403 project_out_of_scope`, and the response names the projects that are allowed: ```json { "error": "project_out_of_scope", "message": "This credential can only move keys between the projects it is scoped to", "allowed": ["cmuel5roi000zop016h40hpi3"] } ``` Omitting `projectId` entirely leaves the scope alone — it is only read when present. ### Delete a key [#delete-a-key] ```bash curl -X DELETE https://api.b1m.ai/v1/keys/$KEY_ID \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" ``` The key is removed and every secret it ever had stops working. Its past spend stays in your usage history — deleting a key does not rewrite what it cost you. *** ## Rotating a key [#rotating-a-key] Rotation issues a new secret for an existing key while keeping its identity, project, budget and usage history. The old secret keeps working for a grace period, so a deployment can pick up the new secret at its own pace instead of losing access the moment you rotate. ```bash curl -X POST https://api.b1m.ai/v1/keys/$KEY_ID/rotate \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" \ -H "Content-Type: application/json" \ -d '{"gracePeriodDays": 7}' ``` `gracePeriodDays` is one of `0`, `1`, `3`, `7` or `14`, and defaults to `7`. ```json { "key": { "prefix": "b1m_pQOAb7YF", "rawKey": "b1m_pQOAb7YF…" }, "rotation": { "oldPrefix": "b1m_p1y5El5i", "newPrefix": "b1m_pQOAb7YF", "gracePeriodDays": 7, "oldMaterialExpiresAt": "2026-09-29T19:16:10.000Z" } } ``` **Both secrets authenticate until `oldMaterialExpiresAt`.** Deploy the new one, confirm it works, and let the old one lapse. Choose `0` when the old secret is compromised: it is revoked on the spot, and anything still using it fails immediately. That is the point — a grace period is for planned rotation, not for a leak. Rotation recomputes the key's permissions rather than copying them, so a permission changed since the key was issued takes effect when it rotates. Only an `ACTIVE` key can be rotated. *** ## Projects [#projects] A project groups keys so their spend is attributed together and can be capped together. Because a key can be created straight into one, the API can make and remove projects too. | Method | Path | Permission | | -------- | ------------------ | --------------------------------------- | | `GET` | `/v1/projects` | Read transfers | | `POST` | `/v1/projects` | Create transfers, at organization scope | | `DELETE` | `/v1/projects/:id` | Create transfers, at organization scope | ```bash curl -X POST https://api.b1m.ai/v1/projects \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" \ -H "Content-Type: application/json" \ -d '{"name": "Data pipeline", "description": "Nightly ingest"}' ``` | Field | | | ------------- | ------------------------------------------------------------------------- | | `name` | Required, at least 2 characters. | | `description` | Optional. | | `memberIds` | Organization members to add. Ignored for anyone outside the organization. | The slug is derived from the name and made unique within the organization, so a second `Data pipeline` becomes `data-pipeline-2`. **Creating and deleting both require the permission at organization scope.** A credential confined to one project cannot mint another or delete the boundary it was given — see [What a credential is allowed to do](#what-a-credential-is-allowed-to-do). ### Delete a project [#delete-a-project] ```bash curl -X DELETE https://api.b1m.ai/v1/projects/$PROJECT_ID \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" ``` A project must be empty first. While any API key or service account still belongs to it, the call returns `409 project_not_empty` and names what is in the way: ```json { "error": "project_not_empty", "message": "This project still has 2 API keys and 1 service account. Move or delete them first." } ``` This is deliberate. A project-scoped key or credential is scoped by pointing at the project; delete the project underneath it and that scope falls away, quietly promoting it to organization-wide reach. Move them to another project, or delete them, and the promotion never happens. Deleting a project removes its members and its budget. Usage already recorded stays in your billing history. *** ## Credits and usage [#credits-and-usage] | Method | Path | Permission | | ------ | ------------- | ------------ | | `GET` | `/v1/credits` | Read billing | | `GET` | `/v1/usage` | Read billing | `/v1/credits` returns the organization's balance: ```json { "organizationId": "org_…", "organizationName": "Acme", "credits": 4820, "restrictionStatus": "NONE" } ``` `/v1/usage` answers where credits went, broken down by key, by project and by action: ```bash curl "https://api.b1m.ai/v1/usage?dateFrom=2026-09-01&dateTo=2026-09-30" \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" ``` | Parameter | | | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `days` | Days to look back. Defaults to 30, capped at 365. | | `dateFrom`, `dateTo` | An explicit window, which takes precedence over `days`. A bare date covers that whole day, UTC, so a calendar month means that month. | | `keyId` | Restrict to one key. | The response carries `totalCreditsUsed`, `totalRequests`, `byKey`, `byProject`, `byAction`, `dailyUsage`, and the 50 most recent usage transactions. All three breakdowns are derived from the same period, so they always agree with the total. Each breakdown is a snapshot of what was true when the credits were spent. Moving a key between projects does not rewrite earlier periods. *** ## Auto top-up [#auto-top-up] Auto top-up buys a credit pack automatically when the balance falls to a threshold. | Method | Path | Permission | | ------- | ------------------------ | -------------------- | | `GET` | `/v1/billing/auto-topup` | Read billing | | `PATCH` | `/v1/billing/auto-topup` | Manage billing | | `GET` | `/v1/billing/packs` | Any valid credential | ```bash curl -X PATCH https://api.b1m.ai/v1/billing/auto-topup \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" \ -H "Content-Type: application/json" \ -d '{"enabled": true, "thresholdCredits": 500, "packId": "pack_50"}' ``` `thresholdCredits` is between 1 and 10,000. `packId` comes from `/v1/billing/packs`. **Adding a card is the one thing this API cannot do.** Card details go to Stripe through the console, never through Beam. Enabling auto top-up without a saved payment method answers `409 payment_method_required`; add one in **Billing** first, then enable it here. Once a card is saved, everything else about auto top-up is configurable programmatically. A failed charge disables further attempts and records the reason, so a dead card does not get retried indefinitely. Writing to this endpoint clears that state, which is how you resume after fixing the card. *** ## Budget alerts [#budget-alerts] A monthly budget is only useful if something tells you when it is running out. Set a budget and its warning thresholds on a key — `monthlyBudgetCredits`, `budgetWarningThresholds`, `budgetBlockOnExceed` — and Beam records an alert the first time each threshold is crossed in a month. | Method | Path | Permission | | ------ | ------------ | ------------ | | `GET` | `/v1/alerts` | Read billing | ```bash curl https://api.b1m.ai/v1/alerts \ -H "Authorization: Bearer $BEAM_MANAGEMENT_CREDENTIAL" ``` | Query | | | ---------------- | ------------------------------------------------------------------------------ | | `since` | ISO timestamp. Only alerts raised after it — poll with the last value you saw. | | `unacknowledged` | `true` to drop alerts already dismissed in the console. | | `limit` | 1–200, default 50. | The response also carries `organizationId` — the organization the credential speaks for. A client holding one credential on behalf of several viewers must check it against whoever is looking, rather than assuming the alerts belong to them. ```json { "alerts": [ { "id": "cmuf…", "targetType": "api_key", "threshold": 80, "usageCredits": 812, "budgetCredits": 1000, "percentUsed": 81, "month": "2026-09-01T00:00:00.000Z", "createdAt": "2026-09-23T14:22:04.000Z", "acknowledgedAt": null, "apiKey": { "id": "cmue…", "name": "production ingest", "prefix": "b1m_p6e-1LXE" }, "project": null } ] } ``` **Each threshold raises one alert per target per month.** Crossing 80% does not alert again on the next transfer, so polling this endpoint gives you a list of crossings rather than a stream that repeats. **Spending the budget always raises a `threshold: 100` alert**, whatever warning thresholds are configured. Without it, a key that crossed 95% earlier in the month and then ran out produced nothing new — exhaustion, the one state worth acting on, was the only silent one. **A refused charge still raises its alert.** With `budgetBlockOnExceed` set, usage beyond the budget is rejected — and the crossing is recorded anyway, so a blocked key explains itself here rather than only through a `403` at the call site. The thresholds recorded are the ones the key has actually reached: a key at 3 of 4 credits that is refused a 2-credit charge reports 75%, not 125%. `beam-cli` signs in as a person rather than as a service account, so the same alerts are also served at `GET /api/alerts` for a device-flow session, taking an `X-Organization-Id` header and the same query parameters. A member needs `billing:read`, which every role carries. ### Where a budget stands right now [#where-a-budget-stands-right-now] Alerts say what already happened. Every key returned by `/v1/keys` also carries a `budget` object saying where it stands: ```json { "budget": { "budgetCredits": 1000, "usageCredits": 812, "percentUsed": 81, "thresholds": [50, 80, 95], "thresholdsReached": [50, 80], "blockOnExceed": true, "state": "warning" } } ``` | `state` | | | ---------- | ------------------------------------------------ | | `none` | No budget set. Nothing to report. | | `ok` | Under every threshold. | | `warning` | At or past a threshold, still under budget. | | `exceeded` | At or past budget, and usage continues. | | `blocked` | At or past budget, and further usage is refused. | `percentUsed` is clamped to 100, so a progress bar built on it never overflows. **`blocked` is enforced, not advisory.** With `budgetBlockOnExceed` set, usage beyond the budget is rejected with `403`. That check runs when usage is recorded, so it stops the next charge rather than one already in flight — bytes that have already moved are still billed. *** ## Errors [#errors] Every error returns a JSON body with a stable `error` code and a human-readable `message`. Match on the code. | Status | Code | | | ------ | ------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | 401 | `unauthorized` | Missing, unknown, or not a service account credential. | | 401 | `credential_inactive` | The credential or its service account is disabled, revoked or expired. | | 403 | `insufficient_scope` | Valid credential, but it does not hold the required permission. The response names it. | | 403 | `kyc_required` | The organization must pass KYC before creating keys. | | 403 | `organization_blocked` | The organization is restricted. | | 403 | `project_out_of_scope` | A project-scoped credential tried to move a key outside its projects. | | 403 | `monthly budget exhausted` | A budget with `budgetBlockOnExceed` is spent. Raise it, or clear the block. | | 404 | `not_found` | No such key or project in this organization. | | 400 | `name_required`, `invalid_credit_limit`, `invalid_expiration` | Bad field on create or update. | | 400 | `invalid_name` | A project name must be at least 2 characters. | | 400 | `invalid_status` | `status` must be `ACTIVE`, `DISABLED` or `REVOKED`. | | 400 | `key_not_active` | Only an active key can be rotated. | | 400 | `invalid_grace_period` | Must be 0, 1, 3, 7 or 14. | | 400 | `invalid_threshold`, `invalid_pack` | Bad auto top-up setting. | | 409 | `payment_method_required` | Enable auto top-up only after a card is saved. | | 409 | `project_not_empty` | Keys or service accounts still belong to the project. | An unknown credential and a transfer key presented to this API both return the same `401 unauthorized`. Telling a transfer key that it is merely the wrong *kind* of credential would confirm it is a valid one. *** ## Related [#related] * [Developer Quickstart](/docs/developer-quickstart) — create your first key and send a transfer. * [Billing & Payments](/docs/billing) — how payments become credits, and the console's own billing screens. * [API Reference](/docs/api-reference) — the transfer API at `beamcore.b1m.ai`. # Beam SDK (/docs/sdk) The **Beam SDK** creates transfers and drives their lifecycle from your own code. It prepares a transfer, signs the routes workers will use, distributes the work to the network, and reconciles the terminal status. Provider credentials stay in your process. The SDK signs task-scoped routes locally, so your S3, R2, Hippius, or Hugging Face keys are never sent to Beam or to a participant. If you are sending your first transfer, start with the [Developer Quickstart](/docs/developer-quickstart). This page is the map of what is available in each language. *** ## Packages [#packages] | Language | Install from | Package | | ----------------- | ------------ | ------------------------------------------------- | | Python | PyPI | `beam-network-sdk` | | TypeScript / Node | npm | `@beam-network/sdk` | | Go | Go modules | `github.com/Beam-Network/beam-sdk-public/sdks/go` | | Rust | crates.io | `beam-network-sdk` | | CLI | npm | `@beam-network/cli` | | Browser | npm | `@beam-network/web-sdk` | | Token broker | npm | `@beam-network/web-sdk-server` | All of them reach the same network and spend the same organization credits, and every transfer they create appears together in the Console. *** ## Install [#install] ```bash python -m pip install beam-network-sdk ``` ```bash npm install @beam-network/sdk ``` ```bash go get github.com/Beam-Network/beam-sdk-public/sdks/go ``` ```toml beam-network-sdk = "0.2" ``` *** ## Command line [#command-line] `@beam-network/cli` installs a `beam-send` binary for creating and monitoring transfers without writing code: ```bash npm install -g @beam-network/cli beam-send --help ``` For machine enrolment, Rooms and sharing, use the [Beam CLI](/docs/cli) instead. The two are separate: `beam-send` drives the transfer lifecycle, `beam` drives your account and machine. *** ## Authenticate [#authenticate] Every server-side client needs a Beam API key from the Console. Pass it from the environment rather than committing it: ```bash export BEAM_API_KEY=b1m_... ``` That is the only configuration a client needs: every SDK targets production and resolves its endpoints itself. API keys spend credits, so they belong server-side. To move data from a page, use the [browser SDK](#browser-transfers), which never holds a key. *** ## The lifecycle [#the-lifecycle] Every language follows the same three steps: 1. **Create** — describe sources and destinations. The SDK prepares the transfer and signs destination routes locally. 2. **Distribute** — hand the transfer to the network. Orchestrators assign workers, which move bytes directly between your endpoints. 3. **Wait** — block on a terminal status, or poll it yourself. See [How Transfers Work](/docs/transfers) for what the network does during each step. ### TypeScript [#typescript] ```typescript import { BeamClient } from "@beam-network/sdk"; const beam = new BeamClient({ apiKey: process.env.BEAM_API_KEY! }); const transfer = await beam.createTransfer({ sources: [{ type: "http", url: process.env.BEAM_SOURCE_URL! }], destinations: [{ type: "http", url: process.env.BEAM_DESTINATION_URL! }], total_size: Number(process.env.BEAM_TOTAL_SIZE), name: "first-transfer", }); await beam.distributeTransfer(transfer.transfer_id); const status = await beam.waitForTransfer(transfer.transfer_id); console.log(status.status); ``` ### Go [#go] ```go client := beamnetworksdk.NewClient( beamnetworksdk.WithAPIKey(os.Getenv("BEAM_API_KEY")), ) defer client.Close() transfer, err := client.CreateTransfer(ctx, beamnetworksdk.TransferCreateRequest{ Sources: []beamnetworksdk.SourceConfig{{"type": "http", "url": sourceURL}}, Destinations: []beamnetworksdk.DestConfig{{"type": "http", "url": destURL}}, TotalSize: totalSize, Name: "first-transfer", }) ``` The Python equivalent is in the [Developer Quickstart](/docs/developer-quickstart). *** ## Storage providers [#storage-providers] The snippets above move data between plain HTTP endpoints. To move it between object storage, use the provider configs, which keep credentials in your process and mint task-scoped access for workers. See [Connectors](/docs/connectors) for S3, Cloudflare R2, Google Cloud Storage, Hippius, and HTTP, including the fields each one needs. *** ## Browser transfers [#browser-transfers] The browser SDK is a different shape from the server SDKs. `@beam-network/web-sdk` runs in a page and never sees a credential. `@beam-network/web-sdk-server` runs in your backend and mints short-lived, scoped tokens for it. Use this pairing for Rooms, broadcast, and transfers started from a web application. The browser packages are not published to npm yet. Ask the Beam team for access if you need them before then. *** ## Source code [#source-code] | Repository | Status | | --------------------------------------------------------------------------------- | ------- | | [`Beam-Network/beam-sdk-public`](https://github.com/Beam-Network/beam-sdk-public) | Public. | See [Build with Beam](/docs/clients#source-code) for the CLI and Studio repositories. *** ## Next steps [#next-steps] * [Developer Quickstart](/docs/developer-quickstart) — Send your first transfer. * [Connectors](/docs/connectors) — Configure the storage you move data between. * [How Transfers Work](/docs/transfers) — The lifecycle behind these calls. * [API Reference](/docs/api-reference) — The HTTP API underneath the SDKs. # Beam Studio (/docs/studio) **Beam Studio** is a self-hosted application for designing and operating data movement visually. Instead of writing transfer code, you compose transfers, transforms, checks, and control flow as a graph, then let Studio run it and show you what happened. Studio is a client of Beam, exactly like the SDK and the HTTP API. It sends transfers through the same network, against the same organization credits, and the transfers it creates appear in the Console alongside every other transfer. *** ## When to use Studio [#when-to-use-studio] | Interface | Use it when | | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Studio** | The work is a pipeline, not a single transfer — several steps, conditions, retries, or a schedule. You want your team to read the process without reading code. | | **[SDK](/docs/sdk)** | A transfer is one step inside an application you already maintain. | | **HTTP API** | Your language has no SDK, or you drive the transfer lifecycle yourself. | | **[CLI](/docs/cli)** | You want to move data from a terminal without writing code. | Studio is not a replacement for the SDK. Reach for it when the interesting part is everything *around* the transfer. *** ## What you can build [#what-you-can-build] A Studio workflow is a graph you assemble from a catalog of Beam operations, storage connectors, webhooks, and data transformations. That lets one workflow cover a whole job: * Move bytes between any [supported connectors](/docs/connectors). * Transform data between steps. * Assert conditions before continuing, and branch on the result. * Call out to your own systems with webhooks. *** ## How work runs [#how-work-runs] Studio turns a workflow into a durable runtime plan, and its workers carry each step to completion. Because the plan is durable, a workflow survives restarts and resumes rather than starting over. Every step reports state, so you can see what is queued, running, waiting, failed, or complete without following terminal output. This is the main practical difference from driving transfers yourself: the run is inspectable after the fact, not just while your process is alive. Workflows start in three ways, all with the same execution model: | Trigger | Use it for | | ---------------------- | ------------------------------------------ | | On demand | One-off and ad hoc runs. | | On a schedule | Recurring syncs and batch jobs. | | From an external event | Reacting to something in your own systems. | *** ## Connect Studio to your organization [#connect-studio-to-your-organization] Studio authenticates to Beam with a device authorization code rather than a pasted API key, so the credential is issued to that Studio installation. 1. Start the connect flow in Studio. It displays a short user code. 2. Approve the code at [console.b1m.ai/studio/connect](https://console.b1m.ai/studio/connect). 3. Sign in if prompted, confirm the organization, and approve. Studio receives its credentials once you approve, and transfers it creates are billed to that organization. User codes are single use and expire. If approval fails, restart the connect flow in Studio to get a fresh code rather than reusing the old one. *** ## Install [#install] Studio runs on your own infrastructure, which is what lets it hold credentials for your storage providers locally. You need a Linux host with Docker Engine and Docker Compose v2, plus `curl`, `jq`, OpenSSL, and systemd. The installer does not install Docker for you. The hosted installer sets up the release updater, pulls the signed images, and starts the stack: ```bash curl -fsSL https://cdn.b1m.ai/studio/install.sh | sudo sh ``` Set the public URL first if Studio will be reachable at a domain rather than on localhost: ```bash export BEAM_STUDIO_PUBLIC_URL=https://studio.example.com curl -fsSL "https://cdn.b1m.ai/studio/install.sh" | sudo -E sh ``` | Variable | Default | Purpose | | ------------------------- | ----------------------- | ------------------------------ | | `BEAM_STUDIO_PUBLIC_URL` | `http://localhost:3004` | Where Studio is served. | | `BEAM_STUDIO_INSTALL_DIR` | `/opt/beam-studio` | Installation directory. | | `BEAM_STUDIO_CONFIG_DIR` | `/etc/beam-studio` | Configuration and release key. | Each release is verified against a pinned signing key before it is applied, so an unsigned or tampered release is rejected rather than installed. ### Run it from source [#run-it-from-source] To build and run the stack yourself instead, clone the source repository (`Beam-Network/beam-studio-public`, see [Source code](#source-code)) and start the stack: ```bash cd beam-studio-public cp .env.example .env docker compose up -d ``` Edit `.env` before starting. It ships placeholder secrets — including `BEAM_STUDIO_SECRET_KEY` — that must be replaced with real random values, and it marks which settings are required. Never expose a Studio installation that still uses the placeholder secrets from `.env.example`. ### Updating [#updating] Installations made with the hosted installer update from signed manifests, with health checks, a backup policy, and rollback, so an update that fails its checks does not leave the installation broken. A source installation updates by pulling the repository and running `docker compose up -d` again. *** ## Source code [#source-code] | Repository | Status | | --------------------------------- | --------------------------------------------------- | | `Beam-Network/beam-studio-public` | Being prepared for publication — not yet reachable. | Until it is published, install Studio with the hosted installer above. See [Build with Beam](/docs/clients#source-code) for the CLI and SDK repositories. *** ## Next steps [#next-steps] * [Connectors](/docs/connectors) — Configure the storage Studio moves data between. * [How Transfers Work](/docs/transfers) — What happens once a Studio step starts a transfer. * [Billing & Payments](/docs/billing) — The credits Studio workflows consume. * [Beam Studio](https://b1m.ai/studio) — Product overview and access. # How Transfers Work (/docs/transfers) A Beam transfer moves data from a source to a destination by splitting it into chunks and distributing those chunks across multiple workers. This page walks through the full lifecycle from request to completion. *** ## Transfer Lifecycle [#transfer-lifecycle] *** ## Step-by-Step [#step-by-step] ### 1. Create a Transfer [#1-create-a-transfer] The client submits a transfer request to the Core Server specifying one or more sources, one or more destinations, and the total byte size. ```http POST /transfers/create Content-Type: application/json X-Api-Key: b1m_... { "sources": [ { "type": "s3", "bucket": "my-data", "key": "dataset.tar.gz" } ], "destinations": [ { "type": "s3", "bucket": "beam-output", "key": "dataset.tar.gz" } ], "total_size": 1073741824, "name": "dataset-transfer" } ``` The Core Server: 1. Validates the request and API key 2. Computes the chunking plan from the total size 3. Creates one **task** per chunk 4. Returns `transfer_id`, `transfer_key`, `total_chunks`, and the selected `chunk_size` Call `POST /transfers/distribute` with the returned `transfer_id` to begin assignment: ```http POST /transfers/distribute Content-Type: application/json X-Api-Key: b1m_... { "transfer_id": "uuid" } ``` ### 2. Task Assignment [#2-task-assignment] The Core Server selects an orchestrator from the **active pool** using PRISM scores as routing weights. Orchestrators in the `qualified` pool are preferred; `qualifying` orchestrators serve as overflow capacity. Tasks are dispatched to the orchestrator's control plane connection. ### 3. Worker Execution [#3-worker-execution] The orchestrator assigns each task to an available worker via the Worker Gateway WebSocket: 1. Download the source chunk 2. Write it to the destination backend 3. Compute a cryptographic hash of the transferred bytes 4. Report the completed chunk with `task_result` ### 4. Completion [#4-completion] Once all chunks are verified, the transfer status transitions to `completed`. The Core Server records: * Total bytes transferred per orchestrator * Task completion counts per worker Failed or missing verified task evidence can reduce the orchestrator's reliability inputs and PRISM routing weight. *** ## Signed URL Multipart (`signed_url_v1`) [#signed-url-multipart-signed_url_v1] For client-supplied destination storage, Beam prepares task-scoped signed access for each chunk. A worker receives only the short-lived source and destination access needed for its assigned chunk, uploads the part, and reports the storage `ETag` in `task_result`. BeamCore verifies the uploaded parts with object storage and completes the multipart object after all chunks are done. Workers do not receive bucket credentials or unrestricted access to the full source or destination object. *** ## Transfer Statuses [#transfer-statuses] | Status | Meaning | | ------------- | ----------------------------------------------------------- | | `pending` | Created, awaiting task assignment | | `in_progress` | One or more chunks being transferred | | `completed` | All chunks verified | | `failed` | Terminal error — the transfer or a chunk could not complete | | `cancelled` | Cancelled by client or timeout | Public Transfer Detail responses convert operational transfer and task failures into fixed, audience-safe messages. Database errors, provider responses, object paths, identifiers, and other diagnostic details are not returned to the browser, and the interface does not provide a raw-error expansion. *** ## Chunking [#chunking] Files are split server-side using BeamCore chunking configuration. The current minimum is **40 MiB**. Chunk size grows for large transfers. Chunk boundaries are deterministic given a file size. Each chunk becomes an independent task that can be executed by a different worker on a different orchestrator, enabling parallelism for large transfers. *** ## Fault Tolerance [#fault-tolerance] When an active task-offer batch has a **5 second** gap between valid task results for current in-progress tasks, BeamCore reassigns the affected active chunk indices. Recovery is automatic: a participant that stalls is replaced rather than waited on. Recovery follows the same orchestrator flow as initial delivery: 1. Eligible orchestrators receive `worker_task_offer_batch` with executable task offers. 2. Each orchestrator selects connected local workers and forwards individual `task_offer` messages. 3. Workers report success or failure with `task_result`; orchestrators relay each result immediately until BeamCore returns a terminal acknowledgement. Qualifying transfers draw recovery candidates from the qualifying pool. Qualified transfers draw from the qualified pool. Orchestrators should keep the NATS control connection healthy and route `worker_task_offer_batch` messages promptly during recovery. Repeated stalls on the same orchestrator reduce its PRISM routing weight until reliability improves. ***