API Documentation

Complete reference for all BuildHut endpoints. Log in to see your app secrets in examples.

Authentication

MethodUsed byHeader / Param
SessionWeb portalCookie: dev-id, session-token
BearerCI/CD, CLIAuthorization: Bearer bh_<token>
SecretTelemetry, OTLPX-Secret header, ?secret= query, or body

API tokens are managed at /portal/tokens. Up to 5 per developer. Format: bh_ + 64 hex chars. Expiry: never, 1w, 2w, or 1 month.

App & Build APIs

GET /api/app/{id} public

Latest build info + presigned download URL. 5-minute cache.

Response
{
  "app": "my-app",
  "version": "1.0.5",
  "architecture": "arm64-v8a",
  "tag": "1.0.5",
  "description": "Bug fixes",
  "tags": ["stable"],
  "downloadUrl": "https://s3.../presigned-url",
  "uploadedAt": "2026-04-01T10:00:00.000Z"
}
GET /api/apps/{name}/latest public

Redirect to latest build download. Increments download count (30s debounce).

GET /api/apps/{name}/latest/{os}/{arch}/{format} public

Platform-specific build download.

Format aliases: appimage, deb, rpm, flatpak, tar.zst, tar.gz, tar.xz, tgz

Append /signature or use .sig/.asc suffix on format to download the PGP signature instead.

Directory APIs

Browse and search apps, developers, and organizations. All endpoints are public.

GET /api/apps public

List all apps with search, org filter, and pagination.

ParamDescription
searchSearch app name or description
orgFilter by organization name
pagePage number (default 1)
Response
{
  "apps": [{ "id", "name", "description", "iconUrl", "tags",
             "buildCount", "platforms", "dev", "org", ... }],
  "pagination": { "page", "pageSize", "totalPages", "totalCount" }
}
GET /api/apps/{name} public

Full app detail with builds, banner, developer, organization, and related apps.

Response
{
  "app": { "id", "name", "description", "iconUrl", "sourceType",
            "sourceUrl", "supportedOses", "totalDownloads", "buildCount",
            "dev": { "id", "name", "email", "pgpKeyId" },
            "org": { "id", "name" } },
  "builds": [{ "id", "version", "os", "architecture", "fileName",
               "downloadCount", "hasSignature", "uploadedAt" }],
  "banner": { "text", "bgColor", "linkUrl" } | null,
  "otherAppsByDev": [...],
  "otherAppsByOrg": [...]
}
GET /api/devs public

List all developers with search, org filter, and pagination.

ParamDescription
searchSearch dev name or email
orgFilter by organization name
pagePage number (default 1)
Response
{
  "devs": [{ "id", "name", "email", "avatarUrl", "appCount",
             "totalDownloads", "recentApps", "org" }],
  "pagination": { "page", "pageSize", "totalPages", "totalCount" }
}
GET /api/devs/{name} public

Developer detail with all apps, stats, PGP key, and org colleagues.

Response
{
  "developer": { "id", "name", "email", "avatarUrl", "pgpKeyId",
                 "org": { "id", "name" } },
  "apps": [{ "id", "name", "buildCount", "totalDownloads",
             "latestVersion", "lastBuildDate" }],
  "stats": { "totalApps", "totalDownloads", "totalBuilds" },
  "orgColleagues": [{ "id", "name", "appCount" }]
}
GET /api/orgs public

List all organizations with search and pagination.

ParamDescription
searchSearch organization name
pagePage number (default 1)
Response
{
  "orgs": [{ "id", "name", "handle", "description", "avatarUrl",
             "appCount", "devCount", "recentApps" }],
  "pagination": { "page", "pageSize", "totalPages", "totalCount" }
}
GET /api/orgs/{name} public

Organization detail with all apps, member developers, and stats.

Response
{
  "org": { "id", "name", "handle", "description" },
  "apps": [{ "id", "name", "buildCount", "totalDownloads",
             "dev": { "id", "name" } }],
  "developers": [{ "id", "name", "role", "appCount", "recentApps" }],
  "stats": { "totalApps", "totalDevelopers", "totalDownloads", "totalBuilds" }
}

Upload APIs

POST /api/upload/presign auth

Generate presigned S3 URL for direct upload. 5-minute expiry.

FieldRequiredDescription
fileNameyesFile name with extension
nameyesApp name
versionyesVersion string
curl -X POST "https://buildhut.fly.dev/api/upload/presign" \
  -H "Authorization: Bearer bh_YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "fileName": "app.apk", "name": "my-app", "version": "1.0.0" }'
POST /api/upload auth

Finalize build upload and create DB records. Max 200MB.

FieldRequiredDescription
nameyesApp name
versionyesVersion string
fileNameyes*Original file name
s3Keyyes*S3 key from presign
osnoAuto-detected from filename
architecturenoe.g. x86_64, arm64-v8a, universal
filenoBinary file (direct upload)
signaturenoPGP signature file (.asc or .sig)
signatureS3KeynoS3 key for pre-uploaded signature
curl -X POST "https://buildhut.fly.dev/api/upload" \
  -H "Authorization: Bearer bh_YOUR_TOKEN" \
  -F "name=my-app" \
  -F "version=1.0.0" \
  -F "file=@app-release.apk"

* Required for presign flow. Use file field for direct upload.

Telemetry API

POST /api/telemetry secret

Submit telemetry events from your app. Secret passed via X-Secret header or body secret field.

FieldLocationDescription
appNamequery/bodyApp name
kindbodyerror | warning | info | trace | debug
versionbodyApp version
bitsbodyArbitrary JSON payload
curl -X POST "https://buildhut.fly.dev/api/telemetry?appName=YOUR_APP" \
  -H "X-Secret: YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "info",
    "version": "1.0.0",
    "bits": { "event": "app_opened" }
  }'
GET /api/telemetry session

List telemetry events.

ParamDescription
appNameFilter by app name
kindFilter by kind (comma-separated)
limitMax results (default 200)

OTLP Endpoints

OpenTelemetry Protocol ingestion. Accept JSON and Protobuf. Auth: app secret.

POST /v1/traces
POST /v1/metrics
POST /v1/logs

Feature Flags API

GET /v1/flags secret

Fetch feature flag definitions for an app.

curl "https://buildhut.fly.dev/v1/flags?appName=YOUR_APP" \
  -H "X-Secret: YOUR_SECRET"
POST /v1/flags/eval secret

Report feature flag evaluations.

{
  "evaluations": [
    { "flagName": "dark_mode", "enabled": true },
    { "flagName": "new_dashboard", "enabled": false, "context": { "userId": "abc" } }
  ]
}

Response: {"accepted": 2, "unknown": []}

Publishing APIs

MethodEndpointDescriptionAuth
POST/api/publish/generatePreview publishing files (PKGBUILD, metadata.yml)session
POST/api/publish/publishExecute async publish runsession
GET/api/publish/status/{runId}Poll publish run statussession
GET/api/publish/ssh-keysList SSH keyssession
POST/api/publish/ssh-keysAdd SSH key (encrypted at rest)session
DEL/api/publish/ssh-keys/{id}Delete SSH keysession
POST/api/publish/rotate-keyRe-encrypt all SSH keys (admin only)session

Utility APIs

MethodEndpointDescriptionAuth
ANY/api/auth/statusCheck auth statepublic
POST/api/logoutClear session cookiespublic
GET/api/img/{key}Serve uploaded imagespublic
GET/api/branches?app={name}List git branches from source reposession
POST/api/pgp/fetch-keyFetch PGP key from keys.openpgp.orgsession
POST/api/validateValidate bot challengepublic
GET/api/svg-challenge?token=...Bot challenge SVG imagepublic
GET/api/logoutClear session and redirect to /public
GET/api/debug/buildsList all builds (dev env only)session