Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools →
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/buildpulse-io:buildpulse-io-auth-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: BuildPulse Platform Auth API
version: 1.0.0
summary: Public REST API for BuildPulse CI analytics.
termsOfService: https://buildpulse.io/terms
description: 'The BuildPulse Platform API exposes read-only test analytics for any
repository onboarded to BuildPulse: paginated test submissions,
disruptive/flaky test inventory, per-test disruption history, and SVG
badges for flakiness and coverage. This API is the drop-in replacement for the legacy Rails API at
`https://buildpulse.io/api`. Endpoint paths, query parameters, and
response JSON shapes are intentionally identical so existing
integrations migrate by changing only the base URL. ## Base URLs
- Production: `https://platform.buildpulse.io`
- Development: `https://platform.dev.buildpulse.io`
## Authentication
All endpoints except `/health` require an API token in the
`Authorization` header. Both `token ` and `Bearer `
prefixes are accepted. Two token shapes are accepted:
- **New** (`bp_`) — minted by the BuildPulse web app under
Organization Settings → API Tokens. SHA256-hashed (lowercase hex)
and stored in `apiTokens` as
`{ type: "api_token", tokenPrefix, tokenHash, expiresAt }`. Plan-gated: the organization needs an active plan that includes
API access (Team, Growth, custom, or a paid legacy Marketplace
plan; the 14-day trial counts). The same gate applies to the
hosted MCP''s `mcpSessions`. - **Legacy** (``) — Rails-era format, stored as
`{ hashedToken: base64(SHA256(token)) }`. Gated against
`marketplacePurchases.unitCount > 0` for parity with the legacy
API. Production currently holds zero of these; the path is
retained for any future migrated tokens. The plaintext token is shown only once at creation time. Example values (do not use):
```
Authorization: Bearer bp_14f56e0c2a8b4d1f9e6a3c7b8d2e5f1a0b9c4d7e6f3a2b1c0d9e8f7a6b5c4d3e
Authorization: token a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0
```
## Response shapes
JSON timestamps are ISO 8601 with second precision in UTC
(e.g. `2026-05-17T12:34:56Z`). List endpoints always return an array
for the data field, never `null`. Empty results return `[]`. ## Errors
| Status | Body |
|--------|------|
| 401 | empty |
| 404 | `{"message":"Not Found"}` |
| 400 | `{"errors":{"after":[""]}}` |
| 500 | empty |
The empty-body 401/500 contract matches the legacy Rails behavior
(`render body: nil`) and is preserved deliberately. ## Pagination
Two cursor styles are in use, both base64-encoded so consumers should
treat them as opaque:
- **Keyset (submissions only)** — cursor is `base64("id:")`. Stable under inserts. - **Offset (tests, flaky tests)** — cursor is `base64("offset:")`. The next-page cursor is returned as `metadata.after`. When there is
no next page, `metadata.after` is `null`. ## Reporting window
Time-bounded endpoints use a rolling window ending now. Which window
depends on the endpoint:
| Endpoint | Window |
|---|---|
| `GET /api/v1/flaky/tests?quarantine=false` | Your plan''s reporting period (default 14 days) |
| `GET /api/tests/{id}/results` | Your plan''s reporting period (default 14 days) |
| `GET /api/v1/flaky/tests` (quarantined view, the default) | Not windowed — every quarantined test is returned |
| `GET /api/repos/{owner}/{name}/tests` | Not windowed — every test with a disruptiveness ratio above 0 |
| `GET /api/repos/{owner}/{name}/submissions` | Fixed 14 days |
| `GET /api/v1/flaky/badges` | Fixed 14 days |
The plan''s reporting period is resolved per organization from its
active plan, so it follows plan changes automatically; there is no
request parameter to override it. Organizations without a resolvable
plan get the 14-day default. Don''t hardcode a window client-side —
treat the returned rows as the source of truth. ## For AI agents (MCP)
The BuildPulse MCP server exposes this API as nine read-only tools
for Claude, ChatGPT, Cursor, VS Code, and any Model Context
Protocol client. Hosted: `https://mcp.buildpulse.io/mcp`
(Streamable HTTP, OAuth sign-in with your BuildPulse account). Stdio: `npx -y @buildpulse/mcp` with `BUILDPULSE_TOKEN` set to an
API token. Setup and tool list:
https://platform.buildpulse.io/docs/mcp.'
license:
name: Proprietary
url: https://buildpulse.io/terms
contact:
name: BuildPulse Support
email: support@buildpulse.io
url: https://buildpulse.io
servers:
- url: https://platform.buildpulse.io
description: Production
- url: https://platform.dev.buildpulse.io
description: Development
security:
- TokenAuth: []
- BearerAuth: []
tags:
- name: Auth
description: 'Token validation and caller identity. Send an API token as
`Authorization: Bearer bp_` (or `Authorization: token …`).
Tokens are created under Organization Settings → API Tokens and
shown once; they are bound to one organization and require a
plan with API access. Hosted-MCP OAuth sessions use the same
endpoints and may span several organizations, selected with
`?organization_id=`. This tag also covers the account-scoped
reads: the organizations and repositories the caller can see,
and the organization''s current usage against its plan.'
paths:
/api:
get:
operationId: validateToken
tags:
- Auth
summary: Validate an API token
description: 'Returns `204 No Content` when the supplied token resolves to an
organization. Use this as a cheap sanity check before issuing
other calls.
Accepts both token shapes (`bp_` and legacy ``).
The legacy 40-hex path additionally requires
`marketplacePurchases.unitCount > 0`; the new `bp_` path treats
issuance as the entitlement check and skips the plan gate.'
responses:
'204':
description: Token is valid (and for legacy 40-hex tokens, the organization has an active plan).
'401':
$ref: '#/components/responses/Unauthorized'
x-codeSamples:
- lang: shell
label: curl
source: "curl -i -H \"Authorization: token $BUILDPULSE_TOKEN\" \\\n https://platform.buildpulse.io/api\n"
- lang: javascript
label: Node
source: "const res = await fetch(\"https://platform.buildpulse.io/api\", {\n headers: { Authorization: `token ${process.env.BUILDPULSE_TOKEN}` }\n});\nconsole.log(res.status); // 204\n"
- lang: python
label: Python
source: "import os, requests\nr = requests.get(\n \"https://platform.buildpulse.io/api\",\n headers={\"Authorization\": f\"token {os.environ['BUILDPULSE_TOKEN']}\"}\n)\nprint(r.status_code) # 204\n"
/api/me/organizations:
get:
operationId: listMyOrganizations
tags:
- Auth
summary: List organizations accessible to the current token
description: 'Returns the set of organizations the calling token may scope
requests to.
For long-lived **apiToken** callers (single-org by
construction), the list always has one element — the org the
token was generated under.
For ephemeral **mcpSession** callers (OAuth-minted from the
hosted MCP), the list contains every org the authenticated
Cognito user has a membership in. The agent should call this
endpoint to enumerate the user''s orgs, then pass the chosen
`id` back as `?organization_id=` on subsequent
org-scoped requests.'
responses:
'200':
description: Caller's accessible organizations.
content:
application/json:
schema:
type: object
required:
- organizations
properties:
organizations:
type: array
items:
type: object
required:
- id
- name
properties:
id:
type: string
description: 'Organization UUID (the value of the
`id` field on the organization document
— NOT the internal `_id` ObjectID).
Pass this as `?organization_id=…` on
subsequent requests.
'
name:
type: string
slug:
type: string
example:
organizations:
- id: 544f50de-5a15-4506-bb79-f00fb29e7317
name: Acme Inc.
slug: acme
- id: 8e3d2c1b-9a07-4f24-b1e3-3a8c2cdda8e1
name: Acme Spinoff
slug: acme-spinoff
'401':
$ref: '#/components/responses/Unauthorized'
x-codeSamples:
- lang: shell
label: curl
source: "curl -H \"Authorization: Bearer $BUILDPULSE_TOKEN\" \\\n https://platform.buildpulse.io/api/me/organizations\n"
/api/me/repositories:
get:
operationId: listMyRepositories
tags:
- Auth
summary: List repositories the current organization can see
description: 'Returns the repositories scoped to the caller''s current
organization (resolved by the auth middleware from the token
and, for multi-org mcpSession callers, the
`?organization_id=` query parameter).
Used by the MCP server''s `list_repositories` tool so the
model can disambiguate "do I have flaky tests?" without the
user having to remember repo names.'
responses:
'200':
description: Caller's accessible repositories.
content:
application/json:
schema:
type: object
required:
- repositories
properties:
repositories:
type: array
items:
type: object
required:
- id
- name
- full_name
- url
properties:
id:
type: string
description: Repository UUID.
name:
type: string
full_name:
type: string
description: '`owner/name`.'
url:
type: string
description:
type: string
example:
repositories:
- id: 16a071e9-4e58-4f7d-99f2-d1a965fe91da
name: web-client
full_name: BuildPulseLLC/web-client
url: https://github.com/BuildPulseLLC/web-client
description: BuildPulse web app.
'401':
$ref: '#/components/responses/Unauthorized'
x-codeSamples:
- lang: shell
label: curl
source: "curl -H \"Authorization: Bearer $BUILDPULSE_TOKEN\" \\\n https://platform.buildpulse.io/api/me/repositories\n"
/api/v1/usage:
get:
operationId: getUsage
tags:
- Auth
summary: Current test-result usage for the organization
description: 'Returns the calling organization''s test-result usage for the
current UTC calendar month, measured against its plan limit.
This is the read-only entitlement contract consumed by the
web-client and the MCP server. It is **always open** — it is
never subject to overage read-enforcement and never returns
`402`, so a restricted organization can still discover why its
data reads are gated.
`status` is the staged-overage stage (the same derivation every
surface uses — derived from the canonical fields the ingestion
lambda stamps on the organization):
- `within` — under the limit, or not on an enforced plan
(legacy / free / unlimited orgs always report `within`).
- `notify` — over the limit, days 0–2 (or in trial): full data
access plus a banner. Not restricted.
- `soft` — over the limit, days 3–13: data-read endpoints return
`402 plan_limit_exceeded`. Ingestion is unaffected.
- `hard` — over the limit, day 14+: data-read endpoints return
`402` AND ingestion is paused (raw retained ~30 days).
Only `soft` and `hard` gate reads; `within` and `notify` keep full
access. `limit` is `0` for organizations with no enforced monthly
limit.'
responses:
'200':
description: Current usage snapshot.
content:
application/json:
schema:
type: object
required:
- usage
- limit
- status
- periodStart
properties:
usage:
type: integer
description: Test results recorded this UTC month.
limit:
type: integer
description: Monthly test-result limit (0 = unlimited / not enforced).
status:
type: string
enum:
- within
- notify
- soft
- hard
periodStart:
type: string
format: date-time
description: Start of the current UTC calendar month (RFC3339).
example:
usage: 1240000
limit: 3000000
status: within
periodStart: '2026-06-01T00:00:00Z'
'401':
$ref: '#/components/responses/Unauthorized'
x-codeSamples:
- lang: shell
label: curl
source: "curl -H \"Authorization: Bearer $BUILDPULSE_TOKEN\" \\\n https://platform.buildpulse.io/api/v1/usage\n"
components:
responses:
Unauthorized:
description: 'Missing, malformed, or invalid token; or — for legacy 40-hex
tokens only — the organization has no active plan
(`marketplacePurchases.unitCount > 0`). The new `bp_<64-hex>`
path has no plan gate, so a 401 there means the token shape
was wrong, the hash didn''t match, or the token has expired.
Response body is empty (matches legacy Rails).
'
securitySchemes:
TokenAuth:
type: apiKey
in: header
name: Authorization
description: "Send `Authorization: token <token>`. Two token shapes are\naccepted:\n\n- **New** (`bp_<64-hex>`) — minted by the refactored web-client\n today (`web-client/src/app/_services/apiTokens.ts`). Stored as\n `{ type: \"api_token\", tokenPrefix, tokenHash (hex SHA256),\n expiresAt }`. No active-plan gate; issuance is the\n entitlement check.\n- **Legacy** (`<40-hex>`) — Rails-era format, stored as\n `{ hashedToken: base64(SHA256(token)) }`. Plan-gated against\n `marketplacePurchases.unitCount > 0`. Retained for any future\n migrated tokens.\n\nThe legacy API only accepted `token`, so existing integrations\nneed no changes.\n"
BearerAuth:
type: http
scheme: bearer
bearerFormat: bp_<64-hex> or <40-hex>
description: 'Send `Authorization: Bearer <token>`. Functionally identical to
`TokenAuth`; both header forms are accepted. Same two token
shapes apply — see `TokenAuth` for the format and plan-gate
details.
'
externalDocs:
description: BuildPulse docs, MCP server and guides
url: https://platform.buildpulse.io/docs/mcp