-
Notifications
You must be signed in to change notification settings - Fork 1
Webhooks
🏠 Home › Webhooks
CHUB exposes one inbound webhook so Sonarr, Radarr, or Tautulli can push a fresh poster the moment a new item lands — no waiting for the next scheduled run.
- The endpoint
- Authentication
- Accepted event types
- Wiring your *arr / Tautulli
- Plex availability retry
- Force re-uploads per instance
- Recent callers
- Troubleshooting
- Additional HTTP triggers
POST http://<chub-host>:8000/api/webhooks/poster/add
Settings → Webhooks renders this URL with your current origin and a one-click copy button.
On a call: the payload is validated, deduplicated against a persistent 600-second rolling cache (keyed on media identity, survives restarts), and a poster job is enqueued scoped to that one item. The job runs the same pipeline as a scheduled poster_renamerr: rename → border replacer (if enabled) → apply, where "apply" follows the module's apply_method (plex uploads to Plex; kometa writes into destination_dir).
Sonarr Download / EpisodeFileImported are season-aware: when the payload carries episodes[*].seasonNumber, CHUB re-checks only that season's posters instead of walking every season.
Auth is optional and off by default. Set general.webhook_secret (in config.yml or Settings → General) to require it on every inbound request:
| Method | How | Use for |
|---|---|---|
| Header (preferred) | X-Webhook-Secret: <secret> |
Sonarr, Radarr |
| Query param (fallback) | ?secret=<secret> |
Tautulli, shortcut apps that can't send headers |
A wrong or missing secret returns 401. Empty secret = unauthenticated (fine on a trusted LAN; don't expose it to the open internet). Settings → Webhooks masks the secret with a Reveal/Hide toggle and copy buttons for the header form, the ?secret= URL, and the plain URL.
See Configuration for where
webhook_secretand the retry knobs live inconfig.yml. This page is their canonical reference.
Only events for a new on-disk file are processed. Anything else gets a 200 ack and is dropped.
| Event | Sonarr trigger | Radarr trigger | Processed? |
|---|---|---|---|
Download |
On Import / On Upgrade | On Import / On Upgrade | ✅ |
EpisodeFileImported |
On Import (v4+) | — | ✅ |
MovieFileImported |
— | On Import (v5+) | ✅ |
SeriesAdd |
On Series Add | — | ✅ |
MovieAdded |
— | On Movie Added | ✅ |
Test |
(Test button) | (Test button) | ✅ acked, no job |
Grab |
On Grab | On Grab | 🚫 file not on disk yet |
Rename |
On Rename | — | 🚫 ignored |
*FileDelete, *Delete, HealthIssue, ApplicationUpdate, … |
— | — | 🚫 ignored |
-
Settings → Connect → + → Webhook.
-
URL: copy from CHUB's Settings → Webhooks page.
-
Method:
POST. -
Notification Triggers: check On Import and On Upgrade, plus:
- Sonarr → also On Series Add.
- Radarr → also On Movie Added.
Leave the rest unchecked — CHUB ignores them.
-
Headers: if a secret is set, add
X-Webhook-Secret: <your secret>(use Reveal to copy the value). -
Click Test (CHUB returns
200; it appears under Recent callers), then Save.
Useful as a single trigger source that also catches Plex-side adds the *arrs don't see (manual uploads, Watchlist auto-adds).
- Settings → Notification Agents → Add a new notification agent → Webhook.
-
URL: Tautulli has no Headers field — use the
?secret=URL form from CHUB's Webhooks page (or the plain URL if no secret is set). - Triggers: Recently Added is usually enough.
- Data format: JSON. Leave the template blank.
A webhook usually fires before Plex has indexed the new file, so CHUB waits for the item to appear before pushing posters. Defaults give a ~5.5-minute window. For a Sonarr season import, the wait is season-aware (waits for that specific season folder).
general:
webhook_initial_delay: 30 # seconds before the first Plex check
webhook_retry_delay: 30 # seconds between retries
webhook_max_retries: 10 # total attempts| Field | Default | Range / note |
|---|---|---|
webhook_initial_delay |
30s | wait before the first check |
webhook_retry_delay |
30s | wait between retries |
webhook_max_retries |
10 | total attempts |
If the budget runs out, the upload is skipped and the next scheduled poster_renamerr picks it up.
By default CHUB hashes each poster on disk and skips the upload if it's unchanged — so a webhook for an unchanged poster is a no-op. To force every webhook from an instance to re-push (e.g. a wiped Plex library), set webhook_force_reupload: true on that *arr instance (Settings → Instances or config.yml):
instances:
sonarr:
main:
url: http://sonarr:8989
api: ...
webhook_force_reupload: true # webhooks from this Sonarr always re-pushThe flag only affects webhook-triggered uploads from that instance. Scheduled and manual runs still respect the hash-skip.
Every webhook job records source host, endpoint, event type, and user agent. Settings → Webhooks rolls up the last 7 days as client_host → endpoint with call counts and status — handy for spotting a noisy integration or confirming a freshly wired *arr is reaching CHUB.
-
401 Unauthorized—webhook_secretis set but the caller isn't sending the header or?secret=. Copy a pre-applied URL/header from Settings → Webhooks. -
404 Not Found— path typo. It's/api/webhooks/poster/add. -
200but nothing happens — the event isn't on the allow-list (e.g. On Grab), the same item fired within the 600s dedup window (look forDuplicate webhook debouncedat debug level), or the job ran but failed downstream (check Settings → Jobs). -
Sonarr "Test connection failed" — network issue; Sonarr can't reach CHUB. Verify from inside its container:
curl -I http://chub:8000/api/health. -
Download didn't get its poster — the Plex availability budget ran out before Plex finished scanning. Bump
webhook_max_retriesor wait for the next scheduled rename.
See Troubleshooting for more.
Not Sonarr/Radarr-style webhooks — plain HTTP triggers for module runs you can fire from external automation (cron, Home Assistant, a phone shortcut). Each is rate-limited and honours general.webhook_secret the same way. CHUB's own UI runs these modules from their dedicated pages.
| Method | Endpoint | What it does |
|---|---|---|
GET |
/api/webhooks/unmatched/status |
Return the current unmatched-assets summary. |
POST |
/api/webhooks/unmatched/process |
Enqueue an unmatched_assets run. |
GET |
/api/webhooks/wiring |
Return the poster/add path + optional secret (used by CHUB's UI to build URLs). |
GET |
/api/jobs/webhook-origins?days=7 |
Summarize recent webhook calls by client_host + endpoint. |
Next: Troubleshooting · Related: Configuration, Modules