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.
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.
| Header | Required | Description |
|---|
Content-Type | Yes | Must be application/json |
soku-api-key | Yes | Your Soku API key |
Idempotency-Key | No | A 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:
| Field | Type | Required | Description |
|---|
post | object | Yes | The post content and targeting configuration |
scheduledTime | string | No | ISO 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. |
enableRepurposing | boolean | No | Set to true to trigger your automation workflows (reposting and content repurposing) for this post. Defaults to false. See Automations for details. |
trial_reel | boolean | No | Set 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
| Field | Type | Required | Description |
|---|
post.content | object | Yes | The content payload for the post |
Content Object
| Field | Type | Required | Description |
|---|
content.text | string | No | The text body of the post (caption, tweet, etc.) |
content.mediaType | string | No | The media type: "video", "image", or "text" |
content.mediaUrls | string[] | No | Array of media URLs (general-purpose, for any media type) |
content.videoUrl | string | No | URL of the video file. Use when mediaType is "video". |
content.imageUrls | string[] | No | Array of image URLs. Use when mediaType is "image". |
content.platform | string or array | Yes | A single platform string, or an array of platform targets. Each array element can be a string or a platform object. |
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"
]
| Field | Type | Required | Description |
|---|
platform | string | Yes | The platform name: "facebook", "facebook_pages", "instagram", "threads", "tiktok", "youtube", "x", "linkedin", "snapchat" |
accountId | string | Conditional | The 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
| Field | Type | Description |
|---|
postSubmissionId | string | A 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 Status | Error Code | Description |
|---|
| 400 | validation_error | Missing or invalid fields in the request body |
| 400 | missing_integrations | One or more target platforms are not connected to your account |
| 400 | missing_account | The specified accountId does not exist for the given platform |
| 400 | upload_failed | Media URL could not be fetched or stored |
| 401 | unauthorized | Missing or invalid API key |
| 403 | forbidden | Subscription is not active |
| 409 | idempotency_conflict | Same idempotency key used with a different request body |
| 429 | rate_limit_exceeded | Too many requests. See Rate Limits. |
| 500 | dispatch_failed | The post was created but delivery to one or more platforms failed |
| 500 | post_creation_failed | An 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
| Topic | Description |
|---|
| Media API | Upload media files before attaching them to posts |
| Templates API | Generate OG images to include in posts |
| Error Handling | Full reference of error codes and troubleshooting |