Unschedule post
const url = 'https://api-v1.tailwind.ai/v1/accounts/example/posts/example/unschedule';const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request POST \ --url https://api-v1.tailwind.ai/v1/accounts/example/posts/example/unschedule \ --header 'Authorization: Bearer <token>'Move a scheduled (queued) Pin back to draft, for example to revise a time-sensitive Pin before it publishes. The Pin keeps its postId and everything stored on it: media, title, description, destination url, board and board section, alt text, product tags and carousel images. Only its status and scheduled time change, so the returned Pin has status draft and no sendAt. Works on any queued Pin on the account, including one created in the Tailwind dashboard and a missed Pin whose scheduled time has already passed. Any pin_schedule credit charged for putting the Pin on the schedule is returned, as in the Tailwind dashboard; a Pin scheduled on a free-trial allowance, scheduled in an earlier billing period, or on a legacy or Shopify plan has nothing to return. Scheduling the draft again with POST /v1/accounts/{accountId}/posts/{postId}/schedule charges again. A Pin that is not queued is rejected with a 400: post_already_published for a Pin that has been published or is publishing now (edit or delete it in the Pinterest app), and post_not_queued for drafts, failed and deleted Pins. A 409 means the Pin’s status changed while it was being unscheduled, or the account’s schedule was busy; nothing was changed, so read the Pin back with GET before retrying.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Numeric Tailwind account ID returned by GET /v1/accounts
Post ID
Responses
Section titled “Responses”Pin moved back to draft
object
object
object
Post ID
Post status. draft = saved in Tailwind only, not created on Pinterest; queued = scheduled; sent = published to Pinterest.
URL of the media file
Type of media
Further images of a carousel Pin, in order after the cover in mediaUrl. Absent on a single-image Pin. Per-slide title, description and link are reported when the Pin carries them, but cannot be set through this API yet.
object
URL of this image
Per-slide title, when the Pin has one
Per-slide description, when the Pin has one
Per-slide destination, when the Pin has one
Pin title
Pin description
Destination URL
Target board ID
Section of boardId the Pin publishes into. Null when it publishes to the board root.
Alt text for accessibility
Scheduled send time (Unix timestamp)
Actual send time (Unix timestamp)
Creation time (Unix timestamp)
Pinterest pin ID (only present after publishing). This is the id GET /v1/accounts/{accountId}/pins/{pinId}/analytics takes.
Whether this is a simplified pin (as opposed to a standard pin)
Pinterest product-catalog pin IDs tagged on the pin (business accounts only).
ID of the AI generation that produced this post, when Tailwind’s AI generated it from a URL (matches the id returned by POST /v1/accounts/{accountId}/generations) or from a connected feed. Absent for posts created any other way. A draft with one is a generated draft waiting for review.
Why a failed Pin did not publish, as a stable code such as board_not_found, expired_token or user_rate_limit. Present only when status is failed and Tailwind recorded a reason. New codes are added over time, so treat an unrecognized code as a generic failure.
A user-facing explanation of failureReason and what to do next, the same copy the Tailwind dashboard shows for a failed Pin. Present whenever failureReason is; a code with no specific copy gets a generic explanation.
object
Unique request ID for debugging
Example
{ "data": { "post": { "status": "draft", "mediaType": "image" } }}Invalid request
object
object
Error code
Error message
Machine-readable reason. On PAYMENT_REQUIRED errors it is the denial reason: insufficient_credits, trial_exhausted, no_access, account_not_connected, legacy_post_limit_exceeded. Other errors may carry an operation-specific reason, such as pinterest_reconnect_required, pinterest_rate_limited, pinterest_timeout, pinterest_request_failed or list_boards_upstream_failed; each operation’s documented error responses show the values it returns. Branch on reason rather than parsing message.
Present on PAYMENT_REQUIRED errors: where the denial can be resolved. Reason-specific, because buying credits does not clear a trial, access or connection denial. Requests sent with X-Request-Source: mcp receive an informational plans page instead, so agent surfaces never present a purchase link.
object
Unique request ID for debugging
Example
{ "error": { "code": "BAD_REQUEST", "message": "Invalid request body" }, "meta": { "requestId": "abc123" }}Authentication required or invalid bearer credentials
object
object
Error code
Error message
Machine-readable reason. On PAYMENT_REQUIRED errors it is the denial reason: insufficient_credits, trial_exhausted, no_access, account_not_connected, legacy_post_limit_exceeded. Other errors may carry an operation-specific reason, such as pinterest_reconnect_required, pinterest_rate_limited, pinterest_timeout, pinterest_request_failed or list_boards_upstream_failed; each operation’s documented error responses show the values it returns. Branch on reason rather than parsing message.
Present on PAYMENT_REQUIRED errors: where the denial can be resolved. Reason-specific, because buying credits does not clear a trial, access or connection denial. Requests sent with X-Request-Source: mcp receive an informational plans page instead, so agent surfaces never present a purchase link.
object
Unique request ID for debugging
Example
{ "error": { "code": "UNAUTHORIZED", "message": "Invalid API key" }, "meta": { "requestId": "abc123" }}Resource not found
object
object
Error code
Error message
Machine-readable reason. On PAYMENT_REQUIRED errors it is the denial reason: insufficient_credits, trial_exhausted, no_access, account_not_connected, legacy_post_limit_exceeded. Other errors may carry an operation-specific reason, such as pinterest_reconnect_required, pinterest_rate_limited, pinterest_timeout, pinterest_request_failed or list_boards_upstream_failed; each operation’s documented error responses show the values it returns. Branch on reason rather than parsing message.
Present on PAYMENT_REQUIRED errors: where the denial can be resolved. Reason-specific, because buying credits does not clear a trial, access or connection denial. Requests sent with X-Request-Source: mcp receive an informational plans page instead, so agent surfaces never present a purchase link.
object
Unique request ID for debugging
Example
{ "error": { "code": "NOT_FOUND", "message": "Account not found" }, "meta": { "requestId": "abc123" }}The Pin changed status while it was being unscheduled, or the account’s schedule was being updated elsewhere. Nothing was changed.
object
object
Error code
Error message
Machine-readable reason. On PAYMENT_REQUIRED errors it is the denial reason: insufficient_credits, trial_exhausted, no_access, account_not_connected, legacy_post_limit_exceeded. Other errors may carry an operation-specific reason, such as pinterest_reconnect_required, pinterest_rate_limited, pinterest_timeout, pinterest_request_failed or list_boards_upstream_failed; each operation’s documented error responses show the values it returns. Branch on reason rather than parsing message.
Present on PAYMENT_REQUIRED errors: where the denial can be resolved. Reason-specific, because buying credits does not clear a trial, access or connection denial. Requests sent with X-Request-Source: mcp receive an informational plans page instead, so agent surfaces never present a purchase link.
object
Unique request ID for debugging
Examplegenerated
{ "error": { "code": "example", "message": "example", "reason": "example", "resolve_url": "example" }, "meta": { "requestId": "example" }}Rate limit exceeded
object
object
Error code
Error message
Machine-readable reason. On PAYMENT_REQUIRED errors it is the denial reason: insufficient_credits, trial_exhausted, no_access, account_not_connected, legacy_post_limit_exceeded. Other errors may carry an operation-specific reason, such as pinterest_reconnect_required, pinterest_rate_limited, pinterest_timeout, pinterest_request_failed or list_boards_upstream_failed; each operation’s documented error responses show the values it returns. Branch on reason rather than parsing message.
Present on PAYMENT_REQUIRED errors: where the denial can be resolved. Reason-specific, because buying credits does not clear a trial, access or connection denial. Requests sent with X-Request-Source: mcp receive an informational plans page instead, so agent surfaces never present a purchase link.
object
Unique request ID for debugging
Example
{ "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Daily rate limit of 10000 requests for this organization exceeded. Resets at midnight UTC." }, "meta": { "requestId": "abc123" }}Headers
Section titled “Headers”Seconds until the daily limit resets at midnight UTC.
