Skip to main content
Rewind exposes two inbound webhook endpoints so Strava and Plex can push events the moment something happens, instead of waiting for the next cron sync. Finish a run on Strava or a movie on Plex, and the new activity lands in your archive within seconds.
These are internal integration endpoints. Strava and Plex call them, not you. They take no API key and there is nothing to fetch from them by hand. You configure each one once as the operator, then they run unattended.

How they work

Every other Rewind route is something you call with a Bearer token. Webhooks invert that: an external service is the caller and Rewind is the receiver. Because Strava and Plex cannot present a Rewind API key, the auth middleware skips any path under /v1/webhooks/, and each endpoint verifies its own source instead. The two endpoints live at /v1/webhooks/strava and /v1/webhooks/plex.

Strava

Strava webhooks begin with a one-time handshake. When you register a subscription, Strava sends a GET to /v1/webhooks/strava with hub.mode, hub.verify_token, and hub.challenge. Rewind echoes the challenge back only when the mode is subscribe and the token matches STRAVA_WEBHOOK_VERIFY_TOKEN; otherwise it returns 400 and the subscription is not established.
{ "hub.challenge": "<value Strava sent>" }
Once the subscription is active, Strava POSTs an event for each activity. Rewind acknowledges within Strava’s roughly two-second window, dedupes retries, then processes asynchronously: a create or update syncs that activity, and a delete removes it. Events for other object types, such as athlete, are ignored.

Plex

Plex POSTs a multipart/form-data payload to /v1/webhooks/plex. Rewind parses it, verifies it against PLEX_WEBHOOK_SECRET (returning 403 otherwise), and ingests only media.scrobble plays of movies or episodes from your own account, enriching the title with TMDB metadata and recomputing your watch stats. Everything else, other event types, other media, or plays from other users, is acknowledged with a 200 so Plex stops retrying.

Configuration

Both endpoints depend on operator-set environment variables, not on anything a reader supplies:
VariableEndpointPurpose
STRAVA_WEBHOOK_VERIFY_TOKENStravaMatched against hub.verify_token during the handshake
PLEX_WEBHOOK_SECRETPlexVerifies that an inbound Plex payload came from your server
To learn what happens once an event is ingested, see the running and watching domain pages.