Metadata-Version: 2.5
Name: tokportal
Version: 0.1.0
Summary: Generated Python SDK for the TokPortal public API.
Project-URL: Homepage, https://developers.tokportal.com/sdks-cli/
Project-URL: Repository, https://github.com/tokportal/tokportal-python
Project-URL: Documentation, https://developers.tokportal.com
Project-URL: Issues, https://github.com/tokportal/tokportal-python/issues
Project-URL: Changelog, https://developers.tokportal.com/changelog
Author-email: TokPortal <team@tokportal.com>
License-Expression: MIT
License-File: LICENSE
Keywords: ai-agents,api,automation,instagram,mcp,sdk,social-media,tiktok,tokportal,youtube
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Internet :: WWW/HTTP
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# tokportal

[![PyPI](https://img.shields.io/pypi/v/tokportal.svg)](https://pypi.org/project/tokportal/)
[![Python](https://img.shields.io/pypi/pyversions/tokportal.svg)](https://pypi.org/project/tokportal/)
[![license](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)

TokPortal is the managed social infrastructure API: real TikTok, Instagram and YouTube accounts created, warmed and operated by human account managers in 16+ countries — exposed as a REST API and an MCP server. No OAuth per account, no 25-posts/day cap, no app review.

Docs https://developers.tokportal.com · API base https://app.tokportal.com/api/ext · OpenAPI https://developers.tokportal.com/openapi.json · MCP remote https://app.tokportal.com/api/ext/mcp · Get an API key https://app.tokportal.com/developer/api-keys · llms.txt https://developers.tokportal.com/llms.txt

---

`tokportal` is the official Python SDK for the TokPortal API (Python 3.9+, typed, standard library only). Every public operation is available as a resource method or through the generated `request_operation` map.

## Install

```bash
pip install tokportal
```

## 30-second quickstart

```python
import os
from tokportal import TokPortal

client = TokPortal(api_key=os.environ["TOKPORTAL_API_KEY"])

# 1. Create a bundle: a fresh managed TikTok account in the USA + 1 video slot.
#    Credits are debited now; the account manager is assigned at publish time.
bundle = client.bundles.create({
    "bundle_type": "account_and_videos",
    "platform": "tiktok",
    "country": "USA",
    "title": "US launch",
    "videos_quantity": 1,
})
bundle_id = bundle["data"]["id"]

# 2. Upload the video straight from disk -> public_url
upload = client.uploads.video_direct("./launch.mp4", bundle_id, content_type="video/mp4")

# 3. Configure the account profile and video slot 1, then publish
client.bundles.configure_account(bundle_id, {
    "username": "mybrand.us",
    "visible_name": "My Brand",
    "biography": "Official account",
})
client.bundles.configure_video(bundle_id, 1, {
    "video_type": "video",
    "video_url": upload["data"]["public_url"],
    "description": "Day 1 - launching in the US #launch",
    "target_publish_date": "2026-09-01",
})
client.bundles.publish(bundle_id)

# 4. Later (webhook `account.in_review` / `account.finalized`, or polling):
#    saved_account_id is the real delivered account -> read it back
current = client.bundles.get(bundle_id)["data"]
if current.get("saved_account_id"):
    account = client.accounts.get(current["saved_account_id"])["data"]
    print(account["username"], account["profile_url"])
```

> Method names follow the generated resource map (`bundles`, `uploads`, `accounts`, `analytics`, `webhooks`). If a helper does not exist for an operation, use `client.request_operation("<operationId>", path=..., query=..., body=...)`.

## Full example

```python
import os
from tokportal import TokPortal, TokPortalApiError

client = TokPortal(api_key=os.environ["TOKPORTAL_API_KEY"])

me = client.me()

bundle = client.bundles.create({
    "bundle_type": "account_and_videos",
    "country": "USA",
    "videos_quantity": 5,
})

csv = client.analytics.export_videos(account=["saved-account-id"])
image = client.uploads.image_from_url({
    "url": "https://cdn.example.com/photo.jpg",
    "bundle_id": bundle["data"]["id"],
})

print(me["data"]["email"], bundle["data"], csv, image["data"])
```

Direct multipart uploads use the same structured errors and idempotency support:

```python
uploaded = client.uploads.video_direct(
    "./video.mp4",
    bundle["data"]["id"],
    content_type="video/mp4",
    idempotency_key="video-upload-123",
)
```

Manage TokPortal Coverage from the latest atomic quote. A zero-credit quote is
valid and still requires an explicit reactivation call:

```python
coverage = client.accounts.coverage("saved-account-id")
quote = coverage["data"]["reactivation_quote"]

if quote:
    client.accounts.reactivate_coverage(
        "saved-account-id",
        {
            "expected_credits": quote["credits"],
            "expected_current_period_end": quote["current_period_end"],
            "expected_lock_version": quote["lock_version"],
        },
        idempotency_key="coverage-reactivate-saved-account-id-v4",
    )

client.accounts.pause_coverage(
    "saved-account-id",
    idempotency_key="coverage-pause-saved-account-id-v4",
)
```

Credential reveal and verification-code access use the same irreversible
two-step policy flow. First call without acceptance to receive HTTP 428 and
`error.details.policy_version`; then show those terms to the account owner and
retry with that exact version. The accepted request may debit credits and
permanently detach the account. These secret-bearing responses are never stored
for replay, so these helpers intentionally do not accept `idempotency_key`.
After an uncertain transport result, reconcile the safe account state before
deciding whether to call the endpoint again without a key:

If an accepted call returns HTTP 409 with
`CREDENTIAL_REVEAL_QUOTE_CHANGED`, no charge or reveal occurred. Read the
current policy and `expected_credit_cost` from `error.details`, show the new
terms to the owner, obtain fresh consent, and retry with the new version. Never
retry a 409 automatically.

```python
try:
    client.accounts.reveal_credentials("saved-account-id")
except TokPortalApiError as error:
    if error.status_code != 428:
        raise

    policy_version = str(error.details["policy_version"])
    credentials = client.accounts.reveal_credentials(
        "saved-account-id",
        acceptance={
            "acknowledge_support_forfeit": True,
            "policy_version": policy_version,
        },
    )
```

The same no-replay rule applies to `webhooks.create`, `uploads.image`,
`uploads.video`, and `analytics.create_report` because they return a signing
secret, signed upload capability, or report access token. These helpers do not
accept `idempotency_key`, and `request_operation` rejects one locally for all
six sensitive operation IDs.

Discover and operate webhooks without dropping to raw HTTP:

```python
catalog = client.webhooks.events()
endpoints = client.webhooks.list(event="bundle.published")
retry = client.webhooks.retry_delivery(endpoints["data"][0]["id"], "delivery-id")
```

Every OpenAPI operation is also reachable through the generated operation map:

```python
same_retry = client.request_operation(
    "retryWebhookDelivery",
    path={"id": endpoints["data"][0]["id"], "delivery_id": "delivery-id"},
)

csv_again = client.request_operation(
    "exportAnalyticsVideos",
    query={"account": ["saved-account-id"]},
)
```

The SDK sends `X-TokPortal-Client: tokportal-python/0.1.0` on API requests for observability and support diagnostics.

Verify signed webhook deliveries with the exact raw request body:

```python
from tokportal import verify_webhook_signature

valid = verify_webhook_signature(
    raw_body,
    request.headers["TokPortal-Signature"],
    os.environ["TOKPORTAL_WEBHOOK_SECRET"],
)
```

```python
from tokportal import TokPortalApiError

try:
    client.bundles.create({
        "bundle_type": "account_and_videos",
        "country": "USA",
        "videos_quantity": 5,
    })
except TokPortalApiError as error:
    print(error.status_code, error.code, error.details, error.request_id)
    if error.retryable:
        wait_seconds = error.retry_after_seconds or 1
        # Retry with backoff.
        pass
    print(error.rate_limit)
```

API keys use the format `sk_` followed by 64 lowercase hex characters. TokPortal stores only a SHA-256 hash of the key and shows the raw key once at creation.

## Source of truth

This package is generated from the TokPortal public OpenAPI schema
(https://developers.tokportal.com/openapi.json) in the private TokPortal
monorepo. Generated files (`tokportal/_generated.py`) are overwritten on every release — do not edit
them by hand. See [CONTRIBUTING.md](./CONTRIBUTING.md) for what we accept as PRs
and [SECURITY.md](./SECURITY.md) for vulnerability reporting.

## Links

- Documentation: https://developers.tokportal.com
- SDKs & CLI guide: https://developers.tokportal.com/sdks-cli
- MCP server: https://developers.tokportal.com/mcp · [`tokportal-mcp`](https://www.npmjs.com/package/tokportal-mcp)
- API reference (OpenAPI): https://developers.tokportal.com/openapi.json
- Other packages: [`@tokportal/node`](https://www.npmjs.com/package/@tokportal/node) · [`@tokportal/cli`](https://www.npmjs.com/package/@tokportal/cli) · [`tokportal` (PyPI)](https://pypi.org/project/tokportal/) · [`github.com/tokportal/tokportal-go`](https://github.com/tokportal/tokportal-go)

MIT © TokPortal
