{"id":20544401,"url":"https://github.com/toddbirchard/ghost-webhook-api","last_synced_at":"2026-03-07T09:31:16.488Z","repository":{"id":37030407,"uuid":"245327108","full_name":"toddbirchard/ghost-webhook-api","owner":"toddbirchard","description":"📑 🎛️ API to automate optimizations for self-hosted blogging platforms.","archived":false,"fork":false,"pushed_at":"2025-11-15T16:00:05.000Z","size":3940,"stargazers_count":11,"open_issues_count":15,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-11-15T18:06:09.523Z","etag":null,"topics":["api","automation","bigquery","blogging","ghost","github-api","google-cloud-storage","python","webhook-api"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/toddbirchard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2020-03-06T04:07:25.000Z","updated_at":"2025-11-15T16:00:08.000Z","dependencies_parsed_at":"2023-02-09T19:01:11.597Z","dependency_job_id":"9c5251c7-d482-4d24-82a1-c2a766874b40","html_url":"https://github.com/toddbirchard/ghost-webhook-api","commit_stats":null,"previous_names":["toddbirchard/ghost-webhook-api","toddbirchard/blog-webhook-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/toddbirchard/ghost-webhook-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddbirchard%2Fghost-webhook-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddbirchard%2Fghost-webhook-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddbirchard%2Fghost-webhook-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddbirchard%2Fghost-webhook-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/toddbirchard","download_url":"https://codeload.github.com/toddbirchard/ghost-webhook-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/toddbirchard%2Fghost-webhook-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30210829,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T09:02:10.694Z","status":"ssl_error","status_checked_at":"2026-03-07T09:02:08.429Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","automation","bigquery","blogging","ghost","github-api","google-cloud-storage","python","webhook-api"],"created_at":"2024-11-16T01:44:16.030Z","updated_at":"2026-03-07T09:31:16.416Z","avatar_url":"https://github.com/toddbirchard.png","language":"Python","funding_links":["https://www.buymeacoffee.com/hackersslackers"],"categories":[],"sub_categories":[],"readme":"# Ghost Webhook API\n\n![Python](https://img.shields.io/badge/Python-^3.12-blue.svg?logo=python\u0026longCache=true\u0026logoColor=white\u0026colorB=5e81ac\u0026style=flat-square\u0026colorA=4c566a)\n![FastAPI](https://img.shields.io/badge/FastAPI-^v0.121.2-blue.svg?longCache=true\u0026logo=fastapi\u0026style=flat-square\u0026logoColor=white\u0026colorB=5e81ac\u0026colorA=4c566a)\n![Databases](https://img.shields.io/badge/Databases-^0.9.0-blue.svg?logo=python\u0026longCache=true\u0026logoColor=white\u0026colorB=5e81ac\u0026style=flat-square\u0026colorA=4c566a)\n![PyDantic](https://img.shields.io/badge/Pydantic-^v2.11.7-blue.svg?longCache=true\u0026logo=python\u0026style=flat-square\u0026logoColor=white\u0026colorB=5e81ac\u0026colorA=4c566a)\n![Google Cloud](https://img.shields.io/badge/Google--Cloud-^v0.34.0-lightgrey.svg?longCache=true\u0026style=flat-square\u0026logo=googlecloud\u0026logoColor=white\u0026colorB=5e81ac\u0026colorA=4c566a)\n![SQLAlchemy](https://img.shields.io/badge/SQLAlchemy-^2.0.44-red.svg?longCache=true\u0026style=flat-square\u0026logo=scala\u0026logoColor=white\u0026colorA=4c566a\u0026colorB=bf616a)\n![Ghost](https://img.shields.io/badge/Ghost-^v6.0.0-lightgrey.svg?longCache=true\u0026style=flat-square\u0026logo=ghost\u0026logoColor=white\u0026colorB=656c82\u0026colorA=4c566a)\n![GitHub Last Commit](https://img.shields.io/github/last-commit/google/skia.svg?style=flat-square\u0026colorA=4c566a\u0026logo=GitHub\u0026colorB=a3be8c)\n[![GitHub Issues](https://img.shields.io/github/issues/toddbirchard/blog-webhook-api.svg?style=flat-square\u0026colorA=4c566a\u0026logo=GitHub\u0026colorB=ebcb8b)](https://github.com/toddbirchard/blog-webhook-api/issues)\n[![GitHub Stars](https://img.shields.io/github/stars/toddbirchard/blog-webhook-api.svg?style=flat-square\u0026colorA=4c566a\u0026logo=GitHub\u0026colorB=ebcb8b)](https://github.com/toddbirchard/blog-webhook-api/stargazers)\n[![GitHub Forks](https://img.shields.io/github/forks/toddbirchard/blog-webhook-api.svg?style=flat-square\u0026colorA=4c566a\u0026logo=GitHub\u0026colorB=ebcb8b)](https://github.com/toddbirchard/blog-webhook-api/network)\n\n![Blog Webhook API](./.github/blog-webhook-api@2x.png?raw=true)\n\nStandalone API to compliment Ghost blogs. Accepts Ghost webhook events tiggers \u0026 executes task to optimize content and serve new features. Handles optimizations including image compression, content sanitation, alerting, and feature enablement via data aggregate (suggested searches, trending posts, etc)\n\n## Installation\n\nGet up and running with `make deploy`:\n\n```shell\ngit clone https://github.com/toddbirchard/ghost-webhook-api.git\ncd ghost-webhook-api\nmake deploy\n```\n\n## Endpoints\n\n### Posts\n\nEndpoints to guarantee published posts have proper metadata \u0026 embedded URLs.\n\n* **GET** `/posts/`: Bulk update metadata for all posts where applicable. Supports meta titles, og titles \u0026 descriptions, and feature images.\n* **POST** `/posts/`: Populate metadata for a single post upon publish. Supports meta title, og title \u0026 description, and feature image.\n* **GET** `/posts/backup`: Fetch JSON backup of all blog data\n  \n### Analytics\n\nAggregate data from Google Cloud \u0026 Algolia to power “trending” widgets.\n\n* **GET** `/analytics/`: Export site analytics from a data warehouse to a SQL database. Useful for trend-related features ie: \"trending this week\" widget.\n* **GET** `/analytics/searches/`: Fetch top Algolia search queries for the current week. Export results to a “trending searches” SQL table, as well as historical searches.\n  \n### Image Optimization\n\nEnsure all posts have retina, mobile, and webp variants.\n\n* **POST** `/images/`: Upon post creation, generate optimized retina and mobile variants of post ‘feature_image’ if they do not exist.\n* **GET** `/images/`: Generates both **retina** and **mobile** varieties of _all_ images in a remote CDN directory. Defaults to directory containing images uploaded within current month, or accepts a `?directory=` parameter which accepts a path to recursively optimize images on the given CDN.\n* **GET** `/images/sort`: Transverses CDN in a given directory (`?directory=`) to organize images into subdirectories based on image type (retina or mobile).\n\n### Accounts\n\nHandle user account creation \u0026 interactions.\n\n* **POST** `/account/`: Create Ghost member from Netlify Auth service (supports auth providers Github, Google, etc.)\n* **POST** `/account/comment/`: Accept user-submitted comments for posts. Each submission notifies the post’s author via a Mailgun email.\n* **POST** `/account/comment/upvote/`: Increment (or de increment) a comment’s upvote count by 1, with maximum 1 vote per user.\n\n### Donate\n\n* **POST** `/donation/`: Adds [BuyMeACoffee](https://www.buymeacoffee.com/hackersslackers) donation to a historical ledger.\n* **DELETE** `/donation/`: Delete a [BuyMeACoffee](https://www.buymeacoffee.com/hackersslackers) donation from historical ledger.\n* **GET** `/donation/`: Get all [BuyMeACoffee](https://www.buymeacoffee.com/hackersslackers) donations.\n\n### Newsletter\n\nLogistics of adding or removing newsletter subscriptions.\n\n* **POST** `/subscription/`: Send welcome email to newsletter subscribers via Mailgun.\n* **DELETE** `/subscription/`: Track newsletter unsubscribe events.\n\n### Authors\n\nInsight to scenarios where Authors likely need assistance.\n\n* **GET** `/authors/updated/`: Update all authors to have correct CDN urls \u0026 sanitized metadata.\n* **POST** `/authors/post/created/`: Notify site editor when posts are ready for review\n* **POST** `/authors/post/updated/`: Notify original post author when a peer edits a post.\n\n### Github\n\nNotifications when user activity is made on project repos.\n\n* **POST** `/github/pr/`: Trigger SMS notification when contributors open a Github PR in a specified Github org.\n* **POST** `/github/issue/`: Trigger SMS notification when contributors open a Github issue in a specified Github org.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoddbirchard%2Fghost-webhook-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftoddbirchard%2Fghost-webhook-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftoddbirchard%2Fghost-webhook-api/lists"}