Authentication and conventions

Conventions of the management API: bearer authentication, roles and capabilities, idempotent mutations, pagination and the error envelope.

  • Availability: Planned
  • Evidence: Read from source
  • Reference

Authentication

Every request carries the bearer token of the shared Beyond authority, the same identity Workspace uses:

HTTP
GET /v1/session HTTP/1.1
Authorization: Bearer <token>

The CDN keeps no accounts and no memberships. An organization is a Workspace team, and the CDN stores only opaque organization and user identifiers. Guest tokens of private applications are never accepted by this API.

Operation Request Capability Retry
session.read GET /v1/session Any signed-in user
organization.read GET /v1/organizations/{organization} application.read

session.read answers the signed-in user, its organizations, roles, CDN capabilities and a plan summary. organization.read answers the context of one organization of the caller. When the authority cannot be reached the answer is 502 UPSTREAM_UNAVAILABLE, never a refusal or an approval.

Roles and capabilities

Roles come from the authority: owner, admin, developer, viewer and none. The CDN owns a table of capabilities over those roles, and each operation names the capability it requires.

Capability Allows owner admin developer viewer
application.read Read applications, targets, registrations, graphs, inventories, jobs, releases, environments, domains and backend closures Yes Yes Yes Yes
application.manage Create, change and delete applications and their targets, and bind an application to a Beyond project or release it Yes Yes Yes
release.prepare Register selections, prepare candidates, cancel jobs and bind the testing environment Yes Yes Yes
release.promote Bind production: promote, roll back and retire releases Yes Yes
access.manage Change visibility and manage guest grants Yes Yes
domain.manage Reserve the testing subdomain and manage custom domains Yes Yes
providers.manage Read the credential-free summary of the organization's registry providers, and set or remove their settings and write-only credentials Yes Yes
usage.read Read usage, quotas, plan, entitlements, credit and ledger Yes Yes Yes
plan.request Join or leave the premium waitlist Yes Yes
events.subscribe Obtain realtime grants, replay events and read snapshots Yes Yes Yes Yes

The role none has no capability and hides the organization's resources.

Two operations require a capability that depends on the environment they act on: promotion and rollback need release.prepare for testing and release.promote for production. The contract states this in a machine-readable form, x-beyond-capability-by, next to x-beyond-capability.

Refusals follow one rule. A resource the caller cannot see answers 404 NOT_FOUND, so its existence is not disclosed. A visible resource the role cannot act on answers 403 FORBIDDEN.

Operations under /v1/platform belong to the platform backoffice. They require a platform operator capability that no organization role implies, and they answer NOT_FOUND to everyone else. They are not documented here.

Registry providers

An organization can resolve packages from registries other than the public one, for example a private registry for one npm scope. The settings belong to the organization and are used by the registrations that run afterwards. Pinned graphs and existing releases never change.

Version 1 reads npm-compatible registries that are reachable over the Internet. A registry reachable only through a private network or a VPN is outside version 1: the workers reach public Internet addresses only, and a registry address that cannot be one is refused when it is saved.

Operation Request Capability Retry
providers.list GET /v1/organizations/{organization}/providers providers.manage
providers.set PUT /v1/organizations/{organization}/providers/{provider} providers.manage natural
providers.remove DELETE /v1/organizations/{organization}/providers/{provider} providers.manage natural

{provider} is default, for every package without a scope setting, or an npm scope such as @acme.

JSON
{ "registry": "https://<registry host>", "token": "<registry token>" }
Member Required Rule
registry Yes The base address, http or https, without user information, query or fragment. It may carry a path prefix. An address of a loopback, private, link-local or other reserved range, or a name only a local resolver answers (localhost, *.internal, a single label), is 400 VALIDATION_FAILED with the message must be a public Internet address. An address this version cannot use as an npm-compatible registry answers 422 UNSUPPORTED_INPUT.
token No The bearer token of the registry. Bearer is the only authentication mode of this version. A request without token leaves the registry without a credential.

Removing a provider makes the packages of that scope resolve from the default registry again. Removing an absent provider answers the same.

Visibility belongs to the package

Whether a package is public is decided for each package, not by the credential it was read with:

  • A package read without a credential is public.
  • A package read with a credential is public only when the same registry, asked anonymously, answers the same version with the same integrity and the same archive, and the archive itself answers anonymously. Any doubt keeps it private: a registry answers "not found" and "not allowed" alike to an anonymous client.
  • A Git repository or an archive URL read with a credential is private.

A public package produces public outputs, even when your token was used to read it, and it is downloaded without the token. A private package stays in your organization, and so does every output that reads it, including a public package's module that imports it. A private application does not make its public dependencies private. Removing a token does not make bytes that were already retained public. See Preparation and inventory.

Retries and concurrent changes

Each mutation states how it tolerates a retry:

Kind How it works Used by
key The Idempotency-Key header is required. A retry with the same key and the same request answers the original result without repeating the work. The same key with a different request is 409 IDEMPOTENCY_MISMATCH; a missing key is 400 IDEMPOTENCY_REQUIRED. Creating applications, registrations, preparations, custom domains and guest grants
version The request carries expected_version. If it is not the current version of the resource, nothing changes and the answer is 409 CONFLICT_VERSION with details.current. Changing an application, promotion and rollback
natural Repeating the request leaves the same state Defining and removing targets, deleting, cancelling, retiring, reserving the testing subdomain, verifying a domain, revoking a grant, setting and removing a provider, asking for a member ticket

An Idempotency-Key matches ^[A-Za-z0-9_.:-]{8,128}$, is chosen by the client, is unique per intended mutation and is scoped to the caller's organization. If a request times out, send it again with the same key: never generate a new key for a retry.

Pagination

List operations take limit (1 to 200, default 50) and after. A page answers items and, when there is more, next. Send next back as after. Cursors are opaque.

Identifiers

Kind Form
CDN resources (applications, releases, jobs, …) <kind>_<random>, matching ^[a-z][a-z0-9]*_[A-Za-z0-9]{6,40}$, for example job_Prep0001x
Organizations and users Opaque values owned by the authority. The CDN never parses them.
Times RFC 3339 date-times
Digests sha256- followed by 64 hexadecimal characters

Errors

Failures use one envelope, shared in shape with the delivery contract. details replaces diagnostics:

JSON
{ "error": { "code": "CONFLICT_VERSION", "message": "…", "details": { "current": 7 } } }
Status Code Meaning
400 VALIDATION_FAILED The request does not follow the schema; details.fields lists the problems
400 IDEMPOTENCY_REQUIRED The mutation requires an Idempotency-Key header
401 UNAUTHENTICATED No valid session accompanies the request
402 CREDIT_INSUFFICIENT The organization's available credit cannot cover the reservation
403 FORBIDDEN The resource is visible and the role lacks the capability
403 ACCESS_REVOKED The session, membership, guest grant or realtime grant was revoked or expired
403 ADMISSION_REQUIRED The caller is a member whose role allows the operation, but has not been admitted to CDN management and preparation, or the admission was revoked; details.policy names the admission policy. See Internal admission of people
403 ENTITLEMENT_REQUIRED The organization's plan does not include the capability; details.entitlement names it
404 NOT_FOUND The resource does not exist, or the caller may not know that it exists
409 CONFLICT_VERSION expected_version is stale; details.current carries the current one
409 IDEMPOTENCY_MISMATCH The key was already used with a different request
409 STATE_INVALID The resource is not in a state that allows the operation
409 NAME_CONFLICT The name is taken inside the organization
409 DOMAIN_CONFLICT, DOMAIN_UNVERIFIED See Domains
409 QUOTA_EXCEEDED A quota would be passed; details.quota names it
409 PROJECT_CONFLICT The application is already bound to another Beyond project; details.current names it. See The project of an application
409 PROJECT_INACTIVE The Beyond project is archived or deleted; details.state carries its state
410 CURSOR_EXPIRED A replay cursor is older than the retained events
413 PAYLOAD_TOO_LARGE The request body exceeds the accepted size
422 UNSUPPORTED_INPUT A well-formed input this version cannot process: provider, publication form, format or dependency shape
422 LIMIT_EXCEEDED The request exceeds a configured limit and is not retried automatically
422 PROJECT_UNKNOWN The Beyond project does not exist or does not belong to the organization of the application; the two are never told apart
501 NOT_IMPLEMENTED The operation exists in the contract and this service instance does not mount its area, or the integration it needs is not configured; details.operation names it
429 RATE_LIMITED Too many requests; honor Retry-After
500 INTERNAL Unexpected failure. The message never carries secrets.
502 UPSTREAM_UNAVAILABLE A registry, the authority, Beyond Projects or another upstream did not answer. It is never a refusal or an approval
503 BUDGET_EXHAUSTED The global admission budget does not accept new work now
503 UNAVAILABLE The service cannot take the request now

Codes are stable and never translated. The reasons a job can fail are a separate vocabulary that travels inside documents and events; see Jobs.

No GET starts work

No GET of this API, and no GET of published delivery, starts, resumes or schedules work. Only the explicit POST operations create jobs. Reading a job, a release or an inventory as often as you like is safe.