Skip to content

Webhooks

chodeus edited this page Jun 17, 2026 · 10 revisions

🏠 Home › Webhooks

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.

On this page

The endpoint

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.

Authentication

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_secret and the retry knobs live in config.yml. This page is their canonical reference.

Accepted event types

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

Wiring your *arr / Tautulli

Sonarr / Radarr

  1. Settings → Connect → + → Webhook.

  2. URL: copy from CHUB's Settings → Webhooks page.

  3. Method: POST.

  4. 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.

  5. Headers: if a secret is set, add X-Webhook-Secret: <your secret> (use Reveal to copy the value).

  6. Click Test (CHUB returns 200; it appears under Recent callers), then Save.

Tautulli

Useful as a single trigger source that also catches Plex-side adds the *arrs don't see (manual uploads, Watchlist auto-adds).

  1. Settings → Notification Agents → Add a new notification agent → Webhook.
  2. 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).
  3. Triggers: Recently Added is usually enough.
  4. Data format: JSON. Leave the template blank.

Plex availability retry

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.

Force re-uploads per instance

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-push

The flag only affects webhook-triggered uploads from that instance. Scheduled and manual runs still respect the hash-skip.

Recent callers

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.

Troubleshooting

  • 401 Unauthorizedwebhook_secret is 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.
  • 200 but nothing happens — the event isn't on the allow-list (e.g. On Grab), the same item fired within the 600s dedup window (look for Duplicate webhook debounced at 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_retries or wait for the next scheduled rename.

See Troubleshooting for more.

Additional HTTP triggers

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

Clone this wiki locally