Agents × jobs · OpenAI Codex

Run multi-client agency operations with OpenAI Codex

Run an agency's TikTok/Instagram operations from OpenAI Codex: per-client external_ref, bulk account fleets, videos_only reposting, ban webhooks and per…

An agency using OpenAI Codex with TokPortal runs every client through the same four primitives — bundles, accounts, videos, webhooks — and keeps them separate with external_ref and account filters. create_bundles_bulk opens a client's fleet in their market, list_bundles/list_accounts filter by client reference, videos_only bundles carry each month's content onto delivered accounts, create_webhook_endpoint pushes account.banned and video.finalized into the agency's tooling, and export_analytics_videos / create_analytics_report produce the client deliverable. One API key, no per-client OAuth, no app audit, human-operated accounts the agency never has to log into.

Connect TokPortal to OpenAI Codex

OpenAI Codex is a terminal agent: OpenAI's coding agent (Codex CLI and IDE extension); MCP servers live in ~/.codex/config.toml.

Add the remote server to ~/.codex/config.toml:

[mcp_servers.tokportal]
url = "https://app.tokportal.com/api/ext/mcp"
# either OAuth (run `codex mcp login tokportal` once) …
# … or a static key from your environment:
# bearer_token_env_var = "TOKPORTAL_API_KEY"

Then codex mcp login tokportal for the OAuth flow. Recent Codex builds also accept the one-liner codex mcp add tokportal --url https://app.tokportal.com/api/ext/mcp; the stdio form always works:

codex mcp add tokportal --env TOKPORTAL_API_KEY=sk_... -- npx -y tokportal-mcp

Snippet status: verified against OpenAI Codex's documentation (source).

Once connected, sanity-check the setup with a read-only call — "What is my TokPortal credit balance?" should trigger tokportal_get_credit_balance. Every tool runs as your TokPortal account and spends your credits; read-only tools (get_*, list_*, export_*) never do.

How it works

Structure comes from external_ref: put the client slug in it (acme-us, bloom-fr) on every bundle — create_bundle and create_bundles_bulk both accept it, and list_bundles?external_ref=acme-us returns that client's work. Video slots have their own external_ref for creative ids. Accounts inherit their bundle; list_account_bundles on an account gives its history. If clients need real isolation, use one API key per client (keys are per workspace, shown once, revocable individually) — the agent can hold several and pick by client.

Monthly operations from OpenAI Codex then look like this. Onboarding: create_bundles_bulk (accounts_count, videos_per_account, country, warming terms) plus per-account configure_bundle_account from the client's brand sheet. Content: upload_video for each asset, batch_configure_bundle_videos for the month at ≤3/day, publish_bundle. Reposting existing accounts next month: create_bundle with bundle_type: videos_only and account_id, videos_quantity, then the same batch fill. Corrections: request_bundle_video_corrections when the client rejects a post during the 72-hour review (in_review), or finalize_bundle_video to approve immediately; set auto_finalize_videos: false on bundles where the client insists on approving.

Risk and reporting: one webhook endpoint per client system with account.banned, account.ban_appeal.submitted, account.ban_resolution.decided, video.finalized; list_account_bans as the single source of truth for ban state and refund/remake outcomes; create_analytics_report (or export_analytics_report_html) for a branded monthly report and export_analytics_videos for the raw CSV. Credits are shared per workspace — list_credit_transactions gives the per-bundle ledger to re-invoice each client.

Run it from OpenAI Codex

Start a OpenAI Codex session in the project folder and paste the prompt below. Every tokportal_* call is shown before it runs; approve read-only tools freely and review write tools (create_*, configure_*, publish_*) before accepting.

Tool sequence

  1. tokportal_get_credit_costs — Per-client quotes; contract allowances show here.
  2. tokportal_create_bundles_bulk — Client fleet with external_ref: <client>.
  3. tokportal_list_bundlesexternal_ref, status, platform filters per client.
  4. tokportal_create_bundlevideos_only + account_id for next month's content on delivered accounts.
  5. tokportal_batch_configure_bundle_videos — Month of slots per bundle.
  6. tokportal_request_bundle_video_corrections — Client rejects a post in review → manager redoes it.
  7. tokportal_create_webhook_endpoint — Per-client endpoint: account.banned, account.ban_appeal.submitted, account.ban_resolution.decided, video.finalized.
  8. tokportal_list_account_bans — Ban lifecycle + refund/remake resolution for client comms.
  9. tokportal_create_analytics_report — Monthly report per client (or export_analytics_report_html).
  10. tokportal_list_credit_transactions — Ledger to re-invoice credits per client.

Prompt to paste

Use the TokPortal MCP tools. Client "acme-us": list_bundles with external_ref acme-us and status published,
list_account_bans since 2026-08-01 for their accounts, then create_analytics_report for 2026-08-01 → 2026-08-31
filtered on those accounts. Summarize: posts finalized, views, bans + resolutions, credits spent (list_credit_transactions).

Run codex in your project, paste the prompt; Codex lists the tokportal_* calls it wants to make and asks for approval unless you run with full-auto.

REST equivalent (same operations, X-API-Key header, base URL https://app.tokportal.com/api/ext)

# Client fleet
curl -X POST https://app.tokportal.com/api/ext/bundles/bulk \
  -H "X-API-Key: sk_..." -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
  -d '{"platforms":["tiktok"],"country":"US","accounts_count":8,"videos_per_account":30,"external_ref":"acme-us"}'

# This client's bundles
curl "https://app.tokportal.com/api/ext/bundles?external_ref=acme-us&status=published" -H "X-API-Key: sk_..."

# Next month on a delivered account
curl -X POST https://app.tokportal.com/api/ext/bundles \
  -H "X-API-Key: sk_..." -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
  -d '{"bundle_type":"videos_only","account_id":"ACCOUNT_UUID","videos_quantity":30,"external_ref":"acme-us","title":"Acme – Oct"}'

# Client-specific ban + delivery webhook
curl -X POST https://app.tokportal.com/api/ext/webhooks \
  -H "X-API-Key: sk_..." -H "Content-Type: application/json" \
  -d '{"url":"https://agency.example/hooks/acme","events":["account.banned","account.ban_appeal.submitted","account.ban_resolution.decided","video.finalized"],"description":"Acme"}'

Key parameters

ParameterValuesNotes
external_ref≤200 charsClient slug on bundles; filter list_bundles by it.
bundle_typeaccount_and_videos · videos_onlyvideos_only + account_id for recurring content.
auto_finalize_videosbooleanfalse when the client must approve each post (72 h window).
status (list_bundles)draft · published · completed …Combine with external_ref for client dashboards.
events (webhooks)account.banned · account.ban_appeal.submitted · account.ban_resolution.decided · video.finalized …One endpoint per client system.
since (list_account_bans)ISO timestampPolling watermark on updated_at.

Full schemas: OpenAPI reference · openapi.json.

Example configurations

Client onboarding fleet

{"platforms":["tiktok","instagram"],"country":"FR","accounts_count":6,"videos_per_account":20,
 "wants_advanced_warming":true,"advanced_warming_terms_count":6,"external_ref":"bloom-fr"}

Approval-required content bundle

{"bundle_type":"videos_only","account_id":"ACCOUNT_UUID","videos_quantity":12,"auto_finalize_videos":false,"external_ref":"bloom-fr"}

Monthly report request

{"title":"Bloom – September","brandName":"Bloom","from":"2026-09-01","to":"2026-09-30","countries":["FR"],"platforms":["tiktok","instagram"]}

Credits

Credits are shared per workspace; use list_credit_transactions (per-bundle lines) to re-invoice each client. Standard rates: 32 per account, 2 per slot, 5 per warming target, 25 per 30 days TokPortal Coverage per eligible account after the included first period. See Credits & Pricing.

Why not the official API

Official APIs make an agency the OAuth broker for every client account — each grant expires, each app must be audited, each token is limited to 6 requests/minute with per-user daily caps, and none of it creates or warms accounts. TokPortal gives the agency one key, human-operated accounts per client market, and a ban lifecycle it can actually report on.

As of August 2026 the first-party routes look like this. TikTok's Content Posting API (Direct Post) requires each account owner to authorize your app with the video.publish scope, limits every user access token to 6 requests per minute, keeps all posts from unaudited apps in private viewing mode until TikTok audits the app, and enforces an unpublished daily post cap per user (spam_risk_too_many_posts) that integrators commonly report at roughly 15–25 posts per account per day. Meta's Instagram Content Publishing API allows 100 API-published posts per professional account in a 24-hour moving window and only for accounts you own and connect via OAuth. Neither creates accounts, warms them, or reports third-party bans. TokPortal is human-operated infrastructure: accounts created and run by managers in the target country, one X-API-Key for all of them, dated slots (max 3 per day per bundle) instead of per-account tokens.

Sources: TikTok Content Posting API – Direct Post, TikTok Content Posting API – Get started, Instagram Platform – Content Publishing.

FAQ

How do I isolate clients?

Lightweight: external_ref per bundle and per-client webhook endpoints. Strict: one API key per client (revocable individually) and let the agent pick the key by client.

Can clients approve posts before they count as done?

Yes — set auto_finalize_videos: false; each post waits in in_review for finalize_bundle_video or request_bundle_video_corrections (72-hour window, then auto-finalize).

What do I tell a client when an account is banned?

Read list_account_bans for the exact status (appeal_pending, appeal_refused, no_appeal_banned…) and the staff resolution (refund, remake, no_remake + reason_code, refund_credits). Never infer bans from other signals.

How do I produce the monthly deliverable?

create_analytics_report (JSON) or export_analytics_report_html (branded HTML) with from/to and country/platform filters, plus export_analytics_videos for the CSV appendix.

Also works with

All 25 agents for "Run multi-client agency operations"

Other jobs with OpenAI Codex