BuildPulse Webhooks API

GitHub App webhook ingress (HMAC-verified; not a customer-callable endpoint).

Operations 1

POST /webhooks/github GitHub App webhook ingress #

Work with this as data

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-webhooks-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 Specification

buildpulse-io-webhooks-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: BuildPulse Platform Webhooks 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: Webhooks
  description: GitHub App webhook ingress (HMAC-verified; not a customer-callable endpoint).
paths:
  /webhooks/github:
    post:
      operationId: githubWebhook
      tags:
      - Webhooks
      summary: GitHub App webhook ingress
      description: 'Receives GitHub App webhook deliveries. Authenticated by HMAC

        signature (`X-Hub-Signature-256`) against the App''s webhook secret,

        not by API token. Verified deliveries are published to the internal

        github-events fan-out topic with `{event, action}` attributes;

        downstream consumers (runner capacity scaling, and future issue /

        installation processors) subscribe with filter policies.


        Not a customer-facing endpoint — it exists for GitHub''s webhook

        delivery system only.'
      security: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: Raw GitHub webhook payload (shape varies by event type).
      responses:
        '200':
          description: Delivery verified and published (or ping acknowledged).
          content:
            application/json:
              schema:
                type: object
        '400':
          description: Missing event header or unreadable body.
        '401':
          description: Signature verification failed.
        '500':
          description: Publish failed; GitHub will redeliver.
        '503':
          description: Ingress not configured in this environment.
components:
  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