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

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tokportal-0.1.0.tar.gz (16.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tokportal-0.1.0-py3-none-any.whl (15.9 kB view details)

Uploaded Python 3

File details

Details for the file tokportal-0.1.0.tar.gz.

File metadata

  • Download URL: tokportal-0.1.0.tar.gz
  • Upload date:
  • Size: 16.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.3

File hashes

Hashes for tokportal-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c50a8fa18e54ff515a8fb0e8b919b2f7fc7cfb09316a2e4ab9983a06329df8ce
MD5 537bc75850e1c736eb89015f235b24f9
BLAKE2b-256 1ffc367dc5d93a1711aa898bf7944e13b105594d2d383f80c6858f9a11d2501e

See more details on using hashes here.

File details

Details for the file tokportal-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: tokportal-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.14.3

File hashes

Hashes for tokportal-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 453491e47f57ea509d9bffd1f6f118707c3df8d553aa178ae41ec7ec2b76cd51
MD5 1310e2ca6696043825a01e46fd8a5aab
BLAKE2b-256 badd0c5d9ee440a76296640bd3db8bc567137f3d97f85b80a89b636d49207707

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page