tiktok-shop-api: TikTok Shop API client for Python
A typed Python client for the TikTok Shop API (the TikTok Shop Partner API). It covers over 300 operations across orders, products, fulfillment, logistics, finance, affiliate, customer service and more, with a sync client and an async client.
It signs requests for you, handles OAuth, works with many shops at once, and verifies and types TikTok Shop webhooks.
Unofficial. Not affiliated with or endorsed by TikTok or ByteDance.
Request signing follows TikTok's documentation and has not been verified against the live API. If TikTok rejects a signature, please open an issue at https://github.com/isaackogan/TikTok-Shop-Api-SDKs/issues.
The client is generated from an OpenAPI spec that is itself built from the TikTok Shop Partner Center docs: tiktok-shop.openapi.yaml.
Install
pip install tiktok-shop-api
Requires Python 3.11 or newer. Its dependencies are httpx and attrs.
OAuth: get an access token
import os
from tiktok_shop_api import TikTokShopAuth
code_from_redirect = "the ?code= value from your redirect URL"
auth = TikTokShopAuth(
os.environ["TTS_APP_KEY"],
os.environ["TTS_APP_SECRET"],
service_id=os.environ["TTS_SERVICE_ID"], # seller and partner flows
)
# 1. Send the seller here. `type` is "seller", "partner" or "creator"; `region` is "us" or "row".
url = auth.authorization_url(type="seller", region="us", state="csrf-token")
# 2. TikTok redirects back with ?code=...; exchange it.
tokens = auth.exchange_code(code_from_redirect)
# tokens.access_token, tokens.refresh_token, tokens.open_id, tokens.granted_scopes, ...
# 3. Before the access token expires (access_token_expire_in is a Unix timestamp):
renewed = auth.refresh(tokens.refresh_token)
AsyncTikTokShopAuth has the same methods as coroutines. A non-zero code in TikTok's response raises a TikTokShopError with code, message and request_id (see Errors).
Make your first call
import os
from tiktok_shop_api import TikTokShop
access_token = os.environ["TTS_ACCESS_TOKEN"]
with TikTokShop(os.environ["TTS_APP_KEY"], os.environ["TTS_APP_SECRET"], access_token=access_token) as client:
# Find the shop cipher
shops = client.authorization.get_authorized_shops()
assert shops is not None
shop_cipher = shops.to_dict()["data"]["shops"][0]["cipher"]
seller = client.with_shop(access_token=access_token, shop_cipher=shop_cipher)
orders = seller.orders.get_order_list(page_size=20)
The async client mirrors it, with await on every call:
import asyncio
import os
from tiktok_shop_api import AsyncTikTokShop
access_token = os.environ["TTS_ACCESS_TOKEN"]
async def main() -> None:
async with AsyncTikTokShop(os.environ["TTS_APP_KEY"], os.environ["TTS_APP_SECRET"], access_token=access_token) as client:
shops = await client.authorization.get_authorized_shops()
assert shops is not None
seller = client.with_shop(shop_cipher=shops.to_dict()["data"]["shops"][0]["cipher"])
orders = await seller.orders.get_order_list(page_size=20)
asyncio.run(main())
One attribute per API area hangs off the client (orders, products, fulfillment, finance, affiliate_seller, and so on). Every call is signed, timestamped and sent with your access token. The shop_cipher query parameter is added for you on the endpoints that need it.
Many shops
with_shop returns a client for another shop. It shares the HTTP transport and your app credentials, so you can keep one per shop. Arguments you leave out keep the original's values, and the original is never changed:
import os
from tiktok_shop_api import TikTokShop
client = TikTokShop(os.environ["TTS_APP_KEY"], os.environ["TTS_APP_SECRET"])
token_a, cipher_a = os.environ["TOKEN_A"], os.environ["CIPHER_A"]
token_b, cipher_b = os.environ["TOKEN_B"], os.environ["CIPHER_B"]
shop_a = client.with_shop(access_token=token_a, shop_cipher=cipher_a)
shop_b = client.with_shop(access_token=token_b, shop_cipher=cipher_b)
Webhooks
Verify the signature against the raw request body, then parse it into a typed event. This example uses Flask; any framework that gives you the unmodified bytes works:
import os
from flask import Flask, request
from tiktok_shop_api import UnknownWebhookEvent, WebhookSignatureError, Webhooks
from tiktok_shop_api.generated.models import OrderStatusChangeWebhook
app = Flask(__name__)
@app.post("/webhooks/tiktok-shop")
def tiktok_shop_webhook():
try:
event = Webhooks.verify_and_parse(
app_key=os.environ["TTS_APP_KEY"],
app_secret=os.environ["TTS_APP_SECRET"],
raw_body=request.get_data(), # exactly as received
signature=request.headers.get("Authorization", ""),
)
except WebhookSignatureError:
return "", 401
except ValueError: # not a webhook this SDK can read
return "", 400
if isinstance(event, UnknownWebhookEvent):
print("unknown webhook type", event.type, event.raw)
elif isinstance(event, OrderStatusChangeWebhook):
print(event.shop_id, event.data)
return "", 200
- Never re-serialize the body before verifying. Changed whitespace or key order makes the signature fail.
- A webhook type this SDK does not know comes back as
UnknownWebhookEvent(type, raw). Known events are the generated model for that webhook, soisinstancenarrows them. - Parsing is strict.
parseraisesValueErrorfor a body that is not a JSON object, atypethat is missing or not an integer, or a known type with a required field missing or null: a known type missing a required field is a parse error. EVENT_TYPESmaps a type number to its name (1isORDER_STATUS_CHANGE).
Options
base_url(on the clients and the auth helpers) must be an origin such ashttps://host:8443, with no path prefix: signing and shop-cipher matching use the request path.timeout(on all four) is in seconds and defaults to 30.Noneor0means no limit; you can also pass anhttpx.Timeout.- Requests carry the User-Agent
tiktok-shop-api-python/<version>. - Token calls send
app_secret,auth_codeandrefresh_tokenin the URL query, and httpx logs every request URL at INFO. Importingtiktok_shop_apiadds a filter to thehttpxlogger that replaces those three values with***, so a service logging at INFO never writes them. Keep the filter if you reconfigure that logger.
Errors
Every failed call raises TikTokShopError, with code, message, request_id, http_status and the original exception as __cause__:
| What happened | code |
http_status |
|---|---|---|
TikTok's reply has a non-zero code, even on HTTP 200 |
TikTok's code | the status |
| A non-2xx reply | TikTok's non-zero code if the body has one, else the HTTP status | the status |
A 2xx reply that can't be read: not a JSON object, a code that isn't an integer, a body that doesn't fit its model, or a token reply without data |
-1 | the status |
| No HTTP response at all: connection refused, DNS, TLS, or a timeout | -1 | None |
About
This is the Python package of a set of generated TikTok Shop API SDKs. The OpenAPI spec and the other languages live in isaackogan/TikTok-Shop-Api-SDKs.
MIT licensed. Unofficial. Not affiliated with or endorsed by TikTok or ByteDance.
Metadata
Release files for tiktok-shop-api 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tiktok_shop_api-0.1.0.tar.gz | 1.3 MB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tiktok_shop_api-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 4.9 MB
Release files / tiktok_shop_api-0.1.0.tar.gz
| Download URL | tiktok_shop_api-0.1.0.tar.gz |
|---|---|
| Size | 1.3 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
7289dc90b3768eeb110582da17050b7310a56a341d52d7b5a8801d6a2ea2b1f6
|
|
BLAKE2b-256 checksum How to use checksums |
f5d48df8169bbd26392cc611961341f67dae572468098cde3483452ea25bda14
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logRelease files / tiktok_shop_api-0.1.0-py3-none-any.whl
| Download URL | tiktok_shop_api-0.1.0-py3-none-any.whl |
|---|---|
| Size | 3.6 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ff5d5082458da8bfb16bb925a87377b1777107ebb4e1f1491b4a8faee52d032d
|
|
BLAKE2b-256 checksum How to use checksums |
398426b6861496c2b26b28d1fc5c05ef7bbf72fcea22d9a6f89555ffb4cdc525
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logSecurity for tiktok-shop-api 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tiktok_shop_api-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 20, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.