Skip to main content

AI

Generate post captions and images with the PostPeer AI endpoints.

Overview

PostPeer ships two AI endpoints powered by Gemini:

  • POST /v1/ai/write generates a social-media caption from a free-form description.
  • POST /v1/ai/image generates a square, vertical, or landscape image and stores it in your project's media bucket.

Both endpoints use the same x-access-key auth as every other PostPeer endpoint.

Credit costs

EndpointCredits per successful call
/v1/ai/write2
/v1/ai/image10

Failed calls do not deduct credits. Costs come out of your subscription cycle first, then your one-time purchased credits.

Generate a caption

Pass a description and the platforms you intend to post to. The AI fits the caption to the strictest character limit among them.

curl -X POST https://api.postpeer.dev/v1/ai/write \
  -H "x-access-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "We just shipped a Bluesky API. Same call as posting to Twitter, free tier, no OAuth complexity.",
    "platforms": ["twitter", "bluesky", "linkedin"]
  }'

Response:

{
  "success": true,
  "content": "We shipped Bluesky support. Same one-line call as Twitter. Free tier. No OAuth dance. Try it: postpeer.dev",
  "creditsCharged": 2
}

You can also pass existingContent to ask the model to rewrite a draft instead of starting fresh:

-d '{
  "description": "Make this snappier and add a question at the end.",
  "existingContent": "We just released a new feature that helps with X.",
  "platforms": ["twitter"]
}'

Generate an image

Minimum required is a description. Everything else is optional.

curl -X POST https://api.postpeer.dev/v1/ai/image \
  -H "x-access-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "A flat-lay desk with a laptop, coffee, and a notebook open to a diagram of a social media API. Soft natural light.",
    "aspectRatio": "square",
    "style": "photo"
  }'

Response:

{
  "success": true,
  "url": "https://assets.postpeer.dev/uploads/<projectId>/ai-<uuid>.png",
  "mimeType": "image/png",
  "creditsCharged": 10
}

The url is permanent and ready to drop into the mediaItems array of POST /v1/posts/.

Aspect ratios

Pass aspectRatio as one of square, vertical, or landscape. The aspect ratio is enforced at the model level (via Gemini's imageConfig.aspectRatio), so it's preserved even when you pass reference images of a different shape.

ValuePixelsUse for
square (default)1:1Instagram, Twitter, LinkedIn, Pinterest
vertical9:16TikTok, Reels, YouTube Shorts
landscape16:9YouTube thumbnails, blog headers

Style presets

Pass style as one of these to bias the output. Omit for the model to pick whatever fits the brief.

ValueEffect
photoPhotorealistic, natural lighting
illustrationFlat vector, bold shapes, limited palette
minimalLots of negative space, two or three colors max
vibrantHigh-saturation, high-contrast pop
cinematicStrong directional light, deep shadows, film grain
3d-renderSoft 3D, clay materials, smooth shading
retro70s/80s palette, slight grain, period typography
hand-drawnPencil lines, light watercolor wash

Reference images vs. asset images

Two roles for image inputs, both are optional, both can be passed together:

  • referenceImageUrls (up to 4): style/vibe inspiration. The model uses them as visual context but does NOT copy them into the result. Use this for "match my brand look", "same composition as this", or "same vibe but different scene".
  • assetImageUrls (up to 4): images that MUST appear in the result, faithfully. Use this for brand logos, product photos, or specific subjects you want placed into the generated image.
curl -X POST https://api.postpeer.dev/v1/ai/image \
  -H "x-access-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "A laptop on a sunny desk with the company logo visible on its lid.",
    "aspectRatio": "square",
    "style": "photo",
    "referenceImageUrls": [
      "https://assets.postpeer.dev/uploads/<projectId>/brand-mood-1.jpg"
    ],
    "assetImageUrls": [
      "https://assets.postpeer.dev/uploads/<projectId>/postpeer-logo.png"
    ]
  }'

The model:

  • Treats referenceImageUrls as inspiration only. It will not put your reference photo in the result.
  • Treats assetImageUrls as content to be placed into the result faithfully, without redrawing or restyling them. The surrounding scene matches your brief, the asset itself is preserved.

If you want to iteratively tweak a previously generated image, pass it as a referenceImageUrl along with a delta description like "warmer lighting" or "same vibe but on a beach". The aspect ratio is hard-locked server-side so the tweak preserves the original shape.

Backwards compat. The older single-image field referenceImageUrl is still accepted and merged into referenceImageUrls. New integrations should use the array form.

End-to-end example

Generate a caption, generate an image with your logo placed in it, then publish both.

# Step 1: caption
curl -X POST https://api.postpeer.dev/v1/ai/write \
  -H "x-access-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "description": "Friday product drop", "platforms": ["twitter"] }'
# → { "content": "Friday product drop. ..." }

# Step 2: image with brand logo placed in
curl -X POST https://api.postpeer.dev/v1/ai/image \
  -H "x-access-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Vertical desk shot, Friday vibes, our logo on the laptop lid",
    "aspectRatio": "vertical",
    "style": "cinematic",
    "assetImageUrls": ["https://assets.postpeer.dev/uploads/.../logo.png"]
  }'
# → { "url": "https://assets.postpeer.dev/uploads/.../ai-...png" }

# Step 3: publish
curl -X POST https://api.postpeer.dev/v1/posts \
  -H "x-access-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Friday product drop. ...",
    "platforms": [ { "platform": "twitter", "accountId": "your-account-id" } ],
    "mediaItems": [ { "type": "image", "url": "https://assets.postpeer.dev/uploads/.../ai-...png" } ],
    "publishNow": true
  }'

Total credits used: 2 (caption) + 10 (image) + 1 (publish) = 13.

Errors

  • 402 Payment Required if your project doesn't have enough credits for the call. Buy more credits or upgrade your plan.
  • 503 Service Unavailable if AI features aren't configured on the server (rare; means GEMINI_API_KEY is unset).
  • 500 for any other failure. No credits are deducted on failure.

Tone of voice

POST /v1/ai/write is tuned to avoid the obvious AI tells: no em-dashes, no buzzwords (leverage, streamline, unlock, etc.), varied sentence length, no "Bold word: explanation" bullets, no transition openings (Moreover, Additionally, etc.). It writes captions, not press releases. The system prompt is locked, you don't need to ask for it in your description.

On this page