Skip to main content

tokportal

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

pip install tokportal

30-second quickstart

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

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:

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:

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.

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:

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:

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:

from tokportal import verify_webhook_signature

valid = verify_webhook_signature(
    raw_body,
    request.headers["TokPortal-Signature"],
    os.environ["TOKPORTAL_WEBHOOK_SECRET"],
)
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 for what we accept as PRs and SECURITY.md for vulnerability reporting.

Links

MIT © TokPortal

Metadata

Release files for tokportal 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tokportal 0.1.0
File Size Uploaded
tokportal-0.1.0.tar.gz 16.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tokportal 0.1.0
File Interpreter ABI Platform
tokportal-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 32.0 kB

Release files / tokportal-0.1.0.tar.gz

Download URL tokportal-0.1.0.tar.gz
Size 16.1 kB
Tags Source
SHA-256 checksum
How to use checksums
c50a8fa18e54ff515a8fb0e8b919b2f7fc7cfb09316a2e4ab9983a06329df8ce
BLAKE2b-256 checksum
How to use checksums
1ffc367dc5d93a1711aa898bf7944e13b105594d2d383f80c6858f9a11d2501e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release files / tokportal-0.1.0-py3-none-any.whl

Download URL tokportal-0.1.0-py3-none-any.whl
Size 15.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
453491e47f57ea509d9bffd1f6f118707c3df8d553aa178ae41ec7ec2b76cd51
BLAKE2b-256 checksum
How to use checksums
badd0c5d9ee440a76296640bd3db8bc567137f3d97f85b80a89b636d49207707
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page