> ## Documentation Index
> Fetch the complete documentation index at: https://docs.signa.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Troubleshooting

> Use the diagnostics endpoint to find out why an alert didn't fire

When an expected alert doesn't arrive, the diagnostics endpoint tells you exactly why -- so you can separate query, delivery, and platform issues quickly.

## Step 1 -- Run the diagnostics

For each (watch, trademark) pair you expected an alert for, call [`GET /v1/watches/{id}/diagnostics`](/api-reference/monitoring/watches/diagnostics):

```ts theme={null}
const trace = await signa.watches.diagnostics('wat_01HK7M...', {
  trademarkId: 'tm_01HK7N...',
});
console.log(trace.reason);
```

The `reason` field gives you the answer in plain English. The endpoint walks the evaluation steps in order and surfaces the first failure.

## Step 2 -- Interpret `reason`

| `reason` value                                                              | Meaning                                                                                                                                                                            | Next step                                                                                                                                                                                                                                   |
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `alert fired`                                                               | Alert was generated. Use `alert_id` to chase webhook delivery.                                                                                                                     | See Step 3.                                                                                                                                                                                                                                 |
| `watch does not include office {code}`                                      | The watch's `filters.offices` (or `filters.jurisdictions`) doesn't include this trademark's office.                                                                                | `PATCH` the watch to add the office. The widened criteria apply to future ingestion going forward — the watch re-evaluates with its new shape on the next sync automatically.                                                               |
| `trademark evaluated more than 90 days ago; provenance no longer available` | Outside the 90-day diagnostic horizon.                                                                                                                                             | The trace cannot be regenerated. Check the diagnostics `data_window` object for every retention horizon, and diagnose future misses within it. If the mark still matches the watch, it will be re-evaluated on the next sync going forward. |
| `trademark not in candidacy window for the most recent {office} sync run`   | No change record was emitted. The trademark hasn't changed in any way Signa considers material during the most recent ingestion cycle for this office since the watch was created. | Run [`POST /v1/watches/preview`](/api-reference/monitoring/watches/preview) with the watch's query to confirm the trademark would match today.                                                                                              |
| `trigger event {type} not in watch.trigger_events`                          | The watch's `trigger_events` filter excluded this event type. For example, you watch only `trademark.created` but this was a `trademark.updated`.                                  | Widen `trigger_events` via `PATCH`. The new shape applies to future ingestion automatically.                                                                                                                                                |
| `no matching reason available`                                              | Fallback.                                                                                                                                                                          | File a support ticket with the `request_id`. This should not happen in steady state.                                                                                                                                                        |

## Step 3 -- Cross-reference webhook delivery

When `alert_fired=true` but you never saw it on your receiver, follow the trace to the delivery log:

```ts theme={null}
// 1. The alert fired. alert_id (alt_*) is the cross-system trace handle.
const trace = await signa.watches.diagnostics('wat_01HK7M...', { trademarkId });
console.log(trace.alert_id);

// 2. List delivery attempts for the endpoint subscribed to alert.created.
const deliveries = await signa.webhooks.listDeliveries('whk_01HK...', {
  since: '2026-05-01T00:00:00Z',
});

// 3. Find the delivery rows for that alert and inspect the outcome.
for await (const d of deliveries) {
  if (d.alert_id === trace.alert_id) {
    console.log(d.status, d.http_status, d.error_reason, d.response_body);
  }
}
```

Likely outcomes:

* `delivered` -- receiver returned 2xx but may not have stored it. Inspect `response_body` and your own logs.
* `failed` -- non-2xx response. `error_reason` (e.g. `non_2xx_500`) and `http_status` tell you which side broke. Up to 7 retries.
* `exhausted` -- all retries failed. Replay manually with [`POST /v1/webhooks/{id}/deliveries/{did}/redeliver`](/api-reference/monitoring/webhooks/redeliver).
* `pending` -- still queued. Wait or check [`/v1/health`](/api-reference/health) to confirm Signa is up.

If the endpoint was auto-disabled mid-flight, check [`GET /v1/webhooks/{id}`](/api-reference/monitoring/webhooks/retrieve). `status='disabled'` plus `disabled_reason` (`auto_consecutive_100`, `auto_failure_rate_50_over_50`, or `manual`) explains why. Re-enable with [`PATCH /v1/webhooks/{id}`](/api-reference/monitoring/webhooks/update) once the receiver is healthy again.

## Step 4 -- Confirm Signa is healthy

Before assuming a Signa-side bug, hit [`/v1/health`](/api-reference/health). It returns instantly without auth and surfaces degraded readiness if a dependency is impaired.

```bash theme={null}
curl https://api.signa.so/v1/health
```

If the platform is degraded the `status` will be `degraded` or `unhealthy`. Retry the diagnostic flow once the page clears.

## Retention

| Data                                        | Window  |
| ------------------------------------------- | ------- |
| Change records (used for candidacy lookups) | 90 days |
| Webhook delivery audit                      | 30 days |
| Alerts                                      | 90 days |
| Diagnostic freshness horizon                | 90 days |

Past the diagnostic horizon, `evaluated=false` and `reason` explains the freshness limit. The provenance is gone at that point, so diagnose suspected misses while they're inside the window. A watch always continues to evaluate new ingestion going forward — the horizon only limits the backward-looking diagnostic trace.
