# PostEverywhere AI Caption Guide > AI-generated social media captions tuned per platform, respecting character limits, hashtag conventions, and emoji style. **Source:** https://posteverywhere.ai/docs/generate-caption **Section:** Core concepts **API reference:** https://posteverywhere.ai/docs/api/reference --- Generates **1-5 caption variants** for a social media post from a topic + tone + platform. Companion to [`/v1/ai/generate-image`](/docs/api/generate-image): together they let an MCP agent compose an entire post in two API calls. Captions respect per-platform character limits and follow each platform's hashtag conventions automatically: | Platform | Hard limit | Hashtag style | |----------|-----------|---------------| | X / Twitter | 280 chars | 1-3 hashtags at end | | Bluesky | 300 chars | 1-3 hashtags | | Threads | 500 chars | 1-3 hashtags | | Pinterest | 500 chars | **No hashtags** (uses natural-language search) | | YouTube | 1,000 chars | 1-3 hashtags | | Instagram | 2,200 chars | 5-10 hashtags at end | | TikTok | 2,200 chars | 5-10 hashtags | | LinkedIn | 3,000 chars | 2-3 hashtags (LinkedIn discourages heavy use) | | Facebook | 5,000 chars | 1-3 hashtags | ## Generate a caption from a prompt: `POST /v1/ai/generate-caption` ```bash curl -X POST https://app.posteverywhere.ai/api/v1/ai/generate-caption \ -H "Authorization: Bearer $POSTEVERYWHERE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "topic": "Black Friday sale on running shoes โ€” 30% off through Monday", "platform": "instagram", "tone": "enthusiastic", "length": "medium", "count": 3 }' ``` Requires the `ai` scope. Costs **1 AI credit per returned caption**. ## Controlling tone, length and platform | Field | Type | Default | Description | |-------|------|---------|-------------| | `topic` | string (required) | N/A | What the post should be about (max 1,000 chars). | | `platform` | string | none | If set, applies platform-specific length + style rules. Omit for generic. | | `tone` | string | `professional` | `professional` \| `casual` \| `witty` \| `enthusiastic` \| `urgent` \| `inspirational` | | `length` | string | `medium` | `short` (~80 chars) \| `medium` (~180 chars) \| `long` (~400 chars) | | `include_hashtags` | boolean | `true` | Set `false` to omit hashtags entirely. | | `include_emojis` | boolean | `true` | Set `false` for emoji-free output. | | `count` | integer | `1` | Number of variants to return (1-5). | ## What the caption response returns ```json { "data": { "captions": [ "๐Ÿƒ 30% OFF until Monday! Time to lace up. Our best running shoes โ€” half a closet, all the comfort. Free shipping over $50. Link in bio.\n\n#blackfriday #runningshoes #sale #fitness #running", "BLACK FRIDAY MADNESS ๐Ÿ›๏ธ ...", "..." ], "platform": "instagram", "tone": "enthusiastic", "length": "medium", "count_requested": 3, "count_returned": 3, "credits_used": 3, "credits_remaining": 197 }, "error": null, "meta": { "request_id": "a1b2c3d4", "timestamp": "2026-06-11T09:55:12.341Z" } } ``` ## Caption generation errors | Code | HTTP | When | |------|------|------| | `validation_error` | 400 | Missing `topic` or `topic` > 1000 chars. | | `insufficient_credits` | 402 | Not enough AI credits for the requested count. Response includes `needed` and `available`. | | `ai_no_content` | 502 | OpenAI returned no content. Rephrase the topic and retry. | ## Pairing captions with generated images ```ts const me = await client.me.get(); if (me.quota.ai_credits.limit - me.quota.ai_credits.used < 6) { showUpgrade(); return; } // 1 image (~5 credits) + 1 caption (1 credit) = 6 credits. const [image, captions] = await Promise.all([ client.ai.generateImage({ prompt: 'Vibrant running shoes on a track', model: 'gemini-3-pro' }), client.ai.generateCaption({ topic: 'Black Friday โ€” 30% off running shoes', platform: 'instagram', tone: 'enthusiastic', count: 1, }), ]); await client.posts.create({ content: captions.captions[0], account_ids: [igAccountId], media_ids: [image.media_id], scheduled_for: '2026-11-29T10:00:00Z', }); ``` ## What caption generation costs in credits - **Tone influences word choice.** `professional` produces measured copy with full sentences. `witty` introduces wordplay. `enthusiastic` uses exclamation marks and energy words. Match tone to brand voice. - **Multi-platform posting.** If you're posting to multiple platforms with different character limits, generate ONE caption sized for the shortest (X/Bluesky). Or call this endpoint per-platform. - **Hashtag placement.** Hashtags always land at the end of the caption (Instagram convention), unless you set `include_hashtags: false`. - **Pinterest** is special: `include_hashtags` is ignored. Pinterest uses natural-language search, not hashtags, so they're omitted. **Related:** [the ai scope](/docs/scopes) ยท [media limits per platform](/docs/media-requirements) ยท [testing without publishing](/docs/testing) ยท [AI credits per plan](/pricing) Full reference: [POST /v1/ai/generate-caption](/docs/api/generate-caption) and [POST /v1/ai/generate-image](/docs/api/generate-image).