Publish pins
Create a pin with POST /v1/pins. This page covers every field on the request, the media options, and the state a pin moves through after you submit it.
Prerequisites
- An API key in the
X-API-Keyheader. See Authentication. - A connected Pinterest account (
account_id) and a board on it (board_id). - Media: either a public
image_url, or an uploadedasset_id. See Upload media.
Pin fields
Every request is a PinCreate object.
Required
| Field | Type | Notes |
|---|---|---|
account_id |
UUID | The connected Pinterest account to publish with. |
board_id |
string | The Pinterest board id. |
title |
string | Max 100 characters. |
idempotency_key |
string | Max 255 characters. Required, never auto-generated. Reusing a key returns the existing pin instead of creating a duplicate. |
one of image_url / asset_id |
string | Exactly one is required (see Media options). |
Optional
| Field | Type | Notes |
|---|---|---|
description |
string | Max 800 characters. |
alt_text |
string | Max 500 characters. Accessibility text. |
dominant_color |
string | 6-digit hex, optional leading # (for example #6E7874); normalized to upper-case. |
link_url |
string | Destination URL, max 2048 characters. |
cover_image_url |
string | Public cover image URL. Video pins only. |
cover_image_asset_id |
UUID | Uploaded image asset used as a video cover. Video pins only. |
related_termsis deprecated. Pinterest doesn’t list it for creating or reading a pin, so PinBridge stopped sending it in API 1.65.1. A request that still includes it keeps working and the value is ignored. Pin responses keep the field for now:nullfor new pins, the stored value for older ones. To find keyword ideas for your titles and descriptions, use List Related Terms.
Media options
Provide the pin’s media in exactly one way:
- Public image URL — set
image_url. Works on every plan. - Uploaded asset — set
asset_idfrom an uploaded image or video. Paid plans only; see Upload media.
Notes:
- Provide exactly one of
image_url/asset_id. Both missing or both present each return422. - A video pin is created by referencing an uploaded video
asset_id. There is novideo_urlfield. - Cover images (
cover_image_url/cover_image_asset_id) apply only to video pins, and you may set at most one of the two.
Heads up: Pinterest can change your title. When your pin has a
link_url, Pinterest re-scrapes that destination page and may override your pin title with the page’s Open Graph / meta tags. If your published title doesn’t match what you sent, this is almost always why. Control it by setting goodog:title(andog:description) meta tags on the destination page. This is the most common “my title changed” surprise.
Publish a pin
curl
curl -X POST https://api.pinbridge.io/v1/pins \
-H "X-API-Key: $PINBRIDGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_id": "6f1c2e4a-3b7d-4c9e-8a21-5d0f9b3e7c41",
"board_id": "987654321098765432",
"title": "My first PinBridge pin",
"description": "A short, useful description.",
"link_url": "https://example.com/product",
"image_url": "https://example.com/pin.png",
"idempotency_key": "publish-demo-001"
}'
Response (201, trimmed):
{
"id": "8a3f6c12-4d5e-4b7a-9c01-2e6f8d4b7a93",
"status": "queued",
"media_type": "image",
"title": "My first PinBridge pin",
"board_id": "987654321098765432",
"idempotency_key": "publish-demo-001",
"pinterest_pin_id": null,
"error_code": null
}
The pin is accepted as queued and published by a background worker. Poll its status or use a webhook to learn the outcome.
Python SDK
from pinbridge_sdk import PinbridgeClient
from pinbridge_sdk.models import PinCreate
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
pin = client.pins.create(
PinCreate(
account_id="6f1c2e4a-3b7d-4c9e-8a21-5d0f9b3e7c41",
board_id="987654321098765432",
title="My first PinBridge pin",
image_url="https://example.com/pin.png", # or asset_id="e3a7c5f9-1b4d-4c8e-a2f6-7d9b3e5a1c80"
link_url="https://example.com/product",
idempotency_key="publish-demo-001",
)
)
print(pin.id, pin.status)
idempotency_key is a required field on PinCreate. To publish a video pin, drop image_url and pass asset_id for an uploaded video.
n8n
Use the PinBridge node with Resource: Pin, Operation: Publish. Choose the Media Source (Uploaded Asset or Public Image URL) and fill in Title, Board, and the account Connection. The Idempotency Key field defaults to ={{$execution.id + "-" + $itemIndex}}, which gives each item a stable, unique key.
Pin states
A pin moves through these statuses:
queued→publishing→publishedon success (setspinterest_pin_idandpublished_at).failedon a non-retryable error (setserror_codeanderror_message).- Retryable errors move the pin to
deferredand auto-retry, up to 8 deferrals, before finally becomingfailed.
Common failure error_code values include rate_limited, token_expired, token_revoked, scope_missing, board_access_denied, transient_upstream, media_url_unreachable, invalid_payload, and publish_timeout. See Rate limits and quotas for how retries and quota interact.
To reprocess failures: POST /v1/pins/{pin_id}/retry (only failed pins; otherwise 409), or the bulk endpoints POST /v1/pins/bulk-retry and POST /v1/pins/bulk-delete.
Verify it worked
- Fetch the pin with
GET /v1/pins/{pin_id}(SDK:client.pins.get(pin_id)) and checkstatus. - When
statusispublished,pinterest_pin_idholds the id of the live Pinterest pin. - For push notifications instead of polling, subscribe to
pin.publishedandpin.failedwebhooks.
Common errors
| Status | Cause |
|---|---|
| 422 | Either image_url or asset_id must be provided / Provide either image_url or asset_id, not both. |
| 422 | Missing a required field such as account_id, or title over 100 chars. |
| 403 | feature_unavailable — used an asset_id on the Free plan. Use a public image_url or upgrade. |
| 400 | cover_image_url is only supported for video pins. |
Next steps
- Upload media — host images and videos and publish by
asset_id. - Schedule pins — publish the same payload at a future time.
- Webhooks — get
pin.published/pin.failedevents. - Rate limits and quotas — publishing quotas and retry behavior.
