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.
# 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.
{
"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.
{
"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.
// 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.
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.
- In your server: Server Settings โ Integrations โ Webhooks.
- Click New Webhook, pick the channel to post into, and name it (the name is what appears on your posts).
- 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.
- Message
@BotFatheron Telegram and send/newbot. It replies with a token like123456:ABC-DEF... - Add the bot to your channel or group as an administrator (a bot cannot post into a chat it is not in).
- Send any message in that chat, then call getUpdates and read the chat id:
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.
- Go to
reddit.com/prefs/appsโ create another app. Choose type script and set the redirect URI tohttp://localhost:8080. - Copy the client ID (the string under the app name) and the secret.
- 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.
# 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
| Code | When | What to do |
|---|---|---|
| 401 | Missing, malformed or revoked X-API-Key. | Mint a new key at /keys. |
| 402 | Trial expired, or the monthly post quota is spent. | Subscribe or wait for the period reset. Nothing is queued โ retry after upgrading. |
| 422 | The 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. |
| 429 | Rate 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