Skip to main content

Ingest alerts via webhooks

Integrator

Ticketra can receive alerts pushed from a SIEM or other tooling through inbound webhooks. Each webhook source is scoped to a tenant and authenticated with HTTP Basic credentials.

How it works

The receive endpoint is separate from the cookie/JWT-authenticated API: it uses Basic Auth only and is exempt from CSRF (which protects browser sessions, not server-to-server calls).

1. Create a webhook source

  1. Sign in as an ADMIN or SUPER_ADMIN.
  2. Go to Admin → Webhooks (or Integrations → Webhooks).
  3. Create a source: give it a name, select the SIEM type (so Ticketra knows how to parse the payload), and generate credentials.
  4. Note the generated username and secret — the secret is shown once.

2. Point your SIEM at the endpoint

Configure your SIEM to POST JSON to:

POST https://<your-host>/api/v1/webhooks/receive/<tenantSlug>
Authorization: Basic <base64(username:secret)>
Content-Type: application/json

Example with cURL:

curl -k -X POST \
https://localhost/api/v1/webhooks/receive/acme \
-u "wh_user:wh_secret" \
-H "Content-Type: application/json" \
-d '{"title":"Brute force detected","src_ip":"203.0.113.10","severity":"high"}'

A successful ingest returns 201 with an alert_id. Duplicate alerts within the dedup window return 200 with status: "duplicate".

Credentials are verified in constant time

The webhook secret is compared using an HMAC + constant-time comparison, so authentication does not leak timing information about the secret.

3. Confirm ingestion

  • Check that an alert appears in the tenant.
  • Observables found in the payload (IPs, hashes, etc.) are extracted into the registry for correlation.

Troubleshooting

SymptomLikely cause
401 UnauthorizedWrong username/secret, or the source is inactive.
400 Bad RequestBody is not a JSON object, or tenantSlug is missing.
Alert parsed with empty fieldsSIEM type doesn't match the payload shape — pick the correct type.