Publish Post
Publish, schedule, reply to a post, or create a social media thread.
Publish, schedule, reply to a post, or create a social media thread.
/api/v1/post/publishPublish, schedule, reply to a post, or create a thread.
{
"accountId": "<accountId>",
"text": "Your post content here",
"media": ["<mediaUrl>"],
"publishAt": "2027-01-20T12:00:00Z"
}{
"accountId": "<accountId>",
"text": "Your post content here",
"media": ["<mediaUrl>"],
"publishAt": "2027-01-20T12:00:00Z"
}| Field | Type | Required | Description |
|---|---|---|---|
accountId | string | Yes | ID of the connected social account |
text | string | Conditional | Post text content. Required if no media provided |
media | array | Conditional | Public URLs or media objects with URL, MIME type and optional size/duration/dimensions; conditional on post type |
publishAt | string | null | No | ISO 8601 date for scheduling. null or omitted = publish now |
timezone | string | No | Optional IANA override. Defaults to the workspace timezone. |
replyTo | string | No | External platform post ID to reply to. Supported on X and Threads; this is not a dopost post ID |
thread | object[] | No | Ordered follow-up posts. Supported on X, Threads, and Mastodon. See Replies and threads |
platformOptions | object | No | Platform-specific overrides. See Platform options |
At least one of text or media must be provided, except for Google Business events and offers.
{
"success": true,
"jobId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"postId": "cm3abc123def456",
"status": "processing",
"threadPosts": 1,
"message": "Post accepted and processing. Use get_post with postId to check the final publishing result."
}{
"success": true,
"jobId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"postId": "cm3abc123def456",
"status": "processing",
"threadPosts": 1,
"message": "Post accepted and processing. Use get_post with postId to check the final publishing result."
}Publishing is asynchronous. Use the postId with the Get Post endpoint to check the result.
Use replyTo to reply to an existing X or Threads post. It must contain the external ID assigned by the social platform, not the internal postId returned by dopost.
{
"accountId": "<xAccountId>",
"text": "A reply published with dopost",
"replyTo": "<externalPlatformPostId>"
}{
"accountId": "<xAccountId>",
"text": "A reply published with dopost",
"replyTo": "<externalPlatformPostId>"
}Use thread to publish an ordered reply chain on X, Threads, or Mastodon. text and media at the top level create the first post; every item in thread replies to the previous post.
{
"accountId": "<xAccountId>",
"text": "First post in the thread",
"thread": [
{ "text": "Second post" },
{
"text": "Third post with media",
"media": ["<mediaUrl>"]
}
]
}{
"accountId": "<xAccountId>",
"text": "First post in the thread",
"thread": [
{ "text": "Second post" },
{
"text": "Third post with media",
"media": ["<mediaUrl>"]
}
]
}thread item | Type | Required | Description |
|---|---|---|---|
text | string | Yes | Follow-up post text |
media | array | No | Up to four public media URLs for this follow-up post |
A thread can contain between 1 and 20 follow-up posts. Platform-specific content limits still apply. You can combine replyTo and thread on X or Threads to reply to an existing post and continue with a new chain.
To schedule a post for later, pass a future ISO 8601 date in the publishAt field:
{
"accountId": "<accountId>",
"text": "Scheduled post!",
"publishAt": "2027-01-20T12:00:00Z"
}{
"accountId": "<accountId>",
"text": "Scheduled post!",
"publishAt": "2027-01-20T12:00:00Z"
}The publishAt date must be in the future. Past dates will return a 400 error.
Pass an array of publicly accessible URLs:
{
"accountId": "<accountId>",
"text": "Check this out!",
"media": ["<mediaUrl>", "<mediaUrl>"]
}{
"accountId": "<accountId>",
"text": "Check this out!",
"media": ["<mediaUrl>", "<mediaUrl>"]
}Media types are auto-detected from the URL extension. Supported formats depend on the target platform — use the Limits endpoint to check.
Telegram accepts up to 10 JPEG, PNG, WebP, or MP4 items per post. Text-only messages allow 4,096 characters; captions on media posts allow 1,024 characters. Photos may be up to 10 MB and MP4 videos up to 50 MB.
Instagram and LinkedIn each have two connection types (INSTAGRAM / INSTAGRAM_DIRECT, LINKEDIN / LINKEDIN_ORGANIZATION). Use the platform value from List Accounts to determine which one applies to your connected account.
Some platforms accept additional configuration via the optional platformOptions field. All properties are optional — defaults are applied when omitted.
| Option | Type | Default | Description |
|---|---|---|---|
postType | string | "feed" | "feed" | "story" | "reel". Automatically set to "carousel" when multiple media items are provided. |
shareToFeed | boolean | Provider legacy behavior when omitted | Only for postType: "reel". Send true to show the Reel in Feed and Reels, or false for Reels only. Feed videos always use true. |
An explicitly selected feed, reel, or story accepts one media item. Requests with multiple items must use carousel; dopost rejects conflicting explicit post types instead of silently publishing only the first item. Existing scheduled Reels that do not contain shareToFeed keep the previous provider behavior.
| Option | Type | Default | Description |
|---|---|---|---|
pin | boolean | false | Pin the published message, or the first message in a media album. The bot must have permission to pin messages. |
| Option | Type | Default | Description |
|---|---|---|---|
privacyLevel | string | "PUBLIC_TO_EVERYONE" | "PUBLIC_TO_EVERYONE" | "MUTUAL_FOLLOW_FRIENDS" | "FOLLOWER_OF_CREATOR" | "SELF_ONLY" |
disableDuet | boolean | false | Prevent others from creating duets |
disableStitch | boolean | false | Prevent others from stitching your video |
disableComment | boolean | false | Disable comments on the video |
discloseContent | boolean | false | Mark the post as promotional or branded content |
isYourBrand | boolean | false | When disclosing content, identify promotion of your own brand |
isBrandedContent | boolean | false | When disclosing content, identify promotion of a third-party brand |
When discloseContent is true, set at least one of isYourBrand or isBrandedContent to true. TikTok account-level privacy restrictions still apply.
| Option | Type | Default | Description |
|---|---|---|---|
videoType | string | "video" | "video" | "short" |
title | string | First 100 chars of text | Video title |
privacyStatus | string | "public" | "public" | "private" | "unlisted" |
| Option | Type | Default | Description |
|---|---|---|---|
board | string | "" | Board ID to pin to. Required for Pinterest posts. |
Use a connected Google Business location as accountId. Standard updates accept up to 1,500 characters and one image; gallery media posts contain no text.
| Option | Type | Description |
|---|---|---|
postType | string | "standard" | "event" | "offer" | "media" |
ctaType | string | "book" | "order" | "shop" | "learn_more" | "sign_up" | "call" |
ctaUrl | string | Public HTTP(S) URL. Required for every CTA except call; omit for call |
eventTitle | string | Required for events and offers |
eventStart, eventEnd | string | Required ISO dates; unzoned values use the workspace timezone |
couponCode | string | Optional offer coupon code |
redeemOnlineUrl | string | Optional public HTTP(S) offer redemption URL |
termsConditions | string | Optional offer terms |
mediaCategory | string | Gallery category; defaults to ADDITIONAL |
Offers do not accept a separate CTA. Google Business scheduling is handled by dopost and delivered when publishAt is reached.
{
"accountId": "<googleBusinessLocationAccountId>",
"text": "Join us for our weekend tasting",
"media": ["https://cdn.example.com/tasting.jpg"],
"publishAt": "2027-01-20T10:00:00",
"platformOptions": {
"postType": "event",
"eventTitle": "Weekend tasting",
"eventStart": "2027-01-23T17:00:00",
"eventEnd": "2027-01-23T20:00:00",
"ctaType": "book",
"ctaUrl": "https://example.com/book"
}
}{
"accountId": "<googleBusinessLocationAccountId>",
"text": "Join us for our weekend tasting",
"media": ["https://cdn.example.com/tasting.jpg"],
"publishAt": "2027-01-20T10:00:00",
"platformOptions": {
"postType": "event",
"eventTitle": "Weekend tasting",
"eventStart": "2027-01-23T17:00:00",
"eventEnd": "2027-01-23T20:00:00",
"ctaType": "book",
"ctaUrl": "https://example.com/book"
}
}Use List X Communities to discover the Communities saved for an X account, then pass the selected communityId:
| Option | Type | Default | Description |
|---|---|---|---|
communityId | string | — | Saved Community ID, numeric Community ID, or x.com Community URL |
shareWithFollowers | boolean | true | Also distribute the same Community Post to the account's followers |
{
"accountId": "<xAccountId>",
"text": "Community update",
"platformOptions": {
"communityId": "1493446837214187523",
"shareWithFollowers": false
}
}{
"accountId": "<xAccountId>",
"text": "Community update",
"platformOptions": {
"communityId": "1493446837214187523",
"shareWithFollowers": false
}
}Community Posts cannot also use replyTo. The account must be a member of the selected Community and have permission to post there.
| Status | Error | Cause |
|---|---|---|
400 | accountId is required | Missing accountId field |
400 | text or media is required | Neither text nor media provided |
400 | publishAt must be a valid future ISO date | Invalid or past date |
400 | replyTo must be a platform post ID | Empty, invalid, or oversized external post ID |
400 | thread must contain between 1 and 20 posts | Empty or oversized thread |
400 | thread is supported only for X, Threads, and Mastodon | Threads requested for an unsupported platform |
400 | Invalid payload | Content doesn't meet platform requirements |
401 | Invalid or missing API key | Bad or missing x-api-key header |
403 | API key does not have permission for this action | API key lacks the required scope |
404 | Account not found or inactive | Account ID doesn't exist or is disconnected |
429 | Monthly post limit reached | Your plan's monthly post quota has been exceeded. Upgrade your plan or wait for the next billing cycle |
429 | Rate limit exceeded | Too many requests. Check X-RateLimit-* response headers and retry after the indicated time |
Select a platform to see a complete publish request with platform-specific options and inline comments:
const res = await fetch("https://dopost.co/api/v1/post/publish", {
method: "POST",
headers: {
"x-api-key": "<apiKey>",
"Content-Type": "application/json",
},
body: JSON.stringify({
accountId: "<accountId>",
text: "Your caption here",
media: [
{ url: "https://example.com/image.jpg", alt: "Image description" },
],
platformOptions: {
postType: "feed", // "feed" | "story" | "reel". Multiple media → "carousel" automatically
},
}),
});const res = await fetch("https://dopost.co/api/v1/post/publish", {
method: "POST",
headers: {
"x-api-key": "<apiKey>",
"Content-Type": "application/json",
},
body: JSON.stringify({
accountId: "<accountId>",
text: "Your caption here",
media: [
{ url: "https://example.com/image.jpg", alt: "Image description" },
],
platformOptions: {
postType: "feed", // "feed" | "story" | "reel". Multiple media → "carousel" automatically
},
}),
});Unzoned dates and times (2027-01-20T10:00:00) use the workspace IANA timezone automatically. Dates with Z or an explicit offset retain their instant; dopost converts and stores UTC. Nonexistent local times during a daylight-saving transition are rejected. Include an explicit offset to distinguish repeated local times.
Publish and reschedule requests accept an optional IANA timezone override, such as Europe/Madrid. For recurring posts, timezone selects the series and initial-date timezone and defaults to the workspace timezone. Updating a series retains its existing timezone. recurrence.endDate is the series' final calendar date.
event and offer require eventTitle, eventStart, and eventEnd; summary and image are optional. End must follow start; an event may have started before publication. standard requires text or one image. Standard/event/offer accept one JPG/PNG image; this integration does not support Local Post video.
media publishes one JPG/PNG or MP4 to the gallery, with no text or CTA. PROFILE and COVER require photos; deprecated LOGO aliases PROFILE. Cover descriptions are omitted. An accepted PROFILE photo updates the connected account's dopost avatar.
The API validates again after resolving actual Media metadata. Known errors return 400 with issues; external URLs without metadata remain subject to Google's processing checks. 202 means accepted by dopost. Poll the post for its result and providerStatus: a resource accepted by Google can remain PROCESSING and not yet be publicly visible.
See the Google Business guide and limits.