DocumentationPython SDK

Python SDK

v1

Typed synchronous and asynchronous clients for the complete Castrook API.

castrook · 0.5.0Python package · MIT
Download

Install

Shell
python -m pip install castrook==0.5.0

Use 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.

Python
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

Python
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.