Skip to content

Schedule a post

POST
/v1/social/posts

Creates one post per target account, so Platforms: ["instagram","linkedin"] with an account on each network returns two posts. Targets are the caller’s active accounts on the requested platforms, narrowed by AccountIds when given.

SAFE-WRITE BOUNDARY: ScheduledAt is required unless PublishNow: true is passed explicitly, which publishes to a live audience immediately. A request with neither is rejected with 400 rather than stored, because the scheduler has no draft state to hold it in.

Per-platform rules are enforced before anything is written (TikTok and YouTube need a video, Instagram needs media, X caps at 280 characters), as are the per-account daily limit and the monthly X fair-use quota. If some targets are accepted and others rejected, the response is 201 and the rejected ones appear under Errors. Requires scope posts:write.

Idempotency-Key
string
<= 255 characters

A unique string of your choosing (a UUID works). The first request with this key runs normally and its response is stored for 24 hours; a retry with the same key returns that stored response verbatim, with Idempotency-Replayed: true, instead of writing again. Reusing a key with a different body returns 409.

object
content

Post text. Required unless mediaUrls is given.

string
platforms
required

Networks to publish on, e.g. [“instagram”, “linkedin”].

Array<string>
>= 1 items
Example
[
"instagram",
"linkedin"
]
accountIds

Narrow the fan-out to specific connected accounts (ids from GET /v1/social/accounts).

Array<integer>
scheduledAt

When to publish. Required unless publishNow is true, and must be in the future.

string format: date-time
mediaUrls
Array<string>
<= 10 items
timeZone

IANA zone that scheduledAt is expressed in when it carries no offset. Ignored for a value that already has one.

string
Example
Europe/Istanbul
publishNow

Publish immediately instead of scheduling. Must be set explicitly; this reaches a live audience.

boolean

Post or posts created.

object
count

Posts actually created.

integer
posts
Array<object>

One scheduled or published post on a single account.

object
id
integer
accountId

Connected account id

integer
nullable
externalAccountId
string
platform
string
Example
linkedin
content
string
mediaUrls
Array<string>
nullable
scheduledAt

Publish instant

string format: date-time
status
string
Allowed values: pending processing published failed cancelled partiallypublished
externalPostId

The network’s post id

string
nullable
publishedUrl
string
nullable
errorMessage
string
nullable
retryCount
integer
createdAt
string format: date-time
updatedAt
string format: date-time
nullable
publishedAt
string format: date-time
nullable
errors

Targets rejected by a platform rule or a quota. Null when every target succeeded.

Array<object>
nullable
object
accountId
integer
platform
string
message
string

The request body or parameters failed validation.

Standard error envelope for all v1 error responses.

object
error

Machine-readable error code.

string
Allowed values: bad_request not_found conflict unauthorized forbidden payment_required provider_rejected rate_limited internal_error
message

Human-readable explanation of the error.

string
details

Optional structured context (field-level validation errors, etc.).

nullable
Example
{
"error": "bad_request",
"message": "at least one of name, username, phone is required"
}

Missing or invalid bearer token.

Standard error envelope for all v1 error responses.

object
error

Machine-readable error code.

string
Allowed values: bad_request not_found conflict unauthorized forbidden payment_required provider_rejected rate_limited internal_error
message

Human-readable explanation of the error.

string
details

Optional structured context (field-level validation errors, etc.).

nullable
Example
{
"error": "unauthorized",
"message": "Invalid bearer principal"
}

The workspace’s plan does not include this module. The social inbox needs channel_social_inbox and the post scheduler needs marketing_social_scheduler; details.FeatureKey names the one that is missing. Upgrading unlocks it, there is nothing to retry.

Standard error envelope for all v1 error responses.

object
error

Machine-readable error code.

string
Allowed values: bad_request not_found conflict unauthorized forbidden payment_required provider_rejected rate_limited internal_error
message

Human-readable explanation of the error.

string
details

Optional structured context (field-level validation errors, etc.).

nullable
Example
{
"error": "payment_required",
"message": "your plan does not include this feature; upgrade to unlock it",
"details": {
"FeatureKey": "marketing_social_scheduler",
"UpgradeRequired": true
}
}

The API key does not have the required scope for this operation.

Standard error envelope for all v1 error responses.

object
error

Machine-readable error code.

string
Allowed values: bad_request not_found conflict unauthorized forbidden payment_required provider_rejected rate_limited internal_error
message

Human-readable explanation of the error.

string
details

Optional structured context (field-level validation errors, etc.).

nullable
Example
{
"error": "forbidden",
"message": "scope contacts:write is required"
}

The request collides with existing state: a duplicate externalId, an Idempotency-Key replayed with a different body or still in flight, or a permanent delete blocked by records that still reference the contact.

Standard error envelope for all v1 error responses.

object
error

Machine-readable error code.

string
Allowed values: bad_request not_found conflict unauthorized forbidden payment_required provider_rejected rate_limited internal_error
message

Human-readable explanation of the error.

string
details

Optional structured context (field-level validation errors, etc.).

nullable
Example
{
"error": "conflict",
"message": "a contact with externalId 'shopify-cust-88213' already exists",
"details": {
"existingContactId": 4821
}
}