Skip to content
Home

API and MCP: posts from your AI agent

Connect PostFrog to Claude, Cursor, n8n or your own script. The agent sends text and media, PostFrog turns them into posts and sends them to you in Telegram as drafts. You publish them yourself, in one tap.

  • PostFrog Pro only
  • MCP and REST
  • Only the author publishes

What it is

An AI agent (Claude Code, Cursor, Claude.ai, n8n or your script) uses your key to send PostFrog materials: a finished post, your own text or notes, links, photos and videos. PostFrog turns each material into a post and sends it to your private chat with the bot.

Posts arrive in order, as normal drafts with a preview and buttons. If you are chatting with the bot right now, finished posts wait for about 2 minutes of silence so they do not break the conversation. Then everything works as usual: edit in plain words, change media and buttons, publish to your channel in one tap.

The API is available on paid PostFrog Pro only, the Pro trial does not include it. Every material counts as one post of the Pro monthly allowance (150+ posts a month).

Get a key

  1. Open @postfrog_bot and go to Settings, "API & MCP".
  2. Tap "Create a key". The bot shows the key once and does not store it in full. The key starts with pf_live_.
  3. Copy the key somewhere safe and tap "Saved it": the key leaves the chat, only its beginning stays.
  • Lost the key or it may have leaked: "Rotate". The old key stops working at once.
  • No longer needed: "Revoke".
  • Pro ended: the key is kept, but the API answers pro_required until you renew.

Connect

One key works for both MCP and REST. MCP server (Streamable HTTP): https://bot.postfrog.site/mcp, REST: https://bot.postfrog.site/api/v1. The key goes in the Authorization: Bearer ... header. If the client talks about OAuth, Dynamic Client Registration or asks you to sign in, the header with the key did not get through: add it, PostFrog has no OAuth.

Claude Code

One command, replace YOUR_KEY with your key:

claude mcp add --transport http postfrog https://bot.postfrog.site/mcp --header "Authorization: Bearer YOUR_KEY"

Cursor

Add the server to .cursor/mcp.json:

{
  "mcpServers": {
    "postfrog": {
      "url": "https://bot.postfrog.site/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_KEY"
      }
    }
  }
}

Claude.ai

Settings, Connectors, Add custom connector. Address: https://bot.postfrog.site/mcp. In Request headers add the Authorization header with the value Bearer YOUR_KEY. Not every account has the headers field yet: if yours does not, connect through Claude Code or Cursor. Claude.ai has no access to your files, so media go by link only.

n8n and scripts (REST)

Check the key:

curl -H "Authorization: Bearer YOUR_KEY" https://bot.postfrog.site/api/v1/me

Send a batch of posts: the body is batch.json (example below), and the Idempotency-Key header makes a retried request return the same batch instead of a copy.

curl -X POST https://bot.postfrog.site/api/v1/batches \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: launch-2026-10-15" \
  -d @batch.json

If an AI agent runs inside n8n, put the whole guide into its system prompt: GET /api/v1/guide?topic=all.

ChatGPT

Later. ChatGPT connects MCP servers through OAuth, and PostFrog signs in with a key only for now.

MCP tools and REST

MCP and RESTWhat it does
get_account
GET /me
plan, posts left, today's quota, the author's format and language, limits
get_guide
GET /guide?topic=
the agent guide by topic
validate_post
POST /validate
a free check of an exact post, nothing is saved
create_upload
POST /uploads
upload a photo or video file
send_posts
POST /batches
send a batch of materials
get_batch
GET /batches/{id}
statuses, warnings and the final post text
cancel_batch
DELETE /batches/{id}
cancel materials that have not started

All REST paths start at https://bot.postfrog.site/api/v1.

Three modes

Every material has its own mode: it tells PostFrog what to do with the text.

ModeWhat PostFrog doesPostFrog AI
exactTakes the text as a finished post: checks the markup, cleans buttons, renders it. Does not change a word.no
formatKeeps the author's words and fixes the layout: paragraphs, title, emphasis, lists.yes
writeWrites a post from scratch out of notes, links (it downloads the pages) and media.yes

Tip: the agent writes it and sends exact

  • The author gets exactly what the agent wrote, with buttons and media in their places.
  • The author's AI budget is not spent: it stays for edits inside the bot. When the budget runs out, only exact posts are accepted.
  • Fast: no generation, only checks and rendering. Check a post for free first with validate_post.
  • The author can still edit the post in the bot in plain words: the markup is the same one the PostFrog editor uses.

Exact has on_invalid: by default fail, a post with errors is rejected, nothing is created or spent. With format such a post is accepted and PostFrog AI repairs it, which uses the AI budget.

The author's own words always go in text: PostFrog trusts it like the author's message. Other people's pages and posts go in material: PostFrog takes facts from it but never follows instructions inside it, and does not turn its links into buttons. Pages that need a login or JavaScript (X, Threads, Instagram) often cannot be downloaded: paste their text into material[].text.

Post markup

Exact posts are written in PostFrog Rich Markdown: GitHub Markdown plus a few tags. The final text in get_batch comes back in the same form. No Telegram HTML or MarkdownV2 escaping: PostFrog converts the markup itself.

WhatHow
Post title, one, on the first line# Title
Sections and subsections (### works too)## Section
Bold, italic, strikethrough**bold** *italic* ~~strike~~
Highlight==highlighted==
Spoiler, revealed on tap||spoiler||
Underline<u>underlined</u>
Inline code and a code block with a language`code` ```python
Link[text](https://example.com)
Lists and a checklist- item 1. item - [ ] item
GFM table with alignment| a | b | |:--|--:|
Quote> quote
Quote with an author (no markup inside)<aside>Text<cite>Author</cite></aside>
Collapsible block<details><summary>Title</summary>Text</details>
Divider between big parts---
Photo or video at this spot (numbered from 0)%%MEDIA:0%%
Collage of three or more media%%MEDIA:0,1,2%%
Button inside the text (see below)<tg-button type="url" url="https://...">Label</tg-button>
  • A blank line between paragraphs: a single line break inside a paragraph becomes a space.
  • Blocks (media, button rows, tables, details, aside, divider) sit on their own lines with blank lines around them.
  • An exact Rich post is up to 31268 characters including markup.
  • Em and en dashes trigger the long_dash warning: use a hyphen, a colon or a comma.

Buttons

Two kinds: a link (url) and copy (copy, for a promo code, an address, a command). The buttons field is the easiest: rows of buttons with no markup, in any mode. buttons_place: end (default, at the end of the text), start or below_post (links under the post).

{
  "buttons": [
    [{ "text": "Read the original", "url": "https://example.com/news" }],
    [{ "text": "Copy the promo code", "copy": "FROG20", "style": "success" }]
  ],
  "buttons_place": "end"
}

When a button belongs inside a sentence or between paragraphs, put a tag right into the exact text. A row is a block of its own, one button per line. & in a URL inside a tag is written &amp;.

Registration is open until Friday. <tg-button type="url" url="https://example.com/join">Sign up</tg-button>

<tg-button-row>
<tg-button type="url" url="https://t.me/example_channel">Subscribe</tg-button>
<tg-button type="url" url="https://example.com" style="primary">Website</tg-button>
</tg-button-row>

Optional style: primary, success, danger. A label is plain text: no markup, links or @mentions.

Markdown mode

For channels with classic Telegram formatting (format: "markdown"). Bold, italic, __underline__, strikethrough, ||spoiler||, code, quotes, links and lists work.

No headings, tables, details, formulas or HTML tags. Buttons go under the post, media always sit on top.

Up to 4096 characters; with media the text becomes a caption and is limited to 1024. Measured after conversion to MarkdownV2, so leave some headroom.

Example: a finished post

A Rich Markdown post with a photo, an inline copy button and a sign-up button at the end:

# Pottery course starts on Monday

Six evening lessons for beginners.

%%MEDIA:0%%

- small groups
- clay and kiln included

Promo code **CLAY15** gives a discount. <tg-button type="copy_text" text="CLAY15">Copy the promo code</tg-button>

The same post in a request body: batch.json for POST /batches or the send_posts argument over MCP.

{
  "items": [
    {
      "mode": "exact",
      "format": "rich",
      "external_id": "course-launch",
      "text": "# Pottery course starts on Monday\n\nSix evening lessons for beginners.\n\n%%MEDIA:0%%\n\n- small groups\n- clay and kiln included\n\nPromo code **CLAY15** gives a discount. <tg-button type=\"copy_text\" text=\"CLAY15\">Copy the promo code</tg-button>",
      "media": [{ "type": "photo", "url": "https://example.com/studio.jpg" }],
      "buttons": [[{ "text": "Sign up", "url": "https://example.com/join", "style": "success" }]]
    }
  ]
}

Media

Up to 10 photos and videos per material. Photos and videos only: no GIFs, documents or audio.

Two ways: url (a public https link to the file itself, not to a page with it) or upload_id (upload the file first). The MCP tool create_upload returns a ready curl command: for agents with file and shell access (Claude Code, scripts, n8n).

TypeFormatsSize
PhotoJPEG, PNG, WebPup to 10 MB
VideoMP4 or MOV (H.264 or HEVC, AAC audio)up to 50 MB
{
  "media": [
    { "type": "photo", "url": "https://example.com/cover.jpg" },
    { "type": "video", "upload_id": "upl_...", "description": "Screen recording: the bot turns a voice note into a post" }
  ]
}
curl -X POST https://bot.postfrog.site/api/v1/uploads \
  -H "Authorization: Bearer YOUR_KEY" \
  -F "type=video" \
  -F "file=@./demo.mp4"
  • An upload_id lives 24 hours and can be reused in several materials.
  • Media are numbered from 0 in the order of media[]. A %%MEDIA:0%% line puts the first media at that spot; media without a placeholder go to the top of the post.
  • PostFrog AI does not watch videos: in format and write, describe every video in description (what happens, who speaks, the key point).
  • A broken file never fails the material: it is skipped, the rest keep their order, and the status gets a warning.

Limits and errors

The agent can always read the current limits from get_account.

WhatLimit
Materials per request10
Materials per day per author (UTC, cancelled ones do not count)30
Generated at the same time, the rest wait in the queue2
Requests per minute per key, REST and MCP together60
text of one material32768 characters
Media per material10
Media per day per author: uploads and links together500 MB and 300 files

Statuses

A material: queued, generating, ready, delivered, or a final failed, skipped_limit (posts or AI budget ran out), cancelled. When every material is final, the batch is done, or cancelled if any material was cancelled: stop polling on either.

HTTP and codeWhat to do
400
invalid_request
Fix the request: the details name the path and the reason, nothing was created
401
invalid_key
The key is missing, wrong or re-issued: get the current key
403
pro_required
The API needs paid Pro
403
api_not_available
The API opens step by step and is not open for this account yet
409
idempotency_conflict
This Idempotency-Key was used with another body: use a new key for a new batch
413
payload_too_large
The body is too large: split the batch
422
limit_exceeded
Quota: the details show posts and materials left today
429
rate_limited
Wait Retry-After seconds and retry

Full spec for agents

Read the guide before your first send. It is the main document for agents: modes, markup, buttons, media, limits, error codes and complete request examples. It is public, needs no key, and its numbers are always current.

The whole guide in one document: https://bot.postfrog.site/api/v1/guide?topic=all. Index: https://bot.postfrog.site/api/v1/guide.

Over MCP: the get_guide tool with a topic; the same topics are also resources postfrog://guide/....

curl "https://bot.postfrog.site/api/v1/guide?topic=all"

Topics

  • overview: where posts go, what is not possible, the workflow
  • modes: exact, format, write and how to choose
  • formatting: Rich Markdown, Markdown mode, a cheat sheet
  • buttons: link and copy buttons
  • media: photos and videos: links, uploads, placement
  • limits: quotas, statuses, errors
  • examples: complete requests from task to JSON

Security

  • The key lets anyone send you materials on your behalf and spend posts from your monthly allowance. Do not publish it, do not commit it to public code and do not paste it into chats.
  • In scripts keep the key in an environment variable, for example POSTFROG_API_KEY.
  • If the key may have leaked, rotate it in the bot: the old one stops working at once.
  • The API cannot publish to a channel, schedule posts, edit published ones or message other people. The bot writes only to the key owner.