Publish from your code. Or hand it to your agent.

Every action in the FoPost dashboard is an API call you can make yourself. Wire it up with the MCP server, the REST API, or the TypeScript SDK. Or skip the account entirely and use the open-source PHP packages on your own server.

Start here

Pick the right integration

Two families of packages. One drives your FoPost account, the other runs entirely on your own infrastructure.

FoPost account

Cloud clients

These authenticate with an FoPost API key and drive the hosted product. You get scheduling, the publishing queue, retries, analytics, and every account you have connected.

No account needed

Open-source packages (MIT)

Free, standalone, and unconnected to the hosted product. You bring your own platform credentials and publish direct to 11 platforms from your own server. No API key, no plan, no FoPost account.

MCP server

Give your assistant the keys

The FoPost MCP server exposes 14 tools over the Model Context Protocol. Claude, Cursor, ChatGPT, and any other MCP client can draft, schedule, and check on your posts without you opening the dashboard.

Install and run
npx -y @owlstackapp/mcp
claude_desktop_config.json
{
  "mcpServers": {
    "owlstack": {
      "command": "npx",
      "args": ["-y", "@owlstackapp/mcp"],
      "env": {
        "OWLSTACK_API_KEY": "your-api-key"
      }
    }
  }
}

Create an API key in your dashboard settings, drop it in, and restart your client. The same command and the same key work in Cursor and every other MCP-compatible client.

All 14 tools

list_postsget_postschedule_postedit_postcancel_postdelete_postlist_post_deliverieslist_accountsget_account_healthlist_workspacesgenerate_captionrewrite_for_platformsrepurpose_urlget_ai_credits

Draft and schedule from chat

Your assistant reads your workspaces, picks the connected accounts, and schedules the post. You approve the wording, not the clicking.

Turn a URL into a week of posts

Point the agent at a blog post and it repurposes the piece for each platform, respecting the limits and conventions of every one.

Check what shipped and what broke

Per-platform delivery status and account health come back as structured data, so the agent can retry or tell you which connection needs attention.

REST API

The same API the dashboard runs on

Predictable resources, one consistent request and response shape, and no endpoint held back for an enterprise tier.

POST /v1/posts
curl -X POST https://api.fopost.com/v1/posts \
  -H "X-API-Key: $OWLSTACK_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "workspaceId": "9b2f6c1e-...",
    "status": "scheduled",
    "scheduleAt": "2026-09-01T09:00:00Z",
    "content": [{ "text": "Shipped a new release today.", "position": 0 }],
    "accounts": [{ "id": "4a71d80b-..." }]
  }'

Authentication

Send your key in an X-API-Key header. Keys are created per workspace from your dashboard settings, and you can revoke one at any time without touching the others.

Scopes

Every key carries only the scopes you grant it. A key scoped to publishing cannot read your billing, and a key for one client workspace cannot reach another.

postsaccountsworkspaceslabelspublishdeliverieswebhooksanalyticsautomations

OpenAPI spec

Served straight from the API, so it always matches what is deployed. Point a generator at it and build a client in any language.

Want the longer argument for building on it? Read the REST API feature page.

TypeScript SDK

Typed client for Node

A thin, fully typed wrapper over the REST API. Ships ESM, CommonJS, and type definitions, and pulls in no dependencies of its own.

Install
npm install @owlstackapp/sdk

Resource namespaces for posts, accounts, workspaces, labels, and ai. Errors come back as a typed error class with the status and code attached.

schedule-post.ts
import { FoPost } from '@owlstackapp/sdk';

const client = new FoPost({ apiKey: process.env.OWLSTACK_API_KEY });

const [workspace] = await client.workspaces.list();
const accounts = await client.accounts.list({ workspaceId: workspace.id });

const post = await client.posts.create({
  workspaceId: workspace.id,
  status: 'scheduled',
  scheduleAt: '2026-09-01T09:00:00Z',
  content: [{ text: 'Shipped a new release today.', position: 0 }],
  accounts: accounts.map((a) => ({ id: a.id })),
});

console.log(post.id, post.status);
Open source

Free packages that need no FoPost account

These are not clients of the hosted product. They are MIT-licensed publishing libraries that run on your own server with your own platform credentials, and they publish direct to 11 platforms.

PHP core library

No account needed

Framework-agnostic PHP 8.1 and up, with no framework dependencies. Immutable content objects, a formatter per platform that respects each one’s limits and markup, and a publisher that never throws: you always get a result object back to inspect.

Install
composer require owlstack/owlstack-core
publish.php
use FoPost\Core\Config\PlatformCredentials;
use FoPost\Core\Content\Post;
use FoPost\Core\Formatting\CharacterTruncator;
use FoPost\Core\Formatting\HashtagExtractor;
use FoPost\Core\Http\HttpClient;
use FoPost\Core\Platforms\PlatformRegistry;
use FoPost\Core\Platforms\Telegram\TelegramFormatter;
use FoPost\Core\Platforms\Telegram\TelegramPlatform;
use FoPost\Core\Publishing\Publisher;

$credentials = new PlatformCredentials('telegram', [
    'api_token'        => getenv('TELEGRAM_BOT_TOKEN'),
    'channel_username' => '@your-channel',
]);

$formatter = new TelegramFormatter(new HashtagExtractor(), new CharacterTruncator());
$platform  = new TelegramPlatform($credentials, new HttpClient(), $formatter);

$registry = new PlatformRegistry();
$registry->register($platform);

$result = (new Publisher($registry))->publish(
    new Post(title: 'Hello World', body: 'My first post via FoPost.'),
    'telegram',
);

echo $result->success ? "Published: {$result->externalUrl}" : "Failed: {$result->error}";

Laravel package

No account needed

A thin wrapper over the core library. It registers the service provider, publishes a config file, and gives you a facade with a method per platform. Platform behavior stays in the core, so there is nothing to keep in sync.

Install
composer require owlstack/owlstack-laravel

php artisan vendor:publish --tag=owlstack-config
PublishController.php
use FoPost\Laravel\Facades\FoPost;

$result = FoPost::telegram('Hello from the facade.');

if ($result->success) {
    logger()->info("Published: {$result->externalUrl}");
}

WordPress plugin

No account needed

Built on the same PHP core and distributed through the WordPress plugin directory, not Composer. Install it from your admin, add your platform credentials, and your posts go out as you publish them.

Developer questions

Which packages need an FoPost account?

The MCP server, the REST API, and the TypeScript SDK all talk to the hosted product, so they need an FoPost account and an API key. The PHP, Laravel, and WordPress packages need neither. They are MIT-licensed, they run on your own server, and they publish with your own platform credentials.

What is the difference between the PHP package and the TypeScript SDK?

They solve different problems. The TypeScript SDK is a client for the FoPost API, so you get scheduling, the queue, retries, analytics, and every connected account. The PHP package is a standalone publishing library: you bring your own platform credentials and it posts directly to 11 platforms, with no FoPost involved at any point.

Can I use the MCP server with something other than Claude?

Yes. It speaks the Model Context Protocol over stdio, so any MCP-compatible client works. Claude Desktop, Cursor, and ChatGPT all use the same command and the same API key.

Is there an OpenAPI spec?

Yes, and it is served from the API itself so it never drifts from what is deployed. Point your generator at it and build a client in whatever language you work in.

How do API key scopes work?

A key carries the scopes you grant it and nothing else, and it belongs to one workspace. A key scoped to posts cannot touch billing, and a key for one client workspace cannot read another. Create and revoke keys from your dashboard settings.

Do the open-source packages work with the WordPress plugin?

The plugin is built on the same PHP core, so the platform behavior and formatting are identical. Install it from the WordPress plugin directory and it publishes your posts as you write them.

Build on it today

Create an account, generate a scoped key, and make your first call in minutes. Or install a PHP package and publish without an account at all.