getBuildLabels

Read a build's current custom labels. Labels are stored on the build and are also included in getBuild responses and todesktop builds --format=json output when present.

GET /v1/getBuildLabels?appId={appId}&buildId={buildId}
Authorization: Bearer <access-token>

Both query parameters are required. IDs must contain 1–128 letters, numbers, underscores or hyphens. Unknown parameters are rejected.

The token must belong to the app owner or a user with current access to the app. This endpoint accepts legacy account access tokens and active personal access tokens scoped to the app. The existing getBuild endpoint continues to require a legacy account access token.

All three label endpoints enforce configured IP allowlists. The request must satisfy the token holder's allowlist and, for delegated access, the app owner's allowlist. Requests from blocked IP addresses return 403 with reason permission-denied.

Response

All three label endpoints return the same response shape, with the current label map. Builds without labels return an empty object. Responses use Cache-Control: private, no-store.

{
  "appId": "your-app-id",
  "buildId": "your-build-id",
  "customLabels": {
    "github-e2e": {
      "text": "E2E passed",
      "color": "green",
      "url": "https://github.com/example/app/actions/runs/123",
      "createdAt": "2026-09-09T10:00:00.000Z",
      "updatedAt": "2026-09-09T10:05:00.000Z",
      "createdBy": { "userId": "user-id", "displayName": "Example User", "via": "api" },
      "updatedBy": { "userId": "user-id", "displayName": "Example User", "via": "api", "tokenDescription": "Nightly E2E" }
    }
  }
}

createdAt, updatedAt, createdBy and updatedBy are assigned by the server. Timestamps use ISO 8601 UTC. Attribution contains the authenticated user ID and display name; personal tokens also include their description. Token secrets and internal token IDs are not included. Display names and token descriptions are snapshots at the time of the change.

Labels are informational and do not affect whether a build can be released. They remain on the same build when packaging is rerun. Cloned builds start without labels.

Build-finished and release webhooks (both full and partial releases) include customLabels from the event's build snapshot, or {} when no labels exist. Later label edits do not modify earlier payloads or trigger additional webhooks. Release webhook signatures cover the labels as part of the complete JSON payload. Test webhooks include an empty label map.

Errors

Label endpoints use structured errors:

{ "error": { "reason": "not-found", "message": "Build not found." } }
StatusReasonMeaning
400invalid-argumentInvalid IDs, keys, label fields, unknown fields, or more than ten labels.
401unauthenticatedMissing, invalid, expired or revoked token, or disabled account.
403permission-deniedToken does not cover the app, the caller lacks write permission, or the request is blocked by an IP allowlist.
404not-foundBuild or app not found, or app is inaccessible to the caller.
409abortedConcurrent edits prevented the write from completing after retries. Retry the request.
413payload-too-largeWrite request exceeds 16 KiB.
415unsupported-media-typeWrite request does not use application/json.
500internalUnexpected server failure.

Example

curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  "https://api.todesktop.com/v1/getBuildLabels?appId=your-app-id&buildId=your-build-id"