Docs /api-reference/webhook-endpoints

Webhook Endpoints Reference

GitHub webhook integration for automated test triggering.


Incoming Webhook: POST /api/webhooks/github/:projectId

The raw HTTP endpoint that receives GitHub push events. Registered in apps/api (Hono route).

Authentication: HMAC-SHA256 signature (GitHub webhook secret)

Headers:

Header Description
X-Hub-Signature-256 sha256=<hmac> computed with your webhook secret
X-GitHub-Event Event type: push, pull_request, etc.
X-GitHub-Delivery Unique delivery ID

Supported events: push, pull_request

Response:

  • 200 — Event received and queued
  • 400 — Missing or invalid signature
  • 404 — Project not found or webhook not configured
  • 429 — Rate limit exceeded (30 req/min per IP)

tRPC Webhook Procedures

All procedures require authentication.

webhooks.configure

Create or replace webhook configuration for a project. Returns the webhook URL and generated secret — the secret is only shown once.

Input:

{
  projectId: string        // ULID
  branches: string[]       // Empty = all branches
  filePatterns: string[]   // Glob patterns, empty = any file
}

Response:

{
  configId: string
  secret: string  // Store this — it won't be shown again
}

Rate limit: 30 req/min (webhook rate limiter)


webhooks.getConfig

Get webhook configuration (without exposing the secret).

Input: { projectId: string }

Response:

{
  configId: string
  active: boolean
  branches: string[]
  filePatterns: string[]
  createdAt: Date
  updatedAt: Date
} | null

webhooks.setActive

Enable or disable webhook delivery for a project.

Input: { projectId: string, active: boolean }

Response: { active: boolean }


webhooks.rotateSecret

Generate a new webhook secret without changing other settings. Returns the new secret — update your GitHub webhook configuration immediately.

Input: { projectId: string }

Response: { secret: string }


webhooks.listEvents

List recent webhook event deliveries.

Input:

{
  projectId: string
  limit?: number  // 1-100, default 20
  status?: 'PENDING' | 'PROCESSED' | 'FAILED' | 'SKIPPED' | 'ABANDONED'
}

Response:

{
  events: Array<{
    id: string
    deliveryId: string
    eventType: string
    status: string
    attempts: number
    error: string | null
    createdAt: Date
    processedAt: Date | null
    nextRetryAt: Date | null
  }>
}

webhooks.delete

Delete webhook configuration for a project.

Input: { projectId: string }

Response: { deleted: true }


Webhook Signature Verification

GitHub signs each delivery using HMAC-SHA256 with your webhook secret. The platform verifies this using a timing-safe comparison:

X-Hub-Signature-256: sha256=<hex>
  • Uses crypto.subtle (Web Crypto API) for constant-time comparison
  • Mismatched or missing signatures return 400

Trigger Conditions

When a webhook event arrives, the trigger service evaluates:

  1. Branch filter — if branches is non-empty, the push must target a listed branch
  2. File pattern filter — if filePatterns is non-empty, at least one changed file must match a glob pattern
  3. Deduplication — if a test run already exists for the same projectId + commitSha + eventType within the last hour, the event is skipped
  4. Debouncing — rapid pushes to the same branch are coalesced (configurable debounceMs)

Reading this with an agent? /docs/api-reference/webhook-endpoints.md serves the raw markdown.

All docs