API documentation

One endpoint, one key, four platforms. Everything you need is on this page.

Quickstart

Four steps from zero to a published post. The API key is the only secret your agent needs โ€” platform credentials stay on our side, encrypted.

shell
# 1. Sign up at https://agentpost.dietsoda.dev/register
# 2. Mint a key at /keys  ->  ap_live_xxxxxxxx
# 3. Connect at least one platform at /connections
# 4. Publish:

curl -X POST https://agentpost.dietsoda.dev/v1/publish \
  -H "X-API-Key: $AGENTPOST_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "platforms": ["x", "discord"],
    "text": "Shipped v2.0 ๐Ÿš€"
  }'

POST /v1/publish

Authenticate with the X-API-Key header. The body is flat: platforms and text are required, and the remaining fields (title, subreddit, link_url, parse_mode) are optional and only read by the platforms that need them. The endpoint is strict: unknown fields are rejected with a 400, so send exactly the fields documented here.

Posting to a single platform? Send "platform": "x" instead of the array โ€” the two forms are interchangeable.

request body
{
  "platforms": ["x", "reddit", "telegram", "discord"],
  "text": "Shipped v2.0 โ€” changelog in the thread.",
  "title": "Shipped v2.0",
  "subreddit": "SideProject",
  "link_url": "https://example.com/changelog",
  "parse_mode": "MarkdownV2"
}

The response returns one entry per requested platform, in the order you asked for them, plus your usage after the call.

200 response
{
  "results": [
    { "platform": "x", "ok": true, "post_id": "18...", "url": "https://x.com/you/status/18..." },
    { "platform": "discord", "ok": false, "error": "webhook returned 404" }
  ],
  "usage": { "used": 12, "limit": 1000, "period": "2026-07" }
}

Partial success is the normal case. A dead Discord webhook should not stop your X post from going out, so a per-platform failure is reported inside a 200 rather than failing the whole request. Only request-level problems (auth, quota, malformed body) use a non-2xx status.

node
// A per-platform failure does not fail the request.
// HTTP 200 with ok:false entries means "some went out, some did not".
const res = await fetch("https://agentpost.dietsoda.dev/v1/publish", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.AGENTPOST_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ platforms: ["x", "discord"], text }),
});

const body = await res.json();
if (res.status === 402) throw new Error("out of posts this period");
const failed = body.results.filter((r) => !r.ok);

Per-platform options

X

No options. Text over 280 characters is rejected with a 422 rather than silently truncated.

Reddit

subreddit and title are both required โ€” a Reddit self-post has no untitled form. Omit either and Reddit comes back 422 while your other platforms still publish. The shared text becomes the post body, or pass link_url to submit a link post instead of a self-post.

Telegram

parse_mode accepts MarkdownV2 or HTML; the default is plain text. MarkdownV2 requires escaping Telegram's reserved characters โ€” if you are passing through LLM output, plain text is the safer default.

Discord

No options. Text over 2,000 characters is rejected with a 422 โ€” that is Discord's own message limit. Webhooks do not return a message URL, so url is omitted on success.

Connect X

Open Connections, click Connect X, approve the OAuth prompt. You are redirected straight back. Nothing to copy, nothing to store.

Connect Discord

Discord uses a channel webhook โ€” no bot to create, invite or host.

  1. In your server: Server Settings โ†’ Integrations โ†’ Webhooks.
  2. Click New Webhook, pick the channel to post into, and name it (the name is what appears on your posts).
  3. Click Copy Webhook URL and paste it into the Discord card on Connections.

The URL is a credential โ€” anyone holding it can post to that channel. Delete the webhook in Discord to revoke it everywhere.

Connect Telegram

You need two values: a bot token and the chat ID it posts into.

  1. Message @BotFather on Telegram and send /newbot. It replies with a token like 123456:ABC-DEF...
  2. Add the bot to your channel or group as an administrator (a bot cannot post into a chat it is not in).
  3. Send any message in that chat, then call getUpdates and read the chat id:
shell
curl "https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates"
# -> {"result":[{"message":{"chat":{"id":-1001234567890, ...

Channel IDs are negative and start with -100. Paste both values into the Telegram card on Connections.

Connect Reddit

Reddit is the fiddly one โ€” it wants a script app plus a one-time refresh token. Ten minutes, once.

  1. Go to reddit.com/prefs/apps โ†’ create another app. Choose type script and set the redirect URI to http://localhost:8080.
  2. Copy the client ID (the string under the app name) and the secret.
  3. Mint a refresh token by visiting the authorize URL below in a browser, approving, and exchanging the returned code. Ask for duration=permanent โ€” a temporary grant expires in an hour and gives you no refresh token.
shell
# 1. Open in a browser, approve, copy ?code= from the redirect:
https://www.reddit.com/api/v1/authorize?client_id=CLIENT_ID&response_type=code\
&state=x&redirect_uri=http://localhost:8080&duration=permanent&scope=submit%20identity

# 2. Exchange it (the code expires in ~10 minutes):
curl -X POST https://www.reddit.com/api/v1/access_token \
  -u "CLIENT_ID:CLIENT_SECRET" \
  -d "grant_type=authorization_code&code=THE_CODE&redirect_uri=http://localhost:8080"
# -> {"refresh_token":"...", ...}

Paste the client ID, secret and refresh token into the Reddit card on Connections. The refresh token does not expire unless you revoke the app.

Error codes

CodeWhenWhat to do
401Missing, malformed or revoked X-API-Key.Mint a new key at /keys.
402Trial expired, or the monthly post quota is spent.Subscribe or wait for the period reset. Nothing is queued โ€” retry after upgrading.
422The request is well-formed but a platform cannot accept it โ€” no text, a platform you have not connected, or a missing Reddit subreddit/title.Check the per-platform entry in results for which one and why.
429Rate limited โ€” either AgentPost's own burst limit or the platform's, passed through.Back off and retry with exponential backoff.

Every error body is {"error": "message"}. Retry 429 and 5xx with backoff; do not retry 401, 402 or 422 โ€” they will not resolve on their own.

Ready to wire it up?

$29/mo, 1,000 posts. 7-day trial with 50 posts, no card to start.

Create an account