Python SDK
A typed Python client for the PinBridge API, with sync and async support. This page covers install, client setup, error handling, and the common recipes.
Install
pip install pinbridge-sdk
The install (package) name is pinbridge-sdk; the import package is pinbridge_sdk. The current SDK version is 1.4.0.
Set up a client
The SDK does not read environment variables. Pass your API key explicitly (the class name is PinbridgeClient, with a lowercase “b”):
from pinbridge_sdk import PinbridgeClient
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
accounts = client.pinterest.list_accounts()
print(accounts)
base_url defaults to https://api.pinbridge.io; override it only if you run a self-hosted API. The key is sent as the x-api-key header. For user sessions, pass bearer_token= instead. See Authentication for how to create a key.
Async client
Use AsyncPinbridgeClient for asyncio code. The resource attributes and methods are the same, just awaited:
import asyncio
from pinbridge_sdk import AsyncPinbridgeClient
async def main():
async with AsyncPinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
pins = await client.pins.list(limit=10)
print(pins)
asyncio.run(main())
Error classes
Errors live in pinbridge_sdk.errors (also re-exported from the top-level pinbridge_sdk). The hierarchy:
PinbridgeError— base exception.APIError(PinbridgeError)— any non-2xx response; carriesstatus_code,message,code,details,response.AuthenticationError— 401 / 403.NotFoundError— 404.ValidationError— 422.RateLimitError— 429.
from pinbridge_sdk import PinbridgeClient
from pinbridge_sdk.errors import NotFoundError, RateLimitError
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
try:
pin = client.pins.get("00000000-0000-0000-0000-000000000000")
except NotFoundError:
print("no such pin")
except RateLimitError as e:
print("slow down:", e.status_code)
The authentication exception is named AuthenticationError (not “AuthError”).
Publish a pin
idempotency_key is required on PinCreate (there is no default), and exactly one of image_url / asset_id must be set:
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="Summer styles 2026",
image_url="https://cdn.shop/img/1.jpg",
idempotency_key="launch-123", # required
)
)
print(pin.status) # queued
Upload an asset, then publish by asset_id
Upload an image (or video) to PinBridge storage, then reference the returned asset_id. Asset uploads require a paid plan; the Free (Playground) plan must publish from a public image_url.
from pinbridge_sdk import PinbridgeClient
from pinbridge_sdk.models import PinCreate
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
with open("pin.jpg", "rb") as f:
asset = client.assets.upload_image(f)
pin = client.pins.create(
PinCreate(
account_id="6f1c2e4a-3b7d-4c9e-8a21-5d0f9b3e7c41",
board_id="987654321098765432",
title="Summer styles 2026",
asset_id=asset.id, # instead of image_url
idempotency_key="launch-124",
)
)
print(pin.status)
Schedule a pin
ScheduleCreate.run_at must be a timezone-aware datetime in the future:
from datetime import datetime, timedelta, 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="Autumn drop",
image_url="https://cdn.shop/img/2.jpg",
run_at=datetime.now(timezone.utc) + timedelta(hours=2),
)
)
print(schedule.status) # scheduled
Cancel with client.schedules.cancel(schedule_id).
List and get
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
page = client.pins.list(limit=50, offset=0)
one = client.pins.get("8a3f6c12-4d5e-4b7a-9c01-2e6f8d4b7a93")
Retry a failed pin
client.pins.retry only works on a failed pin; retrying a pin in any other state returns 409:
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
client.pins.retry("8a3f6c12-4d5e-4b7a-9c01-2e6f8d4b7a93")
Bulk variants are available: client.pins.bulk_retry(ids) and client.pins.bulk_delete(ids).
Manage boards (under client.pinterest)
There is no client.boards resource. Boards live under client.pinterest:
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
boards = client.pinterest.list_boards("6f1c2e4a-3b7d-4c9e-8a21-5d0f9b3e7c41")
# client.pinterest.create_board(...)
# client.pinterest.delete_board(board_id, account_id="6f1c2e4a-3b7d-4c9e-8a21-5d0f9b3e7c41")
Webhooks (CRUD)
Register a webhook to receive pin.published and pin.failed events. The secret must be 16–255 characters:
from pinbridge_sdk import PinbridgeClient
from pinbridge_sdk.models import WebhookCreate, WebhookUpdate
with PinbridgeClient(api_key="$PINBRIDGE_API_KEY") as client:
hook = client.webhooks.create(
WebhookCreate(
url="https://example.com/pinbridge",
secret="a-secret-at-least-16-chars",
events=["pin.published", "pin.failed"],
)
)
client.webhooks.list()
client.webhooks.get(hook.id)
client.webhooks.update(hook.id, WebhookUpdate(url="https://example.com/hook2"))
client.webhooks.delete(hook.id)
What the SDK does not cover
Some billing endpoints exist in the API but have no SDK method and must be called over HTTP directly: buying and consuming credits (/v1/billing/credits/*), subscription cancel (POST /v1/billing/cancel) and resume (POST /v1/billing/resume), and the retention-discount claim. client.billing exposes only pricing(), checkout(), portal(), and status(). See Billing & credits.
More examples
Runnable, versioned examples covering every resource live in the PinBridge python-examples repository (current against SDK 1.4.0).
Next steps
- Authentication — create the API key the client uses.
- Billing & credits — credits, quota, and the API-only endpoints.
- Rate limits & quotas — what counts against your quota.
- MCP setup — the same publishing pipeline from an AI assistant.
