openapi: 3.1.0 info: title: Gradient API description: |- Gradient is a Nix-based Continuous Integration system. It evaluates Nix flakes, schedules derivation builds across remote machines, and exposes build artefacts through an integrated binary cache. ## Authentication Most endpoints require authentication. Three methods are accepted: | Method | How to send | How to obtain | |---|---|---| | JWT (cookie) | `jwt_token` httpOnly cookie | Set automatically on login | | JWT (header) | `Authorization: Bearer ` | `POST /auth/basic/login` or OIDC flow | | API Key | `Authorization: Bearer GRAD` | `POST /user/keys` | Cookie auth is the default for browser clients - the `jwt_token` cookie is set by the login and OIDC-callback endpoints and cleared on logout. The `Authorization` header is accepted as a fallback (e.g. for CI/scripts). ### Artefact downloads `GET /builds/{build}/download/{filename}` serves build artefacts declared in `nix-support/hydra-build-products`. Access is granted when any of the following conditions is met: - The owning project is **public** - no credentials required. - A short-lived (1 h) **download token** is supplied via `?token=`. Obtain one from `GET /builds/{build}/download-token` while authenticated. Tokens are scoped to the build's derivation and are safe to embed in URLs. - A valid session (`jwt_token` cookie or `Authorization: Bearer` header) belonging to a member of the owning project, or of any project with a build of the same derivation (the rule every other build read uses). ## Rate limiting All HTTP endpoints enforce a per-client-IP token-bucket rate limit. The limiter keys solely on client IP, so authenticated and anonymous requests share the same tier. Clients that exceed their bucket receive HTTP `429 Too Many Requests`. The tier depends on the route: | Tier | Routes | Refill | Burst | |---|---|---|---| | auth | `/auth/basic/login`, `/auth/basic/register`, `/auth/check-username`, `/auth/verify-email`, `/auth/resend-verification`, `/auth/oauth/*`, `/auth/oidc/*` | 1 req / 6 s | 5 | | webhook | `/hooks/*` | 1 req / s | 30 | | cache | `/cache/{cache}/*` (public NAR surface) and `/cache/{cache}/proto` | 1 req / 20 ms | 3000 | | cache-inspect | `/cache/{cache}/{ls,serve}/*` | 1 req / 333 ms | 180 | | cache-log | `/cache/{cache}/log/*` | 1 req / 333 ms | 900 | | cache-upload | `POST /caches/{cache}/nars`, `PUT /caches/{cache}/nars/{hash}/chunk`, `POST /caches/{cache}/nars/{hash}/finalize` | 1 req / 2 ms | 10000 | | default | everything else | 1 req / 200 ms | 150 | Client IP is taken from `X-Forwarded-For` / `X-Real-IP` (deployments are expected behind a reverse proxy), falling back to the connection peer IP. ## Request Tracing Every response carries an `x-request-id` header. If the client (or an upstream reverse proxy) supplies an `x-request-id` on the request, it is preserved verbatim; otherwise the server mints a UUID v7. Use this id to correlate client-side traces with server logs - every log line emitted while the request is in flight (handler, DB, spawned cleanup tasks) carries the same id. ## Common Response Envelope Every JSON response is wrapped in a standard envelope: ```json { "error": false, "message": } ``` On errors `"error"` is `true` and `"message"` contains the error description. ## Nix Binary Cache The integrated Nix binary cache lives outside `/api/v1`. Configure Nix with: ``` substituters = https://gradient.example.com/cache/mycache trusted-public-keys = gradient.example.com-mycache:... ``` The public key is returned by `GET /api/v1/caches/{cache}/public-key`. ## State Management Objects whose `managed` field is `true` are controlled by the NixOS module configuration and cannot be mutated through the API. contact: name: Wavelens GmbH email: info@wavelens.io license: name: AGPL-3.0-only identifier: AGPL-3.0-only version: 2.0.0 paths: /api/v1/admin/draining: post: tags: - admin summary: Toggle instance draining description: |- Enables or disables draining for the instance. While draining, the scheduler stops dispatching queued evaluations and builds, and every in-flight evaluation waits (`Waiting`, reason `draining`) so the server can be stopped safely. When draining ends, evaluations with a finished walk go back to `Building` and the others to `Queued`. Draining is in-memory only, so it always clears on the next server startup, and the waiting evaluations return automatically. Requires `superuser`. operationId: setDraining requestBody: content: application/json: schema: $ref: '#/components/schemas/SetDrainingRequest' required: true responses: '200': description: Draining state applied content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DrainingResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/github-app/callback: get: tags: - admin summary: GitHub App manifest callback description: |- Receives the redirect from GitHub after the operator submits the manifest. Validates the `state` token, exchanges the temporary `code` for the App's permanent credentials, stashes them in a one-shot in-memory store per superuser who initiated the manifest flow, and redirects the browser to `/admin/github-app?ready=1`. **Unauthenticated** - GitHub redirects the operator's browser here from `https://github.com/...` and that cross-site navigation does not carry a bearer token. CSRF and identity binding are provided by the one-shot `state` token issued at `POST /admin/github-app/manifest`, which is bound to the initiating superuser at issuance. operationId: githubAppManifestCallback parameters: - name: code in: query required: true schema: type: string - name: state in: query required: true schema: type: string - name: host in: query required: false schema: type: string responses: '302': description: Redirect to `/admin/github-app?ready=1` on success. default: $ref: '#/components/responses/Error' security: [] /api/v1/admin/github-app/credentials: get: tags: - admin summary: Fetch pending GitHub App credentials description: |- One-shot retrieval of the credentials produced by the most recent successful manifest exchange. Calling this endpoint **consumes** the pending credentials; a second call returns `404`. Pending entries also expire 10 minutes after creation. Requires `superuser`. operationId: getGithubAppCredentials responses: '200': description: GitHub App credentials (returned exactly once) content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ManifestResult' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/github-app/manifest: post: tags: - admin summary: Build GitHub App manifest description: |- Builds a GitHub App manifest pre-filled with this server's URLs, permissions, and events, and returns a one-shot CSRF state token plus the GitHub URL the browser should POST the manifest to. Requires `superuser`. The state token is consumed by the matching `GET /admin/github-app/callback` invocation; it expires after 10 minutes. operationId: createGithubAppManifest requestBody: content: application/json: schema: $ref: '#/components/schemas/GithubAppManifestRequest' required: true responses: '200': description: Manifest, post URL, and CSRF state content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/GithubAppManifestResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/maintenance/deep-gc: post: tags: - admin summary: Request a deep GC round description: |- Requests a reconciliation between the database and every storage backend (NAR files, build-request blobs, build logs, upload partials), run without pausing between units. Returns `202` immediately with the task id; poll `GET /admin/tasks/{task_id}` for progress and final state. When a `deep_gc` round is already `pending` or `running`, that round starts over from its first unit and its id is returned. Requires `superuser`. operationId: startDeepGc responses: '202': description: Round requested content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/StartDeepGcResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/state: get: tags: - admin summary: Export the live state configuration description: |- Reconstructs the current users, projects, tasks, caches, custom roles, API keys, teams with their members and grants, workers (team workers name their team) and integrations into a declarative `services.gradient.state` shape, so operators can codify the running system back into their nix configuration. Every credential-file field (`password_file`, `private_key_file`, `signing_key_file`, `token_file`, `key_file`, `secret_file`, `access_token_file`) is redacted to `null` - the hashed/encrypted secrets cannot be recovered and must be filled in by hand. GitHub integration rows are exported with their `installation_id` / `account_login`. The auto-managed `build-request` task and the built-in `Admin`/`Write`/`View` roles are omitted. Requires `superuser`. operationId: exportState parameters: - name: format in: query required: false schema: type: string responses: '200': description: Exported state configuration content: text/plain: schema: type: string application/json: schema: type: object required: - error - message properties: error: type: boolean message: {} default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/tasks: get: tags: - admin summary: List recent admin tasks description: |- Returns the 50 newest admin tasks ordered by `created_at` descending. Requires `superuser`. operationId: listAdminTasks responses: '200': description: Admin task list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/AdminTaskDto' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/tasks/{task_id}: get: tags: - admin summary: Get one admin task operationId: getAdminTask parameters: - name: task_id in: path required: true schema: $ref: '#/components/schemas/AdminTaskId' responses: '200': description: Admin task content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/AdminTaskDto' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/webhooks: get: tags: - webhooks summary: List instance webhooks description: Requires superuser. operationId: listInstanceWebhooks parameters: [] responses: '200': description: Webhooks content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - webhooks summary: Create a instance webhook description: |- Requires superuser. The response carries the signing `secret` once; it is never returned again (use `rotate-secret` to replace it). operationId: createInstanceWebhook parameters: [] requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateWebhookRequest' required: true responses: '200': description: Created webhook and its secret content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CreateWebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/webhooks/{id}: get: tags: - webhooks summary: Read a instance webhook operationId: readInstanceWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' responses: '200': description: Webhook content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - webhooks summary: Delete a instance webhook operationId: deleteInstanceWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' responses: '200': description: Deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeletedResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - webhooks summary: Update a instance webhook operationId: updateInstanceWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateWebhookRequest' required: true responses: '200': description: Updated webhook content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/webhooks/{id}/deliveries: get: tags: - webhooks summary: List a instance webhook's deliveries operationId: listInstanceWebhookDeliveries parameters: - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 - name: offset in: query required: false schema: type: integer format: int64 minimum: 0 - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' responses: '200': description: Deliveries, newest first content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/DeliveryListItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/webhooks/{id}/deliveries/{delivery_id}: get: tags: - webhooks summary: Read one instance webhook delivery with bodies operationId: getInstanceWebhookDelivery parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: delivery_id in: path required: true schema: $ref: '#/components/schemas/WebhookDeliveryId' responses: '200': description: Delivery content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryDetail_WebhookDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/webhooks/{id}/rotate-secret: post: tags: - webhooks summary: Replace a instance webhook's signing secret operationId: rotateInstanceWebhookSecret parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' responses: '200': description: The new secret, shown once content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RotatedSecret' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/webhooks/{id}/test: post: tags: - webhooks summary: Send a `webhook.ping` to a instance webhook description: Delivers immediately (no retry) and returns the recorded delivery. operationId: testInstanceWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' responses: '200': description: Recorded delivery content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryListItem_WebhookDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/admin/workers: get: tags: - admin summary: List connected workers description: |- Returns all workers currently connected to the server via the `/proto` WebSocket, including their capabilities and assigned job counts. Requires the caller to have the `superuser` flag, unless the server is started with `GRADIENT_PUBLIC_STATS=true`. operationId: listWorkers responses: '200': description: Worker list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/WorkerInfo' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/auth/basic/login: post: tags: - auth summary: Login with username/password description: |- Validates credentials and returns a signed JWT. Pass the token as `Authorization: Bearer ` on subsequent requests. `loginname` accepts either the username or the email address. Set `remember_me: true` for a long-lived token. operationId: loginUser requestBody: content: application/json: schema: $ref: '#/components/schemas/MakeLoginRequest' required: true responses: '200': description: JWT token content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/basic/register: post: tags: - auth summary: Register a new user description: |- Creates a new user account. Fails if registration is disabled (OIDC-only mode) or if the username/email is already taken. When email verification is enabled, a verification email is sent and login is blocked until the address is confirmed. operationId: registerUser requestBody: content: application/json: schema: $ref: '#/components/schemas/MakeUserRequest' required: true responses: '200': description: User created content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/check-username: post: tags: - auth summary: Check username availability description: 'Returns `error: false` if the username is valid and not taken, `error: true` otherwise (non-2xx status is not used - always inspect the `error` field).' operationId: checkUsername requestBody: content: application/json: schema: $ref: '#/components/schemas/CheckUsernameRequest' required: true responses: '200': description: Availability result content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/cli/authorize: post: tags: - auth summary: Authorize a pending CLI device session description: |- Marks the device authorization identified by `user_code` as approved, minting a JWT session token (remember_me=true, 30-day lifetime) bound to the calling user. The token is returned to the CLI on its next `/auth/cli/poll` request. operationId: cliDeviceAuthorize requestBody: content: application/json: schema: $ref: '#/components/schemas/CliDeviceAuthorizeRequest' required: true responses: '200': description: Authorized content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/auth/cli/deny: post: tags: - auth summary: Deny a pending CLI device session operationId: cliDeviceDeny requestBody: content: application/json: schema: $ref: '#/components/schemas/CliDeviceAuthorizeRequest' required: true responses: '200': description: Denied content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/auth/cli/info: get: tags: - auth summary: Look up a pending CLI device authorization description: Returns metadata about a pending `user_code` so the browser-side UI can confirm what it authorizes. operationId: cliDeviceInfo parameters: - name: user_code in: query required: true schema: type: string responses: '200': description: Device info content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CliDeviceInfoResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/auth/cli/poll: post: tags: - auth summary: Poll a pending CLI device authorization description: |- Exchanges a `device_code` for a session token once the browser-side flow has been approved. Returns `cli_auth_pending` while the user hasn't yet clicked Authorize, `cli_auth_denied` if they explicitly denied, and `cli_auth_expired` once the device code lifetime elapses. operationId: cliDevicePoll requestBody: content: application/json: schema: $ref: '#/components/schemas/CliDevicePollRequest' required: true responses: '200': description: Authorized - session token returned content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/cli/start: post: tags: - auth summary: Start a CLI device-authorization flow description: |- Mints a `device_code` (returned once, opaque to the server thereafter) and a short, human-friendly `user_code` that the CLI shows in the terminal and the user confirms in the browser at `verification_uri_complete`. The CLI polls `/auth/cli/poll` until the browser-side flow completes. operationId: cliDeviceStart responses: '200': description: Device flow started content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CliDeviceStartResponse' default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/logout: post: tags: - auth summary: Logout description: Invalidates the current session (no-op for stateless JWTs; present for API completeness). operationId: logout responses: '200': description: Logged out content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/oauth/authorize: get: tags: - auth summary: OAuth2 callback (GET) description: |- Handles the authorization code returned by the OAuth2/OIDC provider. Verifies the `state` parameter against the `oidc_csrf` cookie set by `POST /auth/oauth/authorize`, exchanges the code for tokens, verifies the ID token signature against the provider's JWKS, and binds the session to the user identified by `(iss, sub)`. operationId: oauthAuthorizeGet parameters: - name: code in: query required: true schema: type: string - name: state in: query required: true schema: type: string responses: '200': description: JWT token content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] post: tags: - auth summary: Get OAuth2 authorization URL description: |- Returns the authorization URL to redirect the user to for OIDC login and sets a short-lived `oidc_csrf` cookie carrying the signed `state` and `nonce` values that must be presented on the callback. Requires OIDC to be enabled. operationId: oauthAuthorizePost responses: '200': description: Authorization URL content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/oidc/callback: get: tags: - auth summary: OIDC callback description: |- Handles the OIDC provider redirect. Verifies the `state` parameter against the `oidc_csrf` cookie, exchanges the authorization code for tokens, verifies the ID token signature using the provider's JWKS (validating `iss`, `aud`, `exp`, and `nonce`), and binds the session to the user identified by `(iss, sub)`. Sets the `jwt_token` session cookie and clears `oidc_csrf`. operationId: oidcCallback parameters: - name: code in: query required: true schema: type: string - name: state in: query required: true schema: type: string responses: '302': description: Redirect to frontend with session cookie set default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/oidc/login: get: tags: - auth summary: OIDC login redirect description: |- Redirects the browser to the OIDC provider's authorization endpoint (HTTP 302) using PKCE (S256), and sets a short-lived `oidc_csrf` cookie carrying the signed `state`, `nonce`, and PKCE verifier that must be returned on the callback. operationId: oidcLogin responses: '302': description: Redirect to OIDC provider default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/resend-verification: post: tags: - auth summary: Resend verification email description: Issues a fresh verification token and sends a new email. Only available when email verification is enabled. operationId: resendVerification requestBody: content: application/json: schema: $ref: '#/components/schemas/CheckUsernameRequest' required: true responses: '200': description: Email sent content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/auth/verify-email: get: tags: - auth summary: Verify email address description: Consumes the one-time token sent in the verification email. Only available when `email_verification_enabled` is true. operationId: verifyEmail parameters: - name: token in: query required: true schema: type: string responses: '200': description: Email verified content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/board/cache: get: tags: - board summary: Cache statistics description: Cache totals plus hourly traffic and storage-growth series, aggregated across caches (anonymized infra view). operationId: getBoardCache parameters: - name: window_hours in: query required: false schema: type: integer format: int64 responses: '200': description: Cache statistics content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/BoardCacheStats' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/cache/live: get: tags: - board summary: Cache change pings (WebSocket) description: |- Upgrades to a WebSocket emitting a content-free `{"type":"cache_changed"}` ping whenever cache contents or stats change. Subscribers refetch their own scope-filtered `GET /board/cache` view. operationId: boardCacheLive responses: '101': description: Switching Protocols - WebSocket upgrade successful default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/cache/upstream-caches: get: tags: - board summary: Per-URL cache latency and narinfo hit-rate description: 'Per-upstream-URL trailing latency, narinfo hit-rate, and request counts with hourly series. Metrics are per URL: the same URL registered under several caches/projects contributes to one series; `display_name` is the URL host. Project-scoped: superusers see all URLs; members see the URLs used by their projects plus public projects. Each series'' `url` is the caller''s own upstream, so it is returned unmasked. The entries are returned as `upstream_caches`.' operationId: getBoardUpstreamCaches parameters: - name: window_hours in: query required: false schema: type: integer format: int64 responses: '200': description: Per-upstream cache performance content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/BoardUpstreamCacheStats' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/durations/heatmap: get: tags: - board summary: Build-duration heatmap description: 2D build-duration distribution (duration band × hour) computed on demand from builds, scoped to the caller's projects. operationId: getBoardDurationsHeatmap parameters: - name: window_hours in: query required: false schema: type: integer format: int64 responses: '200': description: Duration heatmap content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DurationsHeatmap' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/evals/expensive-by-resource: get: tags: - board summary: Most expensive evaluations by resource description: Top evaluations by a captured per-eval resource (peak RSS/heap, thunks, fn calls, allocated bytes, or total eval time) from `evaluation_metric`. Project-scoped through the evaluation's task. operationId: getBoardExpensiveEvalsByResource parameters: - name: metric in: query required: true schema: type: string - name: window_days in: query required: false schema: type: integer format: int64 responses: '200': description: Top evaluations by resource content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/ExpensiveEval' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/expensive/top-projects: get: tags: - board summary: Top projects by build time (superuser) description: Projects ranked by cumulative completed-build time in a window. Each derivation build counts once per project that built it, timed like `/board/jobs/expensive`; `build_count` counts derivation builds. Superuser only. operationId: getBoardTopProjects parameters: - name: window_days in: query required: false schema: type: integer format: int64 responses: '200': description: Top projects content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TopProjectBuildTime' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/board/fleet: get: tags: - board summary: Worker fleet time-series description: Hourly connected / draining / by-capability worker counts derived from worker samples, scoped to the caller's projects. operationId: getBoardFleet parameters: - name: window_hours in: query required: false schema: type: integer format: int64 responses: '200': description: Fleet time-series content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/BoardFleetPoint' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/health: get: tags: - board summary: System health (superuser) description: Process/runtime snapshot, pipeline rollup lag, HTTP route stats, and the instance `draining` flag. Superuser only. operationId: getBoardHealth responses: '200': description: System health content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/BoardHealth' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/board/jobs/decisions: get: tags: - board summary: Recent assignment decisions (all candidate scores) description: Bounded ring of the most recent assignment decisions, each with every scored candidate including the rejected/negative ones the scheduler passed over. For tuning scoring rules. Superuser-only, as candidates span all projects. operationId: getBoardDispatchDecisions responses: '200': description: Recent assignment decisions, most recent first content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/AssignDecisionView' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/board/jobs/dispatched: get: tags: - board summary: Live assigned jobs description: In-flight assigned jobs visible to the caller; out-of-scope jobs collapse to an aggregate `other_running` count. operationId: getBoardDispatchedJobs responses: '200': description: Assigned jobs plus other_running count content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DispatchedJobsResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/jobs/expensive: get: tags: - board summary: Most expensive builds description: Top 20 completed derivation builds by build time, one row per derivation build. The time is the worker-measured `derivation_metric.build_time_ms`, falling back to the latest attempt's start and finish stamps when no metric exists. Project-scoped; `worker_name` is shown only when the worker is registered by a project the caller can see. operationId: getBoardExpensiveJobs parameters: - name: window_days in: query required: false schema: type: integer format: int64 responses: '200': description: Top builds by build time content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/ExpensiveBuild' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/jobs/expensive-by-resource: get: tags: - board summary: Most expensive builds by resource description: Top 20 derivations by a captured per-build resource (peak RAM, CPU time or total disk bytes) from each derivation's latest `derivation_metric` row in the window, skipping zero values. Project-scoped; `worker_name` is shown only when the worker is registered by a project the caller can see. operationId: getBoardExpensiveByResource parameters: - name: metric in: query required: true schema: type: string - name: window_days in: query required: false schema: type: integer format: int64 responses: '200': description: Top builds by resource content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/ExpensiveResource' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/jobs/pending: get: tags: - board summary: Pending (unassigned) jobs description: Queued jobs not yet assigned to a worker, visible to the caller; out-of-scope jobs collapse to an aggregate `other_pending` count. operationId: getBoardPendingJobs responses: '200': description: Pending jobs plus other_pending count content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/PendingJobsResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/jobs/{id}: get: tags: - board summary: Assigned job detail description: Full assignment record incl. per-rule scoring breakdown, job/worker/instance contexts. Runner-up candidates are superuser-only. operationId: getBoardJob parameters: - name: id in: path required: true schema: type: string format: uuid responses: '200': description: Job detail content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DispatchedJobDetail' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/live: get: tags: - board summary: Job Board live events (WebSocket) description: |- Upgrades to a WebSocket streaming JSON board events (`queue_depth`, `job_dispatched`, `worker_connected`, `worker_disconnected`). Per-project events are masked to the caller's scope; `worker_connected` reaches members of any project the worker serves and names none of them. operationId: boardLive responses: '101': description: Switching Protocols - WebSocket upgrade successful default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/network: get: tags: - board summary: Network & API statistics description: NAR egress series, per-worker latest upload, download and disk speeds with the worker's `worker_name` (project-scoped), and per-route HTTP latency/throughput (superuser-only). operationId: getBoardNetwork parameters: - name: window_hours in: query required: false schema: type: integer format: int64 responses: '200': description: Network statistics content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/BoardNetworkStats' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/scoring/rules: get: tags: - board summary: Scoring rule catalog description: Static name and human-readable description for every scheduler scoring rule, used by the board UI to explain rule names. operationId: getBoardScoringRules responses: '200': description: Rule catalog content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/RuleDescription' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/scoring/summary: get: tags: - board summary: Aggregate scoring summary description: Score histogram and mean per-rule contribution over recently assigned jobs, masked to the caller's projects. operationId: getBoardScoringSummary parameters: - name: window_hours in: query required: false schema: type: integer format: int64 - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Scoring summary content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ScoringSummary' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/storage: get: tags: - board summary: Storage and transport health series (superuser) description: Per-label rollup series for NAR storage call latency and errors, worker protocol lane fill and send stalls, NAR serve queue depth and serve failures. Windows up to 6 h read minute buckets, up to 168 h hour buckets, longer windows day buckets. Superuser only. operationId: getBoardStorage parameters: - name: window_hours in: query required: false schema: type: integer format: int64 responses: '200': description: Storage and transport health series content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/BoardStorage' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/board/workers: get: tags: - board summary: Connected workers description: Connected workers with capability and live load. `projects` lists the served projects visible to the caller; a worker serving none of them has its identity and metrics masked for non-superusers. Each project is `{ id, name, display_name }`. The worker's `name` is its display name from a registration in a project the caller can see. operationId: getBoardWorkers responses: '200': description: Connected workers content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/BoardWorker' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/board/workers/load: get: tags: - board summary: Fleet load by capability, architecture, and feature description: 'Real per-dimension fleet load: for each capability (eval/fetch/build), architecture, and system feature, the in-flight job count against the summed slot capacity of the workers that can serve it. Answers whether the fleet is eval-, build-, or architecture-bound rather than showing one blended busy %. Scoped to the caller''s projects (superusers see the whole fleet). Each bucket carries `{ key, in_flight, capacity, workers }`; busy % = in_flight / capacity.' operationId: getBoardWorkerLoad responses: '200': description: Fleet load breakdowns content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WorkerLoad' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/build-requests/manifest: post: tags: - build-requests summary: Submit a build-request file manifest description: |- Step 1 of the `gradient build` flow. Posts the list of git-tracked files in the working tree, each addressed by BLAKE3 content hash. The server returns an `UploadSession` plus the subset of hashes it does not yet have on disk; the client uploads those via `POST /build-requests/{session}/blobs` and then finalises with `POST /build-requests/{session}/dispatch`. The combined `size` of all files must not exceed `MAX_BUILD_REQUEST_SIZE` (20 MiB). Paths must be relative, free of `.`/`..` components, free of null bytes, and unique within the manifest. operationId: postBuildRequestManifest requestBody: content: application/json: schema: $ref: '#/components/schemas/ManifestRequest' required: true responses: '200': description: Session created content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ManifestResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/build-requests/source: post: tags: - build-requests summary: Upload a pre-packed source NAR and queue an evaluation (single-shot) description: |- One-shot alternative to the manifest/blob flow for clients built with the `nix` feature. The client NAR-packs the git-tracked source itself and uploads it here; the server computes the `/nix/store/-source` path, signs it, lazily creates the per-project `build-request` task, and queues an evaluation. The whole NAR is one request, bounded by `max_source_upload_size`; large sources should use the chunked `POST /build-requests/source/{upload}/chunk` + `finalize` flow instead. operationId: postBuildRequestSource parameters: - name: project in: query required: true schema: type: string requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/SourceUploadForm' required: true responses: '200': description: Evaluation queued content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DispatchResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/build-requests/source/{upload}/chunk: put: tags: - build-requests summary: Append a chunk of a source NAR to a staged upload description: |- Streams a large source NAR to the server in slices so no single request hits a body limit. `upload` is a client-chosen id (the CLI uses the NAR's content hash, which makes a retry resumable). `offset` must equal the bytes already received (`0` starts fresh); a mismatch appends nothing and returns the authoritative `received` so the client resumes. The staged total is bounded by `max_source_upload_size`. Finalise with `POST /build-requests/source/{upload}/finalize`. operationId: putBuildRequestSourceChunk parameters: - name: upload in: path required: true schema: type: string - name: offset in: query required: true schema: type: integer format: int64 minimum: 0 requestBody: content: application/octet-stream: schema: $ref: '#/components/schemas/Binary' required: true responses: '200': description: Chunk staged; returns total bytes received so far. content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ChunkReceived' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/build-requests/source/{upload}/finalize: post: tags: - build-requests summary: Finalise a chunked source upload and queue an evaluation description: |- Reassembles the staged source NAR for `upload`, computes its `/nix/store/-source` path, signs it, lazily creates the per-project `build-request` task, queues an evaluation, and drops the partial. operationId: postBuildRequestSourceFinalize parameters: - name: upload in: path required: true schema: type: string - name: project in: query required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/SourceFinalize' required: true responses: '200': description: Evaluation queued content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DispatchResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/build-requests/url: post: tags: - build-requests summary: Queue a build request against a remote repository description: |- The no-upload build request: the source is already published at a URL, so only the URL and a revision are posted and the worker fetches the flake itself. Use this to build one attribute of a repository on demand - a deployment tool resolving a commit, for instance - without creating a task for it. Executes on the project's reserved `build-request` task, created lazily on first use and shared by every build request in the project, so no task is created per job. Evaluations queued here are `concurrent`: build requests are independent one-shot jobs and never queue behind or abort each other. Supply `rev` for an exact commit, `ref` for a branch or tag the server resolves first, or neither to take the repository's default branch. SSH URLs are authenticated with the project's deploy key. Local paths (`file://`) are rejected. Requires the `TriggerEvaluation` permission on the project. This lets a caller have Gradient fetch and evaluate an arbitrary remote flake on the build fleet - the same capability the source-upload flows already grant. operationId: postBuildRequestUrl requestBody: content: application/json: schema: $ref: '#/components/schemas/UrlRequest' required: true responses: '200': description: Evaluation queued content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DispatchResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/build-requests/{session}/blobs: post: tags: - build-requests summary: Upload missing blobs for an upload session description: |- Step 2. Sends one or more blobs as multipart parts. Each part's **field name** is the 64-character lowercase hex BLAKE3 hash, and the part body is the raw file bytes. The server verifies each blob's hash, rejects any hash that isn't in the session's `missing` set, persists accepted blobs under `nar_storage`, and removes them from `missing`. The route's body limit is `MAX_BUILD_REQUEST_SIZE` (20 MiB). operationId: postBuildRequestBlobs parameters: - name: session in: path required: true schema: $ref: '#/components/schemas/UploadSessionId' requestBody: content: multipart/form-data: schema: type: object additionalProperties: $ref: '#/components/schemas/Binary' propertyNames: type: string required: true responses: '200': description: Blobs accepted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/BlobsResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/build-requests/{session}/dispatch: post: tags: - build-requests summary: Finalise an upload session and queue an evaluation description: |- Step 3. After all `missing` blobs have been uploaded, the client posts here to materialise `/nix/store/-source` from the staged files, sign it with the project's cache key, lazily create the per-project reserved `build-request` task on first use, and queue a new evaluation targeting the supplied `target` attribute path (or the task's wildcard when omitted). operationId: postBuildRequestDispatch parameters: - name: session in: path required: true schema: $ref: '#/components/schemas/UploadSessionId' requestBody: content: application/json: schema: $ref: '#/components/schemas/DispatchRequest' required: true responses: '200': description: Evaluation queued content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DispatchResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/builds/{build}: get: tags: - builds summary: Get build description: |- Returns full build details including status, derivation path, architecture, assigned server, and output store paths. **Access:** Accessible to members of any project whose evaluation references this derivation (a derivation is built once and shared across projects via cache reachability). See `docs/src/concepts/overview.md#shared-builds`. operationId: getBuild parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Build with outputs content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/BuildWithOutputs' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/abort: post: tags: - builds summary: Abort build description: Stops a created, queued or running build of a running evaluation. The build becomes `Aborted` and its dependents in the evaluation become `DependencyFailed`. The evaluation no longer waits for them, and no heal of the evaluation queues them again. A later evaluation builds them again. Requires project membership. Answers 409 when the evaluation has finished, the build has another status, or another running evaluation still needs the build. operationId: abortBuild parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Success content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/builds/{build}/closure: get: tags: - builds summary: Get closure size graph description: |- Returns the full dependency closure of the build's derivation with per-node uncompressed NAR sizes and an exact `total_size_bytes` over the whole closure. The `nodes`/`edges` lists are capped with `truncated` set when the cap is hit: the heaviest subtrees are kept, each still linked to a root. `total_size_bytes` stays exact regardless. Intended for the closure Sankey view and size-trimming tooling. **Access:** Same as the dependency graph endpoint. operationId: getBuildClosure parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Closure size graph content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ClosureGraph' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/download-token: get: tags: - builds summary: Generate a short-lived download token description: |- Returns a signed JWT that is valid for **1 hour** and grants access to all artefact downloads for the specified build. Pass it as `?token=` on `GET /builds/{build}/download/{filename}` to share a link without exposing long-lived credentials. Requires the caller to be a member of the project that owns the build. operationId: getBuildDownloadToken parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Download token content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/builds/{build}/download/{filename}: get: tags: - builds summary: Download build artefact description: |- Streams a build artefact. When the build product is a regular file the response carries the file's contents and a `Content-Type` derived from the extension. When the build product points to a directory inside the output, the response is a zstd-compressed tar archive of the subtree; `Content-Type` is `application/zstd` and `Content-Disposition`'s `filename` ends in `.tar.zst`. Clients should rely on the `Content-Disposition` header for the suggested filename in either case. Access is granted when **any** of the following is satisfied: 1. The owning project is public - no credentials required. 2. `?token=` - a short-lived per-build token from `GET /builds/{build}/download-token` (1 h validity, safe to embed in URLs). 3. `jwt_token` cookie or `Authorization: Bearer` header and the caller is a member of the owning project, or of any project with a build of the same derivation. operationId: downloadBuildArtefact parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' - name: filename in: path required: true schema: type: string - name: token in: query required: false schema: type: string responses: '200': description: File contents (regular file) or zstd-compressed tar archive (directory). content: application/octet-stream: schema: $ref: '#/components/schemas/Binary' application/zstd: schema: $ref: '#/components/schemas/Binary' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/downloads: get: tags: - builds summary: List build artefacts description: |- Returns downloadable artefacts declared in the build's `nix-support/hydra-build-products` file. Each entry has a file type, filename, Nix store path, and file size in bytes. Accessible without authentication when the owning project is public. **Access:** Accessible to members of any project whose evaluation references this derivation (a derivation is built once and shared across projects via cache reachability). See `docs/src/concepts/overview.md#shared-builds`. operationId: getBuildDownloads parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Build artefacts content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/BuildProduct' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/graph: get: tags: - builds summary: Get dependency graph description: |- Returns the full transitive dependency graph rooted at the given build's derivation via BFS over the recorded derivation dependencies, capped at 500 nodes. Node ids are derivation UUIDs; `build` is the build of the same evaluation, or null for a derivation that evaluation does not list. Each edge `source -> target` means `source` must be built before `target`. **Access:** Accessible to members of any project whose evaluation references this derivation (a derivation is built once and shared across projects via cache reachability). See `docs/src/concepts/overview.md#shared-builds`. operationId: getBuildGraph parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Dependency graph content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/BuildGraph' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/live: get: tags: - builds summary: Build live updates (WebSocket) description: |- Upgrades to a WebSocket emitting `build_status_changed` events (`build_id`, `derivation_build`, `evaluation_id`, `status`) for every build in this build's evaluation (covers its dependency graph), and `build_progress` events (`derivation_build`, `phase`, `bytes_done`, `bytes_total`, `paths_done`, `paths_total`) while this build prefetches its inputs, fetches a Substitute or Download, or uploads its outputs. Requires read access. operationId: buildLive parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '101': description: Switching Protocols - WebSocket upgrade successful default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/log: get: tags: - builds summary: Get build log description: |- Returns the complete build log as a single string. Empty string if no log is available yet. A `Substituted` build (its outputs came from a cache) has no log of its own, so the log of the most recent prior build of the same derivation is returned instead. The chunk/lines endpoints fall back the same way. **Access:** Accessible to members of any project whose evaluation references this derivation (a derivation is built once and shared across projects via cache reachability). See `docs/src/concepts/overview.md#shared-builds`. operationId: getBuildLog parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Build log content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] post: tags: - builds summary: Stream build log description: |- Open a streaming NDJSON response: emit the full existing log first, then stream new chunks as they arrive. Close the stream once the build has left the `Building` state. Chunks hold no more than 256 KiB each, split at a line end. Empty strings arrive as keepalives after 15 seconds without output. Ignore them. operationId: streamBuildLog parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: NDJSON log stream content: application/x-ndjson: schema: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/builds/{build}/log/chunk/{index}: get: tags: - builds summary: Get a single decompressed log chunk description: |- Returns one chunk's plaintext (server-decompressed) with the active ANSI color state at the chunk boundary already prepended, so the chunk renders correctly standalone. **Access:** Same as `GET /builds/{build}/log`. operationId: getBuildLogChunk parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' - name: index in: path required: true schema: type: integer format: int32 minimum: 0 responses: '200': description: Chunk plaintext content: text/plain: schema: type: string default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/log/chunks: get: tags: - builds summary: Get build log chunk index description: |- Returns the index of the zstd-compressed log chunks written when the build finalized: total chunk/line/byte counts and per-chunk line/byte offsets. `total_chunks` is `0` for builds whose log has not been finalized yet (use the streaming `POST /log` endpoint for in-progress builds). **Access:** Same as `GET /builds/{build}/log`. operationId: getBuildLogChunks parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Chunk index content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/LogChunkIndex' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/log/lines: get: tags: - builds summary: Get a build log line range description: |- Returns the plaintext for an inclusive 1-based logical line range, resolving the covering chunk(s) server-side and prepending the correct color prefix for the first line. Hand- and CLI-friendly; the frontend also uses this as its lazy fetch path. **Access:** Same as `GET /builds/{build}/log`. operationId: getBuildLogLines parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' - name: start in: query required: false schema: type: integer format: int64 minimum: 0 - name: end in: query required: false schema: type: integer format: int64 minimum: 0 - name: range in: query required: false schema: type: string responses: '200': description: Line range plaintext content: text/plain: schema: type: string default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/log/search: get: tags: - builds summary: Search a build log description: |- Streams NDJSON search hits in scan order as the server decompresses chunks, so first matches and a running count appear immediately. Each line is a `LogSearchHit`; the final frame is a `LogSearchDone` carrying `total_matches`. Matches are per-line substrings (no multi-line matches). **Access:** Same as `GET /builds/{build}/log`. operationId: searchBuildLog parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' - name: q in: query required: true schema: type: string - name: case in: query required: false schema: type: boolean responses: '200': description: NDJSON stream of search hits, terminated by a done frame content: application/x-ndjson: schema: $ref: '#/components/schemas/LogSearchHit' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/builds/{build}/prioritize: post: tags: - builds summary: Prioritize build description: 'Hands out the build and every open build of its dependency closure ahead of unprioritized work. Requires a superuser (`403` with `code: "superuser_required"` otherwise). A build loses its priority when it fails permanently, dependency-fails, times out, is aborted or is skipped.' operationId: prioritizeBuild parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Success content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/builds/{build}/retry: post: tags: - builds summary: Retry build description: Queues a `FailedPermanent`, `FailedTimeout`, `Aborted` or `DependencyFailed` build again, together with its dependents in the evaluation that failed only through it. A `DependencyFailed` build retries the failed builds below it. A reproducible builder failure is retried too. A retry reopens a `Failed` or `Aborted` evaluation that reached its build phase. Requires project membership. Answers 409 when the evaluation has completed or never reached its build phase, a newer or running evaluation of the task exists, the build has another status, no failed dependency is retryable, or its worker has not confirmed an earlier abort yet. operationId: retryBuild parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Success content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/builds/{build}/runtime-closure: get: tags: - builds summary: Get runtime closure size graph description: |- Like `/builds/{build}/closure` but walks runtime store-path references (narinfo `References:`) from the build's outputs instead of build-time dependencies. Only as complete as the cached outputs; node ids are store-path hashes. Same `ClosureGraph` shape. operationId: getBuildRuntimeClosure parameters: - name: build in: path required: true schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: Runtime closure size graph content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ClosureGraph' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/caches: get: tags: - caches summary: List caches description: Returns a paginated list of binary caches the current user owns or can access through a project subscription. operationId: listCaches parameters: - name: page in: query required: false schema: type: integer format: int64 minimum: 0 - name: per_page in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Paginated cache list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Paginated_Cache' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] put: tags: - caches summary: Create cache description: Creates a new binary cache with an auto-generated signing key. operationId: createCache requestBody: content: application/json: schema: $ref: '#/components/schemas/MakeCacheRequest' required: true responses: '200': description: Cache UUID content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/available: get: tags: - caches summary: Check cache name availability description: Returns `true` if no cache with the given name exists, `false` if it is already taken. operationId: checkCacheNameAvailable parameters: - name: name in: query required: true schema: type: string responses: '200': description: Availability result content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/public: get: tags: - caches summary: List public caches description: Returns every public cache. Does not require authentication. operationId: listPublicCaches responses: '200': description: Public cache list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/Cache' default: $ref: '#/components/responses/Error' security: [] /api/v1/caches/{cache}: get: tags: - caches summary: Get cache description: Returns cache details. Public caches are visible to anyone. A private cache is visible to its cache members and to members of any project subscribed to it (matching the visibility of `GET /caches`); other callers receive `404`. operationId: getCache parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Cache details content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CacheResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] delete: tags: - caches summary: Delete cache description: Deletes the cache. Requires `deleteCache`. Managed caches cannot be deleted via the API. operationId: deleteCache parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - caches summary: Update cache description: Updates one or more cache fields. Requires `manageCacheSettings`. Managed caches cannot be edited via the API. operationId: patchCache parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchCacheRequest' required: true responses: '200': description: Updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/active: post: tags: - caches summary: Enable cache description: Also allowed on a state-managed cache. The next server start restores the declared `active` value. operationId: enableCache parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Enabled content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - caches summary: Disable cache description: Also allowed on a state-managed cache. The next server start restores the declared `active` value. operationId: disableCache parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Disabled content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/invitations: get: tags: - caches summary: List pending cache invitations description: Requires `manageCacheMembers`. operationId: listCacheInvitations parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Pending invitations content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/PendingInvitationItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - caches summary: Revoke a pending cache invitation description: Requires `manageCacheMembers`. operationId: revokeCacheInvitation parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/RevokeInvitationRequest' required: true responses: '200': description: Invitation revoked content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/key: get: tags: - caches summary: Get cache secret signing key description: |- Returns the Nix-format secret signing key string for the cache, e.g.: `gradient.example.com-mycache:AAAA...` (base64-encoded 64-byte ed25519 keypair) Requires `manageCacheKeys`. Keep the secret key private - do not add it to `nix.conf`. To configure Nix clients use the public key from `GET /caches/{cache}/public-key` instead. operationId: getCacheKey parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Cache secret signing key content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/members: get: tags: - caches summary: List cache members description: Returns all members of the cache and their assigned roles. Requires `viewCache`. operationId: listCacheMembers parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Member list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/MemberItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - caches summary: Invite cache member description: |- Invites a user to the cache with the given role. Requires `manageCacheMembers`. The user is **not** a member until they accept; the response message is `Invitation sent` and the pending row appears under `GET /caches/{cache}/invitations`. An invitation expires after 7 days. A **superuser** who already holds the permission adds the member directly instead, answering `User added`. operationId: addCacheMember parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/AddMemberRequest' required: true responses: '200': description: Invitation sent, or member added when the caller is a superuser content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - caches summary: Remove cache member description: |- Removes a user from the cache. Requires `manageCacheMembers`. The last Admin cannot be removed (`409`). operationId: removeCacheMember parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/RemoveMemberRequest' required: true responses: '200': description: Member removed content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - caches summary: Update cache member role description: Changes the role of an existing cache member. Requires `manageCacheMembers`. operationId: patchCacheMember parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/AddMemberRequest' required: true responses: '200': description: Role updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/nars: get: tags: - caches summary: List cached NARs description: |- Returns a paginated list of NARs (cached store paths) currently signed by this cache. Public caches allow anonymous access; otherwise requires `readStore`. operationId: listCacheNars parameters: - name: cache in: path required: true schema: type: string - name: hash in: query required: false schema: type: string - name: package in: query required: false schema: type: string - name: sort in: query required: false schema: type: string - name: order in: query required: false schema: type: string - name: page in: query required: false schema: type: integer format: int64 minimum: 0 - name: per_page in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Paginated NAR list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Paginated_NarSummary' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] post: tags: - caches summary: Upload a NAR to a cache description: |- Uploads a single NAR (its bytes plus narinfo metadata) to this cache. Requires `writeStore`. The server validates the byte length against the declared `file_size`, stores the blob, records the cached path, and enqueues a signature for this cache. Re-uploading an existing store path reuses the cached path and only adds this cache's signature. The route's body limit is `GRADIENT_NAR_MAX_UPLOAD_SIZE` (default 512 MiB). The bundled reverse proxy additionally caps each request body at 100 MiB, so NARs above that must use the chunked endpoints (`PUT .../nars/{hash}/chunk` + `POST .../nars/{hash}/finalize`). operationId: uploadCacheNar parameters: - name: cache in: path required: true schema: type: string requestBody: content: multipart/form-data: schema: $ref: '#/components/schemas/NarUploadForm' required: true responses: '201': description: NAR stored content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/StoredNar' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/nars/available: get: tags: - caches summary: Check whether a NAR is available description: |- Returns `{ available: true }` when this cache currently holds a signature row for the given store-path hash. Cheaper than a `GET /nars/{hash}` round-trip for clients that only need a yes/no answer. operationId: getCacheNarAvailable parameters: - name: cache in: path required: true schema: type: string - name: hash in: query required: true schema: type: string responses: '200': description: Availability flag content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/NarAvailable' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/caches/{cache}/nars/stats: get: tags: - caches summary: NAR aggregate statistics description: |- Returns aggregate counts and sizes for all NARs signed by this cache. Public caches allow anonymous access; otherwise requires `readStore`. operationId: getCacheNarStats parameters: - name: cache in: path required: true schema: type: string responses: '200': description: NAR aggregates content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/NarStats' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/caches/{cache}/nars/{hash}: get: tags: - caches summary: Get NAR detail description: |- Returns full metadata for a NAR signed by this cache, including references, deriver, content-addressed flag, fetch count, and signature presence. Public caches allow anonymous access; otherwise requires `readStore`. operationId: getCacheNar parameters: - name: cache in: path required: true schema: type: string - name: hash in: path required: true schema: type: string responses: '200': description: NAR detail content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/NarDetail' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] delete: tags: - caches summary: Delete a NAR from this cache description: |- Removes this cache's signature row for the given store-path hash. The delete is ref-counted: when other caches still hold the same NAR, only this cache's signature is dropped. When this is the last cache holding the NAR, the `cached_path` row is removed in the same transaction and the NAR blob is garbage-collected asynchronously after the response. Requires `writeStore`. Allowed on state-managed caches - NAR content is operational data, distinct from cache configuration. operationId: deleteCacheNar parameters: - name: cache in: path required: true schema: type: string - name: hash in: path required: true schema: type: string responses: '204': description: NAR removed from this cache default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/nars/{hash}/chunk: put: tags: - caches summary: Append a chunk of a NAR being uploaded description: |- Appends one slice of a NAR to a server-side `.partial` staging file, one per `(cache, hash)`. Used to upload NARs larger than the reverse proxy's per-request body limit by splitting them across several requests. Requires `writeStore`. `offset == 0` starts fresh (truncating any stale partial); otherwise the chunk is appended only when `offset` equals the bytes already staged. The response's `received` is authoritative: the client sets its next offset to it (resending if it did not advance) and calls `POST .../finalize` once `received` equals the NAR size. operationId: uploadCacheNarChunk parameters: - name: cache in: path required: true schema: type: string - name: hash in: path required: true schema: type: string - name: offset in: query required: true schema: type: integer format: int64 minimum: 0 requestBody: content: application/octet-stream: schema: $ref: '#/components/schemas/Binary' required: true responses: '200': description: Chunk staged content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ChunkReceived' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/nars/{hash}/finalize: post: tags: - caches summary: Finalize a chunked NAR upload description: |- Validates the fully staged NAR against its narinfo (the staged byte length must equal `file_size`), imports it exactly like the single-shot upload, and drops the `.partial`. Requires `writeStore`. operationId: finalizeCacheNarUpload parameters: - name: cache in: path required: true schema: type: string - name: hash in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/NarinfoPart' required: true responses: '201': description: NAR stored content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/StoredNar' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/public: post: tags: - caches summary: Make cache public description: Makes the cache readable without authentication, by the API and by Nix clients. operationId: makeCachePublic parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Cache is now public content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - caches summary: Make cache private description: Requires credentials to read the cache, by the API and by Nix clients. operationId: makeCachePrivate parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Cache is now private content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/public-key: get: tags: - caches summary: Get cache public key description: |- Returns the Nix-format public key string for the cache, e.g.: `gradient.example.com-mycache:AAAA...` (base64-encoded 32-byte ed25519 public key) Add this value to `trusted-public-keys` in `nix.conf` or NixOS configuration so Nix clients can verify signatures on store paths served from this cache. operationId: getCachePublicKey parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Cache public key content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/caches/{cache}/roles: get: tags: - caches summary: List cache roles description: |- Returns the three built-in roles (Admin/Write/View) plus any custom roles owned by this cache, along with the full catalogue of cache permissions. Visible to any cache member (`viewCache`). operationId: listCacheRoles parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Role catalogue content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RoleListResponse_CacheRoleOwner' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - caches summary: Create custom cache role description: |- Creates a new role scoped to this cache. Requires `manageCacheRoles`. The role's permission set is chosen from the capabilities returned by `GET /caches/{cache}/roles` -> `available_permissions`. operationId: createCacheRole parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateRoleRequest' required: true responses: '200': description: Role created content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RoleResponse_CacheRoleOwner' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/roles/{role_id}: get: tags: - caches summary: Fetch a cache role operationId: getCacheRole parameters: - name: cache in: path required: true schema: type: string - name: role_id in: path required: true schema: $ref: '#/components/schemas/RoleId' responses: '200': description: Role content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RoleResponse_CacheRoleOwner' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - caches summary: Delete a custom cache role description: |- Deletes a custom cache role. Built-in roles cannot be deleted (`403`). A role still assigned to members cannot be deleted until those members are reassigned (`400`). Requires `manageCacheRoles`. operationId: deleteCacheRole parameters: - name: cache in: path required: true schema: type: string - name: role_id in: path required: true schema: $ref: '#/components/schemas/RoleId' responses: '200': description: Role deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - caches summary: Update a custom cache role description: |- Renames a custom role and/or replaces its permission set. Built-in roles (Admin/Write/View) are immutable (`403`). Requires `manageCacheRoles`. operationId: patchCacheRole parameters: - name: cache in: path required: true schema: type: string - name: role_id in: path required: true schema: $ref: '#/components/schemas/RoleId' requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchRoleRequest' required: true responses: '200': description: Role updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RoleResponse_CacheRoleOwner' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/stats: get: tags: - caches summary: Get cache statistics description: Returns bandwidth and hit statistics for the cache. Visible to anyone for public caches, and to cache members or members of any project subscribed to a private cache (matching `GET /caches/{cache}`); other callers receive `404`. operationId: getCacheStats parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Cache statistics content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CacheStatsResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/caches/{cache}/subscription-requests: get: tags: - caches summary: List subscription requests description: Projects that asked to subscribe to this cache and await a decision. Requires `manageCacheSubscriptions`. operationId: listCacheSubscriptionRequests parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Pending requests, newest first content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/SubscriptionRequestItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/subscription-requests/{project}: post: tags: - caches summary: Approve a subscription request description: |- Turns the pending request into a real subscription, using the mode the project asked for, and re-queues any evaluation parked for want of a cache. Requires `manageCacheSubscriptions`. operationId: approveCacheSubscriptionRequest parameters: - name: cache in: path required: true schema: type: string - name: project in: path required: true schema: type: string responses: '200': description: Subscription approved content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - caches summary: Deny a subscription request description: Requires `manageCacheSubscriptions`. operationId: denyCacheSubscriptionRequest parameters: - name: cache in: path required: true schema: type: string - name: project in: path required: true schema: type: string responses: '200': description: Subscription request denied content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/teams: get: tags: - teams summary: List cache team grants description: Includes pending requests. operationId: listCacheTeams parameters: - name: cache in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TeamGrantEntry' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - teams summary: Grant a team on a cache description: |- Needs `manageCacheMembers`. A grant is active at once when the caller is Admin in the team (or a superuser). Otherwise a request waits for a team Admin and the answer is `Request sent`. operationId: grantCacheTeam parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/GrantCacheRequest' required: true responses: '200': description: '`Team granted` or `Request sent`' content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/teams/{team}: delete: tags: - teams summary: Remove a cache team grant description: |- Allowed for `manageCacheMembers` on the cache or Admin in the team. Without a grant, the pending request is withdrawn instead. operationId: removeCacheTeam parameters: - name: cache in: path required: true schema: type: string - name: team in: path required: true schema: type: string responses: '200': description: '`Team grant removed` or `Request withdrawn`' content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - teams summary: Change a cache team grant description: Needs `manageCacheMembers`. operationId: patchCacheTeam parameters: - name: cache in: path required: true schema: type: string - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchCacheGrantRequest' required: true responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/upstream-caches: get: tags: - caches summary: List upstream caches description: 'Returns all upstream caches configured for this cache (both internal Gradient caches and external binary caches), including each upstream''s `public_key` so clients can trust pull-through paths. Follows the same visibility as `GET /caches/{cache}`: public caches are readable by anyone, private caches only by members and subscribed projects.' operationId: listUpstreamCaches parameters: - name: cache in: path required: true schema: type: string responses: '200': description: List of upstream entries content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/UpstreamCacheItem' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] put: tags: - caches summary: Add upstream cache description: |- Adds an upstream cache. Three types are supported, selected by the `type` discriminator: - **internal** - another Gradient-managed cache (referenced by name). Supports ReadOnly / ReadWrite / WriteOnly modes. - **gradient_proto** - a remote Gradient cache accessed via the binary WebSocket protocol (`/cache/{cache}/proto`). Supports optional `api_key` (stored encrypted at rest; write-only - never returned by the API) and pull mode. - **http** - an arbitrary Nix binary cache URL. Always ReadOnly. Requires `manageUpstreamCaches`. operationId: addUpstreamCache parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/AddUpstreamRequest' required: true responses: '200': description: Upstream added - returns the new upstream UUID content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CacheUpstreamId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/upstream-caches/{id}: delete: tags: - caches summary: Remove upstream cache operationId: deleteUpstreamCache parameters: - name: cache in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/CacheUpstreamId' responses: '200': description: Removed content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - caches summary: Update upstream cache description: |- Updates an upstream entry. For external upstream caches the mode is always forced to ReadOnly; `url` and `public_key` may be updated. For internal upstream caches only `mode` and `display_name` apply. `active` toggles any upstream cache. An inactive upstream cache is kept but never queried. A state-managed cache accepts only `active`, and the next server start restores the declared value. Requires `manageUpstreamCaches`. operationId: patchUpstreamCache parameters: - name: cache in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/CacheUpstreamId' requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchUpstreamRequest' required: true responses: '200': description: Updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/upstream-caches/{id}/test: post: tags: - caches summary: Test an HTTP upstream cache over HTTP/1.1 and HTTP/2 description: |- Fetches the upstream cache's `nix-cache-info` twice in parallel, once over HTTP/1.1 only and once over HTTP/2 only, and reports each result. A probe passes on a 2xx body with a `StoreDir:` line. Does not change the upstream cache's `http1_only` pin. Only `http` upstream caches can be tested. Requires `manageUpstreamCaches`; state-managed caches may be tested. operationId: testUpstreamCache parameters: - name: cache in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/CacheUpstreamId' responses: '200': description: Test result content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/UpstreamTestResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/webhooks: get: tags: - webhooks summary: List cache webhooks description: Requires `manageCacheWebhooks` on the cache. operationId: listCacheWebhooks parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Webhooks content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - webhooks summary: Create a cache webhook description: |- Requires `manageCacheWebhooks` on the cache. The response carries the signing `secret` once; it is never returned again (use `rotate-secret` to replace it). operationId: createCacheWebhook parameters: - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateWebhookRequest' required: true responses: '200': description: Created webhook and its secret content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CreateWebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/webhooks/{id}: get: tags: - webhooks summary: Read a cache webhook operationId: readCacheWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: cache in: path required: true schema: type: string responses: '200': description: Webhook content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - webhooks summary: Delete a cache webhook operationId: deleteCacheWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: cache in: path required: true schema: type: string responses: '200': description: Deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeletedResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - webhooks summary: Update a cache webhook operationId: updateCacheWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateWebhookRequest' required: true responses: '200': description: Updated webhook content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/webhooks/{id}/deliveries: get: tags: - webhooks summary: List a cache webhook's deliveries operationId: listCacheWebhookDeliveries parameters: - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 - name: offset in: query required: false schema: type: integer format: int64 minimum: 0 - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: cache in: path required: true schema: type: string responses: '200': description: Deliveries, newest first content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/DeliveryListItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/webhooks/{id}/deliveries/{delivery_id}: get: tags: - webhooks summary: Read one cache webhook delivery with bodies operationId: getCacheWebhookDelivery parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: delivery_id in: path required: true schema: $ref: '#/components/schemas/WebhookDeliveryId' - name: cache in: path required: true schema: type: string responses: '200': description: Delivery content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryDetail_WebhookDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/webhooks/{id}/rotate-secret: post: tags: - webhooks summary: Replace a cache webhook's signing secret operationId: rotateCacheWebhookSecret parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: cache in: path required: true schema: type: string responses: '200': description: The new secret, shown once content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RotatedSecret' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/caches/{cache}/webhooks/{id}/test: post: tags: - webhooks summary: Send a `webhook.ping` to a cache webhook description: Delivers immediately (no retry) and returns the recorded delivery. operationId: testCacheWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: cache in: path required: true schema: type: string responses: '200': description: Recorded delivery content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryListItem_WebhookDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/commits/{commit}: get: tags: - commits summary: Get commit description: |- Returns commit metadata (message, hash, author). Visibility follows the commit's reachability: the caller must be a member of a project that owns an evaluation (or direct build) referencing the commit, or that project must be public. Anonymous callers may read commits reachable through public projects only. All other cases return `404` so existence isn't leaked. operationId: getCommit parameters: - name: commit in: path required: true schema: $ref: '#/components/schemas/CommitId' responses: '200': description: Commit content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Commit' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/config: get: tags: - general summary: Server configuration description: Returns feature flags for the frontend (OIDC enabled, registration disabled, email verification). operationId: getConfig responses: '200': description: Server configuration content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ServerConfig' default: $ref: '#/components/responses/Error' security: [] /api/v1/dashboard/activity: get: tags: - dashboard summary: Daily evaluation activity of the current user description: |- One entry per day from 370 days ago through today, oldest first, days without evaluations included as zero. Counts non-PR evaluations of the projects the viewer may see; `failed` counts evaluations with status `Failed`. operationId: getDashboardActivity responses: '200': description: Daily evaluation counts content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Activity' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/dashboard/rail: get: tags: - dashboard summary: Sidebar rail of the current user description: |- Projects: member projects plus starred public ones, sorted by tier (`starred_active`, `active`, `starred`, `team`, `member`), then name. Active means a non-PR evaluation in the last 14 days; `status` is the latest non-PR evaluation's status or `null`. `tasks` is present only on `starred_active` projects and omitted otherwise. Caches: those the viewer created, is a member of or reaches through a member project, plus starred public ones; starred first, then name. Superusers get no extra caches here. operationId: getDashboardRail responses: '200': description: Rail projects and caches content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Rail' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/dashboard/stats: get: tags: - dashboard summary: Stat tiles of the current user description: |- Totals over the projects the viewer may see (all for a superuser, public plus member projects otherwise). `builds_completed` counts recorded derivation metrics; `queue_wait_p50_ms` is the median wait for a worker over the last 24 hours. `cache_size_bytes` sums the stored size of each cache the viewer created or reaches through a project membership (all caches for a superuser); each size is recounted every metrics rollup pass, and a path held by two caches counts in both. `workers` covers connected workers of visible projects only: `busy_pct` is assigned jobs over summed capacity, capped at 100. operationId: getDashboardStats responses: '200': description: Dashboard stat tiles content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DashboardStats' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/dashboard/tasks: get: tags: - dashboard summary: Ranked task table of the current user description: |- Tasks of the viewer's projects plus starred tasks of public projects, PR-triggered evaluations excluded. Ranked by tier (`starred_active`, `active`, `starred`, `team`, `member`), then newest latest evaluation first. Active means a non-PR evaluation in the last 14 days. `counts` always covers every task; `total` is the number of tasks matching `filter`. operationId: getDashboardTasks parameters: - name: filter in: query required: false schema: $ref: '#/components/schemas/Filter' - name: page in: query required: false schema: type: integer format: int64 minimum: 0 - name: per_page in: query required: false schema: type: integer format: int64 minimum: 0 - name: history in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: One page of ranked tasks content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TasksPage' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/evals/{evaluation}: get: tags: - evals summary: Get evaluation description: Returns the evaluation record including status, commit, and timestamps. operationId: getEvaluation parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: Evaluation content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/EvaluationResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] post: tags: - evals summary: Evaluation action description: |- Performs an action on the evaluation. Currently the only supported action is `"abort"`, which cancels all in-progress and queued builds. operationId: postEvaluation parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' requestBody: content: application/json: schema: $ref: '#/components/schemas/MakeEvaluationRequest' required: true responses: '200': description: Success content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/evals/{evaluation}/artefacts: get: tags: - evals summary: List evaluation artefacts description: |- Returns the artefact tree for an evaluation: entry points grouped by derivation, derivation outputs grouped under each entry point, and `build_product` rows grouped under each output. Consumed by the CLI's `gradient download` picker so users can choose what to fetch without first listing builds. Entry points are sorted by `attr`, outputs by `name`, products by `path`. operationId: listEvaluationArtefacts parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: Artefact tree content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ArtefactTree' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/evals/{evaluation}/builds: get: tags: - evals summary: List evaluation builds description: |- Returns `.drv` builds associated with the evaluation, sorted by status (Building, then Queued, then FailedTransient/FailedPermanent/FailedTimeout, then Aborted/DependencyFailed, then Completed/Substituted, then Skipped), then by display name. Supports optional `limit` and `offset` query parameters for pagination, and an optional `scope` to restrict the list to one package's build-time dependency closure. Each item is a per-evaluation `build_job`; its `id` is used for log, downloads, and dependency-graph endpoints. The build *state* (status, timing, log) comes from the global `derivation_build` row, a shared build for every evaluation that needs the same derivation, so a derivation is built once and the outcome is reused across evaluations and projects. operationId: listEvaluationBuilds parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' - name: limit in: query required: false schema: type: integer minimum: 0 - name: offset in: query required: false schema: type: integer minimum: 0 - name: scope in: query required: false schema: $ref: '#/components/schemas/BuildJobId' responses: '200': description: |- Paginated build list, ordered by build status (running, then failed, aborted, queued, finished), then by dependency layer (`depth`), then by derivation name within a layer - so within one status the entry point heads the list and every build precedes the builds it needs. content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/PaginatedBuilds' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] post: tags: - evals summary: Stream evaluation logs description: |- Open a streaming NDJSON response: replay the stored logs of all builds first, then follow the derivations still building. A derivation-name prefix opens each line. Keep the stream open until the evaluation itself has reached Completed, Failed or Aborted, not merely until no build is pending, so an evaluation without builds yet still has its stream. Evaluation-level messages are not part of this stream. Fetch them from `GET /evals/{evaluation}/messages`. Chunks hold no more than 256 KiB each, split at a line end. Empty strings arrive as keepalives after 15 seconds without output. Ignore them. operationId: streamEvaluationLogs parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: NDJSON log stream content: application/x-ndjson: schema: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/evals/{evaluation}/closure: get: tags: - evals summary: Get closure size graph for an evaluation description: |- Returns the union dependency closure of all the evaluation's entry-point builds with per-node uncompressed NAR sizes and an exact `total_size_bytes`. Same shape as `/builds/{build}/closure`. operationId: getEvalClosure parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: Closure size graph content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ClosureGraph' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/evals/{evaluation}/flake-graph: get: tags: - evals summary: Get the walked flake output graph for an evaluation description: |- Returns the flake output nodes walked during evaluation, each with its attribute path, parent, name, kind, and (for derivations) the `.drv` path. operationId: getEvalFlakeGraph parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: Flake output graph content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/FlakeGraphNode' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/evals/{evaluation}/live: get: tags: - evals summary: Evaluation live updates (WebSocket) description: |- Upgrades to a WebSocket emitting `evaluation_status_changed`, `build_status_changed`, `evaluation_progress` and `evaluation_activity` events for this evaluation. `evaluation_progress` fires as builds and entry-points are persisted during the evaluation phase so the build list grows live. `evaluation_activity` carries an `EvaluationProgress` snapshot at most once per second while the evaluation fetches or evaluates. Requires read access. operationId: evaluationLive parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '101': description: Switching Protocols - WebSocket upgrade successful default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/evals/{evaluation}/messages: get: tags: - evals summary: List evaluation messages description: |- Returns all structured messages (errors, warnings, notices) recorded during the evaluation. Each message carries a `level`, a human-readable `message`, and an optional `source` tag that identifies where the message originated (e.g. `"flake-prefetch"`, `"nix-eval"`, `"nix-eval:"`, `"db-insert"`). Messages scoped to specific entry points list their entry-point UUIDs in the `entry_points` array; evaluation-wide messages have an empty array. operationId: listEvaluationMessages parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: Message list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/EvaluationMessageResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/evals/{evaluation}/prioritize: post: tags: - evals summary: Prioritize evaluation description: 'Hands out every build of an active evaluation, including builds it has not resolved yet, ahead of unprioritized work. Requires a superuser (`403` with `code: "superuser_required"` otherwise). A finished evaluation is left unchanged; a failed or aborted one loses its priority.' operationId: prioritizeEvaluation parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: Success content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/evals/{evaluation}/report: get: tags: - evals summary: Download an evaluation diagnostic report description: |- Exports the evaluation, the instance context that explains it, and its failed-build logs as a SQLite database, for attaching to a bug report. Open it with any SQLite client, or with the `gradient-report` inspector. The export carries the direct dependencies of the evaluation's derivations, build-time and runtime alike, and their outputs' paths, so `blocking_deps` and `missing_runtime_deps` can be recomputed from the file alone and an absent row means the instance never had it. Requires authentication even for a public project, whose evaluations are otherwise browsable anonymously: a report reads every failed build's log in one request. Reading the evaluation requires `ViewProject`. `include_instance` also requires `ManageWorkers`, since the fleet and upstream sections describe more than the evaluation that asked for them; it is refused rather than silently dropped, so the report's manifest always matches the request. Anonymisation replaces identifying strings with tokens derived from a per-report salt, stable within one file and uncorrelatable across two. Build logs are rewritten against those same tokens, plus any store path they name, so a log cannot reintroduce what the columns redacted. Nix store hashes are always preserved: they are one-way, and they are what makes an upstream cache check possible. The parameter defaults below apply to callers that omit them. The web dialog asks the inverse question - what to *include* - and always sends all four explicitly, with build logs off unless asked for. operationId: getEvaluationReport parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' - name: anonymize_identities in: query required: false schema: type: boolean - name: anonymize_packages in: query required: false schema: type: boolean - name: include_logs in: query required: false schema: type: boolean - name: include_instance in: query required: false schema: type: boolean responses: '200': description: SQLite report content: application/vnd.sqlite3: schema: $ref: '#/components/schemas/Binary' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/evals/{evaluation}/retry: post: tags: - evaluations summary: Retry evaluation description: Starts a new evaluation of the same commit without fetching or evaluating again, and returns its UUID in `message`. The new evaluation queues every failed, timed-out, aborted and dependency-failed build of the finished evaluation again, a reproducible builder failure included, whatever the task's `retry_failed_builds`. Requires project membership. Answers 409 while the evaluation or another evaluation of its task is running. operationId: retryEvaluation parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: UUID of the new evaluation content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/evals/{evaluation}/runtime-closure: get: tags: - evals summary: Get runtime closure size graph for an evaluation description: |- Union runtime reference closure of all the evaluation's entry-point build outputs. Runtime counterpart of `/evals/{evaluation}/closure`. operationId: getEvalRuntimeClosure parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: Runtime closure size graph content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ClosureGraph' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/evals/{evaluation}/summary: get: tags: - evals summary: Summarise what went wrong in an evaluation description: |- Returns the builds that failed themselves, each with the packages it blocks, the attributes that failed to evaluate, and the packages fixed since the previous evaluation. A build that only failed because a dependency failed is not listed; it is counted under the build that caused it. `newly_failing` and `fixed` compare against the evaluation in `compared_with`. Without a previous evaluation `compared_with` is `null`, every `newly_failing` is `false` and `fixed` is empty. operationId: getEvaluationSummary parameters: - name: evaluation in: path required: true schema: $ref: '#/components/schemas/EvaluationId' responses: '200': description: Failure summary of the evaluation. content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/EvaluationFailureSummary' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/events/catalog: get: tags: - board summary: List every event name description: |- Every event Gradient emits. `durable` events are delivered to webhooks and task actions; the others only reach `/metrics/events`. Names ending in `*` are families (`proto.client.*`). operationId: getEventsCatalog responses: '200': description: Event catalog content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/CatalogEntry' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/gradient-ci/connections: post: tags: - workers summary: Connect Gradient.CI Servers description: |- Stores a connection token pasted from servers.gradient.ci. `scope = project` creates a worker registration for the project (same permission as registering a worker); `scope = team` creates a worker of the team (Admin in the team). The server dials `wss:///proto` within 15 s, a team connection only once a project grants the team its workers. Turned off by `gradientCi.enable = false`. operationId: connectGradientCi requestBody: content: application/json: schema: $ref: '#/components/schemas/ConnectionRequest' required: true responses: '200': description: Connection stored content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ConnectionResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/health: get: tags: - general summary: Health check description: Returns `200 ALIVE` when the server is running. Does not require authentication. operationId: getHealth responses: '200': description: Server is alive content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: [] /api/v1/hooks/github: post: tags: - git-host-webhooks summary: Receive GitHub App webhook description: |- Receives events from a configured GitHub App. Payloads are authenticated using `X-Hub-Signature-256` HMAC-SHA256 verification against the configured `GRADIENT_GITHUB_APP_WEBHOOK_SECRET_FILE`. **Handled events:** - `push` / `pull_request` / `release` - trigger an evaluation on any task whose repository URL matches the matching trigger. A `push` carrying an all-zero `after` SHA (a branch/tag deletion or a Git host "test" delivery) is accepted as a `200` no-op rather than rejected. - `merge_group` - `checks_requested` evaluates the merge group head on every push trigger whose branch filter matches the queue's base branch. - `check_run` - the "Approve and Run" action clears a fork-PR approval gate. - `issue_comment` - `/gradient run` / `/gradient approve` / `/gradient summary` maintainer commands. - `pull_request_review` - a maintainer's approving review clears a fork-PR approval gate. - `installation` / `installation_repositories` - stores or clears the GitHub App `installation_id` on the matching Gradient project. - `ping` - always returns 200. This endpoint is unauthenticated (verified via HMAC signature). operationId: githubAppWebhook parameters: - name: X-GitHub-Event in: header required: true schema: type: string - name: X-Hub-Signature-256 in: header required: true schema: type: string requestBody: content: application/json: schema: {} required: true responses: '200': description: Webhook processed (may include zero queued evaluations) content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/IncomingWebhookResponse' default: $ref: '#/components/responses/Error' security: [] /api/v1/hooks/{git_host}/{project}/{integration_name}: post: tags: - git-host-webhooks summary: Receive Git host push webhook description: |- Receives push events for a named inbound integration. Authenticated via the integration's stored HMAC secret. Signature header by Git host: - `gitea` / `forgejo`: `X-Gitea-Signature` (HMAC-SHA256 hex) - `gitlab`: `X-Gitlab-Token` (plain token comparison) On a matching push, queues an evaluation for every active task whose `task_integration.inbound_integration` points at this row and whose repository URL matches the webhook payload's clone URL. A push carrying an all-zero `after` SHA (a branch/tag deletion or a Git host "test" delivery) is accepted as a `200` no-op rather than rejected. This endpoint is unauthenticated (verified via Git host specific signature). operationId: gitHostWebhook parameters: - name: git_host in: path required: true schema: type: string - name: project in: path required: true schema: type: string - name: integration_name in: path required: true schema: type: string requestBody: content: application/json: schema: {} required: true responses: '200': description: Webhook processed (may include zero queued evaluations) content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/IncomingWebhookResponse' default: $ref: '#/components/responses/Error' security: [] /api/v1/metrics/catalog: get: tags: - board summary: Metric catalog description: Lists the queryable metrics with their kind, unit, and dimensions. operationId: getMetricsCatalog responses: '200': description: Catalog of available metrics content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/MetricMeta' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/metrics/events: get: tags: - board summary: Stream every event (websocket, debug only) description: |- Should not be used for production! Best-effort, in-process, per server instance, drops on lag. Use webhooks. Upgrades to a websocket that sends one `EventEnvelope` JSON object per text frame. A subscriber that falls behind receives `{"event":"stream.lagged","content":{"skipped":N}}` and keeps streaming. Superuser only. operationId: getEventsFirehose parameters: - name: events in: query required: false schema: type: string responses: '101': description: Switching to websocket; every frame is an `EventEnvelope`. default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/metrics/query: get: tags: - board summary: Query a metric time-series description: |- Returns time-bucketed points for a metric from `metric_rollup`, masked to the caller's scope (superuser = all projects, member = own + public projects, anonymous = public projects). Unknown metrics or out-of-scope projects return 404. operationId: getMetricsQuery parameters: - name: metric in: query required: true schema: type: string - name: granularity in: query required: false schema: type: string - name: from in: query required: false schema: type: string - name: to in: query required: false schema: type: string - name: project in: query required: false schema: type: string format: uuid responses: '200': description: Time-series points content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/MetricPoint' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/metrics/tasks/{project}/{task}/entry-point: get: tags: - board summary: Per-evaluation entry-point metrics description: Per-evaluation build metrics for a single entry point identified by its `eval` attribute path. operationId: getEntryPointEvaluationMetrics parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: eval in: query required: true schema: type: string responses: '200': description: Per-evaluation entry-point metric points content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/EntryPointMetricsResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/metrics/tasks/{project}/{task}/evaluations: get: tags: - board summary: Per-evaluation task metrics description: Per-evaluation series (build time, eval time, output/closure sizes, dependencies) for the task's recent completed evaluations. operationId: getTaskEvaluationMetrics parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Per-evaluation metric points content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TaskMetricsResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/projects: get: tags: - projects summary: List projects description: Returns all projects the current user is a member of. operationId: listProjects parameters: - name: page in: query required: false schema: type: integer format: int64 minimum: 0 - name: per_page in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Project list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Paginated_ProjectSummary' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] put: tags: - projects summary: Create project description: Creates a new project owned by the current user. operationId: createProject requestBody: content: application/json: schema: $ref: '#/components/schemas/MakeProjectRequest' required: true responses: '200': description: Project UUID content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/available: get: tags: - projects summary: Check project name availability description: Returns `true` if no project with the given name exists, `false` if it is already taken. operationId: checkProjectNameAvailable parameters: - name: name in: query required: true schema: type: string responses: '200': description: Availability result content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/public: get: tags: - projects summary: List public projects description: Returns a paginated list of all public projects, ordered by name. Does not require authentication. operationId: listPublicProjects parameters: - name: page in: query required: false schema: type: integer format: int64 minimum: 0 - name: per_page in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Paginated public project list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Paginated_Project' default: $ref: '#/components/responses/Error' security: [] /api/v1/projects/{project}: get: tags: - projects summary: Get project operationId: getProject parameters: - name: project in: path required: true schema: type: string responses: '200': description: Project details content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ProjectResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] delete: tags: - projects summary: Delete project description: |- Permanently deletes the project and all its resources. Requires the caller to hold the **admin** role in the project. operationId: deleteProject parameters: - name: project in: path required: true schema: type: string responses: '200': description: Deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - projects summary: Update project description: |- Updates one or more project fields. Managed projects cannot be edited via the API. Requires the caller to hold the **admin** role in the project. operationId: patchProject parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchProjectRequest' required: true responses: '200': description: Updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/integrations: get: tags: - integrations summary: List integrations description: List all inbound and outbound integrations in this project. operationId: listProjectIntegrations parameters: - name: project in: path required: true schema: type: string responses: '200': description: List of integrations content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/IntegrationResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] put: tags: - integrations summary: Create integration description: |- Creates a named inbound or outbound integration. `secret` and `access_token` are stored encrypted and never returned in responses. Name is unique within `(project, kind)`. One **inbound** integration can serve Gitea/Forgejo/GitLab simultaneously - the caller picks the Git host path segment in the webhook URL (`/hooks/gitea/...`, `/hooks/forgejo/...`, `/hooks/gitlab/...`). The stored `git_host_type` is display metadata only for inbound. `git_host_type: "github"` integrations are creatable by supplying `installation_id`. The server App must be configured (else `400`); the installation id is validated against the App (invalid id returns `400`). An inbound and outbound integration pair is created automatically, named `github-`. Multiple installations per project are supported (one per GitHub account). operationId: createProjectIntegration parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateIntegrationRequest' required: true responses: '200': description: Integration created content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/IntegrationResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/integrations/summary: get: tags: - integrations summary: List integration summaries (credential-free) description: |- List integrations as credential-free summaries. Available to **any project member**, in contrast to the full listing which requires `ManageIntegrations`. The response excludes `secret`, `endpoint_url`, `access_token`, and the `has_secret` / `has_access_token` booleans so non-admin members cannot fingerprint credential state. Intended for UIs that only need an integration's name and Git host type - e.g. populating the trigger create/edit dropdown for users who hold `EditTask` but not `ManageIntegrations`. operationId: listProjectIntegrationSummaries parameters: - name: project in: path required: true schema: type: string responses: '200': description: List of integration summaries content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/IntegrationSummaryResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/integrations/{id}: get: tags: - integrations summary: Get integration operationId: getProjectIntegration parameters: - name: project in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/IntegrationId' responses: '200': description: Integration content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/IntegrationResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - integrations summary: Delete integration description: Deletes an integration. Any task `task_integration` rows referencing it are cleared via `ON DELETE SET NULL`. `git_host_type=github` rows can be deleted; deleting removes the installation binding for that account. State-managed integrations are rejected with `403`, other integrations of a state-managed project can be deleted. operationId: deleteProjectIntegration parameters: - name: project in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/IntegrationId' responses: '200': description: Deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - integrations summary: Update integration description: |- Patch-updates an integration. Omit a field to leave it unchanged. Pass an empty string for `secret` or `access_token` to **clear** it. `git_host_type=github` rows are managed by the App and installation; PATCH rejects them with `400`. Delete the row to remove the integration. State-managed integrations are rejected with `403`. operationId: patchProjectIntegration parameters: - name: project in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/IntegrationId' requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchIntegrationRequest' required: true responses: '200': description: Updated integration content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/IntegrationResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/invitations: get: tags: - projects summary: List pending invitations description: |- Invitations that have been sent but not yet accepted or declined. Requires `manageMembers` on the project. operationId: listProjectInvitations parameters: - name: project in: path required: true schema: type: string responses: '200': description: Pending invitations content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/PendingInvitationItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - projects summary: Revoke a pending invitation description: Requires `manageMembers` on the project. operationId: revokeProjectInvitation parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/RevokeInvitationRequest' required: true responses: '200': description: Invitation revoked content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/public: post: tags: - projects summary: Make project public description: Makes the project, its tasks, evaluations and builds readable without authentication. Requires the manage-project-settings permission; rejects state-managed projects. operationId: makeProjectPublic parameters: - name: project in: path required: true schema: type: string responses: '200': description: Project is now public content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - projects summary: Make project private description: Restricts the project to its members. Requires the manage-project-settings permission; rejects state-managed projects. operationId: makeProjectPrivate parameters: - name: project in: path required: true schema: type: string responses: '200': description: Project is now private content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/roles: get: tags: - projects summary: List roles available in the project description: |- Returns the three immutable built-in roles (Admin/Write/View) plus any custom roles owned by this project, along with the catalogue of permissions that custom roles may carry. Visible to any member of the project so the add-member UI can populate its role dropdown. operationId: listProjectRoles parameters: - name: project in: path required: true schema: type: string responses: '200': description: Role catalogue content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RoleListResponse_ProjectRoleOwner' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - projects summary: Create a custom role description: |- Creates a new role scoped to this project. The caller must hold the **manageRoles** permission. The role's permission set is freely chosen from the capabilities returned by `GET /projects/{project}/roles` -> `available_permissions`. Built-in role names (Admin, Write, View) and any name already used by another role in the same project are rejected with `409`. operationId: createProjectRole parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateRoleRequest' required: true responses: '200': description: Role created content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RoleResponse_ProjectRoleOwner' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/roles/{role_id}: get: tags: - projects summary: Fetch a role operationId: getProjectRole parameters: - name: project in: path required: true schema: type: string - name: role_id in: path required: true schema: $ref: '#/components/schemas/RoleId' responses: '200': description: Role content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RoleResponse_ProjectRoleOwner' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - projects summary: Delete a custom role description: |- Deletes a custom role. The built-in roles cannot be deleted (`403`). A role currently assigned to one or more members cannot be deleted until those members are reassigned (`400`). operationId: deleteProjectRole parameters: - name: project in: path required: true schema: type: string - name: role_id in: path required: true schema: $ref: '#/components/schemas/RoleId' responses: '200': description: Role deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - projects summary: Update a custom role description: |- Renames a custom role and/or replaces its permission set. The three built-in roles (Admin, Write, View) are immutable; attempts to modify them return `403`. operationId: patchProjectRole parameters: - name: project in: path required: true schema: type: string - name: role_id in: path required: true schema: $ref: '#/components/schemas/RoleId' requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchRoleRequest' required: true responses: '200': description: Role updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RoleResponse_ProjectRoleOwner' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/ssh: get: tags: - projects summary: Get SSH public key description: |- Returns the SSH public key for the project. This key must be added to each remote build server's `authorized_keys` to allow Gradient to connect. operationId: getProjectSsh parameters: - name: project in: path required: true schema: type: string responses: '200': description: SSH public key content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - projects summary: Regenerate SSH key pair description: Generates a new Ed25519 key pair for the project. The previous key will stop working on remote servers immediately. operationId: postProjectSsh parameters: - name: project in: path required: true schema: type: string responses: '200': description: New SSH public key content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/subscribe: get: tags: - projects summary: List cache subscriptions description: Returns the binary caches this project currently uses as substituters. operationId: listProjectSubscriptions parameters: - name: project in: path required: true schema: type: string responses: '200': description: Subscribed caches content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/CacheSubscriptionItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/subscribe/{cache}: post: tags: - projects summary: Subscribe to cache, or request a subscription description: |- Requires `manageSubscriptions` on the project, and the cache must be visible to the caller. When the caller also holds `manageCacheSubscriptions` on the cache, or is a superuser, the cache is added to the project's substituters immediately. Otherwise a **subscription request** is recorded instead and the response message is `Subscription requested`; a cache admin then approves it through `POST /caches/{cache}/subscription-requests/{project}`. operationId: subscribeProjectToCache parameters: - name: project in: path required: true schema: type: string - name: cache in: path required: true schema: type: string requestBody: content: application/json: schema: oneOf: - $ref: '#/components/schemas/SubscribeCacheRequest' - type: 'null' responses: '200': description: Subscribed, or subscription requested content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - projects summary: Unsubscribe from cache, or cancel a pending request description: |- Removes a binary cache from the project's substituters. When no subscription exists but a request is still pending, the request is cancelled instead. Requires `manageSubscriptions` on the project. operationId: unsubscribeProjectFromCache parameters: - name: project in: path required: true schema: type: string - name: cache in: path required: true schema: type: string responses: '200': description: Unsubscribed, or subscription request cancelled content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/teams: get: tags: - teams summary: List project team grants description: Includes pending requests. operationId: listProjectTeams parameters: - name: project in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TeamGrantEntry' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] post: tags: - teams summary: Grant a team on a project description: |- Needs `manageMembers` when the grant includes users and `manageWorkers` when it includes workers. A grant is active at once when the caller is Admin in the team (or a superuser). Otherwise a request waits for a team Admin and the answer is `Request sent`. operationId: grantProjectTeam parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/GrantProjectRequest' required: true responses: '200': description: '`Team granted` or `Request sent`' content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/teams/{team}: delete: tags: - teams summary: Remove a project team grant description: |- Allowed for Admin in the team, or on the project for `manageWorkers` when the grant includes only workers and `manageMembers` otherwise. Removing workers aborts their running jobs of the project. Without a grant, the pending request is withdrawn instead. operationId: removeProjectTeam parameters: - name: project in: path required: true schema: type: string - name: team in: path required: true schema: type: string responses: '200': description: '`Team grant removed` or `Request withdrawn`' content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - teams summary: Change a project team grant description: Needs the project permission of the changed part. Turning workers on also needs Admin in the team. operationId: patchProjectTeam parameters: - name: project in: path required: true schema: type: string - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchProjectGrantRequest' required: true responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/users: get: tags: - projects summary: List project members operationId: listProjectUsers parameters: - name: project in: path required: true schema: type: string responses: '200': description: Member list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/MemberItem' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] post: tags: - projects summary: Invite member description: |- Invites a user to the project by username. Requires the caller to hold the **admin** role in the project. The user is **not** a member until they accept. The response message is `Invitation sent`, and the pending row appears under `GET /projects/{project}/invitations` until it is accepted, declined or revoked. An invitation expires after 7 days. A **superuser** who already holds the permission adds the member directly instead, answering `User added`. State-managed projects reject this endpoint entirely; their members come from the state file. operationId: addProjectUser parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/AddMemberRequest' required: true responses: '200': description: Invitation sent, or member added when the caller is a superuser content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - projects summary: Remove member description: |- Removes a user from the project. Requires the caller to hold the **admin** role in the project. operationId: removeProjectUser parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/RemoveMemberRequest' required: true responses: '200': description: Member removed content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - projects summary: Update member role description: |- Updates the role or permissions of an existing project member. Requires the caller to hold the **admin** role in the project. operationId: patchProjectUser parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/AddMemberRequest' required: true responses: '200': description: Updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/webhooks: get: tags: - webhooks summary: List project webhooks description: Requires `manageWebhooks` on the project. operationId: listProjectWebhooks parameters: - name: project in: path required: true schema: type: string responses: '200': description: Webhooks content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - webhooks summary: Create a project webhook description: |- Requires `manageWebhooks` on the project. The response carries the signing `secret` once; it is never returned again (use `rotate-secret` to replace it). operationId: createProjectWebhook parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateWebhookRequest' required: true responses: '200': description: Created webhook and its secret content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CreateWebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/webhooks/{id}: get: tags: - webhooks summary: Read a project webhook operationId: readProjectWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: project in: path required: true schema: type: string responses: '200': description: Webhook content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - webhooks summary: Delete a project webhook operationId: deleteProjectWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: project in: path required: true schema: type: string responses: '200': description: Deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeletedResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - webhooks summary: Update a project webhook operationId: updateProjectWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateWebhookRequest' required: true responses: '200': description: Updated webhook content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/webhooks/{id}/deliveries: get: tags: - webhooks summary: List a project webhook's deliveries operationId: listProjectWebhookDeliveries parameters: - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 - name: offset in: query required: false schema: type: integer format: int64 minimum: 0 - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: project in: path required: true schema: type: string responses: '200': description: Deliveries, newest first content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/DeliveryListItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/webhooks/{id}/deliveries/{delivery_id}: get: tags: - webhooks summary: Read one project webhook delivery with bodies operationId: getProjectWebhookDelivery parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: delivery_id in: path required: true schema: $ref: '#/components/schemas/WebhookDeliveryId' - name: project in: path required: true schema: type: string responses: '200': description: Delivery content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryDetail_WebhookDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/webhooks/{id}/rotate-secret: post: tags: - webhooks summary: Replace a project webhook's signing secret operationId: rotateProjectWebhookSecret parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: project in: path required: true schema: type: string responses: '200': description: The new secret, shown once content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RotatedSecret' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/webhooks/{id}/test: post: tags: - webhooks summary: Send a `webhook.ping` to a project webhook description: Delivers immediately (no retry) and returns the recorded delivery. operationId: testProjectWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: project in: path required: true schema: type: string responses: '200': description: Recorded delivery content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryListItem_WebhookDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/workers: get: tags: - workers summary: List registered workers for a project description: |- Returns all workers registered under this project (peer), merged with live status from the scheduler for currently connected workers, plus the workers of every team the project grants its workers (`team` set, read-only here). Live fields (`architectures`, `system_features`, etc.) are only populated for build-capable workers that have sent `WorkerCapabilities`. operationId: listProjectWorkers parameters: - name: project in: path required: true schema: type: string responses: '200': description: Worker list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/ProjectWorkerEntry' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - workers summary: Register a worker under a project description: |- Registers a worker ID under this project as a peer. Returns a one-time plaintext token that the worker operator must add to their worker config. The token is shown only once - it cannot be retrieved later. operationId: registerProjectWorker parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/RegisterWorkerRequest' required: true responses: '200': description: Worker registered content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RegisterWorkerResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/workers/{worker_id}: delete: tags: - workers summary: Unregister a worker from a project description: |- Removes the worker registration. The worker may still be connected until it disconnects naturally - it will not be able to reconnect after that. A team worker answers `409`; it is deleted on its team. operationId: deleteProjectWorker parameters: - name: project in: path required: true schema: type: string - name: worker_id in: path required: true schema: type: string responses: '200': description: Worker unregistered content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - workers summary: Activate or deactivate a worker registration description: |- Sets the `active` flag on a worker registration. Deactivating a worker triggers an immediate re-auth request, causing the worker to be disconnected if it is currently connected. Active jobs may be aborted. A state-managed worker accepts only `active` and answers `409` for other fields. The next server start restores the declared value. A team worker answers `409`; it is changed on its team. operationId: patchProjectWorker parameters: - name: project in: path required: true schema: type: string - name: worker_id in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchWorkerRequest' required: true responses: '200': description: Worker updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/workers/{worker_id}/metrics: get: tags: - board summary: Per-worker metrics description: Live-metric sample time-series (CPU, RAM, disk, upload, download, load), connect/disconnect history, and total assigned-job count for one worker. Project members only, and only for a worker registered in the project or enabled for it as a base worker; the telemetry covers everything the worker did, not only this project's jobs. operationId: getProjectWorkerMetrics parameters: - name: project in: path required: true schema: type: string - name: worker_id in: path required: true schema: type: string responses: '200': description: Worker statistics content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WorkerMetricsResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/projects/{project}/workers/{worker_id}/test: post: tags: - workers summary: Test worker connectivity and authorization description: |- Checks whether the worker is currently connected and whether it has successfully authorized for the given project. Useful for verifying worker setup without waiting for a real job. operationId: testProjectWorker parameters: - name: project in: path required: true schema: type: string - name: worker_id in: path required: true schema: type: string responses: '200': description: Test result content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WorkerTestResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/search: get: tags: - dashboard summary: Typed search for the command palette description: |- Classifies `q` and performs every lookup it could mean. The name lookup always takes place, and a project named like a commit hash is still found. - Store path or bare 32-char nix32 hash: NARs of that hash in readable caches (`nar`, at most 10). - 7 to 40 hex characters: evaluations of commits with that prefix in readable projects, newest first, PR-triggered ones included (`commit`, at most 5). - Any text: projects, tasks and caches whose name or display name contains it, at most `limit` per kind, starred first. An empty `q` returns the user's starred projects, tasks and caches, labelled by display name like name hits. Visibility matches the rest of the API: a project is readable when public or the user is a member; a cache when public, created by, shared with or subscribed to by a project of the user. There is no superuser bypass, so every hit opens a readable page. Results are ordered NAR hits, commit hits, then name hits (starred first, then kind, then name). operationId: getSearch parameters: - name: q in: query required: false schema: type: string - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Search hits with the frontend route each one navigates to content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/SearchHit' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}: get: tags: - tasks summary: List tasks description: Returns all tasks in the given project with full details. operationId: listTasks parameters: - name: project in: path required: true schema: type: string - name: page in: query required: false schema: type: integer format: int64 minimum: 0 - name: per_page in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Task list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Paginated_TaskResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] put: tags: - tasks summary: Create task description: Creates a new task in the project. `wildcard` is a Nix attribute selector such as `packages.x86_64-linux` or `checks`. operationId: createTask parameters: - name: project in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/MakeTaskRequest' required: true responses: '200': description: Task UUID content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/available: get: tags: - tasks summary: Check task name availability description: Returns `true` if no task with the given name exists in the project, `false` if it is already taken. operationId: checkTaskNameAvailable parameters: - name: project in: path required: true schema: type: string - name: name in: query required: true schema: type: string responses: '200': description: Availability result content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}: get: tags: - tasks summary: Get task operationId: getTask parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Task details content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TaskResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] delete: tags: - tasks summary: Delete task operationId: deleteTask parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - tasks summary: Update task description: Updates one or more task fields. operationId: patchTask parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchTaskRequest' required: true responses: '200': description: Updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/actions: get: tags: - actions summary: List task actions operationId: listTaskActions parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: List of actions content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/ActionResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - actions summary: Create task action operationId: createTaskAction parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateActionRequest' required: true responses: '200': description: Action created; token present only for send_web_request content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CreateActionResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/actions/{id}: get: tags: - actions summary: Get task action operationId: getTaskAction parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskActionId' responses: '200': description: Action (token stripped) content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ActionResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - actions summary: Delete task action operationId: deleteTaskAction parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskActionId' responses: '200': description: Action deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeletedResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - actions summary: Update task action operationId: updateTaskAction parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskActionId' requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateActionRequest' required: true responses: '200': description: Action updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ActionResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/actions/{id}/deliveries: get: tags: - actions summary: List action deliveries operationId: listActionDeliveries parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskActionId' - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 - name: offset in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Paginated delivery list content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/DeliveryListItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/actions/{id}/deliveries/{delivery_id}: get: tags: - actions summary: Get action delivery detail operationId: getActionDelivery parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskActionId' - name: delivery_id in: path required: true schema: $ref: '#/components/schemas/TaskActionDeliveryId' responses: '200': description: Delivery with request/response bodies content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryDetail_TaskActionDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/actions/{id}/regenerate-token: post: tags: - actions summary: Regenerate send_web_request token description: Invalidates the current token and returns a new one in plaintext. Only valid for send_web_request actions. operationId: regenerateActionToken parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskActionId' responses: '200': description: New token (one-time reveal) content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: {} default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/actions/{id}/test: post: tags: - actions summary: Fire action now (synthetic test) description: Fires the action immediately with a synthetic test event, bypassing event matching. Git host integration actions (`git_host_status_report`, `open_pr`) instead perform a non-mutating connectivity check against the task's repository, since a synthetic status/PR posted against a placeholder commit is always rejected by the Git host. operationId: testTaskAction parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskActionId' responses: '200': description: Action fired content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: {} default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/active: post: tags: - tasks summary: Enable task description: Sets the task's active flag to true so it will be evaluated on new commits. Requires Admin or Write role; rejects state-managed tasks. operationId: enableTask parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Enabled content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - tasks summary: Disable task description: Sets the task's active flag to false, pausing automatic evaluations. Requires Admin or Write role; rejects state-managed tasks. operationId: disableTask parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Disabled content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/badge: get: tags: - tasks summary: Task status badge (SVG) description: |- Returns a shields.io-compatible SVG badge reflecting the task's latest evaluation status. Designed to be embedded in GitHub READMEs, Grafana dashboards, or any tool that renders SVG images from a URL. **Badge colours:** | Status | Colour | Label | |--------|--------|-------| | No evaluation yet | grey | `unknown` | | Queued / Evaluating / Building | blue | `queued` / `evaluating` / `building` | | Completed, all entry-point builds passed | green | `passing` | | Completed, some entry-point builds failed | amber | `partial` | | Failed | red | `failing` | | Aborted | yellow | `aborted` | **Authentication:** - **Public projects** - no credentials required. Embed the URL directly. - **Private projects** - supply `?token=GRADxxxx` (API key) or a JWT so the image can be fetched by external services without a session cookie. Responses include `Cache-Control: no-cache` so badge aggregator CDNs always fetch the live status rather than serving a stale image. operationId: getTaskBadge parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: style in: query required: false schema: $ref: '#/components/schemas/BadgeStyle' - name: label in: query required: false schema: type: string - name: eval in: query required: false schema: type: string - name: token in: query required: false schema: type: string responses: '200': description: SVG badge image. content: image/svg+xml: schema: type: string default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/tasks/{project}/{task}/check-repository: post: tags: - tasks summary: Check repository accessibility description: |- Tests whether Gradient can clone the task's repository using the project's SSH key. Requires Admin or Write role; rejects state-managed tasks. Returns `400` with `code: "repository_unreachable"` and the underlying git error when the repository cannot be fetched. operationId: checkTaskRepository parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Repository is accessible content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/details: get: tags: - tasks summary: Get task details description: Returns aggregated task data including the latest evaluation, recent evaluation history, and current entry points. operationId: getTaskDetails parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Task details content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TaskDetailsResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/tasks/{project}/{task}/entry-point-downloads: get: tags: - tasks summary: Download newest-commit entry point build output description: |- Serves the named file from `nix-support/hydra-build-products` for the build of the given entry point in the task's **newest-commit evaluation** (`task.last_evaluation`). Designed as a stable permalink - retriggering an older commit does not shadow the latest one. Returns `404` if no evaluation has been recorded yet, or if the entry point / file is missing from the newest evaluation. Authentication: - **Public projects** - no credentials required. - **Private projects** - supply `?token=GRADxxxx` (API key) or a JWT, **or** authenticate via `Authorization: Bearer` header / `jwt_token` session cookie. The `eval` value may contain double-quoted Nix attribute segments (e.g. `packages."x86_64-linux".hello`). URL-encode `"` as `%22`. operationId: downloadEntryPointOutput parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: eval in: query required: true schema: type: string - name: filename in: query required: true schema: type: string - name: token in: query required: false schema: type: string responses: '200': description: File contents with appropriate `Content-Type` and `Content-Disposition` headers. content: application/octet-stream: schema: $ref: '#/components/schemas/Binary' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/tasks/{project}/{task}/entry-point-metrics: get: tags: - tasks summary: Get entry point metrics description: |- Returns per-evaluation build metrics for a single entry point identified by its Nix attribute path (`eval`), covering the last `keep_evaluations` completed evaluations. The `eval` value is the full Nix attribute path as stored in the database, which may contain double-quoted segments for attribute names with special characters (e.g. `packages."x86_64-linux".hello`). URL-encode `"` as `%22` in query strings. operationId: getEntryPointMetrics parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: eval in: query required: true schema: type: string responses: '200': description: Entry point metrics content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/EntryPointMetricsResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/tasks/{project}/{task}/entry-points: get: tags: - tasks summary: List entry points description: Returns the root builds (entry points) for the task from the last evaluation by default. Pass `evaluation_id` to retrieve entry points from a specific evaluation instead. operationId: listTaskEntryPoints parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: evaluation_id in: query required: false schema: $ref: '#/components/schemas/EvaluationId' - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 - name: offset in: query required: false schema: type: integer format: int64 minimum: 0 - name: search in: query required: false schema: type: string responses: '200': description: Entry points content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/PaginatedEntryPoints' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/tasks/{project}/{task}/evaluate: post: tags: - tasks summary: Trigger evaluation description: |- Queues a new evaluation for the task and returns its UUID in `message`, so a caller can follow the run it just started (`GET /evals/{id}`, or the `GET /evals/{id}/live` stream). `POST /evals/{evaluation}/retry` re-runs the failed builds of a finished evaluation. Returns `400` with `code: "repository_unreachable"` when the repository cannot be fetched (DNS failure, authentication failure, unreachable host, bad URL, …) - the message includes the underlying git error. operationId: triggerEvaluation parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string requestBody: content: application/json: schema: oneOf: - $ref: '#/components/schemas/EvaluateRequest' - type: 'null' responses: '200': description: Evaluation UUID content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/evaluations: get: tags: - tasks summary: List and search evaluations description: |- Returns the `keep_evaluations` most recent evaluations for the task, newest first. The `commit`, `status` and `attr` filters combine (AND) to answer "has this attribute at this commit been evaluated, and is it still running?" without walking the whole history. `attr` matches an evaluation's **wildcard**, not its entry points. The wildcard is set when the evaluation row is created, so the filter answers while the evaluation is still `Queued` or `EvaluatingFlake`; entry points do not exist until derivations have resolved. The flip side is that a match means the attribute was *in scope*, not that it exists in the flake or that it built - read `/tasks/{project}/{task}/entry-points` for that. operationId: getTaskEvaluations parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 - name: before in: query required: false schema: $ref: '#/components/schemas/EvaluationId' - name: commit in: query required: false schema: type: string - name: status in: query required: false schema: type: string - name: attr in: query required: false schema: type: string responses: '200': description: List of evaluation summaries content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/EvaluationSummary' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/tasks/{project}/{task}/flake-inputs: get: tags: - flake-inputs summary: List flake input overrides operationId: listFlakeInputOverrides parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: List of flake input overrides content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/FlakeInputOverrideOut' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - flake-inputs summary: Create a flake input override operationId: createFlakeInputOverride parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateFlakeInputOverrideRequest' required: true responses: '200': description: Flake input override created content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/FlakeInputOverrideOut' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/flake-inputs/{id}: get: tags: - flake-inputs summary: Get a flake input override operationId: getFlakeInputOverride parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/FlakeInputOverrideId' responses: '200': description: Flake input override content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/FlakeInputOverrideOut' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - flake-inputs summary: Delete a flake input override operationId: deleteFlakeInputOverride parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/FlakeInputOverrideId' responses: '200': description: Flake input override deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeletedResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - flake-inputs summary: Update a flake input override operationId: updateFlakeInputOverride parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/FlakeInputOverrideId' requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateFlakeInputOverrideRequest' required: true responses: '200': description: Flake input override updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/FlakeInputOverrideOut' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/live: get: tags: - tasks summary: Task live updates (WebSocket) description: |- Upgrades to a WebSocket emitting `evaluation_status_changed`, `build_status_changed`, `evaluation_progress` and `evaluation_activity` events for this task, so the task page refetches on change instead of polling. `evaluation_progress` fires as builds and entry-points are persisted during the evaluation phase, before any build changes status, so the build/dependency totals grow live. `evaluation_activity` carries an `EvaluationProgress` snapshot at most once per second while the evaluation fetches or evaluates. Requires read access. operationId: taskLive parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '101': description: Switching Protocols - WebSocket upgrade successful default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/tasks/{project}/{task}/metrics: get: tags: - tasks summary: Get task metrics description: Returns per-evaluation metric points for the last `keep_evaluations` completed evaluations. operationId: getTaskMetrics parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Task metrics content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TaskMetricsResponse' default: $ref: '#/components/responses/Error' security: - {} - bearerAuth: [] /api/v1/tasks/{project}/{task}/transfer: post: tags: - tasks summary: Move task to another project description: Moves the task into the project named in the body. Allowed for the task owner or a member with the edit-task permission, who also needs the create-task permission in the target project. Rejects state-managed tasks and target projects. operationId: transferTask parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/TransferOwnershipRequest' required: true responses: '200': description: Task moved content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/triggers: get: tags: - triggers summary: List task triggers operationId: listTaskTriggers parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: List of triggers content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TriggerOut' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - triggers summary: Create task trigger operationId: createTaskTrigger parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateTriggerRequest' required: true responses: '200': description: Trigger created content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TriggerOut' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/triggers/{id}: get: tags: - triggers summary: Get task trigger operationId: getTaskTrigger parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskTriggerId' responses: '200': description: Trigger content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TriggerOut' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - triggers summary: Delete task trigger operationId: deleteTaskTrigger parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskTriggerId' responses: '200': description: Trigger deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeletedResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - triggers summary: Update task trigger operationId: updateTaskTrigger parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskTriggerId' requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateTriggerRequest' required: true responses: '200': description: Trigger updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TriggerOut' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/tasks/{project}/{task}/triggers/{id}/test: post: tags: - triggers summary: Manually fire trigger description: Resolves the task HEAD and applies the trigger immediately, bypassing commit dedup. Returns the apply outcome. operationId: testTaskTrigger parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string - name: id in: path required: true schema: $ref: '#/components/schemas/TaskTriggerId' responses: '200': description: Trigger apply outcome content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: {} default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams: get: tags: - teams summary: List my teams description: Teams the caller is a member of, with the caller's role, sorted by name. operationId: listTeams responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TeamSummary' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] put: tags: - teams summary: Create team description: Creates a team and makes the caller its Admin. Who may create teams is set by `--permissions-create-team`. operationId: createTeam requestBody: content: application/json: schema: $ref: '#/components/schemas/MakeTeamRequest' required: true responses: '200': description: Team created content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/available: get: tags: - teams summary: Check a team name operationId: teamNameAvailable parameters: - name: name in: query required: true schema: type: string responses: '200': description: Whether the name is valid and free content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}: get: tags: - teams summary: Get team description: Members of the team and superusers can read it. operationId: getTeam parameters: - name: team in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TeamResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - teams summary: Delete team description: Needs Admin in the team. Deletes its grants, requests, invitations and workers; connected team workers lose those projects. operationId: deleteTeam parameters: - name: team in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - teams summary: Change team description: Needs Admin in the team. Only superusers set `oidc_group`, `scim_group` and the `new_project_*` fields. State-managed teams refuse changes. operationId: patchTeam parameters: - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchTeamRequest' required: true responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/evaluations: get: tags: - teams summary: List recent team evaluations description: The ten newest evaluations of projects granting the team with users. Members of the team and superusers can read it. operationId: getTeamEvaluations parameters: - name: team in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TeamEvaluation' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/grants: get: tags: - teams summary: List team grants description: Projects and caches that grant the team. operationId: listTeamGrants parameters: - name: team in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TeamGrants' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/invitations: get: tags: - teams summary: List pending team invitations description: Needs Admin in the team. operationId: listTeamInvitations parameters: - name: team in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/PendingInvitationItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - teams summary: Revoke team invitation description: Needs Admin in the team. operationId: revokeTeamInvitation parameters: - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/RevokeInvitationRequest' required: true responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/members: get: tags: - teams summary: List team members operationId: listTeamMembers parameters: - name: team in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TeamMemberItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - teams summary: Invite team member description: Needs Admin in the team. The user joins after accepting the invitation (`Invitation sent`); a superuser adds the member directly (`User added`). operationId: addTeamMember parameters: - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/TeamMemberRequest' required: true responses: '200': description: Invitation sent, or member added when the caller is a superuser content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - teams summary: Remove team member description: Needs Admin in the team. operationId: removeTeamMember parameters: - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/RemoveTeamMemberRequest' required: true responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - teams summary: Change team member role description: Needs Admin in the team. operationId: patchTeamMember parameters: - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/TeamMemberRequest' required: true responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/requests: get: tags: - teams summary: List grant requests description: Needs Admin in the team. Newest first. operationId: listTeamRequests parameters: - name: team in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TeamRequestItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/requests/{request_id}: post: tags: - teams summary: Approve grant request description: Needs Admin in the team. The grant becomes active. operationId: approveTeamRequest parameters: - name: team in: path required: true schema: type: string - name: request_id in: path required: true schema: type: string format: uuid responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - teams summary: Deny grant request description: Needs Admin in the team. operationId: denyTeamRequest parameters: - name: team in: path required: true schema: type: string - name: request_id in: path required: true schema: type: string format: uuid responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/webhooks: get: tags: - webhooks summary: List team webhooks description: Requires Admin role in the team. operationId: listTeamWebhooks parameters: - name: team in: path required: true schema: type: string responses: '200': description: Webhooks content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - webhooks summary: Create a team webhook description: |- Requires Admin role in the team. The response carries the signing `secret` once; it is never returned again (use `rotate-secret` to replace it). operationId: createTeamWebhook parameters: - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateWebhookRequest' required: true responses: '200': description: Created webhook and its secret content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/CreateWebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/webhooks/{id}: get: tags: - webhooks summary: Read a team webhook operationId: readTeamWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: team in: path required: true schema: type: string responses: '200': description: Webhook content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - webhooks summary: Delete a team webhook operationId: deleteTeamWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: team in: path required: true schema: type: string responses: '200': description: Deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeletedResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - webhooks summary: Update a team webhook operationId: updateTeamWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/UpdateWebhookRequest' required: true responses: '200': description: Updated webhook content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/WebhookResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/webhooks/{id}/deliveries: get: tags: - webhooks summary: List a team webhook's deliveries operationId: listTeamWebhookDeliveries parameters: - name: limit in: query required: false schema: type: integer format: int64 minimum: 0 - name: offset in: query required: false schema: type: integer format: int64 minimum: 0 - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: team in: path required: true schema: type: string responses: '200': description: Deliveries, newest first content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/DeliveryListItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/webhooks/{id}/deliveries/{delivery_id}: get: tags: - webhooks summary: Read one team webhook delivery with bodies operationId: getTeamWebhookDelivery parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: delivery_id in: path required: true schema: $ref: '#/components/schemas/WebhookDeliveryId' - name: team in: path required: true schema: type: string responses: '200': description: Delivery content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryDetail_WebhookDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/webhooks/{id}/rotate-secret: post: tags: - webhooks summary: Replace a team webhook's signing secret operationId: rotateTeamWebhookSecret parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: team in: path required: true schema: type: string responses: '200': description: The new secret, shown once content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RotatedSecret' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/webhooks/{id}/test: post: tags: - webhooks summary: Send a `webhook.ping` to a team webhook description: Delivers immediately (no retry) and returns the recorded delivery. operationId: testTeamWebhook parameters: - name: id in: path required: true schema: $ref: '#/components/schemas/WebhookId' - name: team in: path required: true schema: type: string responses: '200': description: Recorded delivery content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/DeliveryListItem_WebhookDeliveryId' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/workers: get: tags: - teams summary: List team workers description: A team worker serves every project that grants the team its workers. `last_error` is shown to team Admins. operationId: listTeamWorkers parameters: - name: team in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/TeamWorkerEntry' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - teams summary: Register team worker description: Needs Admin in the team. The worker answers the server challenge with `:` or `*:` in its peers file. `token` is returned only when the server generated it. operationId: registerTeamWorker parameters: - name: team in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/RegisterWorkerRequest' required: true responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/RegisteredTeamWorker' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/workers/demand: get: tags: - teams summary: Read missing worker capabilities description: 'Needs Admin in the team. Sums the waiting evaluations of projects granting the team its workers that no connected worker eligible for the project can take: builds per system and features, plus fetch and evaluation gaps. `projects` takes comma-separated project names or IDs and limits the sum to those granting projects.' operationId: getTeamWorkerDemand parameters: - name: team in: path required: true schema: type: string - name: projects in: query required: false schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/TeamDemand' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/teams/{team}/workers/{worker_id}: delete: tags: - teams summary: Delete team worker description: Needs Admin in the team. operationId: deleteTeamWorker parameters: - name: team in: path required: true schema: type: string - name: worker_id in: path required: true schema: type: string responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - teams summary: Change team worker description: Needs Admin in the team. Deactivating aborts the worker's running jobs of the granted projects. operationId: patchTeamWorker parameters: - name: team in: path required: true schema: type: string - name: worker_id in: path required: true schema: type: string requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchWorkerRequest' required: true responses: '200': description: OK content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user: get: tags: - user summary: Get current user description: Returns the id, username, display name, and email of the authenticated user. operationId: getUser responses: '200': description: User info content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/UserInfoResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - user summary: Delete current user description: |- Permanently deletes the authenticated user and all associated data. Requires re-authentication: password-auth users must supply their current password in `password`; OIDC-auth users must echo their username in `confirm_username`. operationId: deleteUser requestBody: content: application/json: schema: $ref: '#/components/schemas/DeleteUserRequest' required: true responses: '200': description: User deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/audit-log: get: tags: - user summary: Audit log for the current user description: |- Paginated list of audit events recorded for the caller (login, logout, API-key lifecycle, session revocation, account deletion). operationId: getUserAuditLog parameters: - name: page in: query required: false schema: type: integer format: int64 minimum: 0 - name: per_page in: query required: false schema: type: integer format: int64 minimum: 0 responses: '200': description: Audit entries content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/Paginated_AuditLogEntry' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/invites: get: tags: - user summary: List my pending invitations description: |- Project and cache invitations addressed to the authenticated user, newest first. operationId: listUserInvites responses: '200': description: Pending invitations content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/InviteItem' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/invites/accept: post: tags: - user summary: Accept an invitation description: |- Redeems an invitation token and creates the membership. The token must address the authenticated user: a token forwarded to somebody else answers `404`, so the mailed link is a convenience and never the trust boundary. An expired invitation answers `410` and is discarded. operationId: acceptUserInvite requestBody: content: application/json: schema: $ref: '#/components/schemas/InviteTokenRequest' required: true responses: '200': description: Invitation accepted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/invites/decline: post: tags: - user summary: Decline an invitation description: |- Discards an invitation addressed to the authenticated user. The same token and expiry rules as accept apply. operationId: declineUserInvite requestBody: content: application/json: schema: $ref: '#/components/schemas/InviteTokenRequest' required: true responses: '200': description: Invitation declined content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/keys: get: tags: - user summary: List API keys description: |- Returns all API keys belonging to the authenticated user, including creation, last-used, expiry, and revocation timestamps. operationId: getUserKeys responses: '200': description: List of API keys content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/ApiKeyInfo' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - user summary: Create API key description: |- Creates a new API key. The full key (prefixed with `GRAD`) is returned once - it cannot be retrieved again. Use it as `Authorization: Bearer GRAD`. Pass `expires_in_days` to make the key auto-expire; omit for no expiry. A cache-pinned key may only grant cache permissions the caller already holds; members of a project subscribed to the cache are treated as read-only, so they can mint read-only cache keys. operationId: createUserKey requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateApiKeyRequest' required: true responses: '200': description: New API key content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - user summary: Delete API key description: Deletes the API key with the given name. State-managed keys cannot be deleted. operationId: deleteUserKey requestBody: content: application/json: schema: $ref: '#/components/schemas/ApiKeyRequest' required: true responses: '200': description: Key deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/keys/permissions: get: tags: - user summary: List API-key permission catalogue description: |- Returns the full set of capabilities a user-managed API key may grant. Used by the create / edit dialog to populate the permission checkbox list. operationId: getUserKeyPermissions responses: '200': description: Permission catalogue content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ApiKeyPermissionsResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/keys/{api_id}: patch: tags: - user summary: Update an API key's configurable options description: |- Edit the key's name, permission set, or project pin in place. Permissions replace the existing set wholesale. State-managed keys cannot be edited. Cannot be called from an API-key-authenticated request - sessions only. operationId: patchUserKey parameters: - name: api_id in: path required: true schema: $ref: '#/components/schemas/ApiId' requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchApiKeyRequest' required: true responses: '200': description: Updated key content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/ApiKeyInfo' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/keys/{api_id}/revoke: post: tags: - user summary: Revoke an API key description: |- Marks the key as revoked without deleting the row, so audit trails are preserved. A revoked key fails authentication immediately. operationId: revokeUserKey parameters: - name: api_id in: path required: true schema: $ref: '#/components/schemas/ApiId' responses: '200': description: Key revoked content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/search: get: tags: - user summary: Search users by username description: Returns up to 10 users whose username contains the given query string. Used for autocomplete in member and ownership dialogs. operationId: searchUsers parameters: - name: q in: query required: true schema: type: string responses: '200': description: Matching users content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/UserSearchResult' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/sessions: get: tags: - user summary: List active sessions description: |- Returns the caller's non-revoked, non-expired sessions. Each entry carries the user-agent and IP captured at login plus a `current` flag identifying the session backing this request. operationId: getUserSessions responses: '200': description: Active sessions content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/SessionInfo' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/sessions/{session_id}: delete: tags: - user summary: Revoke a session description: |- Revokes a single session, immediately invalidating its JWT. Useful for signing out a lost device without changing the password. operationId: deleteUserSession parameters: - name: session_id in: path required: true schema: $ref: '#/components/schemas/SessionId' responses: '200': description: Session revoked content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/settings: get: tags: - user summary: Get user settings description: Returns the username, display name, and email of the current user. operationId: getUserSettings responses: '200': description: User settings content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/GetUserSettingsResponse' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] patch: tags: - user summary: Update user settings description: |- Updates one or more user profile fields. Only fields that are present in the request body are changed. Managed users (created via NixOS config) cannot be modified through the API. operationId: patchUserSettings requestBody: content: application/json: schema: $ref: '#/components/schemas/PatchUserSettingsRequest' required: true responses: '200': description: Settings updated content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/ssh-keys: get: tags: - user summary: List SSH keys description: |- Returns the SSH public keys of the authenticated user. Each key may log in to the Nix daemon over SSH (`ssh-ng://@`). `404` when SSH is disabled. operationId: getUserSshKeys responses: '200': description: List of SSH keys content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: array items: $ref: '#/components/schemas/SshKeyInfo' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] post: tags: - user summary: Add SSH key description: Adds an OpenSSH public key. A key can belong to one user only. operationId: createUserSshKey requestBody: content: application/json: schema: $ref: '#/components/schemas/CreateSshKeyRequest' required: true responses: '200': description: Key added content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/SshKeyInfo' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/ssh-keys/{ssh_key_id}: delete: tags: - user summary: Delete SSH key operationId: deleteUserSshKey parameters: - name: ssh_key_id in: path required: true schema: $ref: '#/components/schemas/UserSshKeyId' responses: '200': description: Key deleted content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: string default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/stars: get: tags: - user summary: List starred projects, tasks and caches description: Returns the names of everything the current user starred and can still read (the visibility of `/search`, no superuser bypass), each list sorted by name. A target the user lost access to is hidden, not unstarred. operationId: getUserStars responses: '200': description: Starred names grouped by kind content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: $ref: '#/components/schemas/StarredNames' default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/stars/caches/{cache}: put: tags: - user summary: Star a cache description: Idempotent. `message` is `true`, the cache is starred afterwards. operationId: starCache parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Cache starred content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - user summary: Unstar a cache description: Idempotent, also for a cache that was never starred. `message` is `false`. operationId: unstarCache parameters: - name: cache in: path required: true schema: type: string responses: '200': description: Cache unstarred content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/stars/projects/{project}: put: tags: - user summary: Star a project description: Idempotent. `message` is `true`, the project is starred afterwards. operationId: starProject parameters: - name: project in: path required: true schema: type: string responses: '200': description: Project starred content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - user summary: Unstar a project description: Idempotent, also for a project that was never starred. `message` is `false`. operationId: unstarProject parameters: - name: project in: path required: true schema: type: string responses: '200': description: Project unstarred content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /api/v1/user/stars/tasks/{project}/{task}: put: tags: - user summary: Star a task description: Idempotent. `message` is `true`, the task is starred afterwards. operationId: starTask parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Task starred content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] delete: tags: - user summary: Unstar a task description: Idempotent, also for a task that was never starred. `message` is `false`. operationId: unstarTask parameters: - name: project in: path required: true schema: type: string - name: task in: path required: true schema: type: string responses: '200': description: Task unstarred content: application/json: schema: type: object required: - error - message properties: error: type: boolean message: type: boolean default: $ref: '#/components/responses/Error' security: - bearerAuth: [] /cache/{cache}: get: tags: - nix-cache summary: Cache root description: Redirects to `nix-cache-info`. operationId: getCacheRoot parameters: - name: cache in: path required: true schema: type: string responses: '302': description: Redirect to `/cache/{cache}/nix-cache-info` security: - {} - cacheBasic: [] /cache/{cache}/debuginfo/{build_id}: get: tags: - nix-cache summary: Debug info description: DWARF debug info for an ELF build id, in the Nix `index-debug-info` format. Indexed from `separateDebugInfo` outputs; a miss falls through to the upstream caches. `X-Cache` reports `HIT` or `MISS`. operationId: getDebugInfo parameters: - name: cache in: path required: true schema: type: string - name: build_id in: path required: true schema: type: string responses: '200': description: Debug info redirect content: application/json: schema: $ref: '#/components/schemas/DebugInfoRedirect' default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/gradient-cache-info: get: tags: - nix-cache summary: Gradient cache info description: 'Gradient version and server URL behind this cache, for clients probing a substituter. Sends `Access-Control-Allow-Origin: *`.' operationId: getGradientCacheInfo parameters: - name: cache in: path required: true schema: type: string - name: json in: query required: false schema: type: string responses: '200': description: Gradient metadata content: text/x-gradient-cache-info: schema: type: string application/json: schema: $ref: '#/components/schemas/GradientCacheInfo' default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/log/{drv}: get: tags: - nix-cache summary: Build log description: Build log read by `nix log`. Serves this cache's own log, otherwise the first upstream hit. `X-Cache` reports `HIT` or `MISS`. operationId: getCacheBuildLog parameters: - name: cache in: path required: true schema: type: string - name: drv in: path required: true schema: type: string responses: '200': description: Build log content: text/plain: schema: type: string default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/ls/{hash}: get: tags: - nix-cache summary: NAR listing description: File tree of a NAR in the nix-serve `.ls` v1 schema. operationId: getNarListing parameters: - name: cache in: path required: true schema: type: string - name: hash in: path required: true schema: type: string responses: '200': description: NAR listing content: application/json: schema: $ref: '#/components/schemas/NarList' default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/nar/upstream/{upstream_id}/{path}: get: tags: - nix-cache summary: Upstream NAR description: Streams a NAR from an upstream of the cache. Any upstream serving the same path is tried when the named one is gone. operationId: getUpstreamNar parameters: - name: cache in: path required: true schema: type: string - name: upstream_id in: path required: true schema: type: string format: uuid - name: path in: path required: true schema: type: string responses: '200': description: NAR stream content: application/x-nix-nar: schema: $ref: '#/components/schemas/Binary' default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/nar/{path}: get: tags: - nix-cache summary: NAR description: Compressed NAR archive of a store path. operationId: getNar parameters: - name: cache in: path required: true schema: type: string - name: path in: path required: true schema: type: string responses: '200': description: NAR stream content: application/x-nix-nar: schema: $ref: '#/components/schemas/Binary' default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/nix-cache-info: get: tags: - nix-cache summary: Nix cache info description: Cache metadata read by Nix substituters. `Priority` is the cache priority, or the local priority for clients in `GRADIENT_HTTP_LOCAL_IPS`. operationId: getNixCacheInfo parameters: - name: cache in: path required: true schema: type: string - name: json in: query required: false schema: type: string responses: '200': description: Cache metadata content: text/x-nix-cache-info: schema: type: string application/json: schema: $ref: '#/components/schemas/NixCacheInfo' default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/proto: get: tags: - nix-cache summary: Cache proto WebSocket description: 'Read-only, cache-scoped WebSocket with the `/proto` wire format. Accepts only `CacheQuery` (Normal and Pull) and `NarRequest`. Public caches allow anonymous sessions (`GRADIENT_PROTO_ANONYMOUS_CACHE_ENABLE`), capped per IP by `GRADIENT_PROTO_ANONYMOUS_CACHE_MAX_CONNECTIONS_PER_IP`; private caches need `Authorization: Bearer GRAD`.' operationId: cacheProtoWebSocket parameters: - name: cache in: path required: true schema: type: string responses: '101': description: Switching Protocols - WebSocket upgrade successful default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/serve/{hash}/{path}: get: tags: - nix-cache summary: Serve file description: A single file of a NAR (content type from the file name), or a directory as `tar.zst`. Responses carry sandboxing headers. operationId: serveNarFile parameters: - name: cache in: path required: true schema: type: string - name: hash in: path required: true schema: type: string - name: path in: path required: true schema: type: string responses: '200': description: File or directory archive content: application/octet-stream: schema: $ref: '#/components/schemas/Binary' application/zstd: schema: $ref: '#/components/schemas/Binary' default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /cache/{cache}/{path}: get: tags: - nix-cache summary: Narinfo description: Path info of a store path. A miss here is looked up in the cache's upstream caches, re-signed with the cache key. `X-Cache` reports `HIT` (ours) or `MISS` (upstream). operationId: getNarinfo parameters: - name: cache in: path required: true schema: type: string - name: path in: path required: true schema: type: string - name: json in: query required: false schema: type: string responses: '200': description: Narinfo content: text/x-nix-narinfo: schema: type: string application/json: schema: $ref: '#/components/schemas/NixPathInfo' default: $ref: '#/components/responses/Error' security: - {} - cacheBasic: [] /metrics: get: tags: - general summary: Prometheus metrics description: |- Prometheus exposition endpoint. Disabled (404) until an operator configures `GRADIENT_METRICS_TOKEN_FILE`. Requires a Bearer token matching the contents of that file. Returns the standard Prometheus text format (version 0.0.4) with build, evaluation, scheduler, and cache metrics. operationId: getMetrics responses: '200': description: Prometheus exposition (text/plain; version=0.0.4) content: text/plain: schema: type: string '401': description: Missing or invalid bearer token '404': description: Metrics endpoint not configured on this server security: - metricsAuth: [] /proto: get: tags: - general summary: Binary WebSocket protocol endpoint description: |- Upgrades the connection to a WebSocket carrying binary frames encoded by the `Proto` derive of `gradient-wire`. The upgrade always succeeds; a server with `GRADIENT_PROTO_DISCOVERABLE=false` then rejects the handshake of a worker it did not dial itself with a `403` reject frame. **Protocol flow** 1. Both sides send an 8-byte version frame (`GRAD`, oldest and newest supported version as `u16` little-endian) and encode every later frame for the highest shared version. Without one, the WebSocket closes with code `1002` and the reason. 2. Client sends `ClientMessage::InitConnection { capabilities, id }`. 3. Server responds with `ServerMessage::AuthChallenge`, then `ServerMessage::InitAck { capabilities, .. }` with the negotiated capabilities. operationId: protoWebSocket responses: '101': description: Switching Protocols - WebSocket upgrade successful '503': description: Connection limit (`GRADIENT_PROTO_MAX_CONNECTIONS`) reached; retry after `Retry-After` security: [] /scim/v2/Groups: get: tags: - scim summary: List SCIM groups description: |- Lists SCIM groups. A SCIM group is a team with `scim_group` set, and its members are the team's members; groups are not created through SCIM. Supports the `displayName eq "..."` filter. operationId: scimListGroups parameters: - name: filter in: query required: false schema: type: string responses: '200': description: Group list content: application/scim+json: schema: $ref: '#/components/schemas/ListResponse_GroupResource' '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] /scim/v2/Groups/{id}: get: tags: - scim summary: Get a SCIM group description: Unknown group names return 404. operationId: scimGetGroup parameters: - name: id in: path required: true schema: type: string responses: '200': description: Group content: application/scim+json: schema: $ref: '#/components/schemas/GroupResource' '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] patch: tags: - scim summary: Patch SCIM group membership description: |- Adds or removes members of the team whose `scim_group` matches. Added users join as Members. Unknown group names return 404. operationId: scimPatchGroup parameters: - name: id in: path required: true schema: type: string requestBody: content: application/scim+json: schema: $ref: '#/components/schemas/PatchRequest' required: true responses: '200': description: Group patched content: application/scim+json: schema: $ref: '#/components/schemas/GroupResource' '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] /scim/v2/ResourceTypes: get: tags: - scim summary: SCIM resource types description: Lists the supported resource types (User, Group). operationId: scimResourceTypes responses: '200': description: Resource types content: application/scim+json: schema: {} '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] /scim/v2/Schemas: get: tags: - scim summary: SCIM schemas description: Lists the supported core schemas (User, Group). operationId: scimSchemas responses: '200': description: Schemas content: application/scim+json: schema: {} '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] /scim/v2/ServiceProviderConfig: get: tags: - scim summary: SCIM service provider configuration description: Advertises supported SCIM features (patch, filter, no bulk/sort/etag/change-password). operationId: scimServiceProviderConfig responses: '200': description: Service provider configuration content: application/scim+json: schema: {} '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] /scim/v2/Users: get: tags: - scim summary: List / filter SCIM users description: |- Lists managed (SCIM-provisioned) users. Supports the `userName eq "..."` and `externalId eq "..."` filter subset plus `startIndex`/`count` pagination. operationId: scimListUsers parameters: - name: filter in: query required: false schema: type: string - name: startIndex in: query required: false schema: type: integer format: int64 - name: count in: query required: false schema: type: integer format: int64 responses: '200': description: User list content: application/scim+json: schema: $ref: '#/components/schemas/ListResponse_UserResource' '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] post: tags: - scim summary: Provision a SCIM user description: Creates a passwordless `managed` user. Login happens later via OIDC (claimable path). `userName` conflicts return 409. operationId: scimCreateUser requestBody: content: application/scim+json: schema: $ref: '#/components/schemas/UserRequest' required: true responses: '201': description: User created content: application/scim+json: schema: $ref: '#/components/schemas/UserResource' '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] /scim/v2/Users/{id}: get: tags: - scim summary: Get a SCIM user operationId: scimGetUser parameters: - name: id in: path required: true schema: type: string responses: '200': description: User content: application/scim+json: schema: $ref: '#/components/schemas/UserResource' '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] put: tags: - scim summary: Replace a SCIM user operationId: scimReplaceUser parameters: - name: id in: path required: true schema: type: string requestBody: content: application/scim+json: schema: $ref: '#/components/schemas/UserRequest' required: true responses: '200': description: User replaced content: application/scim+json: schema: $ref: '#/components/schemas/UserResource' '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] delete: tags: - scim summary: Deprovision a SCIM user description: |- Soft-disables the user (`active=false`) by default; hard-deletes (cascade) when `GRADIENT_SCIM_HARD_DELETE=true`. operationId: scimDeleteUser parameters: - name: id in: path required: true schema: type: string responses: '204': description: User deprovisioned '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] patch: tags: - scim summary: Patch a SCIM user description: Applies a SCIM PatchOp. Typically toggles `active` for deactivation/reactivation. operationId: scimPatchUser parameters: - name: id in: path required: true schema: type: string requestBody: content: application/scim+json: schema: $ref: '#/components/schemas/PatchRequest' required: true responses: '200': description: User patched content: application/scim+json: schema: $ref: '#/components/schemas/UserResource' '400': description: Unsupported filter or invalid value content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '401': description: Missing or invalid SCIM bearer token content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '404': description: Resource not found content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' '409': description: Resource already exists (uniqueness) content: application/scim+json: schema: $ref: '#/components/schemas/ScimErrorBody' security: - scimBearer: [] components: schemas: ActionConfig: oneOf: - type: object required: - recipients - type properties: recipients: type: array items: type: string subject_template: type: - string - 'null' type: type: string enum: - send_mail - type: object required: - url - type properties: url: type: string token: type: - string - 'null' type: type: string enum: - send_web_request - type: object required: - integration_id - type properties: integration_id: $ref: '#/components/schemas/IntegrationId' type: type: string enum: - git_host_status_report - type: object required: - integration_id - type properties: integration_id: $ref: '#/components/schemas/IntegrationId' generator: $ref: '#/components/schemas/PatchGeneratorKind' granularity: $ref: '#/components/schemas/PrGranularity' verify_gate: $ref: '#/components/schemas/VerifyGate' branch_pattern: type: string title_template: type: - string - 'null' body_template: type: - string - 'null' update_existing: type: boolean type: type: string enum: - open_pr - type: object required: - homeserver - room_id - type properties: homeserver: type: string room_id: type: string access_token: type: - string - 'null' type: type: string enum: - send_matrix_message - type: object required: - type properties: webhook_url: type: - string - 'null' type: type: string enum: - send_slack_message ActionResponse: type: object required: - id - name - action_type - config - events - active - created_by - created_at - updated_at properties: id: $ref: '#/components/schemas/TaskActionId' name: type: string action_type: type: string config: $ref: '#/components/schemas/Value' events: type: array items: type: string active: type: boolean last_fired_at: type: - string - 'null' format: date-time created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time updated_at: type: string format: date-time Activity: type: object required: - days properties: days: type: array items: $ref: '#/components/schemas/ActivityDay' ActivityDay: type: object required: - date - evaluations - failed properties: date: type: string format: date evaluations: type: integer format: int64 failed: type: integer format: int64 AddMemberRequest: type: object required: - user - role properties: user: type: string role: type: string AddUpstreamRequest: oneOf: - type: object required: - cache_name - type properties: cache_name: type: string display_name: type: - string - 'null' mode: oneOf: - $ref: '#/components/schemas/CacheSubscriptionMode' - type: 'null' type: type: string enum: - internal - type: object required: - display_name - url - public_key - type properties: display_name: type: string url: type: string public_key: type: string type: type: string enum: - http - type: object required: - url - remote_cache - display_name - type properties: url: type: string remote_cache: type: string display_name: type: string mode: oneOf: - $ref: '#/components/schemas/CacheSubscriptionMode' - type: 'null' api_key: type: - string - 'null' type: type: string enum: - gradient_proto AdminTaskDto: type: object required: - id - kind - status - created_at properties: id: $ref: '#/components/schemas/AdminTaskId' kind: type: string status: type: string created_at: type: string format: date-time started_at: type: - string - 'null' format: date-time finished_at: type: - string - 'null' format: date-time progress: {} checkpoint: type: - string - 'null' error: type: - string - 'null' created_by: oneOf: - $ref: '#/components/schemas/UserId' - type: 'null' AdminTaskId: type: string format: uuid ApiId: type: string format: uuid ApiKeyInfo: type: object required: - id - name - managed - permissions - created_at - allowed_ips properties: id: type: string name: type: string managed: type: boolean permissions: type: array items: type: string project: type: - string - 'null' created_at: type: string last_used_at: type: - string - 'null' expires_at: type: - string - 'null' revoked_at: type: - string - 'null' allowed_ips: type: array items: type: string ApiKeyPermissionsResponse: type: object required: - available_permissions - availableCache properties: available_permissions: type: array items: $ref: '#/components/schemas/PermissionEntry' availableCache: type: array items: $ref: '#/components/schemas/PermissionEntry' ApiKeyRequest: type: object required: - name properties: name: type: string ArtefactTree: type: object required: - evaluation - created_at - entry_points properties: evaluation: $ref: '#/components/schemas/EvaluationId' created_at: type: string format: date-time entry_points: type: array items: $ref: '#/components/schemas/EntryPointArtefacts' AssignDecisionView: type: object required: - at - worker_id - kind - candidates properties: at: type: string worker_id: type: string worker_name: type: - string - 'null' kind: type: integer format: int32 winner: type: - string - 'null' candidates: type: array items: $ref: '#/components/schemas/DecisionCandidateView' AttemptSummary: type: object required: - substitute - outcome - created_at properties: dispatched_job_id: type: - string - 'null' format: uuid substitute: type: boolean outcome: type: integer format: int32 reason: type: - integer - 'null' format: int32 failure_message: type: - string - 'null' created_at: type: string AuditLogEntry: type: object required: - id - event - created_at properties: id: type: string event: type: string ip: type: - string - 'null' user_agent: type: - string - 'null' metadata: {} created_at: type: string BadgeStyle: type: string enum: - flat - flat-square Binary: type: string format: binary BlobsResponse: type: object required: - uploaded - remaining properties: uploaded: type: integer minimum: 0 remaining: type: integer minimum: 0 BoardCacheStats: type: object required: - totals - traffic - storage properties: totals: $ref: '#/components/schemas/CacheTotals' traffic: type: array items: $ref: '#/components/schemas/SeriesPoint' storage: type: array items: $ref: '#/components/schemas/SeriesPoint' BoardFleetPoint: type: object required: - bucket_start - connected - draining - eval - fetch - build properties: bucket_start: type: string connected: type: integer format: int64 draining: type: integer format: int64 eval: type: integer format: int64 fetch: type: integer format: int64 build: type: integer format: int64 BoardHealth: type: object required: - version - uptime_seconds - workers_connected - jobs_pending - jobs_active - cache_bytes - cache_packages - process - http - draining - supervised - proto_sessions - unconfirmed_nars - pending_deliveries - failed_deliveries - hot_nar_cache properties: version: type: string uptime_seconds: type: number format: double workers_connected: type: integer format: int64 jobs_pending: type: integer format: int64 jobs_active: type: integer format: int64 cache_bytes: type: integer format: int64 cache_packages: type: integer format: int64 process: $ref: '#/components/schemas/ProcessStat' http: type: array items: $ref: '#/components/schemas/HttpRouteStat' rollup_lag_seconds: type: - number - 'null' format: double latest_rollup_bucket: type: - string - 'null' draining: type: boolean supervised: type: array items: $ref: '#/components/schemas/SupervisedLoop' proto_sessions: type: integer minimum: 0 unconfirmed_nars: type: integer format: int64 minimum: 0 pending_deliveries: type: integer format: int64 description: |- A rising `failed_deliveries` points at a Git host or mail host that is down, not at a backlog. Those rows stay dead letters until an operator acts. failed_deliveries: type: integer format: int64 hot_nar_cache: $ref: '#/components/schemas/HotNarCacheHealth' BoardNetworkStats: type: object required: - nar_egress - workers - http properties: nar_egress: type: array items: $ref: '#/components/schemas/SeriesPoint' workers: type: array items: $ref: '#/components/schemas/WorkerNet' http: type: array items: $ref: '#/components/schemas/HttpRouteStat' BoardProject: type: object required: - id - name - display_name properties: id: type: string format: uuid name: type: string display_name: type: string BoardStorage: type: object required: - granularity - op_latency - op_errors - lane_fill - send_stalls - serve_queue - serve_failures properties: granularity: type: string op_latency: type: array items: $ref: '#/components/schemas/LabelledSeries' op_errors: type: array items: $ref: '#/components/schemas/LabelledSeries' lane_fill: type: array items: $ref: '#/components/schemas/LabelledSeries' send_stalls: type: array items: $ref: '#/components/schemas/LabelledSeries' serve_queue: type: array items: $ref: '#/components/schemas/LabelledSeries' serve_failures: type: array items: $ref: '#/components/schemas/LabelledSeries' BoardUpstreamCache: type: object required: - upstream_id - display_name - url - requests_total - latency - hit_rate_series properties: upstream_id: type: string display_name: type: string url: type: string avg_latency_ms: type: - number - 'null' format: double hit_rate: type: - number - 'null' format: double requests_total: type: integer format: int64 latency: type: array items: $ref: '#/components/schemas/SeriesPoint' hit_rate_series: type: array items: $ref: '#/components/schemas/SeriesPoint' BoardUpstreamCacheStats: type: object required: - upstream_caches properties: upstream_caches: type: array items: $ref: '#/components/schemas/BoardUpstreamCache' BoardWorker: type: object required: - projects - draining - assigned_jobs - max_concurrent_builds - eval - fetch - build - architectures properties: id: type: - string - 'null' name: type: - string - 'null' projects: type: array items: $ref: '#/components/schemas/BoardProject' draining: type: boolean assigned_jobs: type: integer format: int64 max_concurrent_builds: type: integer format: int64 eval: type: boolean fetch: type: boolean build: type: boolean architectures: type: array items: type: string cpu_usage_pct: type: - number - 'null' format: float ram_free_mb: type: - integer - 'null' format: int64 ram_total_mb: type: - integer - 'null' format: int64 BuildGraph: type: object required: - root - nodes - edges properties: root: $ref: '#/components/schemas/DerivationId' nodes: type: array items: $ref: '#/components/schemas/DependencyGraphNode' edges: type: array items: $ref: '#/components/schemas/DependencyEdge' BuildItem: type: object required: - id - name - status - has_artefacts - updated_at - depth - prioritized - ifd properties: id: $ref: '#/components/schemas/BuildJobId' name: type: string status: type: string has_artefacts: type: boolean updated_at: type: string format: date-time build_time_ms: type: - integer - 'null' format: int64 build_started_at: type: - string - 'null' format: date-time dispatched_job: oneOf: - $ref: '#/components/schemas/DispatchedJobId' - type: 'null' depth: type: integer format: int32 minimum: 0 prioritized: type: boolean ifd: type: boolean BuildJobId: type: string format: uuid BuildProduct: type: object required: - file_type - subtype - name - path properties: file_type: type: string subtype: type: string name: type: string path: type: string size: type: - integer - 'null' format: int64 minimum: 0 BuildProductId: type: string format: uuid BuildProgress: type: object required: - phase - bytes_done - paths_done properties: phase: $ref: '#/components/schemas/BuildProgressPhase' bytes_done: type: integer format: int64 minimum: 0 bytes_total: type: - integer - 'null' format: int64 minimum: 0 paths_done: type: integer format: int32 minimum: 0 paths_total: type: - integer - 'null' format: int32 minimum: 0 BuildProgressPhase: type: string enum: - download - prefetch - upload BuildStatus: type: string enum: - Created - Queued - Building - Completed - FailedPermanent - Aborted - DependencyFailed - Substituted - FailedTransient - FailedTimeout - Skipped BuildStatusCounts: type: object required: - completed - failed - building - queued - substituted - aborted properties: completed: type: integer format: int64 failed: type: integer format: int64 building: type: integer format: int64 queued: type: integer format: int64 substituted: type: integer format: int64 aborted: type: integer format: int64 BuildWithOutputs: type: object required: - id - evaluation - status - derivation_path - architecture - output - prioritized - ifd - created_at - updated_at properties: id: $ref: '#/components/schemas/BuildJobId' evaluation: $ref: '#/components/schemas/EvaluationId' status: $ref: '#/components/schemas/BuildStatus' derivation_path: type: string architecture: type: string worker: type: - string - 'null' dispatched_job: oneOf: - $ref: '#/components/schemas/DispatchedJobId' - type: 'null' output: type: object additionalProperties: type: string propertyNames: type: string prioritized: type: boolean ifd: type: boolean created_at: type: string format: date-time updated_at: type: string format: date-time progress: oneOf: - $ref: '#/components/schemas/BuildProgress' - type: 'null' Cache: type: object required: - id - name - display_name - description - active - priority - public_key - public - created_by - created_at - managed - max_storage_gb - pull_through properties: id: $ref: '#/components/schemas/CacheId' name: type: string display_name: type: string description: type: string active: type: boolean priority: type: integer format: int32 local_priority: type: - integer - 'null' format: int32 public_key: type: string public: type: boolean created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time managed: type: boolean max_storage_gb: type: integer format: int32 pull_through: type: boolean CacheId: type: string format: uuid CacheMetricPoint: type: object required: - time - bytes - requests properties: time: type: string bytes: type: integer format: int64 requests: type: integer format: int64 CacheResponse: type: object required: - id - name - display_name - description - active - priority - max_storage_gb - pull_through - public_key - public - created_by - created_at - managed - can_edit properties: id: $ref: '#/components/schemas/CacheId' name: type: string display_name: type: string description: type: string active: type: boolean priority: type: integer format: int32 local_priority: type: - integer - 'null' format: int32 max_storage_gb: type: integer format: int32 pull_through: type: boolean public_key: type: string public: type: boolean created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time managed: type: boolean can_edit: type: boolean CacheRoleOwner: type: object properties: cache: oneOf: - $ref: '#/components/schemas/CacheId' - type: 'null' CacheStatsResponse: type: object required: - total_bytes - total_nar_bytes - total_packages - storage_minutes - storage_hours - storage_days - storage_weeks - minutes - hours - days - weeks properties: total_bytes: type: integer format: int64 total_nar_bytes: type: integer format: int64 total_packages: type: integer format: int64 storage_minutes: type: array items: $ref: '#/components/schemas/StorageMetricPoint' storage_hours: type: array items: $ref: '#/components/schemas/StorageMetricPoint' storage_days: type: array items: $ref: '#/components/schemas/StorageMetricPoint' storage_weeks: type: array items: $ref: '#/components/schemas/StorageMetricPoint' minutes: type: array items: $ref: '#/components/schemas/CacheMetricPoint' hours: type: array items: $ref: '#/components/schemas/CacheMetricPoint' days: type: array items: $ref: '#/components/schemas/CacheMetricPoint' weeks: type: array items: $ref: '#/components/schemas/CacheMetricPoint' CacheSubscriptionItem: type: object required: - id - name - mode - status properties: id: $ref: '#/components/schemas/CacheId' name: type: string mode: $ref: '#/components/schemas/CacheSubscriptionMode' status: $ref: '#/components/schemas/SubscriptionStatus' CacheSubscriptionMode: type: string enum: - ReadWrite - ReadOnly - WriteOnly CacheTotals: type: object required: - bytes - nar_bytes - packages - bytes_sent_total - requests_total properties: bytes: type: integer format: int64 nar_bytes: type: integer format: int64 packages: type: integer format: int64 bytes_sent_total: type: integer format: int64 requests_total: type: integer format: int64 CacheUpstreamId: type: string format: uuid CatalogEntry: type: object required: - name - durable properties: name: type: string durable: type: boolean CheckUsernameRequest: type: object required: - username properties: username: type: string ChunkReceived: type: object required: - received properties: received: type: integer format: int64 minimum: 0 CliDeviceAuthorizeRequest: type: object required: - user_code properties: user_code: type: string CliDeviceInfoResponse: type: object required: - user_code - expires_at properties: user_code: type: string expires_at: type: string format: date-time user_agent: type: - string - 'null' ip: type: - string - 'null' CliDevicePollRequest: type: object required: - device_code properties: device_code: type: string CliDeviceStartResponse: type: object required: - device_code - user_code - verification_uri - verification_uri_complete - expires_in - interval properties: device_code: type: string user_code: type: string verification_uri: type: string verification_uri_complete: type: string expires_in: type: integer format: int64 interval: type: integer format: int64 minimum: 0 ClosureEdge: type: object required: - source - target properties: source: type: string target: type: string ClosureGraph: type: object required: - roots - node_count - edge_count - truncated - nodes - edges properties: roots: type: array items: type: string total_size_bytes: type: - integer - 'null' format: int64 node_count: type: integer minimum: 0 edge_count: type: integer minimum: 0 truncated: type: boolean nodes: type: array items: $ref: '#/components/schemas/ClosureNode' edges: type: array items: $ref: '#/components/schemas/ClosureEdge' ClosureNode: type: object required: - id - name - path properties: id: type: string name: type: string path: type: string nar_size: type: - integer - 'null' format: int64 Commit: type: object required: - id - message - hash - author_name properties: id: $ref: '#/components/schemas/CommitId' message: type: string hash: type: array items: type: integer format: int32 minimum: 0 author: oneOf: - $ref: '#/components/schemas/UserId' - type: 'null' author_name: type: string CommitId: type: string format: uuid ComparedEvaluation: type: object required: - id - commit properties: id: $ref: '#/components/schemas/EvaluationId' commit: type: string ConcurrencyPolicy: type: string enum: - hard_abort - soft_abort - all - skip - auto ConnectionDirection: type: string enum: - outbound - inbound ConnectionFailure: type: object required: - reason - at - direction - before_auth properties: reason: type: string at: type: string format: date-time direction: $ref: '#/components/schemas/ConnectionDirection' before_auth: type: boolean ConnectionRequest: type: object required: - scope - token properties: scope: $ref: '#/components/schemas/ConnectionScope' team: type: - string - 'null' project: type: - string - 'null' token: type: string ConnectionResponse: type: object required: - worker_id properties: worker_id: type: string ConnectionScope: type: string enum: - team - project Counts: type: object required: - all - failing - starred properties: all: type: integer minimum: 0 failing: type: integer minimum: 0 starred: type: integer minimum: 0 CreateActionRequest: type: object required: - name - config properties: name: type: string config: $ref: '#/components/schemas/ActionConfig' events: type: array items: type: string active: type: boolean CreateActionResponse: type: object required: - action properties: action: $ref: '#/components/schemas/ActionResponse' token: type: - string - 'null' CreateApiKeyRequest: type: object required: - name - permissions properties: name: type: string expires_in_days: type: - integer - 'null' format: int32 minimum: 0 permissions: type: array items: type: string project: type: - string - 'null' cache: type: - string - 'null' allowed_ips: type: - array - 'null' items: type: string CreateFlakeInputOverrideRequest: type: object required: - input_name properties: input_name: type: string url: type: - string - 'null' CreateIntegrationRequest: type: object required: - name - kind - git_host_type properties: name: $ref: '#/components/schemas/IndexName' display_name: type: - string - 'null' kind: type: string git_host_type: type: string secret: type: - string - 'null' endpoint_url: type: - string - 'null' access_token: type: - string - 'null' allowed_ips: type: - array - 'null' items: type: string installation_id: type: - integer - 'null' format: int64 CreatePermission: type: string enum: - none - superusers - everyone CreateRoleRequest: type: object required: - name - permissions properties: name: $ref: '#/components/schemas/IndexName' permissions: type: array items: type: string CreateSshKeyRequest: type: object required: - name - public_key properties: name: type: string public_key: type: string CreateTriggerRequest: type: object required: - config properties: config: $ref: '#/components/schemas/TriggerConfig' active: type: boolean CreateWebhookRequest: type: object required: - name - url properties: name: type: string url: type: string events: type: array items: type: string active: type: boolean CreateWebhookResponse: type: object required: - webhook - secret properties: webhook: $ref: '#/components/schemas/WebhookResponse' secret: type: string DashboardStats: type: object required: - cpu_time_ms - cpu_time_ms_7d - builds_completed - cache_size_bytes - workers - queue_wait_p50_ms properties: cpu_time_ms: type: integer format: int64 cpu_time_ms_7d: type: integer format: int64 builds_completed: type: integer format: int64 cache_size_bytes: type: integer format: int64 workers: $ref: '#/components/schemas/OnlineWorkerLoad' queue_wait_p50_ms: type: integer format: int64 DebugInfoRedirect: type: object required: - archive - member properties: archive: type: string member: type: string DecisionCandidateView: type: object required: - id - job_id - kind - project - evaluation_id - score - won properties: id: type: string format: uuid job_id: type: string kind: type: integer format: int32 project: type: string format: uuid build_id: type: - string - 'null' format: uuid evaluation_id: type: string format: uuid subject: type: - string - 'null' score: type: number format: double won: type: boolean DeleteUserRequest: type: object properties: password: type: - string - 'null' confirm_username: type: - string - 'null' DeletedResponse: type: object required: - deleted properties: deleted: type: boolean DeliveryDetail_TaskActionDeliveryId: allOf: - $ref: '#/components/schemas/DeliveryListItem_TaskActionDeliveryId' - type: object required: - request_body properties: request_body: type: string response_body: type: - string - 'null' DeliveryDetail_WebhookDeliveryId: allOf: - $ref: '#/components/schemas/DeliveryListItem_WebhookDeliveryId' - type: object required: - request_body properties: request_body: type: string response_body: type: - string - 'null' DeliveryListItem: type: object required: - id - event - success - duration_ms - delivered_at properties: id: $ref: '#/components/schemas/TaskActionDeliveryId' event: type: string success: type: boolean response_status: type: - integer - 'null' format: int32 error_message: type: - string - 'null' duration_ms: type: integer format: int32 delivered_at: type: string format: date-time DeliveryListItem_TaskActionDeliveryId: type: object required: - id - event - success - duration_ms - delivered_at properties: id: type: string format: uuid event: type: string success: type: boolean response_status: type: - integer - 'null' format: int32 error_message: type: - string - 'null' duration_ms: type: integer format: int32 delivered_at: type: string format: date-time DeliveryListItem_WebhookDeliveryId: type: object required: - id - event - success - duration_ms - delivered_at properties: id: type: string format: uuid event: type: string success: type: boolean response_status: type: - integer - 'null' format: int32 error_message: type: - string - 'null' duration_ms: type: integer format: int32 delivered_at: type: string format: date-time DependencyEdge: type: object required: - source - target properties: source: $ref: '#/components/schemas/DerivationId' target: $ref: '#/components/schemas/DerivationId' DependencyGraphNode: type: object required: - id - name - path - created_at - updated_at properties: id: $ref: '#/components/schemas/DerivationId' build: oneOf: - $ref: '#/components/schemas/BuildJobId' - type: 'null' name: type: string path: type: string status: type: - string - 'null' created_at: type: string format: date-time updated_at: type: string format: date-time DerivationId: type: string format: uuid DispatchRequest: type: object properties: target: type: - string - 'null' system: type: - string - 'null' input_overrides: type: array items: $ref: '#/components/schemas/InputOverrideBody' DispatchResponse: type: object required: - evaluation - task - commit properties: evaluation: $ref: '#/components/schemas/EvaluationId' task: $ref: '#/components/schemas/TaskId' commit: $ref: '#/components/schemas/CommitId' cache: type: - string - 'null' DispatchedJobDetail: allOf: - $ref: '#/components/schemas/ReportGap' - type: object required: - id - kind - project - project_name - project_display_name - worker_id - score - queued_at - dispatched_at - phases - derivations - evaluation_id - score_breakdown - worker_context - job_context - instance_context - previous_attempts - passed_over properties: id: type: string format: uuid kind: type: integer format: int32 project: type: string format: uuid project_name: type: string project_display_name: type: string worker_id: type: string worker_name: type: - string - 'null' score: type: number format: double queued_at: type: string dispatched_at: type: string finished_at: type: - string - 'null' ready_at: type: - string - 'null' outcome: type: - string - 'null' phases: type: array items: $ref: '#/components/schemas/JobPhaseView' build_id: type: - string - 'null' format: uuid derivation_build_id: type: - string - 'null' format: uuid derivations: type: array items: $ref: '#/components/schemas/JobDerivationView' evaluation_id: type: string format: uuid evaluation: oneOf: - $ref: '#/components/schemas/JobEvaluationView' - type: 'null' pname: type: - string - 'null' score_breakdown: {} worker_context: {} job_context: {} instance_context: {} candidates: {} previous_attempts: type: array items: $ref: '#/components/schemas/AttemptSummary' passed_over: type: boolean DispatchedJobId: type: string format: uuid DispatchedJobSummary: type: object required: - id - kind - project - worker_id - score - dispatched_at - evaluation_id properties: id: type: string format: uuid kind: type: integer format: int32 project: type: string format: uuid worker_id: type: string worker_name: type: - string - 'null' score: type: number format: double dispatched_at: type: string build_id: type: - string - 'null' format: uuid evaluation_id: type: string format: uuid subject: type: - string - 'null' DispatchedJobsResponse: type: object required: - jobs - other_running properties: jobs: type: array items: $ref: '#/components/schemas/DispatchedJobSummary' other_running: type: integer format: int64 minimum: 0 DisplayName: type: string DrainingResponse: type: object required: - draining properties: draining: type: boolean DurationsHeatmap: type: object required: - times - bands properties: times: type: array items: type: string bands: type: array items: $ref: '#/components/schemas/HeatmapBand' EmailResource: type: object required: - value properties: value: type: string primary: type: boolean EntryPointArtefacts: type: object required: - attr - derivation - build_id - outputs properties: attr: type: string derivation: type: string build_id: $ref: '#/components/schemas/BuildJobId' outputs: type: array items: $ref: '#/components/schemas/OutputArtefacts' EntryPointBrief: type: object required: - id - eval - build_status properties: id: $ref: '#/components/schemas/EntryPointId' eval: type: string build_status: $ref: '#/components/schemas/BuildStatus' EntryPointId: type: string format: uuid EntryPointMetricPoint: type: object required: - evaluation_id - build_id - created_at - build_status - dependencies_count properties: evaluation_id: $ref: '#/components/schemas/EvaluationId' build_id: $ref: '#/components/schemas/BuildJobId' created_at: type: string format: date-time build_status: $ref: '#/components/schemas/BuildStatus' build_time_ms: type: - integer - 'null' format: int64 output_size_bytes: type: - integer - 'null' format: int64 closure_size_bytes: type: - integer - 'null' format: int64 runtime_closure_size_bytes: type: - integer - 'null' format: int64 dependencies_count: type: integer format: int64 EntryPointMetricsResponse: type: object required: - eval - keep_evaluations - points properties: eval: type: string keep_evaluations: type: integer format: int32 points: type: array items: $ref: '#/components/schemas/EntryPointMetricPoint' EntryPointSummary: type: object required: - id - build_id - derivation_path - eval - build_status - has_artefacts - outputs - architecture - deps - deps_total - prioritized - ifd - created_at properties: id: $ref: '#/components/schemas/EntryPointId' build_id: $ref: '#/components/schemas/BuildJobId' derivation_path: type: string eval: type: string build_status: $ref: '#/components/schemas/BuildStatus' has_artefacts: type: boolean outputs: type: object additionalProperties: type: string propertyNames: type: string architecture: type: string build_time_ms: type: - integer - 'null' format: int64 build_started_at: type: - string - 'null' format: date-time deps: $ref: '#/components/schemas/BuildStatusCounts' deps_total: type: integer format: int64 prioritized: type: boolean ifd: type: boolean created_at: type: string format: date-time ErrorResponseBody: type: object required: - error - code - message properties: error: type: boolean code: type: string message: type: string EvalCapability: type: string enum: - fetch - eval EvaluateRequest: type: object properties: commit: type: - string - 'null' attr: type: - string - 'null' walk: oneOf: - $ref: '#/components/schemas/WalkMode' - type: 'null' EvaluationFailureSummary: type: object required: - packages - failures - failures_total - failed_attributes - fixed - fixed_total properties: compared_with: oneOf: - $ref: '#/components/schemas/ComparedEvaluation' - type: 'null' packages: $ref: '#/components/schemas/PackageCounts' failures: type: array items: $ref: '#/components/schemas/FailedBuildSummary' failures_total: type: integer minimum: 0 failed_attributes: type: array items: $ref: '#/components/schemas/FailedAttributeReport' fixed: type: array items: type: string fixed_total: type: integer minimum: 0 EvaluationId: type: string format: uuid EvaluationMessageId: type: string format: uuid EvaluationMessageResponse: type: object required: - id - level - message - created_at - entry_points properties: id: $ref: '#/components/schemas/EvaluationMessageId' level: $ref: '#/components/schemas/MessageLevel' message: type: string source: type: - string - 'null' created_at: type: string format: date-time entry_points: type: array items: $ref: '#/components/schemas/EntryPointId' EvaluationProgress: oneOf: - type: object required: - inputs - kind properties: inputs: type: array items: $ref: '#/components/schemas/InputFetch' kind: type: string enum: - fetching - type: object required: - thunks - kind properties: thunks: type: integer format: int64 minimum: 0 kind: type: string enum: - evaluating EvaluationResponse: type: object required: - id - repository - commit - wildcard - status - created_at - updated_at - error_count - warning_count - entry_points - prioritized properties: id: $ref: '#/components/schemas/EvaluationId' task: oneOf: - $ref: '#/components/schemas/TaskId' - type: 'null' task_name: type: - string - 'null' task_display_name: type: - string - 'null' repository: type: string commit: type: string wildcard: type: string status: $ref: '#/components/schemas/EvaluationStatus' previous: oneOf: - $ref: '#/components/schemas/EvaluationId' - type: 'null' next: oneOf: - $ref: '#/components/schemas/EvaluationId' - type: 'null' created_at: type: string format: date-time started_at: type: - string - 'null' format: date-time finished_at: type: - string - 'null' format: date-time updated_at: type: string format: date-time error_count: type: integer format: int64 minimum: 0 warning_count: type: integer format: int64 minimum: 0 error: type: - string - 'null' entry_points: type: array items: $ref: '#/components/schemas/EntryPointBrief' prioritized: type: boolean trigger: oneOf: - $ref: '#/components/schemas/EvaluationTriggerSummary' - type: 'null' triggered_by: type: - string - 'null' waiting_reason: oneOf: - $ref: '#/components/schemas/WaitingReason' - type: 'null' progress: oneOf: - $ref: '#/components/schemas/EvaluationProgress' - type: 'null' expected_thunks: type: - integer - 'null' format: int64 minimum: 0 EvaluationStatus: type: string enum: - Queued - EvaluatingFlake - EvaluatingDerivation - Building - Waiting - Completed - Failed - Aborted - Fetching EvaluationSummary: type: object required: - id - commit - status - wildcard - total_builds - builds - errors - warnings - prioritized - created_at - updated_at properties: id: $ref: '#/components/schemas/EvaluationId' commit: type: string commit_message: type: - string - 'null' status: $ref: '#/components/schemas/EvaluationStatus' wildcard: type: string trigger: oneOf: - $ref: '#/components/schemas/EvaluationTriggerSummary' - type: 'null' triggered_by: type: - string - 'null' pr_number: type: - integer - 'null' format: int64 minimum: 0 total_builds: type: integer format: int64 builds: $ref: '#/components/schemas/BuildStatusCounts' errors: type: integer format: int64 warnings: type: integer format: int64 dispatched_job: oneOf: - $ref: '#/components/schemas/DispatchedJobId' - type: 'null' prioritized: type: boolean created_at: type: string format: date-time started_at: type: - string - 'null' format: date-time finished_at: type: - string - 'null' format: date-time updated_at: type: string format: date-time progress: oneOf: - $ref: '#/components/schemas/EvaluationProgress' - type: 'null' expected_thunks: type: - integer - 'null' format: int64 minimum: 0 EvaluationTriggerSummary: type: object required: - id - type properties: id: $ref: '#/components/schemas/TaskTriggerId' type: $ref: '#/components/schemas/TriggerType' ExpensiveBuild: type: object required: - build_id - project - name - build_time_ms properties: build_id: type: string format: uuid project: type: string format: uuid name: type: string build_time_ms: type: integer format: int64 worker: type: - string - 'null' worker_name: type: - string - 'null' ExpensiveEval: type: object required: - evaluation - project - project_name - project_display_name - task_name - task_display_name - name - value - unit - worker properties: evaluation: type: string format: uuid project: type: string format: uuid project_name: type: string project_display_name: type: string task_name: type: string task_display_name: type: string name: type: string value: type: number format: double unit: type: string worker: type: string worker_name: type: - string - 'null' ExpensiveResource: type: object required: - derivation - project - name - value - unit - worker properties: derivation: type: string format: uuid project: type: string format: uuid name: type: string value: type: number format: double unit: type: string worker: type: string worker_name: type: - string - 'null' FailedAttributeReport: type: object required: - attr - message - newly_failing properties: attr: type: string message: type: string newly_failing: type: boolean FailedAttributeSummary: type: object required: - eval - message properties: eval: type: string message: type: string FailedBuildSummary: type: object required: - build_id - name - derivation_path - architecture - status - attributes - blocked - blocked_total - newly_failing properties: build_id: $ref: '#/components/schemas/BuildJobId' name: type: string derivation_path: type: string architecture: type: string status: $ref: '#/components/schemas/BuildStatus' attributes: type: array items: type: string blocked: type: array items: type: string blocked_total: type: integer minimum: 0 newly_failing: type: boolean FileTree: oneOf: - type: object required: - size - type properties: executable: type: boolean size: type: integer format: int64 minimum: 0 narOffset: type: - integer - 'null' format: int64 minimum: 0 type: type: string enum: - regular - type: object required: - target - type properties: target: type: string type: type: string enum: - symlink - type: object required: - entries - type properties: entries: type: object additionalProperties: $ref: '#/components/schemas/FileTree' propertyNames: type: string type: type: string enum: - directory Filter: type: string enum: - all - failing - starred FlakeGraphNode: type: object required: - path - name - kind - is_derivation properties: path: type: string parent: type: - string - 'null' name: type: string kind: type: string is_derivation: type: boolean drv_path: type: - string - 'null' FlakeInputOverrideId: type: string format: uuid FlakeInputOverrideOut: type: object required: - id - task - input_name - created_at - updated_at properties: id: $ref: '#/components/schemas/FlakeInputOverrideId' task: $ref: '#/components/schemas/TaskId' input_name: type: string url: type: - string - 'null' created_at: type: string format: date-time updated_at: type: string format: date-time GetUserSettingsResponse: type: object required: - username - name - email - is_oidc - managed properties: username: type: string name: type: string email: type: string is_oidc: type: boolean managed: type: boolean GithubAppManifestRequest: type: object properties: host: type: - string - 'null' GithubAppManifestResponse: type: object required: - manifest - post_url - state properties: manifest: {} post_url: type: string state: type: string GradientCacheInfo: type: object required: - GradientVersion - GradientUrl properties: GradientVersion: type: string GradientUrl: type: string GradientCapabilities: type: object required: - core - federate - fetch - eval - build - cache properties: core: type: boolean federate: type: boolean fetch: type: boolean eval: type: boolean build: type: boolean cache: type: boolean GrantCacheRequest: type: object required: - team - role properties: team: type: string role: type: string GrantProjectRequest: type: object required: - team properties: team: type: string role: type: - string - 'null' users: type: boolean workers: type: boolean GroupMember: type: object required: - value properties: value: type: string display: type: - string - 'null' GroupResource: type: object required: - schemas - id - displayName - members - meta properties: schemas: type: array items: type: string id: type: string displayName: type: string members: type: array items: $ref: '#/components/schemas/GroupMember' meta: $ref: '#/components/schemas/Meta' HeatmapBand: type: object required: - band - counts properties: band: type: string counts: type: array items: type: integer format: int64 HistoryBar: type: object required: - id - status - created_at properties: id: $ref: '#/components/schemas/EvaluationId' status: $ref: '#/components/schemas/EvaluationStatus' duration_ms: type: - integer - 'null' format: int64 created_at: type: string format: date-time HitKind: type: string enum: - project - task - cache - nar - commit HotNarCacheHealth: type: object required: - entries - bytes - hits - misses - evictions properties: entries: type: integer format: int64 minimum: 0 bytes: type: integer format: int64 minimum: 0 hits: type: integer format: int64 minimum: 0 misses: type: integer format: int64 minimum: 0 evictions: type: integer format: int64 minimum: 0 HttpRouteStat: type: object required: - method - route - count - avg_ms - errors properties: method: type: string route: type: string count: type: integer format: int64 minimum: 0 avg_ms: type: number format: double errors: type: integer format: int64 minimum: 0 IncomingWebhookResponse: type: object required: - event - repository_urls - tasks_scanned - queued - skipped properties: event: type: string repository_urls: type: array items: type: string tasks_scanned: type: integer format: int32 minimum: 0 queued: type: array items: $ref: '#/components/schemas/QueuedEvaluation' skipped: type: array items: $ref: '#/components/schemas/SkippedTask' IndexName: type: string InputFetch: type: object required: - name - state - downloaded_bytes - expected_bytes properties: name: type: string state: $ref: '#/components/schemas/InputFetchState' downloaded_bytes: type: integer format: int64 minimum: 0 expected_bytes: type: integer format: int64 minimum: 0 InputFetchState: type: string enum: - Queued - Fetching - Done - Failed InputOverrideBody: type: object required: - input_name - url properties: input_name: type: string url: type: string IntegrationId: type: string format: uuid IntegrationResponse: type: object required: - id - project - name - display_name - kind - git_host_type - has_secret - has_access_token - allowed_ips - created_by - created_at - managed properties: id: $ref: '#/components/schemas/IntegrationId' project: $ref: '#/components/schemas/ProjectId' name: type: string display_name: type: string kind: type: string git_host_type: type: string endpoint_url: type: - string - 'null' has_secret: type: boolean has_access_token: type: boolean allowed_ips: type: array items: type: string installation_id: type: - integer - 'null' format: int64 account_login: type: - string - 'null' created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time managed: type: boolean IntegrationSummaryResponse: type: object required: - id - name - display_name - kind - git_host_type properties: id: $ref: '#/components/schemas/IntegrationId' name: type: string display_name: type: string kind: type: string git_host_type: type: string InviteItem: type: object required: - kind - token - scope - scope_display_name - role - invited_by - created_at - expires_at properties: kind: $ref: '#/components/schemas/InviteKind' token: type: string scope: type: string scope_display_name: type: string role: type: string invited_by: type: string created_at: type: string format: date-time expires_at: type: string format: date-time InviteKind: type: string enum: - project - cache - team InviteTokenRequest: type: object required: - token properties: token: type: string JobDerivationView: type: object required: - derivation_build - drv_path properties: build: type: - string - 'null' format: uuid derivation_build: type: string format: uuid drv_path: type: string pname: type: - string - 'null' JobEvaluationView: type: object required: - repository - commit - wildcard properties: repository: type: string commit: type: string commit_message: type: - string - 'null' wildcard: type: string task: type: - string - 'null' JobPhaseView: type: object required: - seq - phase - start_ms - end_ms - paths - bytes properties: seq: type: integer format: int32 parent_seq: type: - integer - 'null' format: int32 phase: type: string start_ms: type: integer format: int64 end_ms: type: integer format: int64 paths: type: integer format: int32 bytes: type: integer format: int64 LabelledPoint: type: object required: - bucket_start - count - avg - max properties: bucket_start: type: string count: type: integer format: int64 avg: type: number format: double max: type: number format: double LabelledSeries: type: object required: - label - points properties: label: type: string points: type: array items: $ref: '#/components/schemas/LabelledPoint' Latest: type: object required: - id - status - commit - created_at properties: id: $ref: '#/components/schemas/EvaluationId' status: $ref: '#/components/schemas/EvaluationStatus' commit: type: string created_at: type: string format: date-time ListResponse_GroupResource: type: object required: - schemas - totalResults - startIndex - itemsPerPage - Resources properties: schemas: type: array items: type: string totalResults: type: integer minimum: 0 startIndex: type: integer minimum: 0 itemsPerPage: type: integer minimum: 0 Resources: type: array items: type: object required: - schemas - id - displayName - members - meta properties: schemas: type: array items: type: string id: type: string displayName: type: string members: type: array items: $ref: '#/components/schemas/GroupMember' meta: $ref: '#/components/schemas/Meta' ListResponse_UserResource: type: object required: - schemas - totalResults - startIndex - itemsPerPage - Resources properties: schemas: type: array items: type: string totalResults: type: integer minimum: 0 startIndex: type: integer minimum: 0 itemsPerPage: type: integer minimum: 0 Resources: type: array items: type: object required: - schemas - id - userName - name - displayName - emails - active - meta properties: schemas: type: array items: type: string id: type: string userName: type: string externalId: type: - string - 'null' name: $ref: '#/components/schemas/NameResource' displayName: type: string emails: type: array items: $ref: '#/components/schemas/EmailResource' active: type: boolean meta: $ref: '#/components/schemas/Meta' LoadBucket: type: object required: - key - in_flight - capacity - workers properties: key: type: string in_flight: type: integer format: int32 minimum: 0 capacity: type: integer format: int32 minimum: 0 workers: type: integer format: int32 minimum: 0 LogChunkIndex: type: object required: - total_chunks - total_lines - total_bytes - chunks properties: total_chunks: type: integer format: int32 minimum: 0 total_lines: type: integer format: int64 minimum: 0 total_bytes: type: integer format: int64 minimum: 0 chunks: type: array items: $ref: '#/components/schemas/LogChunkMeta' LogChunkMeta: type: object required: - index - line_start - line_count - byte_start - byte_len properties: index: type: integer format: int32 minimum: 0 line_start: type: integer format: int64 minimum: 0 line_count: type: integer format: int32 minimum: 0 byte_start: type: integer format: int64 minimum: 0 byte_len: type: integer format: int32 minimum: 0 LogSearchHit: type: object required: - line_number - chunk_index - byte_offset - preview properties: line_number: type: integer format: int64 minimum: 0 chunk_index: type: integer format: int32 minimum: 0 byte_offset: type: integer format: int64 minimum: 0 preview: type: string MakeCacheRequest: type: object required: - name - display_name - description - priority properties: name: $ref: '#/components/schemas/IndexName' display_name: $ref: '#/components/schemas/DisplayName' description: type: string priority: type: integer format: int32 public: type: - boolean - 'null' local_priority: type: - integer - 'null' format: int32 max_storage_gb: type: - integer - 'null' format: int32 pull_through: type: - boolean - 'null' MakeEvaluationRequest: type: object required: - method properties: method: type: string MakeLoginRequest: type: object required: - loginname - password properties: loginname: type: string password: type: string remember_me: type: boolean MakeProjectRequest: type: object required: - name - display_name - description properties: name: $ref: '#/components/schemas/IndexName' display_name: $ref: '#/components/schemas/DisplayName' description: type: string public: type: - boolean - 'null' hide_build_requests: type: - boolean - 'null' MakeTaskRequest: type: object required: - name - display_name - description - repository - wildcard properties: name: $ref: '#/components/schemas/IndexName' display_name: $ref: '#/components/schemas/DisplayName' description: type: string repository: type: string wildcard: type: string concurrency: oneOf: - $ref: '#/components/schemas/ConcurrencyPolicy' - type: 'null' sign_cache: type: - boolean - 'null' wait_for_workers: type: - boolean - 'null' retry_failed_builds: type: - boolean - 'null' MakeTeamRequest: type: object required: - name - display_name properties: name: $ref: '#/components/schemas/IndexName' display_name: $ref: '#/components/schemas/DisplayName' MakeUserRequest: type: object required: - username - name - email - password properties: username: type: string name: $ref: '#/components/schemas/DisplayName' email: type: string password: type: string ManifestEntry: type: object required: - path - hash - size properties: path: type: string hash: type: string size: type: integer format: int64 ManifestRequest: type: object required: - project - files properties: project: type: string files: type: array items: $ref: '#/components/schemas/ManifestEntry' ManifestResponse: type: object required: - session - missing properties: session: $ref: '#/components/schemas/UploadSessionId' missing: type: array items: type: string ManifestResult: type: object required: - id - slug - html_url - pem - webhook_secret - client_id - client_secret properties: id: type: integer format: int64 slug: type: string html_url: type: string pem: type: string webhook_secret: type: string client_id: type: string client_secret: type: string MemberItem: type: object required: - id - name properties: id: type: string name: type: string MessageLevel: type: string enum: - Error - Warning - Notice Meta: type: object required: - resourceType properties: resourceType: type: string MetricMeta: type: object required: - key - kind - unit - dimensions properties: key: type: string kind: type: string unit: type: string dimensions: type: array items: type: string MetricPoint: type: object required: - bucket_start - count - sum - min - max - avg properties: bucket_start: type: string count: type: integer format: int64 sum: type: number format: double min: type: number format: double max: type: number format: double avg: type: number format: double NameRequest: type: object properties: formatted: type: - string - 'null' givenName: type: - string - 'null' familyName: type: - string - 'null' NameResource: type: object required: - formatted properties: formatted: type: string NarAvailable: type: object required: - available properties: available: type: boolean NarDetail: type: object required: - hash - store_path - package - references - created_at - fetch_count - signed properties: hash: type: string store_path: type: string package: type: string nar_size: type: - integer - 'null' format: int64 file_size: type: - integer - 'null' format: int64 file_hash: type: - string - 'null' nar_hash: type: - string - 'null' references: type: array items: type: string deriver: type: - string - 'null' ca: type: - string - 'null' created_at: type: string format: date-time last_fetched_at: type: - string - 'null' format: date-time fetch_count: type: integer format: int64 signed: type: boolean NarList: type: object required: - version - root properties: version: type: integer format: int32 minimum: 0 root: $ref: '#/components/schemas/FileTree' NarStats: type: object required: - total_nars - total_nar_size - total_file_size properties: total_nars: type: integer format: int64 total_nar_size: type: integer format: int64 total_file_size: type: integer format: int64 last_uploaded_at: type: - string - 'null' format: date-time oldest_fetched_at: type: - string - 'null' format: date-time NarSummary: type: object required: - hash - store_path - package - created_at properties: hash: type: string store_path: type: string package: type: string nar_size: type: - integer - 'null' format: int64 file_size: type: - integer - 'null' format: int64 created_at: type: string format: date-time last_fetched_at: type: - string - 'null' format: date-time NarUploadForm: type: object required: - narinfo - nar properties: narinfo: $ref: '#/components/schemas/NarinfoPart' nar: type: string format: binary NarinfoPart: type: object required: - store_path - file_hash - file_size - nar_size - nar_hash properties: store_path: type: string file_hash: type: string file_size: type: integer format: int64 nar_size: type: integer format: int64 nar_hash: type: string references: type: array items: type: string deriver: type: - string - 'null' NixCacheInfo: type: object required: - WantMassQuery - StoreDir - Priority properties: WantMassQuery: type: boolean StoreDir: type: string Priority: type: integer format: int32 NixPathInfo: type: object required: - StorePath - URL - Compression - FileHash - FileSize - NarHash - NarSize - References - Sig properties: StorePath: type: string URL: type: string Compression: type: string FileHash: type: string FileSize: type: integer format: int32 minimum: 0 NarHash: type: string NarSize: type: integer format: int64 minimum: 0 References: type: array items: type: string Sig: type: string Deriver: type: - string - 'null' CA: type: - string - 'null' OnlineWorkerLoad: type: object required: - online - busy_pct properties: online: type: integer minimum: 0 busy_pct: type: integer format: int32 minimum: 0 Outcomes: type: object required: - ok - failing - total properties: ok: type: integer format: int64 failing: type: integer format: int64 total: type: integer format: int64 OutputArtefacts: type: object required: - name - store_path - products properties: name: type: string store_path: type: string products: type: array items: $ref: '#/components/schemas/ProductArtefact' PackageCounts: type: object required: - total - built - failed - blocked - unfinished properties: total: type: integer minimum: 0 built: type: integer minimum: 0 failed: type: integer minimum: 0 blocked: type: integer minimum: 0 unfinished: type: integer minimum: 0 PaginatedBuilds: type: object required: - builds - total - active_count properties: builds: type: array items: $ref: '#/components/schemas/BuildItem' total: type: integer minimum: 0 active_count: type: integer minimum: 0 PaginatedEntryPoints: type: object required: - entry_points - total - failed_attributes properties: entry_points: type: array items: $ref: '#/components/schemas/EntryPointSummary' total: type: integer format: int64 minimum: 0 failed_attributes: type: array items: $ref: '#/components/schemas/FailedAttributeSummary' Paginated_AuditLogEntry: type: object required: - items - total - page - per_page properties: items: type: array items: $ref: '#/components/schemas/AuditLogEntry' total: type: integer format: int64 minimum: 0 page: type: integer format: int64 minimum: 0 per_page: type: integer format: int64 minimum: 0 Paginated_Cache: type: object required: - items - total - page - per_page properties: items: type: array items: $ref: '#/components/schemas/Cache' total: type: integer format: int64 minimum: 0 page: type: integer format: int64 minimum: 0 per_page: type: integer format: int64 minimum: 0 Paginated_NarSummary: type: object required: - items - total - page - per_page properties: items: type: array items: $ref: '#/components/schemas/NarSummary' total: type: integer format: int64 minimum: 0 page: type: integer format: int64 minimum: 0 per_page: type: integer format: int64 minimum: 0 Paginated_Project: type: object required: - items - total - page - per_page properties: items: type: array items: $ref: '#/components/schemas/Project' total: type: integer format: int64 minimum: 0 page: type: integer format: int64 minimum: 0 per_page: type: integer format: int64 minimum: 0 Paginated_ProjectSummary: type: object required: - items - total - page - per_page properties: items: type: array items: $ref: '#/components/schemas/ProjectSummary' total: type: integer format: int64 minimum: 0 page: type: integer format: int64 minimum: 0 per_page: type: integer format: int64 minimum: 0 Paginated_TaskResponse: type: object required: - items - total - page - per_page properties: items: type: array items: $ref: '#/components/schemas/TaskResponse' total: type: integer format: int64 minimum: 0 page: type: integer format: int64 minimum: 0 per_page: type: integer format: int64 minimum: 0 PatchApiKeyRequest: type: object properties: name: type: - string - 'null' permissions: type: - array - 'null' items: type: string project: type: - string - 'null' description: An omitted field leaves the pin unchanged. A name pins the key, and JSON null unpins it. allowed_ips: type: - array - 'null' items: type: string PatchCacheGrantRequest: type: object required: - role properties: role: type: string PatchCacheRequest: type: object properties: name: oneOf: - $ref: '#/components/schemas/IndexName' - type: 'null' display_name: type: - string - 'null' description: type: - string - 'null' priority: type: - integer - 'null' format: int32 local_priority: type: - integer - 'null' format: int32 max_storage_gb: type: - integer - 'null' format: int32 pull_through: type: - boolean - 'null' PatchGeneratorKind: type: string enum: - flake_lock PatchIntegrationRequest: type: object properties: name: oneOf: - $ref: '#/components/schemas/IndexName' - type: 'null' display_name: type: - string - 'null' git_host_type: type: - string - 'null' endpoint_url: type: - string - 'null' secret: type: - string - 'null' access_token: type: - string - 'null' allowed_ips: type: - array - 'null' items: type: string PatchOperation: type: object required: - op properties: op: type: string path: type: - string - 'null' value: {} PatchProjectGrantRequest: type: object properties: role: type: - string - 'null' users: type: - boolean - 'null' workers: type: - boolean - 'null' PatchProjectRequest: type: object properties: name: oneOf: - $ref: '#/components/schemas/IndexName' - type: 'null' display_name: type: - string - 'null' description: type: - string - 'null' hide_build_requests: type: - boolean - 'null' PatchRequest: type: object required: - Operations properties: Operations: type: array items: $ref: '#/components/schemas/PatchOperation' PatchRoleRequest: type: object properties: name: oneOf: - $ref: '#/components/schemas/IndexName' - type: 'null' permissions: type: - array - 'null' items: type: string PatchTaskRequest: type: object properties: name: oneOf: - $ref: '#/components/schemas/IndexName' - type: 'null' display_name: type: - string - 'null' description: type: - string - 'null' repository: type: - string - 'null' wildcard: type: - string - 'null' keep_evaluations: type: - integer - 'null' format: int32 concurrency: oneOf: - $ref: '#/components/schemas/ConcurrencyPolicy' - type: 'null' sign_cache: type: - boolean - 'null' wait_for_workers: type: - boolean - 'null' retry_failed_builds: type: - boolean - 'null' PatchTeamRequest: type: object properties: display_name: oneOf: - $ref: '#/components/schemas/DisplayName' - type: 'null' new_project_users: type: - boolean - 'null' new_project_workers: type: - boolean - 'null' new_project_role: type: - string - 'null' oidc_group: type: - string - 'null' scim_group: type: - string - 'null' PatchUpstreamRequest: type: object properties: display_name: type: - string - 'null' mode: oneOf: - $ref: '#/components/schemas/CacheSubscriptionMode' - type: 'null' url: type: - string - 'null' public_key: type: - string - 'null' active: type: - boolean - 'null' PatchUserSettingsRequest: type: object properties: username: type: - string - 'null' name: oneOf: - $ref: '#/components/schemas/DisplayName' - type: 'null' email: type: - string - 'null' PatchWorkerRequest: type: object properties: active: type: - boolean - 'null' display_name: type: - string - 'null' enable_fetch: type: - boolean - 'null' enable_eval: type: - boolean - 'null' enable_build: type: - boolean - 'null' PendingInvitationItem: type: object required: - user - name - role - created_at - expires_at properties: user: type: string name: type: string role: type: string created_at: type: string format: date-time expires_at: type: string format: date-time PendingJobSummary: type: object required: - kind - project - evaluation_id - queued_at - dependency_count properties: kind: type: integer format: int32 project: type: string format: uuid evaluation_id: type: string format: uuid build_id: type: - string - 'null' format: uuid queued_at: type: string dependency_count: type: integer format: int32 minimum: 0 subject: type: - string - 'null' PendingJobsResponse: type: object required: - jobs - other_pending properties: jobs: type: array items: $ref: '#/components/schemas/PendingJobSummary' other_pending: type: integer format: int64 minimum: 0 PermissionEntry: type: object required: - id - mutating properties: id: type: string mutating: type: boolean PrGranularity: type: string enum: - per_run - per_input ProcessStat: type: object required: - resident_memory_bytes - virtual_memory_bytes - open_fds - max_fds - cpu_seconds_total - threads properties: resident_memory_bytes: type: number format: double virtual_memory_bytes: type: number format: double open_fds: type: number format: double max_fds: type: number format: double cpu_seconds_total: type: number format: double threads: type: number format: double ProductArtefact: type: object required: - id - type - subtype - name - path properties: id: $ref: '#/components/schemas/BuildProductId' type: type: string subtype: type: string name: type: string path: type: string size: type: - integer - 'null' format: int64 Project: type: object required: - id - name - display_name - description - public_key - private_key - public - hide_build_requests - created_by - created_at - managed properties: id: $ref: '#/components/schemas/ProjectId' name: type: string display_name: type: string description: type: string public_key: type: string private_key: type: string public: type: boolean hide_build_requests: type: boolean created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time managed: type: boolean ProjectId: type: string format: uuid ProjectResponse: type: object required: - id - name - display_name - description - public - hide_build_requests - managed - created_by - created_at - github_app_available properties: id: $ref: '#/components/schemas/ProjectId' name: type: string display_name: type: string description: type: string public_key: type: - string - 'null' public: type: boolean hide_build_requests: type: boolean managed: type: boolean created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time github_app_available: type: boolean github_app_install_url: type: - string - 'null' role: type: - string - 'null' ProjectRoleOwner: type: object properties: project: oneOf: - $ref: '#/components/schemas/ProjectId' - type: 'null' ProjectSummary: type: object required: - id - name - display_name - description - public - hide_build_requests - managed - created_by - created_at - running_evaluations properties: id: $ref: '#/components/schemas/ProjectId' name: type: string display_name: type: string description: type: string public_key: type: - string - 'null' public: type: boolean hide_build_requests: type: boolean managed: type: boolean created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time running_evaluations: type: integer format: int64 role: type: - string - 'null' ProjectWorkerEntry: allOf: - $ref: '#/components/schemas/WorkerConnection' - type: object required: - worker_id - display_name - registered_at - active - enable_fetch - enable_eval - enable_build - gradient_ci properties: worker_id: type: string display_name: type: string registered_at: type: string format: date-time active: type: boolean url: type: - string - 'null' created_by: oneOf: - $ref: '#/components/schemas/UserId' - type: 'null' enable_fetch: type: boolean enable_eval: type: boolean enable_build: type: boolean team: type: - string - 'null' gradient_ci: type: boolean live: oneOf: - $ref: '#/components/schemas/WorkerLiveInfo' - type: 'null' ProtocolProbe: type: object required: - ok - latency_ms properties: ok: type: boolean status: type: - integer - 'null' format: int32 minimum: 0 latency_ms: type: integer format: int64 minimum: 0 error: type: - string - 'null' QueueSummary: type: object required: - building - queued properties: building: type: integer format: int64 queued: type: integer format: int64 QueuedEvaluation: type: object required: - task_id - task_name - project - evaluation_id properties: task_id: $ref: '#/components/schemas/TaskId' task_name: type: string project: type: string evaluation_id: $ref: '#/components/schemas/EvaluationId' Rail: type: object required: - projects - caches properties: projects: type: array items: $ref: '#/components/schemas/RailProject' caches: type: array items: $ref: '#/components/schemas/RailCache' RailCache: type: object required: - name - display_name - starred - nar_count properties: name: type: string display_name: type: string starred: type: boolean nar_count: type: integer format: int64 RailProject: type: object required: - name - display_name - starred - tier - task_count properties: name: type: string display_name: type: string starred: type: boolean tier: $ref: '#/components/schemas/Tier' status: oneOf: - $ref: '#/components/schemas/EvaluationStatus' - type: 'null' task_count: type: integer format: int64 tasks: type: - array - 'null' items: $ref: '#/components/schemas/RailTask' RailTask: type: object required: - name properties: name: type: string status: oneOf: - $ref: '#/components/schemas/EvaluationStatus' - type: 'null' RegisterWorkerRequest: type: object required: - worker_id - display_name properties: worker_id: type: string url: type: - string - 'null' display_name: type: string token: type: - string - 'null' enable_fetch: type: boolean enable_eval: type: boolean enable_build: type: boolean RegisterWorkerResponse: type: object required: - peer_id properties: peer_id: $ref: '#/components/schemas/ProjectId' token: type: - string - 'null' RegisteredTeamWorker: type: object required: - team properties: team: $ref: '#/components/schemas/TeamId' token: type: - string - 'null' RemoveMemberRequest: type: object required: - user properties: user: type: string RemoveTeamMemberRequest: type: object required: - user properties: user: type: string ReportGap: type: object properties: worker_elapsed_ms: type: - integer - 'null' format: int64 worker_tail_ms: type: - integer - 'null' format: int64 transit_ms: type: - integer - 'null' format: int64 RequestKind: type: string enum: - project - cache RevokeInvitationRequest: type: object required: - user properties: user: type: string RoleId: type: string format: uuid RoleListResponse_CacheRoleOwner: type: object required: - roles - available_permissions properties: roles: type: array items: $ref: '#/components/schemas/RoleResponse_CacheRoleOwner' available_permissions: type: array items: $ref: '#/components/schemas/PermissionEntry' RoleListResponse_ProjectRoleOwner: type: object required: - roles - available_permissions properties: roles: type: array items: $ref: '#/components/schemas/RoleResponse_ProjectRoleOwner' available_permissions: type: array items: $ref: '#/components/schemas/PermissionEntry' RoleResponse_CacheRoleOwner: allOf: - type: object properties: cache: oneOf: - $ref: '#/components/schemas/CacheId' - type: 'null' - type: object required: - id - name - builtin - managed - permissions properties: id: $ref: '#/components/schemas/RoleId' name: type: string builtin: type: boolean managed: type: boolean permissions: type: array items: type: string RoleResponse_ProjectRoleOwner: allOf: - type: object properties: project: oneOf: - $ref: '#/components/schemas/ProjectId' - type: 'null' - type: object required: - id - name - builtin - managed - permissions properties: id: $ref: '#/components/schemas/RoleId' name: type: string builtin: type: boolean managed: type: boolean permissions: type: array items: type: string RotatedSecret: type: object required: - secret properties: secret: type: string RuleContribution: type: object required: - rule - avg - min - max properties: rule: type: string avg: type: number format: double min: type: number format: double max: type: number format: double RuleDescription: type: object required: - rule - description properties: rule: type: string description: type: string ScimErrorBody: type: object required: - schemas - status - detail properties: schemas: type: array items: type: string status: type: string scimType: type: - string - 'null' detail: type: string ScoreBucket: type: object required: - lo - hi - count properties: lo: type: number format: double hi: type: number format: double count: type: integer format: int64 ScoringSummary: type: object required: - sample_size - score_min - score_max - score_avg - histogram - rules properties: sample_size: type: integer format: int64 score_min: type: number format: double score_max: type: number format: double score_avg: type: number format: double histogram: type: array items: $ref: '#/components/schemas/ScoreBucket' rules: type: array items: $ref: '#/components/schemas/RuleContribution' SearchHit: type: object required: - kind - label - sublabel - route - starred properties: kind: $ref: '#/components/schemas/HitKind' label: type: string sublabel: type: string route: type: string starred: type: boolean SeriesPoint: type: object required: - bucket_start - count - sum properties: bucket_start: type: string count: type: integer format: int64 sum: type: number format: double ServerConfig: type: object required: - version - oidc_enabled - oidc_required - registration_enabled - email_verification_enabled - smtp_enabled - quic - create_project - create_team - create_cache - github_app_enabled - ssh_enabled - gradient_ci_enabled - gradient_ci_url properties: version: type: string oidc_enabled: type: boolean oidc_required: type: boolean registration_enabled: type: boolean email_verification_enabled: type: boolean smtp_enabled: type: boolean quic: type: boolean create_project: $ref: '#/components/schemas/CreatePermission' create_team: $ref: '#/components/schemas/CreatePermission' create_cache: $ref: '#/components/schemas/CreatePermission' github_app_enabled: type: boolean ssh_enabled: type: boolean ssh_port: type: - integer - 'null' format: int32 minimum: 0 gradient_ci_enabled: type: boolean gradient_ci_url: type: string logo_url: type: - string - 'null' SessionId: type: string format: uuid SessionInfo: type: object required: - id - created_at - last_used_at - expires_at - remember_me - current properties: id: type: string user_agent: type: - string - 'null' ip: type: - string - 'null' created_at: type: string last_used_at: type: string expires_at: type: string remember_me: type: boolean current: type: boolean SetDrainingRequest: type: object required: - enabled properties: enabled: type: boolean SkippedTask: type: object required: - task_id - task_name - project - reason properties: task_id: $ref: '#/components/schemas/TaskId' task_name: type: string project: type: string reason: type: string SourceFinalize: type: object properties: target: type: - string - 'null' system: type: - string - 'null' input_overrides: type: array items: $ref: '#/components/schemas/InputOverrideBody' SourceUploadForm: type: object required: - nar properties: nar: type: string format: binary target: type: - string - 'null' SshKeyInfo: type: object required: - id - name - fingerprint - created_at properties: id: $ref: '#/components/schemas/UserSshKeyId' name: type: string fingerprint: type: string created_at: type: string format: date-time last_used_at: type: - string - 'null' format: date-time StarredNames: type: object required: - projects - tasks - caches properties: projects: type: array items: type: string tasks: type: array items: $ref: '#/components/schemas/StarredTask' caches: type: array items: type: string StarredTask: type: object required: - project - task properties: project: type: string task: type: string StartDeepGcResponse: type: object required: - task_id - status properties: task_id: $ref: '#/components/schemas/AdminTaskId' status: type: string StorageMetricPoint: type: object required: - time - packages - bytes properties: time: type: string packages: type: integer format: int64 bytes: type: integer format: int64 StoredNar: type: object required: - store_path - created properties: store_path: type: string created: type: boolean SubscribeCacheRequest: type: object properties: mode: oneOf: - $ref: '#/components/schemas/CacheSubscriptionMode' - type: 'null' SubscriptionRequestItem: type: object required: - project - project_display_name - mode - requested_by - created_at properties: project: type: string project_display_name: type: string mode: $ref: '#/components/schemas/CacheSubscriptionMode' requested_by: type: string created_at: type: string format: date-time SubscriptionStatus: type: string enum: - active - pending SupervisedLoop: type: object required: - name - restarts - pass_errors - pass_timeouts properties: name: type: string restarts: type: integer format: int32 minimum: 0 pass_errors: type: integer format: int64 minimum: 0 pass_timeouts: type: integer format: int64 minimum: 0 last_ok_seconds_ago: type: - number - 'null' format: double last_error: type: - string - 'null' TaskActionDeliveryId: type: string format: uuid TaskActionId: type: string format: uuid TaskDetailsResponse: type: object required: - id - name - display_name - description - repository - wildcard - active - created_at - keep_evaluations - queue - last_evaluations - can_edit - can_trigger - managed properties: id: $ref: '#/components/schemas/TaskId' name: type: string display_name: type: string description: type: string repository: type: string wildcard: type: string active: type: boolean created_at: type: string format: date-time keep_evaluations: type: integer format: int32 last_check_at: type: - string - 'null' format: date-time queue: $ref: '#/components/schemas/QueueSummary' last_evaluations: type: array items: $ref: '#/components/schemas/EvaluationSummary' can_edit: type: boolean can_trigger: type: boolean managed: type: boolean TaskId: type: string format: uuid TaskMetricPoint: type: object required: - evaluation_id - created_at - build_time_total_ms - eval_time_ms - dependencies_count properties: evaluation_id: $ref: '#/components/schemas/EvaluationId' created_at: type: string format: date-time build_time_total_ms: type: integer format: int64 eval_time_ms: type: integer format: int64 output_size_bytes: type: - integer - 'null' format: int64 closure_size_bytes: type: - integer - 'null' format: int64 runtime_closure_size_bytes: type: - integer - 'null' format: int64 dependencies_count: type: integer format: int64 TaskMetricsResponse: type: object required: - keep_evaluations - points properties: keep_evaluations: type: integer format: int32 points: type: array items: $ref: '#/components/schemas/TaskMetricPoint' TaskResponse: type: object required: - id - project - name - active - display_name - description - repository - wildcard - force_evaluation - created_by - created_at - managed - keep_evaluations - concurrency - sign_cache - wait_for_workers - retry_failed_builds - can_edit - can_trigger properties: id: $ref: '#/components/schemas/TaskId' project: $ref: '#/components/schemas/ProjectId' name: type: string active: type: boolean display_name: type: string description: type: string repository: type: string wildcard: type: string last_evaluation: oneOf: - $ref: '#/components/schemas/EvaluationId' - type: 'null' last_evaluation_status: oneOf: - $ref: '#/components/schemas/EvaluationStatus' - type: 'null' force_evaluation: type: boolean created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time managed: type: boolean keep_evaluations: type: integer format: int32 concurrency: $ref: '#/components/schemas/ConcurrencyPolicy' sign_cache: type: boolean wait_for_workers: type: boolean retry_failed_builds: type: boolean can_edit: type: boolean can_trigger: type: boolean TaskRow: type: object required: - project - task - starred - tier - history properties: project: type: string task: type: string starred: type: boolean tier: $ref: '#/components/schemas/Tier' latest: oneOf: - $ref: '#/components/schemas/Latest' - type: 'null' entry_points: oneOf: - $ref: '#/components/schemas/Outcomes' - type: 'null' delta: type: - integer - 'null' format: int64 speed_ms: type: - integer - 'null' format: int64 history: type: array items: $ref: '#/components/schemas/HistoryBar' TaskTriggerId: type: string format: uuid TasksPage: type: object required: - filter - counts - total - tasks properties: filter: $ref: '#/components/schemas/Filter' counts: $ref: '#/components/schemas/Counts' total: type: integer minimum: 0 tasks: type: array items: $ref: '#/components/schemas/TaskRow' TeamCacheGrant: type: object required: - cache - display_name properties: cache: type: string display_name: type: string role: type: - string - 'null' TeamDemand: type: object required: - builds - fetch - eval properties: builds: type: array items: $ref: '#/components/schemas/UnmetRequirement' fetch: type: integer format: int32 minimum: 0 eval: type: integer format: int32 minimum: 0 TeamEvaluation: type: object required: - id - project - task - status - created_at properties: id: $ref: '#/components/schemas/EvaluationId' project: type: string task: type: string status: $ref: '#/components/schemas/EvaluationStatus' created_at: type: string format: date-time TeamGrantEntry: type: object required: - team - display_name - users - workers - pending properties: team: type: string display_name: type: string role: type: - string - 'null' users: type: boolean workers: type: boolean pending: type: boolean TeamGrants: type: object required: - projects - caches properties: projects: type: array items: $ref: '#/components/schemas/TeamProjectGrant' caches: type: array items: $ref: '#/components/schemas/TeamCacheGrant' TeamId: type: string format: uuid TeamMemberItem: type: object required: - user - name - role - source properties: user: type: string name: type: string role: $ref: '#/components/schemas/TeamRole' source: $ref: '#/components/schemas/TeamMemberSource' TeamMemberRequest: type: object required: - user - role properties: user: type: string role: $ref: '#/components/schemas/TeamRole' TeamMemberSource: type: string enum: - api - state - group TeamProjectGrant: type: object required: - project - display_name - users - workers properties: project: type: string display_name: type: string role: type: - string - 'null' users: type: boolean workers: type: boolean TeamRequestItem: type: object required: - id - kind - target - display_name - users - workers - created_at properties: id: type: string format: uuid kind: $ref: '#/components/schemas/RequestKind' target: type: string display_name: type: string role: type: - string - 'null' users: type: boolean workers: type: boolean requested_by: type: - string - 'null' created_at: type: string format: date-time TeamResponse: type: object required: - id - name - display_name - managed - new_project_users - new_project_workers properties: id: $ref: '#/components/schemas/TeamId' name: type: string display_name: type: string managed: type: boolean role: oneOf: - $ref: '#/components/schemas/TeamRole' - type: 'null' oidc_group: type: - string - 'null' scim_group: type: - string - 'null' new_project_users: type: boolean new_project_workers: type: boolean new_project_role: type: - string - 'null' TeamRole: type: string enum: - admin - member TeamSummary: type: object required: - name - display_name - role properties: name: type: string display_name: type: string role: $ref: '#/components/schemas/TeamRole' TeamWorkerEntry: allOf: - $ref: '#/components/schemas/WorkerConnection' - type: object required: - worker_id - display_name - registered_at - active - managed - gradient_ci - enable_fetch - enable_eval - enable_build properties: worker_id: type: string display_name: type: string registered_at: type: string format: date-time active: type: boolean managed: type: boolean url: type: - string - 'null' gradient_ci: type: boolean enable_fetch: type: boolean enable_eval: type: boolean enable_build: type: boolean live: oneOf: - $ref: '#/components/schemas/WorkerLiveInfo' - type: 'null' Tier: type: string enum: - starred_active - active - starred - team - member TopProjectBuildTime: type: object required: - project - project_name - project_display_name - total_build_ms - build_count properties: project: type: string format: uuid project_name: type: string project_display_name: type: string total_build_ms: type: integer format: int64 build_count: type: integer format: int64 TransferOwnershipRequest: type: object required: - project properties: project: type: string TriggerConfig: oneOf: - type: object required: - interval_secs - type properties: interval_secs: type: integer format: int32 minimum: 0 branch: type: - string - 'null' type: type: string enum: - polling - type: object required: - integration_id - type properties: integration_id: $ref: '#/components/schemas/IntegrationId' branches: type: array items: type: string tags: type: array items: type: string releases_only: type: boolean type: type: string enum: - reporter_push - type: object required: - integration_id - type properties: integration_id: $ref: '#/components/schemas/IntegrationId' branches: type: array items: type: string actions: type: array items: type: string require_approval: type: boolean type: type: string enum: - reporter_pull_request - type: object required: - cron - type properties: cron: type: string type: type: string enum: - time TriggerIntegrationSummary: type: object required: - id - name - display_name - git_host_type properties: id: $ref: '#/components/schemas/IntegrationId' name: type: string display_name: type: string git_host_type: type: string TriggerOut: type: object required: - id - task - type - config - active - created_at - updated_at properties: id: $ref: '#/components/schemas/TaskTriggerId' task: $ref: '#/components/schemas/TaskId' type: $ref: '#/components/schemas/TriggerType' config: {} active: type: boolean last_fired_at: type: - string - 'null' format: date-time created_at: type: string format: date-time updated_at: type: string format: date-time integration: oneOf: - $ref: '#/components/schemas/TriggerIntegrationSummary' - type: 'null' TriggerType: type: string enum: - polling - reporter_push - reporter_pull_request - time UnmetRequirement: type: object required: - architecture - required_features - build_count properties: architecture: type: string required_features: type: array items: type: string build_count: type: integer format: int32 minimum: 0 UpdateActionRequest: type: object properties: name: type: - string - 'null' config: oneOf: - $ref: '#/components/schemas/ActionConfig' - type: 'null' events: type: - array - 'null' items: type: string active: type: - boolean - 'null' UpdateFlakeInputOverrideRequest: type: object properties: input_name: type: - string - 'null' url: type: - string - 'null' UpdateTriggerRequest: type: object properties: config: oneOf: - $ref: '#/components/schemas/TriggerConfig' - type: 'null' active: type: - boolean - 'null' UpdateWebhookRequest: type: object properties: name: type: - string - 'null' url: type: - string - 'null' events: type: - array - 'null' items: type: string active: type: - boolean - 'null' UploadSessionId: type: string format: uuid UpstreamCacheItem: type: object required: - id - display_name - mode - kind - http1_only - active properties: id: $ref: '#/components/schemas/CacheUpstreamId' display_name: type: string mode: $ref: '#/components/schemas/CacheSubscriptionMode' upstream_cache_id: oneOf: - $ref: '#/components/schemas/CacheId' - type: 'null' url: type: - string - 'null' public_key: type: - string - 'null' kind: type: string remote_cache: type: - string - 'null' http1_only: type: boolean active: type: boolean UpstreamTestResponse: type: object required: - ok - http1 - http2 - message properties: ok: type: boolean http1: $ref: '#/components/schemas/ProtocolProbe' http2: $ref: '#/components/schemas/ProtocolProbe' message: type: string UrlRequest: type: object required: - project - url properties: project: type: string url: type: string ref: type: - string - 'null' rev: type: - string - 'null' target: type: - string - 'null' input_overrides: type: array items: $ref: '#/components/schemas/InputOverrideBody' UserId: type: string format: uuid UserInfoResponse: type: object required: - id - username - name - email - superuser properties: id: type: string username: type: string name: type: string email: type: string superuser: type: boolean UserRequest: type: object required: - userName properties: userName: type: string externalId: type: - string - 'null' name: oneOf: - $ref: '#/components/schemas/NameRequest' - type: 'null' displayName: type: - string - 'null' emails: type: array items: $ref: '#/components/schemas/EmailResource' active: type: boolean UserResource: type: object required: - schemas - id - userName - name - displayName - emails - active - meta properties: schemas: type: array items: type: string id: type: string userName: type: string externalId: type: - string - 'null' name: $ref: '#/components/schemas/NameResource' displayName: type: string emails: type: array items: $ref: '#/components/schemas/EmailResource' active: type: boolean meta: $ref: '#/components/schemas/Meta' UserSearchResult: type: object required: - id - username - name properties: id: type: string username: type: string name: type: string UserSshKeyId: type: string format: uuid Value: {} VerifyGate: type: string enum: - none - eval - build WaitingReason: oneOf: - type: object required: - unmet - connected_workers - available_architectures - kind properties: unmet: type: array items: $ref: '#/components/schemas/UnmetRequirement' connected_workers: type: integer format: int32 minimum: 0 available_architectures: type: array items: type: string kind: type: string enum: - workers - type: object description: |- `connected_workers` is the whole connected pool. It can be above zero while only build-only workers are online and an eval or fetch worker is missing. required: - capability - connected_workers - kind properties: capability: $ref: '#/components/schemas/EvalCapability' connected_workers: type: integer format: int32 minimum: 0 kind: type: string enum: - eval_workers - type: object required: - pr_number - pr_author - kind properties: pr_number: type: integer format: int64 minimum: 0 pr_author: type: string kind: type: string enum: - approval - type: object required: - kind properties: kind: type: string enum: - no_cache - type: object required: - kind properties: kind: type: string enum: - cache_storage_full - type: object required: - kind properties: kind: type: string enum: - draining - type: object required: - pending_shared_builds - kind properties: pending_shared_builds: type: integer format: int32 minimum: 0 kind: type: string enum: - graph_stuck WalkMode: type: string enum: - pruned - full WebhookDeliveryId: type: string format: uuid WebhookId: type: string format: uuid WebhookResponse: type: object required: - id - scope - name - url - events - active - created_by - created_at - updated_at properties: id: $ref: '#/components/schemas/WebhookId' scope: $ref: '#/components/schemas/WebhookScope' name: type: string url: type: string events: type: array items: type: string active: type: boolean last_fired_at: type: - string - 'null' format: date-time created_by: $ref: '#/components/schemas/UserId' created_at: type: string format: date-time updated_at: type: string format: date-time WebhookScope: type: string enum: - project - cache - instance - team WorkerConnection: type: object required: - connected properties: connected: type: boolean last_error: oneOf: - $ref: '#/components/schemas/ConnectionFailure' - type: 'null' WorkerConnectionEntry: type: object required: - connected_at properties: connected_at: type: string format: date-time disconnected_at: type: - string - 'null' format: date-time WorkerInfo: type: object required: - id - capabilities - architectures - system_features - max_concurrent_builds - assigned_job_count - draining properties: id: type: string capabilities: $ref: '#/components/schemas/GradientCapabilities' architectures: type: array items: type: string system_features: type: array items: type: string max_concurrent_builds: type: integer format: int32 minimum: 0 assigned_job_count: type: integer minimum: 0 draining: type: boolean authorized_peers: type: - array - 'null' items: $ref: '#/components/schemas/ProjectId' uniqueItems: true WorkerLiveInfo: type: object required: - capabilities - architectures - system_features - max_concurrent_builds - assigned_job_count - draining properties: capabilities: $ref: '#/components/schemas/GradientCapabilities' architectures: type: array items: type: string system_features: type: array items: type: string max_concurrent_builds: type: integer format: int32 minimum: 0 assigned_job_count: type: integer minimum: 0 draining: type: boolean ram_total_mb: type: - integer - 'null' format: int64 minimum: 0 WorkerLoad: type: object required: - by_capability - by_architecture - by_feature properties: by_capability: type: array items: $ref: '#/components/schemas/LoadBucket' by_architecture: type: array items: $ref: '#/components/schemas/LoadBucket' by_feature: type: array items: $ref: '#/components/schemas/LoadBucket' WorkerMetricsResponse: type: object required: - worker_id - display_name - samples - connections - jobs_dispatched properties: worker_id: type: string display_name: type: string samples: type: array items: $ref: '#/components/schemas/WorkerSamplePoint' connections: type: array items: $ref: '#/components/schemas/WorkerConnectionEntry' jobs_dispatched: type: integer format: int64 minimum: 0 WorkerNet: type: object properties: worker_id: type: - string - 'null' worker_name: type: - string - 'null' upload_speed_mbps: type: - number - 'null' format: float download_speed_mbps: type: - number - 'null' format: float disk_speed_mbps: type: - number - 'null' format: float WorkerSamplePoint: type: object required: - at - assigned_jobs - max_concurrent_builds - state properties: at: type: string format: date-time cpu_usage_pct: type: - number - 'null' format: float ram_free_mb: type: - integer - 'null' format: int64 ram_total_mb: type: - integer - 'null' format: int64 disk_speed_mbps: type: - number - 'null' format: float upload_speed_mbps: type: - number - 'null' format: float download_speed_mbps: type: - number - 'null' format: float assigned_jobs: type: integer format: int32 max_concurrent_builds: type: integer format: int32 state: type: integer format: int32 WorkerTestResponse: type: object required: - ok - connected - authorized_for_project - message properties: ok: type: boolean connected: type: boolean authorized_for_project: type: boolean message: type: string responses: Error: description: Refused or failed request, with the reason in `code` and `message` content: application/json: schema: $ref: '#/components/schemas/ErrorResponseBody' securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT description: |- JWT obtained from `/auth/basic/login`, or an API key prefixed with `GRAD` (e.g. `Bearer GRADabcdef...`). cacheBasic: type: http scheme: basic description: Any username; a JWT or an API key as the password. Private caches only. metricsAuth: type: http scheme: bearer description: |- Operator-configured bearer token loaded from `GRADIENT_METRICS_TOKEN_FILE`. Independent of user authentication. scimBearer: type: http scheme: bearer description: |- Operator-configured SCIM provisioning token loaded from `GRADIENT_SCIM_TOKEN_FILE`. Presented by the IdP (Okta/Entra) on every `/scim/v2` request. Independent of user authentication. tags: - name: general description: Health check and server configuration - name: board description: Job Board - metric queries, live assigned jobs, workers, scoring, and expensive builds - name: webhooks description: Project, cache and instance webhooks for durable events - name: auth description: Authentication - login, register, OAuth/OIDC - name: user description: Current user profile, API keys, and settings - name: dashboard description: Personal dashboard - the viewer's task table, stat tiles and activity heatmap - name: projects description: Project management, members, SSH keys, cache subscriptions - name: teams description: Teams, their members, workers, grants and requests - name: tasks description: Task management and evaluation triggers - name: triggers description: Per-task evaluation triggers (polling, reporter_push, reporter_pull_request, time) - name: flake-inputs description: Per-task flake input URL overrides applied during evaluation fetch. - name: evals description: Evaluation details, status, and log streaming - name: builds description: Build details, logs, artefact downloads, and dependency graph - name: build-requests description: Ad-hoc build requests from `gradient build` - CLI-uploaded source evaluated under a per-project build-request task. Flake inputs served over `git+ssh://` are fetched using the project's SSH key, and `input_overrides` can override remote flake inputs for the run. - name: workers description: Worker registration and live status (proto workers connected via WebSocket) - name: caches description: Binary cache management - name: nix-cache description: Nix binary cache protocol, served at the server root - name: commits description: Commit records - name: actions description: Per-task Actions (Send Mail, Send Web Request, Git Host Status Report) - name: git-host-webhooks description: Incoming Git host webhooks (external Git hosts -> Gradient push triggers) - name: integrations description: Per-project named Git host integrations (inbound HMAC secrets + outbound API credentials) - name: admin description: Server-wide administrative endpoints. All routes require the caller to have the `superuser` flag. - name: scim description: SCIM 2.0 instance-level provisioning (Users + Groups), bearer-token authenticated, mounted at `/scim/v2` only when SCIM is enabled.