Headless CMS with an API and CLI: A Working Example
A headless CMS with an API and CLI is a content backend with no built-in front end: content lives behind endpoints you call, and a command-line tool wraps those endpoints so publishing can be scripted instead of clicked through a dashboard. You render the content wherever you want, and you can automate the whole publishing loop, including from an AI agent. This post walks through what that setup looks like in practice: a create-post call, a JavaScript SDK example, and where a CLI and custom collections take it further.
What 'headless CMS with an API and CLI' means for a working setup
In a working setup, three pieces do three separate jobs. The API stores and serves content as data (JSON in, JSON out), with no opinion on how it gets displayed. The CLI is a thin wrapper around that same API, built for a terminal or a script instead of a browser. The SDK is a typed client library that turns raw HTTP calls into function calls in your language of choice.
The distinction that matters: a traditional CMS couples the editor to the renderer, so the software that stores your post is also the software that displays it. A headless CMS separates those two jobs. You can publish from a script, a CI pipeline, or an agent, and render the result on any front end, a static site, a mobile app, a newsletter, without touching the CMS's own templates.
For an agent-driven or programmatic workflow, the API and CLI are the part that actually matters. A web dashboard is for a human clicking buttons. A script that publishes fifty pages on a schedule needs an endpoint it can call and a predictable response it can parse, which is what the next two sections walk through.
A worked example: creating and publishing a post through the API
Creating a post through a headless CMS's API is a single authenticated POST request with a JSON body: a title, a body in markdown or HTML, a slug, and a status field that controls whether it publishes immediately or sits as a draft. The response returns the stored post with its generated ID and URL.
Here is the shape of that call, written as an illustrative example rather than a copy of any specific API's exact syntax:
POST /api/posts
Authorization: Bearer <api_key>
Content-Type: application/json
{
"title": "Headless CMS with an API and CLI: A Working Example",
"slug": "headless-cms-api-cli-example",
"body_markdown": "# Heading\n\nPost body in markdown.",
"status": "published"
}A successful response looks like this:
201 Created
{
"id": "post_9f2a",
"slug": "headless-cms-api-cli-example",
"status": "published",
"url": "https://yoursite.example/blog/headless-cms-api-cli-example",
"created_at": "2026-08-31T00:00:00Z"
}The CLI does the same job with one command instead of a hand-built request:
floggy posts create \
--title "Headless CMS with an API and CLI: A Working Example" \
--file ./post.md \
--status publishedThe command reads the markdown file, sets the request body, and prints back the same kind of response the API returns. That is the whole appeal of a CLI on top of an API: no request-building code for the common case, and it drops straight into a shell script or a CI step that runs on a schedule.
A JavaScript/SDK example end to end
An SDK wraps the same POST request in a typed client so you write client.posts.create({...}) instead of building headers and a fetch call by hand. The example below shows the pattern any well-formed headless CMS SDK follows: initialize a client with an API key, then call a method that maps directly to an API endpoint.
import { FloggyClient } from "@floggy/sdk";
const client = new FloggyClient({
apiKey: process.env.FLOGGY_API_KEY,
});
async function publishPost() {
const post = await client.posts.create({
title: "Headless CMS with an API and CLI: A Working Example",
slug: "headless-cms-api-cli-example",
bodyMarkdown: "# Heading\n\nPost body in markdown.",
status: "published",
});
console.log(post.url);
}
publishPost();Three things happen in that snippet worth naming directly. The client authenticates once at construction, not on every call. The create method returns the same fields the raw API response would, so error handling and logging code work the same whether you call the API directly or through the SDK. And the function is a normal async function, so it drops into any Node script, a serverless function, or an agent's tool-calling loop with no adapter layer.
That last point is why the API-and-CLI pairing matters for agent-driven publishing specifically. An agent that can call a function can call client.posts.create(). It does not need to understand a CMS's admin UI, click through a form, or wait for a human to approve a draft in a dashboard. The SDK is the interface an agent actually uses.
Open-source vs. hosted: what changes in practice
Open-source and hosted headless CMS options both give you an API and a CLI. What changes is who runs the server, who handles upgrades and backups, and how much setup happens before you can make your first API call.
With an open-source, self-hosted CMS, you deploy the application yourself: a database, a runtime, environment variables, and usually a reverse proxy in front of it. You get full control over the data and the ability to modify the source directly, and you take on the operational work: applying updates, backing up the database, and keeping the service running. Custom collections or content types are typically defined by editing schema files and redeploying.
With a hosted CMS, the vendor runs the server. You sign up, get an API key, and the API is live: no database to provision, no runtime to keep patched. Custom collections are usually created through a dashboard or an API call rather than a schema file and a deploy. The tradeoff is that you depend on the vendor's uptime and roadmap instead of your own infrastructure.
For a solo founder or a small team automating publishing with an agent, the practical question is usually not which model is more powerful, both expose a comparable API and CLI, but which one gets a working POST /api/posts call running in minutes instead of after a deployment. Floggy is hosted: sign up, get an API key, and the API, CLI and SDK are live immediately, with no server to run yourself.
What developers actually ask for in an API-only CMS
Developers evaluating a headless CMS with an API and CLI consistently ask the same handful of questions before adopting one, based on the concerns that come up repeatedly in developer communities and CMS comparison discussions. None of these are unique to any one product; they are the baseline checklist for API-first content tooling.
The first is a real API instead of scraped or hand-parsed markdown files. Developers want structured JSON in and out, with predictable fields, not a system where they have to regex a file to extract a title.
The second is a CLI or scriptable interface, so publishing does not require opening a browser. This is the requirement that makes CI-driven or agent-driven publishing possible at all.
The third is control over the data: the ability to export content, or in the open-source case to self-host, so the CMS is not a one-way door. Nobody wants to build a year of content into a system they cannot get out of.
The fourth is a git-friendly or version-controllable workflow, particularly among developers who already keep everything else in a repository and want their content to follow the same review-and-deploy pattern.
The fifth, increasingly, is compatibility with automation and agents specifically: an API and SDK an agent's tool-calling loop can call directly, without a human clicking through an admin panel for every post. That is the shape of demand the JavaScript SDK example above is built to answer.
Where custom collections extend this beyond blog posts
A custom collection is a content type you define beyond the built-in blog post, with its own fields, its own API endpoint, and its own CLI and SDK methods generated to match. The same POST-and-CLI pattern used for a blog post applies to any structured content you define.
A blog post has a fixed shape: title, body, slug, status. A custom collection lets you define a different shape entirely, a directory of tools with a name, a description and a pricing field, a set of city landing pages with a city name and a list of local facts, a changelog with a version number and a release date. Once defined, that collection gets its own create, update, list and delete endpoints, following the same pattern as POST /api/posts, plus the matching CLI commands and SDK methods.
This is where an API-and-CLI headless CMS moves from single-post publishing into programmatic SEO: an agent or a script can loop over a list of cities, products, or topics and call the collection's create endpoint once per item, generating hundreds of structured pages the same way the worked example above generates one blog post. The publishing mechanism does not change between one post and a thousand rows in a custom collection, only the number of times the create call runs.
Floggy ships both pieces: standard blog posts through the API, CLI and SDK, and custom collections for any other structured content type, reachable through the same three interfaces so an agent can run the whole loop, creating, publishing, and iterating, on a schedule.


