Skip to content
Home / Docs / Docs

Pins API

GET /v1/pins

List Pins

List pins for the workspace, newest first by default, with optional filters.

The X-Total-Count response header carries the number of pins matching the
filters and search, so clients can page with limit and offset.

Auth: ApiKeyAuth, BearerAuth

Parameters

Name In Required Type Description
limit query no integer
offset query no integer
q query no string? Case-insensitive search across title, description and link URL
sort query no enum(created_at_desc, created_at_asc, published_at_desc, published_at_asc, title_asc, title_desc, status_asc, status_desc) Sort order
account_id query no string? Only pins for this Pinterest account
board_id query no string? Only pins targeting this board
status query no PinStatus? Only pins in this status
error_code query no string? Only failed pins with this error code
removed query no boolean? true: only published pins that no longer exist on Pinterest; false: exclude them
since query no string? Only pins created at or after this ISO 8601 timestamp
until query no string? Only pins created before this ISO 8601 timestamp

Response 200

curl -X GET "https://api.pinbridge.io/v1/pins" \
  -H "X-API-Key: $PINBRIDGE_API_KEY"

POST /v1/pins

Create Pin

Create and publish a pin.

The pin is queued for publishing and processed asynchronously.
Use idempotency_key to prevent duplicate pins.

Before the pin is accepted PinBridge checks that the connected account can
publish to the board. Failures return 422 with a stable error.code
(board_not_found, board_not_owned, board_deleted, scope_missing,
token_expired, token_revoked, board_access_denied, …) and a
remediation hint.

Every response carries X-PinBridge-Quota-* and X-Pinterest-RateLimit-*
headers describing the remaining headroom. To check a request without
publishing, use POST /v1/pins/validate.

Auth: ApiKeyAuth, BearerAuth

Request body (PinCreate)

Field Type Required Description
account_id string yes Pinterest account ID to publish with
board_id string yes Pinterest board ID
title string yes Pin title (max 100)
description string? no Pin description
alt_text string? no Alternative text used for accessibility
dominant_color string? no Dominant hex color of the pin media (for example #6E7874)
cover_image_url string? no Optional public cover image URL for video pins
cover_image_asset_id string? no Optional uploaded image asset ID used as a video cover image
link_url string? no Destination URL for the pin
image_url string? no Public URL of the image to pin
asset_id string? no Uploaded PinBridge asset ID to use for the pin image or video
idempotency_key string yes Idempotency key to prevent duplicate pins (max 255)

Response 201 (PinResponse)

curl -X POST "https://api.pinbridge.io/v1/pins" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "board_id": "987654321098765432", "title": "Autumn table setting", "idempotency_key": "pin-2026-001", "image_url": "https://example.com/image.jpg"}'

POST /v1/pins/batch

Create Pins Batch

Create and publish several pins in one call.

Each entry is processed independently and reported with its own outcome
(created, existing for an idempotency-key hit, or failed with an error
envelope). Requires the bulk publishing plan feature and enough monthly quota
for every entry that would be created. Quota headers describe the workspace;
Pinterest rate headers are only included when every entry targets one account.

Auth: ApiKeyAuth, BearerAuth

Request body (PinBatchRequest)

Field Type Required Description
pins array yes Pins to create, in order

Response 200 (PinBatchResponse)

curl -X POST "https://api.pinbridge.io/v1/pins/batch" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"pins": [{"account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "board_id": "987654321098765432", "title": "Autumn table setting", "idempotency_key": "pin-2026-001", "image_url": "https://example.com/image.jpg"}]}'

POST /v1/pins/bulk-delete

Bulk Delete Pins

Soft-delete multiple pins in one call (or hard-delete in sandbox).

Per-item outcomes:
* succeeded — pin was deleted.
* failed (error_code=not_found) — pin not found in workspace or already deleted.

Auth: ApiKeyAuth, BearerAuth

Request body (BulkIdsRequest)

Field Type Required Description
ids array yes List of resource IDs to act on (up to 500 per request).

Response 200 (BulkOperationResponse)

curl -X POST "https://api.pinbridge.io/v1/pins/bulk-delete" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"]}'

POST /v1/pins/bulk-retry

Bulk Retry Pins

Retry multiple failed pins in one call.

Per-item outcomes:
* succeeded — pin was reset to QUEUED and publish task enqueued.
* skipped (error_code=ineligible_status) — pin status is not FAILED.
* failed (error_code=not_found) — pin not found in workspace or deleted.

Auth: ApiKeyAuth, BearerAuth

Request body (BulkIdsRequest)

Field Type Required Description
ids array yes List of resource IDs to act on (up to 500 per request).

Response 200 (BulkOperationResponse)

curl -X POST "https://api.pinbridge.io/v1/pins/bulk-retry" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["3fa85f64-5717-4562-b3fc-2c963f66afa6"]}'

GET /v1/pins/imports

List Import Jobs

List bulk import jobs for a workspace.

Auth: ApiKeyAuth, BearerAuth

Parameters

Name In Required Type Description
limit query no integer
offset query no integer
status query no ImportJobStatus? Filter import jobs by processing status
source_type query no ImportSourceType? Filter import jobs by source type

Response 200

curl -X GET "https://api.pinbridge.io/v1/pins/imports" \
  -H "X-API-Key: $PINBRIDGE_API_KEY"

POST /v1/pins/imports/csv

Create Csv Import Job

Queue a bulk pin import from an uploaded CSV file.

Auth: ApiKeyAuth, BearerAuth

Request body: multipart/form-data with a file field.

Response 202 (ImportJobResponse)

curl -X POST "https://api.pinbridge.io/v1/pins/imports/csv" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -F "file=@/path/to/file"

POST /v1/pins/imports/json

Create Json Import Job

Queue a bulk pin import from a JSON array.

Auth: ApiKeyAuth, BearerAuth

Request body (BulkPinImportJsonRequest)

See schema.

Response 202 (ImportJobResponse)

curl -X POST "https://api.pinbridge.io/v1/pins/imports/json" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[{"account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "board_id": "987654321098765432", "title": "Autumn table setting", "image_url": "https://example.com/image.jpg", "idempotency_key": "import-2026-001"}]'

GET /v1/pins/imports/{job_id}

Get Import Job

Get a bulk import job and row results.

Auth: ApiKeyAuth, BearerAuth

Parameters

Name In Required Type Description
job_id path yes string

Response 200 (ImportJobResponse)

curl -X GET "https://api.pinbridge.io/v1/pins/imports/$JOB_ID" \
  -H "X-API-Key: $PINBRIDGE_API_KEY"

POST /v1/pins/validate

Validate Pin

Dry-run a pin request.

Runs the full acceptance path — account, media, cover image, board access,
idempotency, billing, quota and Pinterest rate headroom — and reports each
step. Returns the exact payload that would be published. Nothing is queued.

Auth: ApiKeyAuth, BearerAuth

Request body (PinCreate)

Field Type Required Description
account_id string yes Pinterest account ID to publish with
board_id string yes Pinterest board ID
title string yes Pin title (max 100)
description string? no Pin description
alt_text string? no Alternative text used for accessibility
dominant_color string? no Dominant hex color of the pin media (for example #6E7874)
cover_image_url string? no Optional public cover image URL for video pins
cover_image_asset_id string? no Optional uploaded image asset ID used as a video cover image
link_url string? no Destination URL for the pin
image_url string? no Public URL of the image to pin
asset_id string? no Uploaded PinBridge asset ID to use for the pin image or video
idempotency_key string yes Idempotency key to prevent duplicate pins (max 255)

Response 200 (PinValidationResponse)

curl -X POST "https://api.pinbridge.io/v1/pins/validate" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "board_id": "987654321098765432", "title": "Autumn table setting", "idempotency_key": "pin-2026-001", "image_url": "https://example.com/image.jpg"}'

DELETE /v1/pins/{pin_id}

Delete Pin

Delete a pin.

By default this removes the PinBridge record only and returns 204. Pass
delete_from_pinterest=true to also delete the published pin on Pinterest,
the proportionate fix for one wrong pin (deleting the board is not); that
variant returns 200 with removed_from_pinterest so the outcome is visible.

Auth: ApiKeyAuth, BearerAuth

Parameters

Name In Required Type Description
pin_id path yes string
delete_from_pinterest query no boolean Also remove the published pin from Pinterest. Without this flag only the PinBridge record is deleted and the pin stays live on Pinterest.

Response 204

curl -X DELETE "https://api.pinbridge.io/v1/pins/$PIN_ID" \
  -H "X-API-Key: $PINBRIDGE_API_KEY"

GET /v1/pins/{pin_id}

Get Pin

Get pin status and details.

Auth: ApiKeyAuth, BearerAuth

Parameters

Name In Required Type Description
pin_id path yes string

Response 200 (PinResponse)

curl -X GET "https://api.pinbridge.io/v1/pins/$PIN_ID" \
  -H "X-API-Key: $PINBRIDGE_API_KEY"

PATCH /v1/pins/{pin_id}

Update Pin

Edit a pin’s title, description, link, alt text, or board before it publishes.

Queued, deferred and failed pins are edited in place and publish with the new
values. A published pin cannot be edited: Pinterest’s API does not let
PinBridge change a pin once it is live, so the call returns
409 pin_already_published; delete the pin and publish a corrected one
instead. Pins currently publishing return 409 pin_publishing. Both refusals
are recorded in the activity log as pin.update_rejected. In a simulated
sandbox board_id cannot change.

Auth: ApiKeyAuth, BearerAuth

Parameters

Name In Required Type Description
pin_id path yes string

Request body (PinUpdate)

Field Type Required Description
title string? no Pin title
description string? no Pin description
link_url string? no Destination URL for the pin
alt_text string? no Alternative text used for accessibility
board_id string? no Move the pin to another board

Response 200 (PinResponse)

curl -X PATCH "https://api.pinbridge.io/v1/pins/$PIN_ID" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Autumn table setting", "alt_text": "A dinner table set with candles and autumn leaves"}'

GET /v1/pins/{pin_id}/analytics

Get Pin Analytics

Pin-level analytics (impressions, saves, clicks, outbound clicks) over a date range.

PinBridge copies every published pin’s analytics nightly, so most reads are
answered from that stored history (source: stored in the response, with
data_as_of) without calling Pinterest. Live ranges are capped at 90 days,
stored ranges at 366. Sandbox-simulated pins return zeroed metrics.

A pin deleted on Pinterest (removed_from_pinterest_at set) is answered
from the stored history. Without stored history it fails with 409
pin_removed_on_pinterest
, which is also what a live read returns when
Pinterest no longer has the pin.

Auth: ApiKeyAuth, BearerAuth

Parameters

Name In Required Type Description
pin_id path yes string
start_date query no string? Inclusive start (YYYY-MM-DD); default 30 days ago
end_date query no string? Inclusive end (YYYY-MM-DD); default today
metrics query no string? Comma-separated Pinterest metric types, e.g. IMPRESSION,SAVE,PIN_CLICK,OUTBOUND_CLICK. Defaults to the organic engagement set.
source query no enum(auto, stored, live) auto (default): PinBridge’s stored history when it covers the range, else Pinterest. stored: stored history only (up to 366 days, beyond Pinterest’s 90). live: always ask Pinterest (counts against the read limit).
include_daily query no boolean false: return only the range totals, with an empty daily list. Use it when the totals are all you need, e.g. over 90 days.

Response 200 (PinAnalyticsResponse)

curl -X GET "https://api.pinbridge.io/v1/pins/$PIN_ID/analytics" \
  -H "X-API-Key: $PINBRIDGE_API_KEY"

POST /v1/pins/{pin_id}/retry

Retry Failed Pin

Retry a failed pin.

Re-queues a pin that previously failed for publishing.
Optionally override the board or Pinterest account to fix
the root cause of the failure before retrying. The target board is
preflighted the same way as on creation.

Auth: ApiKeyAuth, BearerAuth

Parameters

Name In Required Type Description
pin_id path yes string

Request body

See schema.

Response 200 (PinResponse)

curl -X POST "https://api.pinbridge.io/v1/pins/$PIN_ID/retry" \
  -H "X-API-Key: $PINBRIDGE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{}'

Last updated October 30, 2026 Was this page helpful? Tell us →