---
title: "Register a webhook (job.complete / job.failed)"
method: POST
path: "/api/webhooks"
tags: ["Webhooks"]
---

# Register a webhook (job.complete / job.failed)

`POST /api/webhooks`

## Request

- Base URL: `https://epw.tools`
- URL: `https://epw.tools/api/webhooks`
- Auth: none declared. Required headers: `X-API-Key`

Registers an HTTPS endpoint that receives a POST when one of your jobs finishes. Body: `{"event": "job.complete" | "job.failed", "data": {...}}`. Headers: `X-EPWTools-Event` and `X-EPWTools-Signature: sha256=<hex>`, the HMAC-SHA256 of the raw body keyed with your `secret`. Verify it before trusting the payload, for example in Python: `hmac.compare_digest(sig, 'sha256=' + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest())`. Delivery is attempted once with a 10 s timeout, so keep polling as a fallback for critical jobs.

## Headers

- `X-API-Key` string, required

## Request body

- WebhookCreateBody
  - `url` string, required
  - `secret` string, required: Shared secret used to sign the HMAC-SHA256 delivery header.
  - `events` string

## Response `201`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/epw/apis/epw-tools-api.md) · [All operations](https://skmtc.dev/epw/apis/epw-tools-api/llms.txt) · [OpenAPI document](https://skmtc.dev/epw/apis/epw-tools-api/revisions/e6b60fc7a6d7?raw)
