Skip to main content
This page shows a compact Python client for the CreatorAudit API. It sets the bearer header and base URL once, follows cursor pagination automatically, and turns RFC 9457 error responses into a typed exception that carries the code, detail, and request id.
The examples use httpx (pip install httpx). The same shapes work with requests — swap the transport calls. Create a key on the API keys page and pass it as a bearer token.

The client

client.py
from __future__ import annotations

import os
from collections.abc import Iterator
from typing import Any

import httpx

BASE_URL = "https://api.creatoraudit.com/v2"


class CreatorAuditError(Exception):
    """An RFC 9457 problem document returned by the API."""

    def __init__(
        self,
        *,
        status: int,
        type: str,
        title: str,
        detail: str,
        code: str,
        request_id: str | None,
    ) -> None:
        super().__init__(f"[{status} {code}] {title}: {detail}")
        self.status = status
        self.type = type
        self.title = title
        self.detail = detail
        self.code = code
        self.request_id = request_id


class CreatorAudit:
    def __init__(self, api_key: str, base_url: str = BASE_URL) -> None:
        self._client = httpx.Client(
            base_url=base_url,
            headers={"Authorization": f"Bearer {api_key}"},
            timeout=30.0,
        )

    def request(
        self,
        method: str,
        path: str,
        *,
        params: dict[str, Any] | None = None,
        json: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        response = self._client.request(method, path, params=params, json=json)
        if response.is_error:
            self._raise_for_problem(response)
        return response.json()

    @staticmethod
    def _raise_for_problem(response: httpx.Response) -> None:
        request_id = response.headers.get("X-Request-ID")
        # Errors are application/problem+json; fall back gracefully if a
        # non-JSON body sneaks through (e.g. a proxy 502).
        try:
            problem = response.json()
        except ValueError:
            problem = {}
        raise CreatorAuditError(
            status=problem.get("status", response.status_code),
            type=problem.get("type", "about:blank"),
            title=problem.get("title", response.reason_phrase),
            detail=problem.get("detail", response.text),
            code=problem.get("code", "INTERNAL_ERROR"),
            request_id=request_id,
        )

    def close(self) -> None:
        self._client.close()

Identify your key

GET /whoami confirms the key works and returns the organization it belongs to.
client = CreatorAudit(os.environ["CREATORAUDIT_API_KEY"])

me = client.request("GET", "/whoami")["data"]
print(me["organization_id"], me.get("api_key_name"))

Paginate any list endpoint

List endpoints return { "data": [...], "pagination": { next_cursor, has_next, limit } }. This helper yields every item across pages by passing the previous next_cursor back as cursor and stopping when has_next is false.
def paginate(
    client: CreatorAudit,
    path: str,
    *,
    params: dict[str, Any] | None = None,
    limit: int = 200,
) -> Iterator[dict[str, Any]]:
    """Yield every item from a cursor-paginated endpoint."""
    cursor: str | None = None
    while True:
        page_params: dict[str, Any] = {**(params or {}), "limit": limit}
        if cursor is not None:
            page_params["cursor"] = cursor

        page = client.request("GET", path, params=page_params)
        yield from page["data"]

        pagination = page["pagination"]
        if not pagination["has_next"]:
            break
        cursor = pagination["next_cursor"]


# Walk every tracked TikTok account:
accounts = list(paginate(client, "/accounts", params={"platform": "tiktok"}))
print(f"{len(accounts)} accounts")
Treat next_cursor as opaque — pass back the exact value you received. See Pagination for the full contract.

Track an account

POST /accounts requires platform (instagram or tiktok) and username. Optional fields tune how the account is tracked.
created = client.request(
    "POST",
    "/accounts",
    json={
        "platform": "tiktok",
        "username": "creatoraudit",
        "category": "tech",
        "scrape_interval_hours": 24,
    },
)["data"]
print("tracking", created["id"])
To track a single video instead, POST /videos takes platform and an identifier (a full URL, a numeric id, or — for Instagram — a bare shortcode):
video = client.request(
    "POST",
    "/videos",
    json={
        "platform": "tiktok",
        "identifier": "https://www.tiktok.com/@creatoraudit/video/712345",
        "is_active": True,
    },
)["data"]
print("tracking video", video["id"])

Organization overview

GET /overview accepts a period of 7d, 30d, or 90d.
overview = client.request("GET", "/overview", params={"period": "30d"})["data"]
print(overview["current"], overview["changes"])

Handling errors

Any non-2xx response raises CreatorAuditError with the parsed problem fields and the X-Request-ID, so you can branch on code and include the request id when reporting an issue.
try:
    client.request("POST", "/accounts", json={"platform": "tiktok"})  # missing username
except CreatorAuditError as exc:
    if exc.code == "VALIDATION_ERROR":
        print("fix the request body:", exc.detail)
    print("status:", exc.status, "request-id:", exc.request_id)
finally:
    client.close()

Next steps