# Triggers (/docs/api/gateway/triggers)

Webhook triggers that turn GitHub, Sentry, monitoring or custom events into agent sessions, plus the notification inbox.

A trigger is a signed inbound webhook bound to your account. Each delivery is verified with the trigger's own secret, normalised into an event card, run through the trigger policy (filters, budget, rate limit, dedupe) and then either opens a session, appends to an open one or only posts a notification.

## Signing generic deliveries [#signing-generic-deliveries]

Custom senders sign with the codai scheme:

```http
x-codai-signature: t=<unix seconds>,v1=<hex HMAC-SHA256(secret, "<t>.<raw body>")>
x-codai-delivery: <your delivery id>
```

- The HMAC covers the timestamp, a literal `.` and the **raw** request body, byte for byte — sign before any re-serialisation.
- `t` must be within **5 minutes** of the gateway clock; older or future timestamps are rejected as `stale_timestamp`.
- `x-codai-delivery` is the idempotency key: a repeated delivery id is recorded once. Without it the gateway derives an id from `t` and a hash of the body.
- GitHub (`X-Hub-Signature-256`) and Sentry (`Sentry-Hook-Signature`) sources use their native signatures instead.

## Ingress [#ingress]

The trigger policy field `ingress` decides where deliveries are accepted:

- `public` (default) — the internet-facing `POST /v1/hooks/{id}`.
- `local` — LAN-only sources. The public URL answers **404**; deliveries arrive through the codaid daemon or the desktop app broker on your network, which forward them with the same signature check.
- `both` — either path.

Use `rotate-secret` to mint a new generated secret, or `PUT …/secret` to set the secret a third-party service already signs with. `POST …/test` fires a signed sample delivery through the full pipeline.

<OpenAPIPage document="./openapi/en/gateway.yaml" operations={[{path: '/v1/triggers',method: 'get'},{path: '/v1/triggers',method: 'post'},{path: '/v1/triggers/{id}',method: 'patch'},{path: '/v1/triggers/{id}',method: 'delete'},{path: '/v1/triggers/{id}/rotate-secret',method: 'post'},{path: '/v1/triggers/{id}/secret',method: 'put'},{path: '/v1/triggers/{id}/test',method: 'post'},{path: '/v1/triggers/{id}/events',method: 'get'},{path: '/v1/hooks/{id}',method: 'post'},{path: '/v1/notifications',method: 'get'},{path: '/v1/notifications/read',method: 'post'},{path: '/v1/notifications/{id}',method: 'delete'},{path: '/v1/notifications/delete',method: 'post'}]} />
