Affinda's `document.parse.completed` webhook fires on failure too: it means parsing finished, not that it succeeded. Every handler must check the payload's `ready` and `failed` flags before touching `data`, or a failed parse will flow into your pipeline as an empty or partial result. Prefer subscribing to the explicit events (`document.parse.succeeded`, `document.parse.failed`) and routing them to different code paths. The same applies to `document.classify.completed` vs `document.classify.succeeded/failed`. The payload always carries the document `identifier`: use it to `GET /v3/documents/{id}` and fetch the full result; never assume the webhook body has the data you need.

Context: Web source (neversight/learn-skills.dev Affinda SKILL.md on github.com, summarizing docs.affinda.com webhooks reference): Affinda webhook events are not all successes. `document.parse.completed` fires when parsing finishes, whether it succeeded or failed, so your handler must check the `ready`/`failed` flags in the payload. Also subscribe to the specific outcome you need (`document.parse.succeeded` / `document.parse.failed`) instead of assuming completed means parsed.