REST API

Call Postlaty from code

HTTP for curl, n8n, Make, or a custom GPT Action. Same account, tokens, and 19 networks as the app. If you want an agent to do this in chat, use MCP.

https://www.postlaty.com/api/v1

1. Authentication

Create a key in Profile → API & MCP. Send it as a Bearer token. Keys look like plt_live_…. The secret is shown once. One key covers every company on the account. MCP clients that support OAuth do not need this key.

Authorization: Bearer $POSTLATY_API_KEY

Requires an active or trialing subscription. Rate limit: 60 requests per minute per key. Authenticated responses include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset (Unix epoch seconds). Unauthenticated and protocol-error responses omit those headers. Errors are { "error": { "code", "message" } }. Machine-readable spec: GET /api/v1/openapi.json (no auth). CORS is * without credentials. CSRF does not apply to this API.

2. REST /api/v1

  • GET /api/v1 — name, version, docs URL, OpenAPI URL
  • GET /api/v1/openapi.json — OpenAPI 3.1 (no auth)
  • GET /api/v1/me — remaining tokens, companies, posts.* (logical post groups), platformPosts.* (platform rows), folders, models
  • GET /api/v1/companies — every company on the account. companyId in this API is the company display name (case-insensitive lookup, 404 if unknown)
  • GET /api/v1/models — image and video ids plus catalog (per-model token cost, durations, sizes)
  • GET /api/v1/accounts — connected accounts with companyId (no tokens). Optional ?companyId=
  • POST /api/v1/accounts/connect — OAuth URL for TikTok, Instagram, Facebook, YouTube, X, LinkedIn, Threads, Reddit, Pinterest, Slack, Discord, Tumblr. Credential platforms (Bluesky, Telegram, Whop, Skool, Mastodon, Dev.to, Pixelfed) connect in the same call with credentials. Chat destinations (Telegram, Skool, Whop) also need destinationType and destinationId. Tokens stay on Postlaty
  • DELETE /api/v1/accounts/:id — disconnect
  • POST /api/v1/companies — { "name", "makeDefault"? } (default is unchanged unless makeDefault: true). Names: trim, 2–80 chars, letters/numbers/spaces/./_/- , no control characters or markup
  • PATCH /api/v1/companies — body { "from", "to" }
  • DELETE /api/v1/companies?name= — keep at least one company
  • GET /api/v1/templates, POST /api/v1/templates/import — product template library
  • GET /api/v1/influencers?category=men|women|others, POST /api/v1/influencers/import — UGC influencer library
  • GET /api/v1/billing, POST /api/v1/billing/checkout, POST /api/v1/billing/portal — Stripe hosted URLs (user pays / manages billing)
  • POST /api/v1/generate — generate or edit (spends tokens; tokensRemaining is after the charge). Optional folderId and publish. dryRun: true quotes without spending. Status: pending → ready or failed
  • GET /api/v1/generate/:id — poll until ready or failed. url is the private /api/v1/media/:id/files/shared proxy (same as GET /media/:id). Includes tokenCost and completedAt
  • POST /api/v1/media/uploads — presigned PUT URL (max 200 MB; videos never pass through Netlify). Response includes uploadUrl, not storage paths
  • POST /api/v1/media/:id/complete — enqueue the existing encode worker for videos
  • POST /api/v1/media/import — validate an https URL, return a signed PUT (bytes are not proxied)
  • GET /api/v1/media/:id — poll until ready. Media URLs go through /api/v1/media/:id/files/shared|vertical. urls.vertical is omitted when it is the same file as shared
  • GET /api/v1/folders, POST /api/v1/folders, DELETE /api/v1/folders/:id
  • GET /api/v1/gallery — folderId, limit max 200, cursor. URLs expire, use an opaque token, and do not put the user UUID in the path
  • GET /api/v1/gallery/files/:fileName — streams bytes (opaque ?token=)
  • GET /api/v1/profile/updates — Profile → Updates changelog. Optional since, limit
  • POST /api/v1/gallery/move — { "fileName", "folderId" } (folderId null = All). Missing file → 404
  • POST /api/v1/posts — Idempotency-Key optional; one scheduled_posts row per account
  • GET /api/v1/posts — status (including deleted), source=all|api|app, companyId, from/to ISO-8601, limit max 100, cursor
  • GET /api/v1/posts/:id — post group id only. PATCH/DELETE with a platform row id affect only that row
  • GET /api/v1/inbox — comments, mentions, and messages. kind, companyId, unread, limit, cursor
  • GET /api/v1/inbox/:id — thread + messages. Optional markRead=true
  • POST /api/v1/inbox/:id/reply — { "body" } (sends on the platform)
  • POST /api/v1/inbox/sync — pull from connected accounts. Optional companyId and kind
  • GET /api/v1/webhooks, POST /api/v1/webhooks, DELETE /api/v1/webhooks/:id — HTTPS callback. Omitting events subscribes to every event. Secret shown once. X-Postlaty-Signature is HMAC-SHA256 of the raw body

3. Upload a video and schedule TikTok + Instagram

# 1) List accounts
curl -s https://www.postlaty.com/api/v1/accounts \
  -H "Authorization: Bearer $POSTLATY_API_KEY"

# 2) Create a signed upload (video bytes go straight to Storage)
UPLOAD=$(curl -s https://www.postlaty.com/api/v1/media/uploads \
  -H "Authorization: Bearer $POSTLATY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"kind":"video","filename":"clip.mp4","contentType":"video/mp4"}')
MEDIA_ID=$(echo "$UPLOAD" | jq -r .id)
PUT_URL=$(echo "$UPLOAD" | jq -r .uploadUrl)

curl -X PUT --data-binary @clip.mp4 -H "Content-Type: video/mp4" "$PUT_URL"
curl -s https://www.postlaty.com/api/v1/media/$MEDIA_ID/complete \
  -X POST -H "Authorization: Bearer $POSTLATY_API_KEY"

# 3) Poll until ready (encode worker writes shared.mp4 + 9:16)
while true; do
  STATUS=$(curl -s https://www.postlaty.com/api/v1/media/$MEDIA_ID \
    -H "Authorization: Bearer $POSTLATY_API_KEY" | jq -r .status)
  [ "$STATUS" = "ready" ] && break
  sleep 5
done

# 4) Schedule 14:30 Europe/Paris to TikTok + Instagram
curl -s https://www.postlaty.com/api/v1/posts \
  -H "Authorization: Bearer $POSTLATY_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "accountIds": ["TIKTOK_ACCOUNT_ID", "INSTAGRAM_ACCOUNT_ID"],
    "caption": "Shipped from the API",
    "mediaIds": ["'"$MEDIA_ID"'"],
    "scheduledAt": "2026-10-02T14:30",
    "timezone": "Europe/Paris",
    "tiktok": { "privacyLevel": "PUBLIC_TO_EVERYONE", "allowComment": true }
  }'

# 5) Poll group status
curl -s https://www.postlaty.com/api/v1/posts/$GROUP_ID \
  -H "Authorization: Bearer $POSTLATY_API_KEY"

4. Platform rules

  • TikTok, Instagram, and YouTube require media. Those three use the 9:16 encode; other platforms use the shared file.
  • Pinterest requires an image. Pixelfed requires a photo.
  • If a platform does not support the media type, the file is not sent and is not turned into a storage link (see the table below).
  • Schedule at least 1 minute ahead, or pass now: true / publishAt: "now" to publish immediately.
  • publishAt must include a timezone offset. scheduledAt is local wall time and needs an IANA timezone (for example Europe/Paris).

Capabilities

Messages, comments, and mentions: Yes means read and reply in Inbox. Mentions are @tags and tagged posts.

PlatformConnectPublishMessagesCommentsMentionsNotes
YouTubeOAuthYes, media requiredNoYesNoComments on your videos. No DMs.
TikTokOAuthYes, media requiredNoNoNoNo comments or DMs on Login Kit / Content Posting. Reconnect TikTok if Published views stay empty so video.list is granted.
InstagramOAuthYes, media requiredYesYesYesComments, tagged posts in Mentions, and DMs on the connected professional account. Reconnect Instagram if Messages is empty so instagram_manage_messages is granted.
FacebookOAuthYesYesYesYesPage comments, tagged posts in Mentions, and Page inbox. Reconnect Facebook if Messages is empty so Page inbox (pages_messaging) is granted. Not a personal profile.
ThreadsOAuthYesYesYesYesReplies, mentions, and DMs after a Meta login popup.
XOAuthYesYesNoNoDMs in Messages after you reconnect once for dm.read / dm.write. Comments, mentions, and analytics are paused: those X API endpoints need a paid plan.
LinkedInOAuthYesNoYesNoComments on your posts after reconnect. Personal and Page analytics after reconnect. Member DMs are partner-only. Ads reporting uses a separate LinkedIn app.
BlueskyCredentialsYesYesYesYesReplies in Comments, @mentions in Mentions, and chat in Messages. Native images (up to 4) and video.
RedditOAuthPerson or groupYesYesYesComments on your posts, username mentions in Mentions, and inbox messages.
PinterestOAuthYes, media requiredNoYesNoPin comments. Image required. Needs a free Business account. No DMs.
TelegramCredentialsPerson or groupYesNoNoCreate sends as you to the person, group, or channel you pick at connect.
DiscordOAuthPerson or groupYesNoNoCreate sends to the channel or user set at connect.
SlackOAuthPerson or groupYesNoNoCreate sends to the channel or user set at connect.
WhopCredentialsPerson or groupYesYesNoFeed comments and DMs for the connected experience.
SkoolCredentialsPerson or groupNoYesNoClassroom comments via unofficial cookies. No DMs.
MastodonCredentialsYesNoYesYesReplies on your posts in Comments, @mentions in Mentions. No DMs.
TumblrOAuthYesNoYesYesPosts to one blog. Replies in Comments, mentions in Mentions when the token allows. No DMs.
Dev.toCredentialsYesNoNoNoPublishes as an article with a separate title on Create. No inbox.
PixelfedCredentialsYes, media requiredNoYesYesAny Pixelfed server. Photo required. Mentions and replies like Mastodon. No DMs.

Publishing

Same rules as Create and POST /api/v1/posts / MCP create_post. First media item only unless noted. Unsupported media is not sent and is never pasted as a storage URL.

PlatformText-onlyImagesVideosNotes
YouTube❌❌✅All videos in Shorts
TikTok❌✅ Up to 35✅Media required
Instagram❌⚠️ First only✅ ReelsAspect ratio 4:5-1.91:1
Facebook✅⚠️ First only⚠️ First only-
Threads✅⚠️ First only⚠️ First onlyFirst media item only
X✅✅ Multiple✅Mixed media supported
LinkedIn✅✅ Carousel✅-
Bluesky✅✅ Up to 4✅ First onlyNative Bluesky image and video upload
Reddit✅❌❌Media not supported
Pinterest❌✅ First only❌Image required
Telegram✅⚠️ First only⚠️ First onlySends as you to the chat picked at connect
Discord✅❌❌Media not supported
Slack✅❌❌Media not supported
Whop✅❌❌Media not supported
Skool✅❌❌Title field on Create; caption is the body. Media not supported
Mastodon✅⚠️ First only❌Native image upload of the first file. Video not supported
Tumblr✅⚠️ First only⚠️ First onlyNative image or video block
Dev.to✅❌❌Title field on Create; caption is the body. Media not supported
Pixelfed❌✅ First only⚠️ First onlyAny Pixelfed server. Photo required