Schedule pins
Publish a pin at a future time with POST /v1/schedules. A schedule carries the same media and pin details you’d send to Publish pins, plus a run_at timestamp. A background task materializes the pin when the time arrives.
Prerequisites
- An API key in the
X-API-Keyheader. See Authentication. - A connected Pinterest account (
account_id) and aboard_id. - Media: a public
image_urlor an uploadedasset_id. See Upload media.
Fields a schedule supports
A ScheduleCreate accepts:
| Field | Required | Notes |
|---|---|---|
account_id |
yes | Connected Pinterest account (UUID). |
run_at |
yes | Future ISO 8601 timestamp with a timezone offset (see below). |
board_id |
yes | Pinterest board id. |
title |
yes | Max 100 characters. |
description |
no | Max 800 characters. |
link_url |
no | Destination URL, max 2048 characters. |
one of image_url / asset_id |
yes | Exactly one, same rule as publishing. |
cover_image_url / cover_image_asset_id |
no | Video pins only; at most one. |
Schedule fields vs. publish fields
Schedules carry fewer fields than a direct publish. These PinCreate fields are not part of ScheduleCreate:
related_termsalt_textdominant_color
If you need those, publish directly with Publish pins instead of scheduling.
run_at rules
- Must include an explicit timezone offset (for example
2026-12-25T09:00:00-05:00or...Z). A naive timestamp is rejected with422. It’s normalized to UTC on the server. - Must be in the future, else
400 run_at must be in the future.
Create a schedule
curl
curl -X POST https://api.pinbridge.io/v1/schedules \
-H "X-API-Key: $PINBRIDGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"account_id": "6f1c2e4a-3b7d-4c9e-8a21-5d0f9b3e7c41",
"board_id": "987654321098765432",
"title": "Holiday promo pin",
"image_url": "https://example.com/pin.png",
"link_url": "https://example.com/promo",
"run_at": "2026-12-25T09:00:00-05:00"
}'
Response (201, trimmed):
{
"id": "c4e2a9b1-7d3f-4e6a-8b50-1f9d2c7e3a64",
"pinterest_account_id": "6f1c2e4a-3b7d-4c9e-8a21-5d0f9b3e7c41",
"run_at": "2026-12-25T14:00:00Z",
"status": "scheduled",
"pin_id": null,
"last_error": null
}
Python SDK
from datetime import datetime, timezone
from pinbridge_sdk import PinbridgeClient
from pinbridge_sdk.models import ScheduleCreate
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
schedule = client.schedules.create(
ScheduleCreate(
account_id="6f1c2e4a-3b7d-4c9e-8a21-5d0f9b3e7c41",
board_id="987654321098765432",
title="Holiday promo pin",
image_url="https://example.com/pin.png",
run_at=datetime(2026, 12, 25, 14, 0, tzinfo=timezone.utc),
)
)
print(schedule.id, schedule.status)
run_at must be timezone-aware.
n8n
Use the PinBridge node with Resource: Schedule, Operation: Create. Set Run At (a dateTime), the Connection, Board, Title, and Media Source. Note the schedule form has no Alt Text, Related Terms, or Dominant Color fields, matching the API.
Schedule statuses
A schedule’s status is one of:
scheduled → queued → running → done on success. Retryable errors go to deferred; a hard failure is failed; a canceled schedule is canceled. Once the pin is created you can follow it with pin_id and the pin’s own publish states.
Manage schedules
List and fetch
curl "https://api.pinbridge.io/v1/schedules?limit=50&offset=0" \
-H "X-API-Key: $PINBRIDGE_API_KEY"
curl "https://api.pinbridge.io/v1/schedules/c4e2a9b1-7d3f-4e6a-8b50-1f9d2c7e3a64" \
-H "X-API-Key: $PINBRIDGE_API_KEY"
Cancel, retry, delete
# Cancel a pending schedule
curl -X POST https://api.pinbridge.io/v1/schedules/c4e2a9b1-7d3f-4e6a-8b50-1f9d2c7e3a64/cancel \
-H "X-API-Key: $PINBRIDGE_API_KEY"
# Retry a failed schedule
curl -X POST https://api.pinbridge.io/v1/schedules/c4e2a9b1-7d3f-4e6a-8b50-1f9d2c7e3a64/retry \
-H "X-API-Key: $PINBRIDGE_API_KEY"
# Delete a schedule (returns 204 No Content)
curl -X DELETE https://api.pinbridge.io/v1/schedules/c4e2a9b1-7d3f-4e6a-8b50-1f9d2c7e3a64 \
-H "X-API-Key: $PINBRIDGE_API_KEY"
Cancel, retry, and delete are status-dependent: you’ll get a 400 such as Cannot cancel schedule with status <status>, Cannot retry schedule with status <status>, or Cannot delete schedule with status <status>; cancel it first. when the current status doesn’t allow the action.
In the SDK: client.schedules.cancel(id), client.schedules.retry(id), client.schedules.delete(id).
Bulk actions
Each bulk endpoint takes { "ids": [...] } with up to 500 ids.
curl -X POST https://api.pinbridge.io/v1/schedules/bulk-cancel \
-H "X-API-Key: $PINBRIDGE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"ids": ["c4e2a9b1-7d3f-4e6a-8b50-1f9d2c7e3a64", "9f5b3d1e-2a7c-4b8d-a4e6-6c0f1b9d5e27"]}'
Response (200, trimmed):
{
"succeeded_count": 1,
"skipped_count": 1,
"failed_count": 0,
"results": [
{"id": "c4e2a9b1-7d3f-4e6a-8b50-1f9d2c7e3a64", "status": "succeeded"},
{"id": "9f5b3d1e-2a7c-4b8d-a4e6-6c0f1b9d5e27", "status": "skipped", "error_code": "ineligible_status"}
]
}
The same shape applies to POST /v1/schedules/bulk-retry and POST /v1/schedules/bulk-delete (SDK: client.schedules.bulk_cancel(ids), bulk_retry(ids), bulk_delete(ids)).
Verify it worked
- The create response returns
201withstatus: scheduledand therun_atnormalized to UTC. - Fetch with
GET /v1/schedules/{schedule_id}and watchstatusadvance. - Once
pin_idis set, follow the pin withGET /v1/pins/{pin_id}or a webhook.
Common errors
| Status | Cause |
|---|---|
| 422 | run_at missing a timezone offset, or a missing required field. |
| 400 | run_at must be in the future. |
| 400 | Cannot cancel / retry / delete schedule with status <status>. |
| 403 | feature_unavailable — used an asset_id on the Free plan. |
Next steps
- Publish pins — publish immediately, and the full field reference.
- Upload media — host media and schedule an asset-backed pin.
- Webhooks — get notified when a scheduled pin publishes or fails.
- Rate limits and quotas — how scheduled publishes count against quota.
