Small ASP.NET Core minimal API intended to run as a Windows Service.
It exposes a single endpoint (POST /webhook) that accepts Plex Webhooks form posts and, on relevant playback events, updates the last write time of the folder that contains the media file being played.
Why: some library/file sync/indexing workflows look at folder timestamps. Touching the folder on playback can be used to trigger downstream jobs (backup, metadata refresh, external indexers, etc.).
While the behavior in this repo is intentionally specific (touching a folder timestamp, and a couple of playback events), it’s also meant as a small, practical example of how to receive Plex webhook events and trigger your own actions (run a script, call another API, enqueue a job, etc.).
http://0.0.0.0:5000.application/x-www-form-urlencoded) with a payload form field containing JSON.media.playmedia.scrobbleMetadata.Media[0].Part[0].fileDateTime.UtcNow.The app writes a simple text log to:
./logs/app-YYYYMMDD.log (relative to the deployed executable directory)Logs are retained for 7 days.
It logs:
webhook_received)event valueprocessing_started / processing_completed for media.play and media.scrobblefile/folder was touchedIf any field is missing/unknown, the handler returns 200 OK (so Plex doesn’t keep retrying) and does nothing.
Some Plex webhook payloads do not include the full filesystem path (no Metadata.Media[].Part[].file). In that case, this app will optionally call back into Plex using Metadata.ratingKey to resolve the real file path.
Set these environment variables on the machine running the service:
PLEX_BASEURL e.g. http://localhost:32400 or http://CHUWI02:32400PLEX_TOKEN your Plex tokenIf these are not set, the app will log that lookup was skipped and it will not be able to touch folders.
This token is the X-Plex-Token value.
Options:
https://app.plex.tv/desktop)/library/...)X-Plex-Token query valuePlexOnlineToken="..." in Preferences.xmlEnvironment variables are read from the process environment.
sc.exe), set them at the System level.dotnet run, or directly from the published bin folder as your normal user, set them at the User level (or configure them in your run profile).Run PowerShell as Administrator:
setx PLEX_BASEURL "http://<plex-server>:32400" /M
setx PLEX_TOKEN "<your-x-plex-token>" /M
Restart the service after setting these.
Run PowerShell (non-admin is fine):
setx PLEX_BASEURL "http://<plex-server>:32400"
setx PLEX_TOKEN "<your-x-plex-token>"
Close and re-open your terminal / Visual Studio so the new environment variables are picked up.
From the repository root:
dotnet build
dotnet run
Then test it is listening:
curl -Method Post http://localhost:5000/webhook -ContentType "application/x-www-form-urlencoded" -Body "payload={}"
You should get a 400 for invalid payload JSON, or 200 for a valid Plex-style payload.
Publish self-contained or framework-dependent. Framework-dependent is smaller and requires the .NET runtime installed on the machine.
Framework-dependent example:
dotnet publish -c Release -o C:\Services\PlexWebhookFolderToucher
Run PowerShell as Administrator.
sc.exe create PlexWebhookFolderToucher binPath= "C:\Services\PlexWebhookFolderToucher\per-plexed.exe" start= auto
Optional: set a friendly description:
sc.exe description PlexWebhookFolderToucher "Receives Plex webhooks and touches media folders on playback events."
Start it:
sc.exe start PlexWebhookFolderToucher
Check status:
sc.exe query PlexWebhookFolderToucher
Stop / delete:
sc.exe stop PlexWebhookFolderToucher
sc.exe delete PlexWebhookFolderToucher
Allow inbound TCP 5000 from your Plex server to the machine running this service.
http://<service-host>:5000/webhook
<service-host>.Plex webhooks post form data and include a payload JSON field.
This app specifically uses Metadata.Media[0].Part[0].file from that payload.
application/x-www-form-urlencoded; this app will return 400 if something else is posted.app.Run("http://0.0.0.0:5000") line in Program.cs.file path provided by Plex exists on the machine where this service is running (paths are local to that machine).