Skip to main content

Posts API

The Posts API lets you create and submit posts to one or more social media platforms through a single API call. You can publish immediately or schedule posts for a future time.

Create a Post

Submit a new post for publishing.
POST /v1/posts

Authentication

This endpoint uses API key authentication. Include your API key in the soku-api-key header. An active Soku subscription (trialing or active) is required.

Headers

HeaderRequiredDescription
Content-TypeYesMust be application/json
soku-api-keyYesYour Soku API key
Idempotency-KeyNoA unique string to prevent duplicate post submissions. See Idempotency.

Rate Limit

30 requests per 60 seconds, in addition to the global tier limit. See Rate Limits.

Request Body

The request body is a JSON object with the following top-level fields:
FieldTypeRequiredDescription
postobjectYesThe post content and targeting configuration
scheduledTimestringNoISO 8601 timestamp for scheduling. If omitted, the post is published immediately. Must be at least 1 minute in the future. An invalid format returns a 400 error with code validation_error.
enableRepurposingbooleanNoSet to true to trigger your automation workflows (reposting and content repurposing) for this post. Defaults to false. See Automations for details.
trial_reelbooleanNoSet to true to publish Instagram Reels as trial reels with limited visibility. Defaults to false. Only applies to video posts targeting Instagram. Ignored for other platforms and non-video content.

Post Object

FieldTypeRequiredDescription
post.contentobjectYesThe content payload for the post

Content Object

FieldTypeRequiredDescription
content.textstringNoThe text body of the post (caption, tweet, etc.)
content.mediaTypestringNoThe media type: "video", "image", or "text"
content.mediaUrlsstring[]NoArray of media URLs (general-purpose, for any media type)
content.videoUrlstringNoURL of the video file. Use when mediaType is "video".
content.imageUrlsstring[]NoArray of image URLs. Use when mediaType is "image".
content.platformstring or arrayYesA single platform string, or an array of platform targets. Each array element can be a string or a platform object.

Platform Targets

Each element in the platform array specifies a destination for the post. There are two formats: String format (single account): Use a plain string when you have only one connected account for a platform, or to target the default account.
"platform": ["threads", "x"]
Object format (multi-account): Use an object when you need to target a specific account for a platform. The accountId field is required when you have multiple accounts connected for the same platform.
"platform": [
  { "platform": "instagram", "accountId": "ig_main" },
  { "platform": "instagram", "accountId": "ig_brand" },
  "threads"
]
FieldTypeRequiredDescription
platformstringYesThe platform name: "facebook", "facebook_pages", "instagram", "threads", "tiktok", "youtube", "x", "linkedin", "snapchat"
accountIdstringConditionalThe ID of the specific account to target. Required when multiple accounts are connected for the same platform.
You can mix string and object formats in the same platform array. Use objects only where you need to specify an accountId.

Response

Status: 201 Created
FieldTypeDescription
postSubmissionIdstringA unique identifier for the post submission. Use this to track the status of the post.
{
  "postSubmissionId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

Examples

Publish a text post immediately

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: sk_live_your_api_key_here" \
  -d '{
    "post": {
      "content": {
        "text": "Just shipped a new feature. Check it out!",
        "mediaType": "text",
        "platform": ["threads", "x", "linkedin"]
      }
    }
  }'

Publish a video post to specific accounts

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: sk_live_your_api_key_here" \
  -d '{
    "post": {
      "content": {
        "text": "New product walkthrough",
        "mediaType": "video",
        "videoUrl": "https://storage.mysoku.io/media/abc123/video.mp4",
        "platform": [
          { "platform": "instagram", "accountId": "ig_main" },
          { "platform": "tiktok", "accountId": "tt_brand" },
          "youtube"
        ]
      }
    }
  }'

Publish an image post with multiple images

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: sk_live_your_api_key_here" \
  -d '{
    "post": {
      "content": {
        "text": "Behind the scenes from today'\''s shoot",
        "mediaType": "image",
        "imageUrls": [
          "https://storage.mysoku.io/media/img1.jpg",
          "https://storage.mysoku.io/media/img2.jpg",
          "https://storage.mysoku.io/media/img3.jpg"
        ],
        "platform": ["instagram", "facebook"]
      }
    }
  }'

Schedule a post for later

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: sk_live_your_api_key_here" \
  -d '{
    "post": {
      "content": {
        "text": "Monday motivation incoming.",
        "mediaType": "text",
        "platform": ["threads", "x"]
      }
    },
    "scheduledTime": "2026-03-09T09:00:00.000Z"
  }'

Publish with an idempotency key

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: sk_live_your_api_key_here" \
  -H "Idempotency-Key: post-launch-announcement-2026-03-07" \
  -d '{
    "post": {
      "content": {
        "text": "We just launched v2.0!",
        "mediaType": "text",
        "platform": ["threads", "x", "linkedin"]
      }
    }
  }'

Publish a video as an Instagram trial reel

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: sk_live_your_api_key_here" \
  -d '{
    "post": {
      "content": {
        "text": "Testing this new video idea",
        "mediaType": "video",
        "videoUrl": "https://storage.mysoku.io/media/abc123/reel.mp4",
        "platform": [{ "platform": "instagram", "accountId": "ig_main" }]
      }
    },
    "trial_reel": true
  }'
When trial_reel is true, your Instagram Reel is published with limited visibility. It is shown to a small audience first so you can see how it performs before sharing it with all of your followers. This flag only applies to video posts targeting Instagram and is ignored for other platforms and non-video content.

Publish and trigger automation workflows

curl -X POST https://api.mysoku.io/v1/posts \
  -H "Content-Type: application/json" \
  -H "soku-api-key: sk_live_your_api_key_here" \
  -d '{
    "post": {
      "content": {
        "text": "New video just dropped!",
        "mediaType": "video",
        "videoUrl": "https://storage.mysoku.io/media/abc123/video.mp4",
        "platform": ["x"]
      }
    },
    "enableRepurposing": true
  }'
When enableRepurposing is true, Soku publishes the post and also feeds it into your configured automation workflows. This means your repost and repurpose rules will apply to this post, just as they would for content detected organically on the source platform. By default, posts created through the API or dashboard do not trigger automations.

Error Responses

HTTP StatusError CodeDescription
400validation_errorMissing or invalid fields in the request body
400missing_integrationsOne or more target platforms are not connected to your account
400missing_accountThe specified accountId does not exist for the given platform
400upload_failedMedia URL could not be fetched or stored
401unauthorizedMissing or invalid API key
403forbiddenSubscription is not active
409idempotency_conflictSame idempotency key used with a different request body
429rate_limit_exceededToo many requests. See Rate Limits.
500dispatch_failedThe post was created but delivery to one or more platforms failed
500post_creation_failedAn internal error occurred while creating the post
Example error response:
{
  "error": {
    "type": "invalid_request_error",
    "code": "missing_integrations",
    "message": "The following platforms are not connected: tiktok. Connect them in Settings > Integrations.",
    "timestamp": "2026-02-28T12:00:00.000Z",
    "requestId": "req_abc123def456",
    "details": {
      "missingPlatforms": ["tiktok"]
    }
  }
}
Ensure all target platforms are connected in your Soku dashboard before making API calls. You can connect platforms in Settings > Integrations.

Idempotency

The Idempotency-Key header prevents duplicate post submissions when retrying requests.
  • Include an Idempotency-Key header with a unique string value (for example, a UUID) on POST /v1/posts requests.
  • If the header is omitted, Soku auto-derives a key from your user ID and a hash of the request payload.
  • If you send the same idempotency key with the same request body, the API returns the original cached response without creating a duplicate post.
  • If you send the same idempotency key with a different request body, the API returns a 409 error with code idempotency_conflict.

Next Steps

TopicDescription
Media APIUpload media files before attaching them to posts
Templates APIGenerate OG images to include in posts
Error HandlingFull reference of error codes and troubleshooting