Skip to content
← butverify.dev

Public API

Generated from the service OpenAPI contract. Only operations marked x-bv-audience: cli are included. Run task docs:generate after changing the public API contract.

Base URL: https://api.butverify.dev

Auth: Most endpoints use Authorization: Bearer <butverify installation token>. POST /v1/auth/login uses a GitHub user token and returns the butverify token.

POST /v1/auth/login

Exchange a GitHub user token for a butverify installation token.

  • Stability: stable
  • Auth: Bearer GitHub user token

Request body:

None.

Responses:

statusschemadescription
200LoginResponseLogin succeeded.
401ErrorEnvelopeGitHub token missing, invalid, or no matching butverify installation exists.
429-Login rate limit exceeded.

GET /v1/auth/whoami

Resolve the caller’s tenant from the bearer token.

  • Stability: stable
  • Auth: Bearer installation token

Request body:

None.

Responses:

statusschemadescription
200WhoamiResponseResolved tenant.
401ErrorEnvelopeToken missing or invalid.
426-

GET /v1/sites

List sites for the authenticated tenant.

  • Stability: stable
  • Auth: Bearer installation token

Request body:

None.

Responses:

statusschemadescription
200ListSitesResponseSite list.

POST /v1/sites

Provision a new site (or idempotent retry).

  • Stability: stable
  • Auth: Bearer installation token

Request body:

  • Schema: CreateSiteRequest
  • Required: yes

Responses:

statusschemadescription
200CreateSiteResponseIdempotent retry — existing site returned.
201CreateSiteResponseNew site created.
402ErrorEnvelopeQuota exceeded or unpaid invoice.
429-Rate limit exceeded; carries Retry-After header.

GET /v1/sites/{site_id}

Get a single site’s metadata.

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring

Request body:

None.

Responses:

statusschemadescription
200SiteSite found.
404-No site with that ID owned by the authenticated tenant.

DELETE /v1/sites/{site_id}

Soft-delete a site (status → expired).

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring

Request body:

None.

Responses:

statusschemadescription
200DeleteSiteResponseSite soft-deleted (idempotent on already-expired).

GET /v1/sites/{site_id}/files

List files in the site (parsed from the manifest).

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring

Request body:

None.

Responses:

statusschemadescription
200FilesListResponseFile list.

GET /v1/sites/{site_id}/files/{file_path}

Stream a single file from the site.

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring
file_pathpathyesstringSlash-separated path within the site (no ../, no leading slash).
RangeheadernostringRFC 7233 single byte-range (e.g. bytes=0-1023). Server returns 206 on hit.

Request body:

None.

Responses:

statusschemadescription
200-Full body.
206-Partial body (Range hit).
404-File not found in this site.

POST /v1/sites/{site_id}/finalize

Finalize a push — server untars staging, computes manifest, transitions to active.

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring

Request body:

  • Schema: FinalizeRequest
  • Required: yes

Responses:

statusschemadescription
200FinalizeResponseFinalize succeeded (or idempotent ack on already-active site).
409-Conflicting upload_id or manifest_sha.

POST /v1/sites/{site_id}/heartbeat

Heartbeat from a long-running CLI push (E7 / S-6).

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring

Request body:

  • Schema: HeartbeatRequest
  • Required: yes

Responses:

statusschemadescription
200HeartbeatResponseHeartbeat recorded.

GET /v1/sites/{site_id}/manifest

Stream the site’s manifest.json.

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring

Request body:

None.

Responses:

statusschemadescription
200SiteManifestManifest body (application/json).
409-Site has no manifest yet (still creating/uploading).

POST /v1/sites/{site_id}/pin

Pin an active site (paid plan only; clears expires_at).

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring

Request body:

None.

Responses:

statusschemadescription
200PinResponsePinned (idempotent on already-pinned).
402-Free tier — pinning requires upgrade.
409-Site is not in active state.

POST /v1/sites/{site_id}/unpin

Unpin a site (re-stamps default TTL).

  • Stability: stable
  • Auth: Bearer installation token

Parameters:

nameinrequiredschemadescription
site_idpathyesstring

Request body:

None.

Responses:

statusschemadescription
200PinResponseUnpinned (idempotent on already-active).
409-Site is not in pinned state, or state changed under us.