Python SDK
v1Typed synchronous and asynchronous clients for the complete Castrook API.
Install
python -m pip install castrook==0.5.0Use a server-held credential
The client defaults to https://castrook.com/api/v1. Use api_key for an API key or token for an OAuth access token bound to the REST resource. A grant issued for MCP cannot be reused for another resource. Responses preserve the API envelope and typed definitions; errors expose code, status, details and request ID.
import os
from castrook import Castrook, CastrookError
with Castrook(api_key=os.environ["CASTROOK_API_KEY"]) as api:
account = api.accounts.create_test({
"platform": "facebook",
"name": "API demo",
})["data"]
post = api.posts.create({
"text": "Hello from Castrook.",
"account_ids": [account["id"]],
"platform_options": {
"facebook": {"sandbox_outcome": "published"}
},
}, idempotency_key="api-demo-first-post-v1")["data"]
result = api.posts.wait(post["id"], timeout=300, poll_interval=1)["data"]
print(result["status"], result["targets"])This example creates a simulated Facebook account and post. Use a Test credential with accounts:write, posts:write and posts:read. A post response means acceptance; inspect its targets until delivery completes.
Waiting is bounded. A distant schedule can outlast the timeout while remaining valid.
Async and pagination
from castrook import AsyncCastrook
async with AsyncCastrook(api_key=api_key) as api:
async for post in api.posts.iter(status="published"):
print(post["id"], post["targets"])Use paginate(lambda cursor: api.posts.list(cursor=cursor)) for custom pagination. Lists accept snake_case keyword filters; analytics uses from_ for the API’s from field.
Upload a durable asset
with Castrook(api_key=api_key) as api:
asset = api.media.upload(
"./launch.mp4", profile_id=profile_id
)["data"]
post = api.posts.create({
"text": "Launch day.",
"account_ids": [account_id],
"profile_id": profile_id,
"media_items": [{"type": "video", "asset_id": asset["id"]}],
"scheduled_at": scheduled_at_iso8601,
}, idempotency_key="customer-42-launch-v1")["data"]Paths infer filename and media type. Byte input requires filename and content_type. The helper hashes, transfers and verifies the original file; media.download(id) returns authenticated bytes. Destination options and creator consent still apply.
Resource parity
Use profiles, connect_sessions, accounts, media, posts, analytics, comments, webhooks, deliveries, logs and usage. Methods use snake_case, including create_test, assign_profile, publishing_options and accept_analytics_policy. Pinterest discovery uses accounts.list_boards and list_board_sections; iter_boards and iter_board_sections follow cursor pages, including empty ones.
Handle uncertainty
Bounded timeouts and safe retries preserve idempotency. Persist the body and idempotency_key for a logical post. Monthly limits are not transient failures. CastrookError provides the API’s reason and request ID; missing metrics remain unavailable.
Read this guide as Markdown or use the machine manifest.