Heroku runs the dynos — your app takes delivery of every article.
Heroku’s Platform API manages apps, builds, config vars, domains, dynos and releases — nothing on that list can store an article, so there is no "Heroku blog" for any tool to post into. There is your app, though, built by a language buildpack and running on dynos. Give it one webhook route and DraftSEO delivers every finished article there as signed JSON; your code saves it, your templates render it, and Heroku keeps the dynos running.
| Heroku content API | None — apps, dynos, releases — the Platform API has no post, page or article resource |
|---|---|
| Article destination | A webhook route in your app — buildpacks run Node.js, Python, Ruby, PHP, Go, Java, Kotlin and .NET apps |
| Signed deliveries | HMAC-SHA256 with timestamp — checked over ${timestamp}.${rawBody}; anything older than 5 minutes is refused |
| Port binding | Must listen on $PORT — not bound within 60 seconds of boot, the app is killed with error R10 |
| Dyno filesystem | Wiped at least daily — store posts in a database such as Heroku Postgres |
Who does what
Tell DraftSEO which language your app is written in, paste the matching receiver, verify each signature and save the post to your database. Once the test delivery comes back green, you spend no time per article, and your views, routes and layouts stay exactly as you built them.
Ship it once — your dynos take every article from then on.
Setup
Your buildpack’s language sets the recipe, so the first choice is the stack rather than the host.
Connect a site → Heroku, then pick what your dynos run — Ruby on Rails, Django, FastAPI, Laravel, Java / Spring, Kotlin (Ktor), ASP.NET Core, Go, Next.js or Node.js / Express. You get that recipe plus a signing secret.
~1 minute
Heroku gives the web dyno a different port on every boot and stops an app that has not bound it within 60 seconds (R10). The recipes read PORT; a Procfile passes it on, for example web: uvicorn main:app --host 0.0.0.0 --port $PORT.
~10 minutes
Run heroku config:set DRAFTSEO_WEBHOOK_SECRET="<your signing secret>" -a <app-name>, or add it under Settings → Config Vars. Heroku restarts the app with the new value by itself.
~2 minutes
Take the address from Settings → Domains — apps created since June 2023 carry a random suffix. DraftSEO sends a signed test delivery — and a deliberately invalid one, which your receiver must reject.
~1 minute
Articles now reach your dynos as the calendar comes due, images and meta tags included — nobody clicks publish.
Ongoing · zero clicks
FAQ
No — Heroku holds no content for anyone to publish into. The Platform API manages apps, builds, config vars, domains, dynos and releases, and none of those is an article. DraftSEO publishes into the app your dynos run, and that app is what renders the blog.
Heroku’s language buildpacks cover Next.js, Astro, SvelteKit, Nuxt (Vue), Expo and Node.js / Express, PHP (plain) and Laravel, Django and FastAPI, Ruby on Rails, Go (net/http), ASP.NET Core (.NET 8 or later), Java / Spring and Kotlin (Ktor). Rust and Elixir have no official buildpack: Rust / Axum and Elixir / Phoenix apps use a community buildpack (emk/heroku-buildpack-rust, HashNuke/heroku-buildpack-elixir) or a container deployed with heroku.yml — both only on the standard Cedar platform.
R10 means the web process never bound to $PORT: Heroku assigns a new port on every boot and kills an app that has not bound it within 60 seconds. The recipes already read PORT; your Procfile has to pass it through. A first test that times out is usually an Eco dyno waking up — Eco dynos sleep after 30 minutes without web traffic. Press Send test again, or run a Basic dyno, which never sleeps.
Even static files on Heroku come from a web dyno, and that dyno cannot take a POST by itself. Run the receiver as a separate small Heroku app — the Node.js recipe deploys there unchanged — and point the DraftSEO endpoint at it.
No — the dyno filesystem is wiped at least once a day, taking any file-based posts with it. Keep them in a database such as Heroku Postgres, upsert on the article id, and render the blog from that table.
No card required. Signed test delivery in under a minute.