---
title: "Retry failed post"
method: POST
path: "/v1/posts/{postId}/retry"
tags: ["Posts"]
---

# Retry failed post

`POST /v1/posts/{postId}/retry`

Immediately retries publishing a failed post. Returns the updated post with its new status.

## Path parameters

- `postId` string, required

## Response `200`

Retry successful

- PostRetryResponse
  - `message` string
  - `post` Post
    - `_id` string
    - `userId` union
      - string
      - User
        - `_id` string
        - `email` string
        - `name` string
        - `role` string
        - `createdAt` string, date-time
    - `title` string — YouTube: title must be ≤ 100 characters.
    - `content` string
    - `mediaItems` MediaItem[]
      - `type` 'image' | 'video' | 'gif' | 'document'
      - `url` string, uri
      - `title` string — Optional title for the media item. Used as the document title for LinkedIn PDF/carousel posts. If omitted, falls back to the post title, then the filename.
      - `altText` string — Accessibility alternative text for an image, applied on every platform that supports it: Instagram (feed images only, not Reels/Stories), Facebook, Threads, X/Twitter (max 1000 chars), LinkedIn, Bluesky, and Pinterest (max 500 chars). Ignored on platforms without alt-text support (TikTok, YouTube, Snapchat, Telegram, Reddit, Google Business, WhatsApp) and on video items where the platform does not accept it. Set once per image; the same value is sent to each selected platform.
      - `filename` string
      - `size` integer — Optional file size in bytes
      - `mimeType` string — Optional MIME type (e.g. image/jpeg, video/mp4)
      - `thumbnail` string, uri — Optional custom thumbnail/cover image URL for videos. Supported for Facebook video posts, Facebook Reels, regular video uploads, and LinkedIn video posts. Max 10MB, JPG/PNG recommended.
      - `instagramThumbnail` string, uri — Custom cover image URL for Instagram Reels. Can also be set via platformSpecificData.instagramThumbnail or platformSpecificData.reelCover. Resolution order: this field > platformSpecificData.instagramThumbnail > platformSpecificData.reelCover > platformSpecificData.thumbnailUrl (legacy).
      - `tiktokProcessed` boolean — Internal flag indicating the image was resized for TikTok
    - `platforms` PlatformTarget[]
      - `platform` string — Supported values: twitter, threads, instagram, youtube, facebook, linkedin, pinterest, reddit, tiktok, bluesky, googlebusiness, telegram
      - `accountId` union
        - string
        - SocialAccount
          - `_id` string, required
          - `platform` 'tiktok' | 'instagram' | 'facebook' | 'youtube' | 'linkedin' | 'twitter' | 'threads' | 'pinterest' | 'reddit' | 'bluesky' | 'googlebusiness' | 'telegram' | 'snapchat' | 'discord' | 'slack' | 'whatsapp' | 'linkedinads' | 'metaads' | 'pinterestads' | 'tiktokads' | 'xads' | 'googleads' | 'openaiads' | 'sms' | 'phone' | 'rcs', required
          - `profileId` union, required
            - string
            - Profile
              - …
          - `username` string
          - `displayName` string
          - `profilePicture` string, nullable — URL to the account's profile picture on the platform. May be null if the platform does not provide one.
          - `profileUrl` string — Full profile URL for the connected account on its platform.
          - `isActive` boolean, required
          - `needsReconnection` boolean — The platform definitively reported the stored OAuth token as dead. While true, GET /v1/connect/{platform}/ads returns a fresh authUrl (implicit force=true) instead of alreadyConnected, so re-running the connect flow recovers the account. Cleared automatically when the account is re-authorized.
          - `followersCount` number — Follower count (only included if user has analytics add-on)
          - `followersLastUpdated` string, date-time — Last time follower count was updated (only included if user has analytics add-on)
          - `parentAccountId` string, nullable — Reference to the parent posting SocialAccount. Set for ads accounts that share or derive from a posting account's OAuth token. null for standalone ads (Google Ads) and all posting accounts.
          - `enabled` boolean — Whether the user explicitly activated this account. false means the account was created as a side effect (e.g., posting account auto-created when user connected ads first). Posting UI and scheduler ignore accounts with enabled: false.
          - `metadata` object — Platform-specific metadata. Fields vary by platform. For WhatsApp accounts, includes: - qualityRating: Phone number quality rating from Meta (GREEN, YELLOW, RED, or UNKNOWN) - nameStatus: Display name review status (APPROVED, PENDING_REVIEW, DECLINED, or NONE). A declined or pending display name does not by itself block sending; sendability is reported separately via health_status (can_send_message). - messagingLimitTier: Maximum unique business-initiated conversations per 24h rolling window (TIER_250, TIER_1K, TIER_10K, TIER_100K, or TIER_UNLIMITED). Scales automatically as quality rating improves. - verifiedName: Meta-verified business display name - displayPhoneNumber: Formatted phone number (e.g., "+1 555-123-4567") - wabaId: WhatsApp Business Account ID - phoneNumberId: Meta phone number ID For LinkedIn accounts, profileData carries the profile details refreshed on each daily snapshot: - profileData.bio: The member's headline for personal accounts, or the organization description for organization accounts. null when the member has not set one. - profileData.extraData.vanityName: The member's profile slug, i.e. the /in/{vanityName} segment of profileUrl. Personal accounts only; an organization's own slug is in metadata.organizationInfo.vanityName.
      - `customContent` string — Platform-specific text override. When set, this content is used instead of the top-level post content for this platform. Useful for tailoring captions per platform (e.g. keeping tweets under 280 characters).
      - `customMedia` MediaItem[]
        - `type` 'image' | 'video' | 'gif' | 'document'
        - `url` string, uri
        - `title` string — Optional title for the media item. Used as the document title for LinkedIn PDF/carousel posts. If omitted, falls back to the post title, then the filename.
        - `altText` string — Accessibility alternative text for an image, applied on every platform that supports it: Instagram (feed images only, not Reels/Stories), Facebook, Threads, X/Twitter (max 1000 chars), LinkedIn, Bluesky, and Pinterest (max 500 chars). Ignored on platforms without alt-text support (TikTok, YouTube, Snapchat, Telegram, Reddit, Google Business, WhatsApp) and on video items where the platform does not accept it. Set once per image; the same value is sent to each selected platform.
        - `filename` string
        - `size` integer — Optional file size in bytes
        - `mimeType` string — Optional MIME type (e.g. image/jpeg, video/mp4)
        - `thumbnail` string, uri — Optional custom thumbnail/cover image URL for videos. Supported for Facebook video posts, Facebook Reels, regular video uploads, and LinkedIn video posts. Max 10MB, JPG/PNG recommended.
        - `instagramThumbnail` string, uri — Custom cover image URL for Instagram Reels. Can also be set via platformSpecificData.instagramThumbnail or platformSpecificData.reelCover. Resolution order: this field > platformSpecificData.instagramThumbnail > platformSpecificData.reelCover > platformSpecificData.thumbnailUrl (legacy).
        - `tiktokProcessed` boolean — Internal flag indicating the image was resized for TikTok
      - `scheduledFor` string, date-time — Optional per-platform scheduled time override (uses post.scheduledFor when omitted)
      - `platformSpecificData` object — The platform-specific options stored on this target, echoed back as they were sent. Typed per platform on the way in (see the *PlatformData schemas on the request body); free-form on the way out, because a response is not guaranteed to match exactly one of those variants and generated clients that pick a variant by structure reject the entire response when it doesn't. Zernio's internal publishing state (snapshots, container ids, publish stage) is never returned here, and the key is omitted rather than sent as an empty object.
      - `status` string — Platform-specific status: pending, publishing, published, failed
      - `platformPostId` string — The native post ID on the platform (populated after successful publish)
      - `platformPostUrl` string, nullable — Public URL of the published post. Included in the response for immediate posts; for scheduled posts, fetch via GET /v1/posts/{postId} after publish time. Empty when the platform confirmed the publish without returning an id a permalink can be built from (TikTok returns a publish id for some uploads); the TikTok reconcile cron backfills it later.
      - `publishedAt` string, date-time — Timestamp when the post was published to this platform
      - `removedFromPlatformAt` string, date-time, nullable — Set when a post that was successfully published later disappears from the platform (deleted on-platform or taken down by the platform). status stays "published" (it reflects the publish outcome); poll this field to detect post-publish removals. Absent while the post is live, and cleared if the post reappears. Detection runs with the analytics sync, so expect up to a few hours of lag.
      - `isTrialReel` boolean — Present and true only when this Instagram reel was launched as a Trial through Zernio (created with platformSpecificData.trialParams). Use it to segment trial reels in analytics. Note: Instagram's Graph API exposes no readable trial field, so this reflects creation-time intent only. It indicates the reel STARTED as a trial, not whether or when it graduated.
      - `trialGraduationStrategy` 'MANUAL' | 'SS_PERFORMANCE' — Graduation strategy the trial reel was launched with. Present only when isTrialReel is true.
      - `errorMessage` string — Human-readable error message when status is failed. Contains platform-specific error details explaining why the publish failed.
      - `errorCategory` 'auth_expired' | 'user_content' | 'user_abuse' | 'account_issue' | 'platform_rejected' | 'platform_error' | 'platform_rate_limit' | 'quota_exhausted' | 'system_error' | 'unknown' — Error category for programmatic handling: auth_expired (token expired/revoked), user_content (wrong format/too long), user_abuse (rate limits/spam), account_issue (config problems), platform_rejected (policy violation), platform_error (5xx/maintenance), platform_rate_limit (platform throttling, retried automatically), quota_exhausted (shared daily API quota empty, resumes at the platform's reset), system_error (Zernio infra), unknown
      - `errorSource` 'user' | 'platform' | 'system' — Who caused the error: user (fix content/reconnect), platform (outage/API change), system (Zernio issue, rare)
    - `scheduledFor` string, date-time
    - `timezone` string
    - `status` 'draft' | 'scheduled' | 'publishing' | 'published' | 'failed' | 'partial'
    - `tags` string[] — YouTube constraints: each tag max 100 chars, combined max 500 chars, duplicates removed.
    - `hashtags` string[]
    - `mentions` string[] — Stored for reference only. This field does NOT automatically create @mentions when publishing. For LinkedIn @mentions, use the /v1/accounts/{accountId}/linkedin-mentions endpoint to resolve profile URLs to URNs, then embed the returned mentionFormat directly in the post content field.
    - `visibility` 'public' | 'private' | 'unlisted'
    - `metadata` object
    - `recycling` RecyclingState — Current recycling configuration and state on a post
      - `enabled` boolean — Whether recycling is currently active
      - `gap` integer — Number of interval units between reposts
      - `gapFreq` 'week' | 'month' — Interval unit (week or month)
      - `startDate` string, date-time
      - `expireCount` integer
      - `expireDate` string, date-time
      - `contentVariations` string[] — Content variations for recycled copies (if configured)
      - `contentVariationIndex` integer — Current position in the content variations rotation (read-only)
      - `recycleCount` integer — How many recycled copies have been created so far (read-only)
      - `nextRecycleAt` string, date-time — When the next recycled copy will be created (read-only)
      - `lastRecycledAt` string, date-time — When the last recycled copy was created (read-only)
    - `recycledFromPostId` string — ID of the original post if this post was created via recycling
    - `queuedFromProfile` string — Profile ID if the post was scheduled via the queue
    - `queueId` string — Queue ID if the post was scheduled via a specific queue
    - `createdAt` string, date-time
    - `updatedAt` string, date-time

## Other responses

- `207` — Partial success
- `400` — Invalid state
- `401` — Unauthorized
- `402` — Payment required: the account owner has a failed payment.
- `403` — Forbidden
- `404` — Resource not found
- `409` — Post is currently publishing
- `429` — Rate limit exceeded. Possible causes: API rate limit (requests per minute), velocity limit (25 posts/hour per account), or account cooldown (temporarily rate-limited due to repeated errors).

## Changes

- **2026-08-27** `0cdc3e98bff9` — 1 breaking, 1 info
  - the `post/platforms/items/platformSpecificData` response's property type/format changed from ``/`` to `object`/`` for status `200`
  - removed `#/components/schemas/TwitterPlatformData, #/components/schemas/ThreadsPlatformData, #/components/schemas/FacebookPlatformData, #/components/schemas/InstagramPlatformData, #/components/schemas/LinkedInPlatformData, #/components/schemas/PinterestPlatformData, #/components/schemas/YouTubePlatformData, #/components/schemas/GoogleBusinessPlatformData, #/components/schemas/TikTokPlatformData, #/components/schemas/TelegramPlatformData, #/components/schemas/SnapchatPlatformData, #/components/schemas/RedditPlatformData, #/components/schemas/BlueskyPlatformData, #/components/schemas/DiscordPlatformData, #/components/schemas/SlackPlatformData` from the `post/platforms/items/platformSpecificData` response property `oneOf` list for the response status `200`
- …earlier changes not shown

[Full history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/posts/:postId/retry/post.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) · [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/zernio/zernio-api/revisions/dd66917efd2e/schema)
