TL;DR: You can automate dev.to posts through the official Forem API (
POST /api/articles) with a personal API key, which is the cleanest posting API in the overseas platform ecosystem. It has real limits: 10 requests per 30 seconds, no built-in scheduling, and a key tied to one personal account. For a single blog that’s fine. Once dev.to is one of five platforms you post to, driving your own logged-in browser session through one AI-controlled flow removes the need to wire up a separate key and integration for each one.
A developer who cross-posts a technical write-up to their own blog, dev.to, and Hashnode by hand spends most of that time on formatting, not writing: pasting Markdown into dev.to’s editor, re-adding the cover image, re-tagging the post, then doing it again somewhere else. Dev.to solved half of this problem years ago with a real API. The other half, the part where you’re running this across four or five platforms that don’t all have an API, is where most setups start to crack.
Dev.to’s API is the good case, and here’s what it looks like
Dev.to (built on the open-source Forem platform) exposes POST /api/articles for creating posts. You generate a personal API key from your dev.to account settings, send the key in an api-key header, and the request body carries title, body_markdown, tags, series, and canonical_url. Set published: true and the post goes live immediately; leave it false and it lands as a draft you finish in the web editor.
The common developer pattern is a GitHub Actions workflow: store the key as a repo secret (often named something like DEV_TO_GIT_TOKEN), trigger on a push to a posts/ folder, and let the action push each Markdown file straight to dev.to. It’s a solid setup for one blog feeding one platform, and it’s the reason dev.to shows up so often in “how I automated my blog” write-ups.
Where the official API approach runs out of road
Rate limits are real, not theoretical. The Forem API docs put a limit of 10 requests per 30 seconds on the articles endpoint, and the admin rate-limit docs note that new accounts get tighter limits by default for the first three days. Batch-import a backlog of old posts on a brand-new account and you’ll hit 429s before you’re a quarter of the way through.
There’s no native scheduling. The API only accepts published: true or false. If you want a post to go live at a specific time, you’re either running a cron job that flips a draft to published, or reaching for a third-party workaround like PublishTo.Dev, which exists specifically because dev.to never shipped this itself.
The key belongs to one person, not the workflow. If you write under a dev.to organization, the API key still comes from an individual account’s settings. Handing automation to a teammate or an AI agent means handing over a personal key, and revoking access later means rotating it, which breaks every pipeline that still references the old value.
It only solves dev.to. The moment your list grows to include Medium (whose official publish API was retired in 2023), Tumblr, or Pinterest, you’re not looking at “one more API integration.” You’re maintaining a different auth model and a different client library for each platform, on top of the GitHub Actions setup you already have.
Where a local, logged-in session changes the shape of the problem
PublishPort’s approach is to skip the API-key-per-platform model entirely. The client runs on your own machine, using the same browser session you’re already logged into for dev.to, Medium, Tumblr, Pinterest, and 60-plus other platforms. An AI agent gets exactly two tools: local_bash to run a command, and list_capabilities to see what’s available (opencli devto supports search, drafts, and publish, for instance). The AI reads the tool’s own --help output the way you would, then runs it. See how the MCP side of this connects up.
That trade removes the standing credential: there’s no dev.to API key sitting in a CI secret waiting to be leaked or rotated. It also means dev.to, Medium, and Tumblr all go through the same login model instead of three different ones, which matters more the longer your platform list gets. The client itself is a free download; the paid tier is what lets a cloud AI reach your machine to run the command.
Dev.to API vs. a local browser session: what changes
| Official dev.to API | Local logged-in session | |
|---|---|---|
| Auth | Personal API key in a secret store | Your existing browser login, nothing new to generate |
| Rate limit | 10 requests / 30 sec, tighter for new accounts | Same posting speed as a human using the site |
| Scheduling | Not supported natively | Runs whenever the AI or a cron trigger tells it to |
| Covers other platforms | Only dev.to | Same flow for any platform with a browser login, dev.to included |
| Credential risk | Key can leak from CI logs or a misconfigured secret | Session lives on your machine, nothing to leak to a third party |
Bottom line: if dev.to is the only place you publish, the official API is the right tool and you don’t need anything else. If it’s one stop on a longer list, a single logged-in session covers more ground with less to manage.
Setting it up
- Install the PublishPort client and let it detect your existing Chrome profile.
- Log into dev.to normally in that browser, the same way you already do to write a post.
- Confirm the capability:
list_capabilitiesshould return a line foropencli devtocovering publish. - Point your AI client at the tool: give it the draft, including a
canonical_urlback to your own blog if this is a cross-post, not an original. - Let it run
local_bashto publish, then check the live URL the same way you would after posting manually.
Limits worth stating plainly
Running dev.to through a real session doesn’t lift dev.to’s own anti-spam limits: it’s still your account doing the posting, so the same new-account throttling and community moderation apply. Always set canonical_url when the content originated elsewhere; skipping it is how cross-posted technical writing quietly loses its search ranking to the copy instead of the original. And nothing here is a promise that automated posting is invisible to a platform that actively looks for bot-like patterns. It reduces the moving parts, not the platform’s rules.
Before you publish on a schedule:
-
canonical_urlis set correctly if this isn’t the original post - Tags and cover image match what you’d set by hand
- You know the account’s rate limit standing (new accounts are throttled harder)
- You’re not blasting a backlog of old posts in one run
FAQ
Does dev.to have a public API?
Yes. The Forem API (the open-source platform dev.to runs on) exposes POST /api/articles for creating and updating posts, authenticated with a personal API key generated in your account settings. It’s documented at developers.forem.com.
Can I schedule posts on dev.to?
Not natively. The API only takes a published true/false flag, with no future publish date field. People work around this with an external cron job or a third-party tool like PublishTo.Dev that flips a draft to published at a set time.
What is canonical_url for when cross-posting to dev.to?
It tells search engines and dev.to itself where the original version of the article lives, so ranking signals go to your own site instead of the dev.to copy. Skip it and a cross-post can end up outranking the original in search results.
Is there a rate limit on the dev.to API?
Yes, 10 requests per 30 seconds on the articles endpoint, with stricter limits for accounts less than three days old. Batch operations on a new account will hit that ceiling fast.
Can I automate posting to dev.to with GitHub Actions?
Yes, this is a common pattern: store your dev.to API key as a repo secret, trigger on new Markdown files, and post through the API. It works well for a single blog-to-dev.to pipeline, but it’s a separate integration to maintain for every other platform you add.
Will automating my dev.to posts get my account flagged?
Automation itself isn’t against dev.to’s terms since the official API exists for this. What gets accounts flagged is spam-like behavior: identical unformatted cross-posts with no canonical URL, or publishing bursts that trip the anti-spam rate limits.
