Notification Patterns

Webhooks support two delivery patterns, set with the notification_pattern field when the webhook is created:

  • result (default) — one delivery per job, fired when the job reaches a terminal state (success or failure).
  • subscription — one delivery for every status change as the job moves through the pipeline.

notification_pattern is set on creation and is read-only afterwards. To change the pattern of an existing webhook, delete it and create a new one.

Setting the pattern

Pass notification_pattern in the create request:

curl -X POST https://api.selfdecode.com/service/health-analysis/b2b-integrations/user-webhook/ \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "job_type": "report_job",
    "callback_url": "https://example.com/webhooks/reports",
    "email": "[email protected]",
    "notification_pattern": "subscription"
  }'
FieldRequiredNotes
job_typeYesRead-only after create. One webhook per (user, job_type).
callback_urlYesMust be HTTPS.
emailYesReceives a notice if delivery fails after all retries.
notification_patternNoresult or subscription. Defaults to result. Read-only after create.

Comparison

result (default)subscription
Deliveries per job1, on terminal state1 per status change
Delivers intermediate statesNoYes
IdempotencyExactly-once (up to retry limit)At-least-once per change
Typical use caseReplace polling for the final resultReal-time progress / pipeline tracking

Result mode

Default behavior. The webhook fires once when the job reaches a terminal status. Once a delivery has succeeded, no further deliveries are sent for that job, even if the job is updated later.

Subscription mode

The webhook fires every time the job's status changes. The payload is always the current state of the job at delivery time, not the state that triggered the delivery — late retries always carry the freshest values.

A typical report_job will deliver in this order:

waiting_file_processing → file_processed → waiting_report_gen
  → report_generated → waiting_pdf → pdf_generated

A failure path delivers the matching failed_* status instead of advancing.

Status reference

The status field in each delivery comes from the job's status enum. Below are the values for the most common job types.

report_job, pdf_job, ancestry_job, and other PDF-style jobs

StatusMeaning
initJob created
waiting_file_processingWaiting on the genome file
file_processedGenome file ready
waiting_report_genReport generation in progress
report_generatedReport ready
waiting_pdfPDF generation in progress
pdf_generatedPDF ready — terminal success
failed_downloading_fileTerminal failure
failed_uploading_fileTerminal failure
failed_file_processingTerminal failure
failed_report_genTerminal failure
failed_pdfTerminal failure

dna_kit_job

StatusMeaning
shippedKit shipped to user
registeredKit activated
received_by_labSample received by lab
analyzed_by_labSample analyzed
waiting_reanalysisLow quality, awaiting reanalysis
processing_dna_fileGenome file being created
completedTerminal success
failedTerminal failure
cancelledTerminal failure

For other job types, the status field follows the same enum as report_job unless the OpenAPI schema indicates otherwise.

Payload

The payload shape is the same in both patterns: the job's serialized fields plus job_type. Subscription deliveries are distinguished only by the value of status.

Example mid-pipeline subscription delivery for a report_job:

{
  "id": "8a4f…",
  "user_id": "1c9d…",
  "profile_id": "b210…",
  "report_id": "37f1…",
  "status": "report_generated",
  "created_at": "2026-04-29T10:15:03Z",
  "pdf_url": null,
  "error": null,
  "job_type": "report_job"
}

Headers, signing (X-Hub-Signature-256), retries, the failure email, the recover action, and the reset-secret action are all identical to the standard webhook flow — see the Webhooks Guide.

Handling subscription deliveries

  • Match deliveries by id to track a single job through its lifecycle.
  • Treat handlers as idempotent. The same status may arrive more than once on retry, and intermediate statuses can, in rare cases, arrive out of order.
  • Treat the job as finished when status is one of the terminal values listed above (pdf_generated, completed, or any failed_* / cancelled).