Skip to main content
Rather than polling, you can register a webhook endpoint to be notified when a review reaches a terminal state.

Events

EventFired when
review.completedThe review finished and its report is available.
review.failedThe review could not be completed.

Payload

{
  "event": "review.completed",
  "review_id": "9b1f....",
  "reference_id": "LN-2026-0042",
  "status": "completed",
  "occurred_at": "2026-05-30T18:09:12Z"
}
The payload intentionally carries only identifiers and status; fetch GET /reviews/{review_id}/report to retrieve the result over an authenticated channel.

Verifying signatures

Each delivery is signed so you can verify it came from Flightline. The signature is sent in the X-Flightline-Signature header as t=<timestamp>,v1=<hex-hmac>, where the HMAC is HMAC_SHA256(secret, "<t>.<raw-body>") using the signing secret shown when you register the endpoint.
import hashlib, hmac

def verify(raw_body: bytes, header: str, secret: str) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    signed = f"{parts['t']}.{raw_body.decode()}".encode()
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts["v1"])
Reject any delivery whose signature does not verify, or whose timestamp is older than a few minutes.

Managing endpoints

Register, list, and delete your webhook endpoints with your organization API key (Authorization: Bearer <key>), the same key you use for every other /v1 call.
MethodPathPurpose
POST/v1/webhook-endpointsRegister an endpoint; returns the signing secret once.
GET/v1/webhook-endpointsList your registered endpoints.
DELETE/v1/webhook-endpoints/{id}Delete an endpoint.

Register

curl -X POST https://api.flightlinehq.com/v1/webhook-endpoints \
  -H "Authorization: Bearer $FLIGHTLINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/hooks/flightline", "description": "prod"}'
{
  "id": "5f0c....",
  "url": "https://example.com/hooks/flightline",
  "enabled": true,
  "description": "prod",
  "secret_hint": "whsec_…a1b2",
  "created_at": "2026-05-30T18:09:12Z",
  "signing_secret": "whsec_3f9c...store-this-now"
}
The signing_secret is returned only in this registration response. Store it immediately; it cannot be retrieved again. List and delete responses return only a non-reversible secret_hint, never the secret itself.
The endpoint URL must be HTTPS and resolve to a public host. URLs pointing at internal, private, loopback, link-local, or cloud-metadata addresses are rejected with a 400.

List

curl https://api.flightlinehq.com/v1/webhook-endpoints \
  -H "Authorization: Bearer $FLIGHTLINE_API_KEY"
{
  "endpoints": [
    {
      "id": "5f0c....",
      "url": "https://example.com/hooks/flightline",
      "enabled": true,
      "description": "prod",
      "secret_hint": "whsec_…a1b2",
      "created_at": "2026-05-30T18:09:12Z"
    }
  ]
}

Delete

curl -X DELETE https://api.flightlinehq.com/v1/webhook-endpoints/5f0c... \
  -H "Authorization: Bearer $FLIGHTLINE_API_KEY"
Returns 204 No Content. Endpoints are scoped to your organization; an id that belongs to another organization returns 404.

Delivery, retries, and security

  • Transport: POST with a JSON body to your registered https URL. Endpoints must be https; internal/private hosts are rejected at registration.
  • Retries: up to 3 attempts with exponential backoff (~0.5s, 1s) on a non-2xx response or transport error. Return a 2xx quickly (within ~10s) to acknowledge; we time out a slow endpoint and retry.
  • Best-effort: webhooks are a convenience, not the source of truth. If every attempt fails, the review state is unchanged; always treat GET /reviews/{review_id} / …/report as authoritative, and reconcile on a schedule as a backstop.
  • Verify the signature (see above) on every delivery. Reject any delivery whose signature doesn’t verify, or whose t timestamp is more than 5 minutes old, to prevent replay.
  • Idempotency: a delivery may arrive more than once. De-duplicate on (review_id, event); processing should be idempotent.
  • Source: deliveries originate from Flightline’s infrastructure without a fixed source-IP range; authenticate them by verifying the signature, not by IP allowlisting.