Skip to content

HTTP API

This runs unattended; unattended operation is the paid plan.

Base URL: https://www.extension.dev.

Authentication

Send a project token in the header:

Authorization: Bearer <project token>

Tokens in a query string are refused with a named error, never accepted. In GitHub Actions, use POST /api/oidc/exchange instead of a stored token.

Device flow

RFC 8628. Approval happens at www.extension.dev/device.

  • GET /api/cli/login/config: device flow discovery. No auth.
  • POST /api/cli/device/code: body {project, clientName?}. Returns a user code with a 15 minute TTL. Poll every 5 seconds.
  • POST /api/cli/device/token: body {device_code}. RFC 8628 errors: authorization_pending, slow_down, expired_token.

Token exchange

  • POST /api/oidc/exchange: trades a GitHub Actions OIDC assertion for a 1-hour platform token, audience extension-dev-registry.

CLI actions

  • POST /api/cli/publish: body {ttlHours?, buildSha?}. Returns the project's build page URL: the canonical public page for a public project, a ?share= tokenized link for a private one, whose lifetime is ttlHours (1 to 168, default 24). It uploads nothing and is not store submission.
  • POST /api/cli/stores/submit: body {browsers[], buildSha, channel?, version?, dryRun?}.
  • POST /api/cli/release/promote: promotes a cut release.

Access tokens

  • GET /api/projects/{id}/access-tokens: list tokens.
  • POST /api/projects/{id}/access-tokens: mint a token.
  • DELETE /api/projects/{id}/access-tokens/{tokenId}: revoke a token. Revocation is immediate.

Builds

  • GET /api/projects/{id}/builds: list builds.
  • GET /api/projects/{id}/builds/{buildId}: one build.
  • GET /api/projects/{id}/builds/{buildId}/logs: build logs.
  • GET /api/projects/{id}/builds/{buildId}/artifacts: build artifacts.
  • GET /api/projects/{id}/builds/{buildId}/usage: minutes and cost.
  • GET /api/projects/{id}/builds/{buildId}/integrity/{browser}: the integrity record for one browser's artifact.
  • POST /api/projects/{id}/builds/dispatch: body {commitSha?, buildEnv?, force?}. Starts a build on the mirror.

Releases

  • GET /api/projects/{id}/releases: list releases.
  • POST /api/projects/{id}/releases: create a release.
  • POST /api/projects/{id}/releases/cut: cut a release. Opens the version-bump PR in the source repository.
  • POST /api/projects/{id}/releases/promote-ready: arm the pending release so a green build promotes it.
  • POST /api/projects/{id}/releases/{channel}/rollback: roll a channel back.

Stores

  • GET /api/projects/{id}/stores/config: store configuration.
  • POST /api/projects/{id}/stores/config: update store configuration.
  • GET /api/projects/{id}/stores/status: submission status per store.
  • GET /api/projects/{id}/stores/{store}/submissions: submission history.
  • POST /api/projects/{id}/stores/test/{store}: test one store's credentials.

Error contract

POST /api/cli/stores/submit returns 503 with Retry-After: 10 when the platform cannot take the submission. The guarantee: nothing was dispatched and nothing was recorded. Retry the same call unchanged.

404 UNKNOWN_BUILD means the sha is not in the build index. Push, or dispatch a build for that commit, before submitting it.

Preflight

dryRun: true on POST /api/cli/stores/submit runs the preflight. The response carries a verdict per store: configured, healthy, ok, reason, consoleUrl. Nothing dispatches.