API Reference for LLMs

This is the machine-readable API reference for AI agents and LLM integrations.

BLOTATO API REFERENCE
=====================

Base URL: https://backend.blotato.com/v2
Auth Header: blotato-api-key: YOUR_API_KEY
Content-Type: application/json

All creation operations are ASYNC. Submit a request, then poll for status.

Docs: https://help.blotato.com/api/start
OpenAPI: https://help.blotato.com/api/api-reference/openapi-reference
Errors: https://help.blotato.com/support/errors

================================================================================
ENDPOINTS
================================================================================

ACCOUNTS
  GET  /users/me              - Verify API key, get user info
  GET  /users/me/accounts     - List connected social accounts (get accountId)
  GET  /users/me/accounts/:accountId/subaccounts - Get Facebook/LinkedIn pageId

PUBLISHING
  POST /posts                 - Create/publish a post (30 req/min)
  GET  /posts/:postSubmissionId - Poll post status (60 req/min)

VISUALS
  POST /videos/from-templates - Create visual from template (30 req/min)
  GET  /videos/creations/:id  - Poll visual status
  GET  /videos/templates      - List available templates
  DELETE /videos/:id          - Delete a video

SOURCES (Content Extraction)
  POST /source-resolutions-v3 - Extract content from URL/text (30 req/min)
  GET  /source-resolutions-v3/:id - Poll source status (60 req/min)

MEDIA
  POST /media                 - Upload media from URL (30 req/min, optional)

================================================================================
STEP 0: GET ACCOUNTS (always do this first)
================================================================================

GET /users/me/accounts
GET /users/me/accounts?platform=twitter  (filter by platform)

Response:
{
  "items": [
    { "id": "98432", "platform": "twitter", "fullname": "Jane", "username": "jane" }
  ]
}

For Facebook/LinkedIn, also fetch subaccounts to get pageId:
GET /users/me/accounts/98432/subaccounts

Response:
{
  "items": [
    { "id": "123456789", "accountId": "98432", "name": "My Business Page" }
  ]
}

Use items[].id as target.pageId when publishing to Facebook or LinkedIn.

Pinterest boardId is not available via API. Ask the user for it.

================================================================================
PUBLISHING A POST
================================================================================

POST /posts

Minimal payload (Twitter):
{
  "post": {
    "accountId": "98432",
    "content": {
      "text": "Hello world",
      "mediaUrls": [],
      "platform": "twitter"
    },
    "target": {
      "targetType": "twitter"
    }
  }
}

RULES:
- content.platform and target.targetType must be set to the same value
- mediaUrls is required. Pass [] for text-only posts. Pass public URLs for media.
- accountId comes from GET /users/me/accounts
- No upload step needed. Pass any public URL in mediaUrls.

Platform-specific target fields:
- twitter: no extra fields
- instagram: mediaType ("reel"|"story"), collaborators, altText, coverImageUrl
- facebook: pageId (REQUIRED, from subaccounts), mediaType, link
- linkedin: pageId (optional, from subaccounts for company pages)
- tiktok: privacyLevel, disabledComments, disabledDuet, disabledStitch,
          isBrandedContent, isYourBrand, isAiGenerated (ALL REQUIRED)
- pinterest: boardId (REQUIRED, manual from user), title, altText, link
- threads: replyControl
- bluesky: no extra fields
- youtube: title (REQUIRED), privacyStatus (REQUIRED), shouldNotifySubscribers (REQUIRED)
- webhook: url (REQUIRED)

Response: { "postSubmissionId": "uuid" }

Poll: GET /posts/{postSubmissionId}
Status values: "in-progress" | "published" | "failed"
- published: response includes "publicUrl"
- failed: response includes "errorMessage"

================================================================================
CREATING VISUALS
================================================================================

POST /videos/from-templates

RECOMMENDED: Use "prompt" to describe what you want. Set "inputs" to {}.
AI fills in the template inputs automatically from your prompt.
Do NOT manually construct the "inputs" object unless you have a specific reason.

templateId: Use the bare UUID from the templates list (e.g., "77f65d2b-48cc-4adb-bfbb-5bc86f8c01bd").
Do NOT use the full path format (e.g., "/base/v2/quote-card/.../v1").

CORRECT:
{
  "templateId": "77f65d2b-48cc-4adb-bfbb-5bc86f8c01bd",
  "inputs": {},
  "prompt": "Create 5 motivational quotes about entrepreneurship",
  "render": true
}

WRONG (do not manually fill inputs, use prompt instead):
{
  "templateId": "77f65d2b-48cc-4adb-bfbb-5bc86f8c01bd",
  "inputs": { "text": "Slide 1: ..." },
  "render": true
}

Response: { "item": { "id": "vid_123", "status": "queueing" } }

Poll: GET /videos/creations/{id}
Status values: "queueing" | "generating-script" | "script-ready" |
               "generating-media" | "media-ready" | "exporting" |
               "done" | "creation-from-template-failed"

Terminal states: "done" (success) or "creation-from-template-failed" (failure)
When done: response includes "mediaUrl" and/or "imageUrls"

Use mediaUrl or imageUrls in your publish request's mediaUrls field.

Discover templates: GET /videos/templates?fields=id,name,description,inputs
Template reference: https://help.blotato.com/api/visuals

================================================================================
EXTRACTING CONTENT (SOURCES)
================================================================================

POST /source-resolutions-v3

Body MUST contain a "source" object. Do NOT put fields at the top level.

source.sourceType (REQUIRED, no auto-detection):
- "text"             - Transform raw text (uses source.text)
- "article"          - Extract from article URL (uses source.url)
- "youtube"          - Extract from YouTube URL (uses source.url)
- "twitter"          - Extract from Twitter/X URL (uses source.url)
- "tiktok"           - Extract from TikTok URL (uses source.url)
- "perplexity-query" - AI web research (uses source.text)
- "audio"            - Extract from audio URL (uses source.url)
- "pdf"              - Extract from PDF URL (uses source.url)

CORRECT:
{
  "source": {
    "sourceType": "youtube",
    "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
  }
}

WRONG (missing "source" wrapper):
{ "sourceType": "youtube", "url": "..." }

Response: { "id": "src_123" }

Poll: GET /source-resolutions-v3/{id}
Status values: "queued" | "processing" | "completed" | "failed"
When completed: response includes "content" and "title"

================================================================================
COMPLETE WORKFLOW (for AI agents)
================================================================================

1. accounts = GET /users/me/accounts
2. sourceId = POST /source-resolutions-v3 { source: { sourceType, url/text } }
3. POLL: GET /source-resolutions-v3/{sourceId} until status = "completed"
4. videoId = POST /videos/from-templates { templateId, prompt, render: true }
5. POLL: GET /videos/creations/{videoId} until status = "done"
6. postId = POST /posts { post: { accountId, content: { text, mediaUrls, platform }, target: { targetType } } }
7. POLL: GET /posts/{postId} until status = "published"
8. DONE: use publicUrl from step 7

================================================================================
RATE LIMITS
================================================================================

POST /posts:                    30 requests / minute
GET  /posts/:id:                60 requests / minute
POST /videos/from-templates:    30 requests / minute
POST /source-resolutions-v3:    30 requests / minute
GET  /source-resolutions-v3/:id: 60 requests / minute
POST /media:                    30 requests / minute
GET  /users/me/accounts:        No limit
GET  /users/me:                 No limit

429 response means rate limit exceeded. Check "message" for retry timing.

Last updated