Buildkite API
Do not treat REST as read-only and GraphQL as the write API. Default to REST for builds, pipelines, organization administration, hosted resources, diagnostics, and notification-service writes. Use GraphQL when typed nested reads avoid several requests or for GraphQL-only mutations.
To execute API calls interactively from the terminal, see the
buildkite-cli skill for
commands. With the Buildkite MCP server, prefer purpose-built tools for supported reads and actions.
Quick Start
List lightweight build records with REST:
bash
curl -sS -H "Authorization: Bearer $BUILDKITE_API_TOKEN" \
"https://api.buildkite.com/v2/organizations/my-org/pipelines/my-pipeline/builds?exclude_jobs=true&exclude_pipeline=true&per_page=5" \
| jq '.[] | {number, state, branch}'
Query selected nested fields with GraphQL:
bash
curl -sS -X POST "https://graphql.buildkite.com/v1" \
-H "Authorization: Bearer $BUILDKITE_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ pipeline(slug: \"my-org/my-pipeline\") { builds(first: 5) { edges { node { number state message } } } } }"}' \
| jq '.data.pipeline.builds.edges[].node'
Authentication and access
Pass a personal API access token as a bearer token. Scope tokens to the required organizations and grant the minimum scopes. Treat an HTTP
as potentially meaning either absent or unavailable: several permission-gated and feature-gated resources deliberately do not disclose existence.
bash
curl -sS -H "Authorization: Bearer $BUILDKITE_API_TOKEN" \
"https://api.buildkite.com/v2/organizations"
For short-lived credentials, public-key API access tokens (preview) can authenticate REST API access with an RS256-signed JWT. Set the access token UUID as
, keep
within 10 seconds of the current time, and set
no more than five minutes after
. The JWT inherits the token's organization access and scopes.
Common scopes include:
| Capability | Scopes |
|---|
| Builds, pipelines, and artifacts | /, /, / |
| Job logs, environments, and agents | /, , / |
| Organization members | / |
| Organization settings | read_organization_settings
/write_organization_settings
|
| Audit events | |
| Repository connections and discovery | read_organization_repository_connections
|
| Notification services | read_notification_services
/write_notification_services
|
| Organization invitations | read_organization_invitations
/write_organization_invitations
|
| Teams | / |
| Hosted and cluster resources | / |
Scopes are necessary but not always sufficient. Treat
and permission-gated
responses as access or availability boundaries, not evidence that another payload or endpoint should be tried. Use observable organization state and known caller context when available; otherwise report the required role, permission, or feature and ask an administrator to verify it. See
API token scopes for the full catalogue.
REST API
Use
https://api.buildkite.com/v2
as the base URL and
Content-Type: application/json
for JSON request bodies. Most organization-scoped resources begin with
/organizations/{org.slug}
; user, organization-list, and other top-level resources do not.
For build metadata and status reads, default to
exclude_jobs=true&exclude_pipeline=true
. Fetch jobs from the Jobs API only when job details are required.
Capability map
Use this map to select a resource family, then open the linked reference for exact schemas and response behavior.
| Family | Protocol and access | Scope, permission, or gate | Key boundary and docs |
|---|
| Organization settings | REST read/write | read_organization_settings
/write_organization_settings
; organization admin; field gates | Read before writing; API allowlist changes can lock out the caller. API settings and pipeline settings |
| Audit events | REST read-only | ; organization admin; Enterprise | Cursor-paginated independently of settings. Audit events |
| Members and invitations | REST read/write | /, read_organization_invitations
/write_organization_invitations
; organization admin for member updates and all invitation operations | Member changes only and and cannot target the caller; pending invitations are not memberships. Members and invitations |
| Teams activation | REST enable-only; GraphQL Organization.isTeamsEnabled
state read | ; organization access; ; plan gate when disabled | Idempotent POST /organizations/{org.slug}/teams/enable
; may create Everyone when no teams exist; no REST read or disable route. Teams |
| Repository connections | REST read-only | read_organization_repository_connections
; organization admin; provider support | Connections have no API mutations; unsupported discovery providers return . Connections and discovery |
| Pipeline setup | REST read/write | /; pipeline access | Create validates and mutates together; there is no REST dry run. Pipelines |
| Notification services | REST read/write lifecycle | read_notification_services
/write_notification_services
; organization admin or Manage Notification Services | OAuth Slack Workspace and Linear require initial browser authorization; preserve omitted secrets. Notification services |
| Inbound GitHub processing | REST read/write | /; Full Access; provider and feature gates | Processing controls do not register a repository webhook or configure the GitHub App. Pipelines |
| Build lifecycle | REST read/write | /; pipeline access | Rebuild replays the original context instead of fetching current source-control state. Builds |
| Hosted resources | REST mixed access | /; manage-cluster permission; hosted-agent and resource gates | Cluster read/update exposes hosted Git mirror and container cache settings only to cluster managers; image creation is asynchronous with no update; cache deletion is explicit. Clusters, images, network ranges, and cache volumes |
| Diagnostics | REST read-only | , | Signal and agent lifecycle fields are evidence, not proof that retry is safe. Jobs and agents |
| Artifacts | REST read/write; GraphQL deletion | / for REST; GraphQL API access; Build & Read access or higher on the artifact's pipeline for deletion | Filter before pagination and confirm deletion explicitly. Artifacts |
Pagination
Most REST list responses return arrays and HTTP
headers. Follow the URL marked
rather than constructing page numbers. Keep query filters on the initial request and use the server-provided next URL thereafter.
The Jobs API, invitations, notification services, and audit events use cursor-oriented bodies. Read records from
and follow
until it is
. Audit events also expose a
header. Do not run array-only
filters against these body shapes.
REST requests consume both organization and per-user quotas. On
, stop requests until the matching
or
window expires; do not retry in a tight loop. Remote Buildkite MCP server requests use a separate per-user limit, while local MCP server requests consume the organization REST quota.
Pipeline creation
Default to pipeline YAML in the REST
string. Include
when a cluster has been selected. Omission is valid when the organization allows unclustered pipelines; otherwise the server returns
with
Cluster must be specified
. Do not reject a create client-side solely because
is absent. Use
when the user or organization workflow has selected a template. Send a visual
array only for a known legacy visual-step workflow; no public organization field reliably identifies that mode before creation.
The create request performs server validation and mutation together. Validate YAML locally first when useful, but do not describe local schema validation as proof that repository access, provider setup, permissions, or server-side create constraints will pass. Report a
validation response instead of silently retrying with a different step source.
Organization administration
Read settings before mutation, compare only managed fields, and send the smallest supported update. Preserve unknown or feature-gated fields. For API settings, model an allowlist change as a lockout-sensitive operation: verify the caller's source address, retain a rollback path, and avoid concurrent settings writes.
Treat invitations and memberships as different states. List invitations to reconcile pending requests, use show for any invitation state, and use
only to revoke a pending invitation. Bulk invitation creation supports role, SSO mode, and team assignments, but validates the entire request atomically. A failure creates none of the requested invitations.
Update an existing member with
PATCH /organizations/{org.slug}/members/{user.uuid}
only after reading that membership. The request accepts only
(
or
) and
(
or
), requires
and organization-admin permission, and cannot update the caller's own membership. Send only the fields intended to change; use invitations for people who are not yet members.
Enable Teams only when the requested outcome explicitly requires team-based permissions. Do not use the mutation to probe availability. Read
Organization.isTeamsEnabled
through GraphQL when the current state is needed; when Teams is disabled, explain the plan and permission requirements before enabling it.
Hosted resources
Read a cluster with
before changing hosted cache behavior. For callers with manage-cluster permission, cluster show responses include
hosted_git_mirror_enabled
and
hosted_container_cache_enabled
; callers without that permission do not receive these fields, so do not interpret absence as
. Update either boolean with
PUT /organizations/{org.slug}/clusters/{id}
using
and manage-cluster permission. Changing either value is supported only for hosted clusters; a non-hosted cluster returns
.
Artifact filtering
Apply
and
before pagination on build-level and job-level artifact lists. A path without
is exact; include
only when glob matching is intended. URL-encode paths and state filters rather than filtering a single page locally.
Download by artifact ID with
because the download endpoint redirects. REST deletion requires
; both REST and GraphQL deletion also require
Build & Read access or higher on the artifact's pipeline. REST accepts the artifact UUID at either
/organizations/{org.slug}/jobs/{job.id}/artifacts/{id}
or the fully qualified pipeline/build/job route. The build-level artifact-list route has no corresponding delete operation. GraphQL
accepts the artifact global ID and requires GraphQL API access. Require explicit confirmation for either path, and never turn filtered discovery into an automatic deletion loop.
If the organization uses customer-managed artifact storage, deleting the Buildkite artifact does not remove the underlying object. Do not infer the storage backend or delete external objects automatically; consult the organization's artifact-storage configuration and deletion runbook.
Job and agent diagnostics
Query jobs directly once the build number is known. Prefer server-side
,
, and
filters to fetching every job and filtering locally. A step key matches every job for that step, including parallel jobs; a group key matches every job in that group. Follow each
URL as returned so filters remain applied across cursor pages.
Use
and
to distinguish signal termination from an ordinary nonzero exit. Inspect the embedded agent's
,
,
,
,
,
, and
to correlate platform, routing, and lifecycle timing.
Treat this context as diagnostic evidence, not proof that retry is safe. Before retrying, inspect logs, side effects, retry history, and whether the command is idempotent. A lost agent can explain interruption without establishing that an external deployment or write did not complete.
GraphQL API
Use
https://graphql.buildkite.com/v1
. Prefer GraphQL when a typed query avoids several nested REST reads or when its mutation shape better fits the workflow. GraphQL access tokens use the
Enable GraphQL API Access permission rather than granular REST scopes. Use global node IDs for mutation inputs, not REST UUIDs or pipeline slugs unless the schema explicitly requests them.
| Scenario | Prefer | Reason |
|---|
| Trigger a build | REST | Straightforward body and identifiers |
| Filter builds, jobs, or artifacts | REST | Purpose-built server filters and pagination |
| Read audit events | REST | Dedicated read-only audit endpoint and cursor response |
| Fetch selected nested relationships | GraphQL | Typed field selection can avoid multiple calls |
| Delete an artifact | REST or GraphQL | REST accepts the artifact UUID; accepts a global ID. Apply the same confirmation and storage caveats to both |
| Use another GraphQL-only mutation | GraphQL | Follow the live schema and mutation-specific permissions |
Check both top-level HTTP failures and the GraphQL
array. A
response can still contain operation errors or partial data. See
references/graphql-reference.md
for pagination, global IDs, and artifact deletion.
Webhooks
Separate outbound notifications from inbound source-control processing:
- Create and manage an outbound webhook as a notification service through the organization notification-services REST lifecycle.
- Enable or disable Buildkite processing of inbound GitHub events with the pipeline REST resource.
- Register an SCM webhook for an eligible GitHub App pipeline with
POST /pipelines/{slug}/webhook
; Buildkite then creates the provider-side delivery. This is separate from the processing toggle.
- Configuring an organization GitHub App connection is a separate browser and organization-administration workflow.
For outbound handlers, branch on
or the payload
. Do not assume every event has build, job, pipeline, and sender objects with an identical shape. Acknowledge quickly, process idempotently, and consult the
webhooks reference for the selected event and current authentication fields.
For notification-service lifecycle and inbound GitHub delivery diagnosis, see
.
Common Mistakes
| Mistake | What happens | Fix |
|---|
| Assuming is always required or always optional | Valid unclustered creation is rejected client-side, or clustered-only creation returns | Include a selected cluster; otherwise let the server enforce whether the organization permits unclustered pipelines |
| Creating a REST pipeline without a valid step source | Creation returns | Use YAML , legacy visual , or as applicable; treat create validation as mutating |
| Updating settings without reading first | Feature-gated fields are overwritten or an IP allowlist locks out automation | Read, compare managed fields, and preserve a tested rollback path |
| Treating an invitation as active membership | Automation assumes access before acceptance or provisioning | Track pending invitations separately from members |
| Assuming repository connections have CRUD endpoints | Automation attempts unsupported mutations | Use list/show and repository discovery only |
| Replacing notification secrets because GET omits them | Working credentials are rotated unnecessarily | Account for provider-specific secret response behavior and preserve omitted secrets |
| Confusing outbound notification webhooks with inbound GitHub processing | The wrong endpoint is changed and repository delivery remains broken | Identify notification service, processing toggle, repository registration, and app connection separately |
| Filtering artifacts after reading one page | Matching artifacts on later pages are missed | Apply and on the API request before pagination |
| Retrying solely because signal or agent timing suggests interruption | Non-idempotent external effects may run twice | Inspect logs, side effects, and retry history before retrying |
Additional Resources
Reference Files
references/graphql-reference.md
— GraphQL pagination, global IDs, common queries, and safe artifact deletion
- — Notification-service lifecycle and boundaries between outbound and inbound webhook concepts
- — Copy-paste REST workflows for audit inventory, repository-to-pipeline setup, notification reconciliation, and diagnostics
Further Reading