Update post
const url = 'https://api-v1.tailwind.ai/v1/accounts/example/posts/example';const options = { method: 'PATCH', headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'}, body: '{"title":"example","description":"example","url":"https://example.com","boardId":"example","boardSectionId":"example","altText":"example","productTagPinIds":["example"],"isSimplifiedPin":true}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}curl --request PATCH \ --url https://api-v1.tailwind.ai/v1/accounts/example/posts/example \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "title": "example", "description": "example", "url": "https://example.com", "boardId": "example", "boardSectionId": "example", "altText": "example", "productTagPinIds": [ "example" ], "isSimplifiedPin": true }'Edit an unpublished Pin’s copy. Fields absent from the body are left unchanged. Only drafts and scheduled (queued) Pins can be edited — a Pin already published to Pinterest is terminal in Tailwind and must be edited in the Pinterest app. Editing does not consume credits. sendAt, status and the Pin’s media are deliberately not accepted here and are rejected with a message naming the operation that does handle them: scheduling goes through POST /v1/accounts/{accountId}/posts/{postId}/schedule, which is where putting a Pin on the schedule is charged — one credit on modular billing with Publishing access (winback plans excepted), and no credits on legacy and Shopify accounts, which count it against the plan’s post limit instead. title and description cannot be set to an empty string — a scheduled Pin left without them could not be published. Moving a Pin to a different board clears any board section it was in, since a section belongs to one board. productTagPinIds replaces the Pin’s tags wholesale — an empty array clears them, and omitting the field leaves them alone; tagging forces a simplified Pin, and tags are refused on a carousel Pin because Pinterest will not publish that combination. isSimplifiedPin switches a draft or scheduled Pin between a simplified and a standard Pin; false is refused on a Pin that keeps product tags, so send productTagPinIds: [] alongside it to make a tagged Pin standard. A 409 means the Pin changed status while the edit was being applied and the edit was not saved.
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
Request Bodyrequired
Section titled “Request Bodyrequired”At least one field must be supplied. Fields you omit are left unchanged. sendAt, status, mediaUrl and uploadId are rejected rather than ignored — see the endpoint description.
object
Pin title
Pin description
Destination link for the Pin. At most 1000 bytes in UTF-8.
Target board ID. Must be the numeric Pinterest board ID from GET /v1/accounts/{accountId}/boards — not a board name or URL. A leading “b_” (Tailwind CSV export format) is accepted and stripped.
Section to publish into, validated against the board the Pin ends up on (boardId if you send one, otherwise its current board). Send “” to move the Pin to the board root. Supplying boardId WITHOUT this field clears any section the Pin already had, since a section is only valid on its own board. Use GET /v1/accounts/{accountId}/boards/{boardId}/sections to look up section IDs.
Accessibility alt text
Pinterest product-catalog pin IDs to tag on the Pin, replacing any it already had (business accounts only; max 24). Send an empty array to remove every tag — omitting the field leaves the existing tags untouched. Tagging forces a simplified Pin, since Pinterest rejects tags on standard Pins. Rejected on carousel Pins, which Pinterest refuses to publish with tags; an empty array is still accepted on one, so tags can be cleared off it.
True makes the Pin a simplified Pin, false a standard Pin. Applies to draft and scheduled Pins alike. false is rejected while the Pin has product tags, since Pinterest rejects tags on standard Pins; send productTagPinIds: [] in the same request to remove them.
Examplegenerated
{ "title": "example", "description": "example", "url": "https://example.com", "boardId": "example", "boardSectionId": "example", "altText": "example", "productTagPinIds": [ "example" ], "isSimplifiedPin": true}Responses
Section titled “Responses”Updated post
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
Name of the Board in boardId, as Tailwind last saw it when listing the account’s Boards. Returned by the get and list reads only; absent when the Pin has no Board or the Board has not been listed yet, such as one created moments ago.
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 the edit was being applied — it is no longer a draft or scheduled Pin, and the edit was not saved.
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.
Pinterest failed the request with an error of its own. A create may still have taken effect, so list Boards or sections before repeating one; other requests can be retried. If the same request keeps failing, Pinterest is refusing it rather than having an outage.
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_GATEWAY", "message": "Pinterest couldn't complete this request. Please try again.", "reason": "pinterest_request_failed" }, "meta": { "requestId": "abc123" }}Pinterest rate-limited the request. Pinterest refused it before acting, so nothing was changed. Distinct from a 429, which means the organization’s shared daily request limit — retry this request in a few minutes rather than backing off across the API.
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": "SERVICE_UNAVAILABLE", "message": "Pinterest is limiting requests for this account right now. Nothing was changed. Retry in a few minutes.", "reason": "pinterest_rate_limited" }, "meta": { "requestId": "abc123" }}Headers
Section titled “Headers”Seconds until Pinterest’s limit for this account resets. Sent by the analytics and Pin inventory operations when Pinterest reports it; absent otherwise.
