MCP server: drive Pamba from Claude Code, Codex or any MCP client
Connect an MCP client to your workspace, pick the toolsets you need, and learn how calls, credits, waits, approvals and hand-offs behave before you automate anything.
Pamba's MCP server exposes every tool the in-app assistant has, over the Model Context Protocol, at one endpoint: https://api.pamba.app/mcp. Your client's model gets the same product knowledge the assistant runs on, so it can chain the tools into whole workflows (research a format, build the avatar, create the projects, generate, schedule) without you translating screens into API calls. This guide covers what the reference cannot: how the surface is cut, how a call behaves, what waits, what costs credits, and the ordering rules that trip people up. The exact tool list, with every parameter, is the MCP tool reference.
Connect from a chat app
Choose your chat app in the visual setup guide: Claude, ChatGPT, Grok or Gemini. Each walkthrough shows the provider’s menus, where to paste the URL, how to approve access on Pamba and a read-only prompt to try. Account requirements and links to the provider’s current instructions are included.
In a chat app that supports remote MCP with OAuth, add https://api.pamba.app/mcp as a custom connector. Pamba opens an approval page: sign in and choose one or more workspaces, or enter your workspace API key on that Pamba page. Review the requesting app's return address and approve. Never paste the key into a chat message.
Find the URL in Settings → Connected apps and choose Copy URL. The same setup instructions and URL are available on Connected apps, where you can also disconnect apps later.
If signing in takes you to Pamba's onboarding flow, finish that setup, then return to your chat app and connect Pamba again. The original connection request does not resume automatically. You need an existing workspace to approve access.
OAuth connections get every tool an API-key connection has: projects, avatars and generation, scheduling and publishing posts, campaigns, social accounts, workspace settings and members, billing checkouts and API keys. They act in the workspaces you approved. Tool calls run immediately; your chat app controls any per-action confirmation. URL filters can narrow a connection but cannot expand it.
Beyond the approved workspaces, the app can read the name and company details of every workspace you belong to, create workspaces, accept workspace invitations, list or revoke your API keys in any workspace, disconnect your other connected apps, and change your notification settings.
What the app sets up keeps running after you disconnect it or the connection ends: posts it schedules still publish, campaigns it turns on keep spending credits, and API keys, invite links and members it adds keep working until you turn them off or remove them in Pamba.
Each authorization lasts up to 90 days. Access tokens expire after one hour and the client refreshes them automatically; reconnect when the authorization expires. Disconnect anytime from Connected apps. Losing membership or deleting a workspace stops access to that workspace. Revoking a source API key stops the connection. Disconnecting stops the entire connection in every approved workspace, including queued calls that have not started; it does not cancel generation already running. Disconnecting an app does not revoke an existing API key.
One connection can cover up to 50 workspaces you explicitly select at approval. Ask your chat app to use a workspace by name. It calls list_connected_workspaces to find approved IDs, then passes workspace_id on each action. A multi-workspace grant requires that ID; the server never silently switches workspaces. Projects, avatars and credit charges stay within the selected workspace. New memberships and workspaces are not added automatically—reconnect to approve a different selection. Existing connections keep their original workspace. API-key approval remains limited to that key’s workspace.
Pamba staff accounts cannot connect a chat app; staff connect Claude Code or Codex with a workspace API key instead.
Availability and setup menus depend on the chat provider, account and administrator settings. A supported connector must be installed; an API key pasted into regular chat does not give the model an API tool. The API-key setup for Claude Code and Codex below continues to work.
Connect using an API key
- •Endpoint:
https://api.pamba.app/mcp, Streamable HTTP, one JSON-RPC message per POST. - •Credential: an
X-API-Keyheader with a workspace API key. Create one in workspace settings (open the workspace switcher, then Settings, then API keys); the secret is shown once. A key belongs to exactly one workspace and every call runs there; sending anX-Workspace-Idheader that names a different workspace is refused. To work in another workspace, connect with that workspace's key. A key can make one for a workspace it created itself:create_workspaceover the key, thencreate_api_keywithkey_workspace_idset to the new workspace's id, sets up a new workspace and gives its key without opening the app; it never makes keys for the person's other workspaces. Three tools act on the person behind the key rather than the connected workspace, because that is what they do in the app too:delete_workspaceaccepts any workspace the person administers, andlist_api_keysandrevoke_api_keycover their keys in every workspace. The instructions tell the model to confirm with the person before the destructive two. Deleting the person's own Pamba account is not available over MCP, to the in-app assistant or with an API key: only the person can delete it, in the app's Settings. AnAuthorization: Bearer <JWT>plusX-Workspace-Idheader works too, the same way it does on the REST API.
Claude Code:
claude mcp add --transport http pamba https://api.pamba.app/mcp --header "X-API-Key: <your workspace API key>"
Codex (~/.codex/config.toml or the project's .codex/config.toml):
[mcp_servers.pamba]
url = "https://api.pamba.app/mcp"
http_headers = { "X-API-Key" = "<your workspace API key>" }Any client that takes a JSON server list:
{
"mcpServers": {
"pamba": {
"type": "http",
"url": "https://api.pamba.app/mcp",
"headers": { "X-API-Key": "<your workspace API key>" }
}
}
}Once connected, ask the model "What can you do with Pamba?": the answer comes from the product map the server sends at connection, not from guesses.
Choose how much of the surface to load
The full surface is about three hundred tools. Most clients work best with fewer in context, and a script that only reads analytics has no reason to see the tools that spend money. Three switches on the endpoint URL shape a connection: two cut the surface, one caps spend.
- •
?toolsets=videos,avatarsloads only the named toolsets. The names:videos(create, generate, replicate, drafts, scheduling, campaigns, the avatar wizard, andlist_avatars, because every project starts from an avatar id),editing(the editor: concepts, takes, renders, text hooks, captions, model switches),avatars(appearance, voices, scene libraries, image editing),accounts(the account fleet, seats and billing, profile edits, warming, health, comments, individual scheduled posts),ideas(the ideas library and tracked inspiration accounts),discover(the viral corpus, niche feed, trends, the source picker),content(script batches and their drafts, knowledge base, writer engine, learning loop),automation(campaign strategy and content plans),workspace(settings, members, onboarding, billing and credits, the media library, API keys, help, support). - •
?readonly=trueloads only read-only tools. A tool outside the connection's scope is unknown to it, so this is a guard, not a hint: a read-only connection cannot be talked into a write. - •
?max_credits=500refuses any single credit-spending call whose up-front estimate is above five hundred credits, or that cannot be estimated, withstatus: spend_limit_exceededand nothing charged. It is a gate on the estimate, not a meter on the charge: the estimate is what the tool would charge on its first attempt, and a tool's own retries and model fallbacks follow its usual accounting once it runs. The in-app assistant's per-turn spend tripwire does not apply over MCP, so an autonomous client without a ceiling has only the workspace's balance as a brake.
Combine them: https://api.pamba.app/mcp?toolsets=accounts,videos&readonly=true. A toolset name the server does not know is refused at connection time with the list of known names, and so is a toolsets value that names nothing, so a typo or an empty computed list shows up in your client's connection error rather than as a silently widened surface.
Every tool is annotated. readOnlyHint is true on reads; everything else carries destructiveHint, which is what clients such as Claude Code use to decide when to ask you before a call. The description of every tool that spends credits ends with its cost basis.
What else the client receives
- •Instructions. The initialize response carries the transport rules below, workspace selection rules (or, for API keys, the connected workspace's name, niche and website), and the assistant's full product map. Clients inject this into the model's context, which is why the model knows the order of operations without you explaining it.
- •Prompts. Four golden-path workflows, listed as prompts (Claude Code shows them as slash commands):
first_video,replicate_tiktok,new_avatar,performance_review. Each is the tool chain the assistant runs for that goal, with the waits and the spend points named. A connection only lists the prompts whose every tool is inside its scope, so a read-only or narrowed connection is not offered a workflow it cannot run. - •Resources. Every help-center article, including this one and the tool reference, as
pamba://help/<slug>in markdown. The model can read them on demand, and clients that let you attach resources let you drop an article into the conversation.
How a call behaves
- •Nothing waits for your approval on Pamba's side. In the app, the assistant parks writes and credit spends on a confirmation card, and a turn that accumulates about eight hundred credits of estimated spend parks too. Over MCP there is no card and no per-turn tripwire: a write or credit-spending tool runs the moment the client sends it. Your client's own permission prompt is the safety net, so keep it on for anything that is not read-only, connect with
readonly=truefor exploration, and setmax_creditson a connection an autonomous agent drives. Three server-side refusals remain: affordability, where a spend the workspace cannot cover is refused before anything runs withstatus: insufficient_credits, the credits required and the credits remaining; the plan rule, where a workspace on its free signup credits alone is refused every video generation withstatus: video_generation_locked(see Credits below); and the connection's ceiling, where a call estimated abovemax_creditsis refused withstatus: spend_limit_exceeded(a TikTokschedule_postthat must generate its video first counts, priced likegenerate_video). None of them charges anything. - •Results are JSON objects, in both the text content and
structuredContent. Astatusfield carries the outcome. Success readsok,created,updated,saved,deleted,scheduledand similar.not_foundmeans no such object in this workspace.invalid_idmeans an id was not a UUID from the matching list tool. Otherinvalid_*statuses name a rejected field, andmessagesays why.insufficient_credits,payment_required(a paid plan is required),video_generation_locked(the workspace is on its free signup credits alone, which never pay for video: a plan, seats or an admin grant unlocks it, andnextnames the checkout tools),forbidden(the caller's workspace role is too low, for example a member trying an admins-only setting),operator_only(an action limited to Pamba operator accounts),busy,queue_full,work_in_flightandautomation_running(work in flight, wait for it),rate_limitedandfree_tier_exhausted(a usage limit, withretry_at; see Usage limits below) anderror(the operation failed unexpectedly) are refusals.messageis written to be relayed to a person. Anextfield, when present, names the follow-up call. - •Refusals are results, not protocol errors. Only
status: errorsets MCP'sisErrorflag. A JSON-RPC error comes back for protocol problems only: an unknown tool or one outside the scope, arguments that do not fit the input schema, an unknown method, malformed JSON. - •Never retry a failed or lost call blindly. A tool may have completed part of its work (a charge, a scheduled row) before it failed, which is why
status: errorcarries a generic line rather than the internal cause. A call your client abandons or times out is not cancelled either: it runs to completion on the server and its answer is simply lost. The assistant is told to report and stop; give your own automation the same rule, read the matching status tool after a lost answer, and retry only once the cause named inmessageis fixed. - •Arguments. Omit an optional argument to leave it unset; do not send an empty string in its place unless the tool says an empty string clears the field (the company profile fields do). Every argument is checked against the tool's input schema before anything runs, and every refusal names the argument: a name the tool does not declare is refused with the accepted names, a missing or null required argument is refused, a whole-number parameter takes a JSON integer or an integral numeric string and refuses a fraction, a boolean takes true or false, a string must be a JSON string (a parameter whose description says it carries JSON, a list of ids say, also takes the JSON list or object itself), and a parameter with listed choices refuses a value outside them. A typo therefore never runs the tool with a default in place of your value. Ids are UUIDs; take them from the matching list tool and pass them back verbatim. An avatar is addressed by its avatar project id:
list_avatarsreturns bothidandavatar_project_id, and almost every other tool wants the latter. Dates areYYYY-MM-DD. Scheduling tools take a precise ISO-8601 time in UTC (2026-12-25T14:00:00Z) or a date-only value that auto-picks a time in the posting window. The workspace timezone (update_workspace_settings) is the clock for posting windows and campaign schedules. - •Lists are truncated, not paged. Most list tools return the full
countalongside a fixed-size slice and no cursor:list_projectsforty (archived excluded unlessinclude_archived=true),list_scheduled_postsandlist_accountstwo hundred,list_workspacestwenty,list_scene_framesone hundred,list_video_generationsforty clips with ten takes each, or twenty-five takes when asked for one clip,list_creative_conceptstwenty versions. Narrow with the tool's filters rather than expecting a next page. The exceptions that do page or take a limit:list_ideasandsearch_tracked_videos(page, twenty-five per page), the Discover tools (page, twenty per page),browse_picker_videos(page, twenty-four per page),list_assets(limitandoffset),get_studio_overview(limitup to two hundred),list_post_analytics(limitup to one hundred, thirty by default, withtotalthe full count). - •Result size.
get_projectreturns the complete editor state andget_content_batchthe whole batch. Read the narrower tools (list_projects,get_render_job,list_video_generations) when you only need a status. - •Media URLs come in two kinds. A
source_urlon an ingest tool (upload_editor_media,set_edited_video,upload_scene_frame,upload_asset,import_avatar) is fetched from Pamba's servers: publichttp(s)only, anything resolving to a private or loopback address is refused, and redirects are re-checked. Every other media field (an editor item'ssrc, a post'svideo_url,edit_image'simage_url, a starting frame,update_account_profile'snew_profile_picture_url) takes a file already on Pamba storage (https://storage.googleapis.com/pamba_videos/...,pamba_images/...orpamba_audio/..., with no query string) and refuses a link to another host with amessagenaming the fix. Slideshow pictures and sounds and a replicationsource_video_urlalso take a media-library link. So bring an outside file in with the ingest tool that fits and pass on the Pamba URL it returns:upload_editor_mediafor timeline media,set_edited_videofor a project's final video (then schedule the project and leavevideo_urlout),upload_scene_framefor a starting frame,upload_editor_mediafor a profile picture (a media-library link or another host is refused with the error code profile_picture_invalid). A media-library link fromupload_assetis signed and expires: to put a library file on the timeline, pass its link toupload_editor_mediaand place the URL that comes back. Over REST,POST /uploads/videosandPOST /projects/{projectId}/upload-editor-assettake the file itself and return its Pamba URL. - •Conversation id.
get_conversation_inforeturnsmcpas the conversation id because there is no chat transcript over this transport. The workspace id it returns is what support needs.
Waiting for work
Most tools that produce media are asynchronous: the tool returns at once with a status, and the work finishes in the background over minutes. Poll the matching read tool about once a minute, and do not re-trigger the same work while a status reads pending, queued, generating, building, rendering or applying; a second call either reuses the live job or is refused.
- •Clips and videos:
get_projectandlist_video_generations. A failed clip generation retries itself up to three times, including an AI reword of the script after a content refusal, and falls back to the more permissive Grok Imagine model when the chosen model's safety filter still blocks it (the clip'svideo_model_fallback_fromrecords the blocked model, and the clip's model preference then follows the fallback). An on-camera talking take (not anedit_clip_videosedit) whose speech plays over a closed mouth, or that does not say its line as written (a word that carries meaning missing, added or swapped, a phrase said twice, or the line cut off before its end), is generated again on the same model, at most twice for both together, and its clip reads pending again while it waits. So a clip can sit in pending or generating for several minutes before it completes or fails for good. A project stays "generating" through the editing pass, captions, render and text hook, not just until the first clip lands. - •Drafts and replications:
get_replication_status(build step, failure kind, whether a retry applies). A review-queue item withbuilding: trueis a draft still writing its concept, frames and script; do not generate or edit it until that clears. - •Renders:
get_render_job, andrender_stateon the project (none,current,dirty,rendering,failed). Renders are never cancelled: an in-flight one settles and the next render supersedes stale output. - •Avatars:
get_avatar_wizardfor the wizard,get_avatar_generationandlist_avatar_generationsfor redesigns, voices and scene jobs. - •Accounts:
list_accountsshows a purchased seat's setup progress until the account is ready andget_seat_billingeach seat's state;list_account_profile_editstracks an avatar's profile edits,get_account_profile_editone edit by its job_id,get_account_link_statusa link andget_account_import_statusan account import (every few seconds while it may stop on a verification code). These run on Pamba-managed phones; a profile edit takes about two minutes and a creation longer. - •Onboarding jobs:
get_onboarding_state(media_capture_status, the presenter match, the avatar job).
A few tools block instead, for up to minutes, and return the finished result: create_avatar, update_wizard_appearance, generate_wizard_scenes, generate_avatar_voices, redesign_avatar, render_project, update_account_profile when it edits a TikTok profile, and create_workspace with a website_url, or with niche_description and what_they_do (it reads the site, or writes the brief from what the company does, in the call). Give them a generous client timeout.
Credits, plans and money
- •Metered operations consume credits: video generation per second at the clip model's rate (roughly sixteen credits a second on Grok Imagine, twenty-two on Gemini Omni, fifty-three on Seedance, rounded up per clip;
get_credit_pricingis the live list), avatar photos, scenes and variations at fifteen credits an image, replication frames at about eighteen (generation plus a realism pass), premium voice clones at one thousand five hundred, clip transcription for captions at about two credits per minute of video (repeat calls served from cache), content-engine script runs, and Ideas script generation by tokens. Basic voices are free.get_credit_balanceis the balance, and readsunlimitedrather than a number for internal accounts. - •Charging is reserve-then-charge. Credits are reserved when work starts, the charge commits only on success, and a failed generation is never charged. A reservation holds for up to two hours and reduces the reported balance meanwhile, so a balance can look low while work is in flight.
- •The affordability refusal is skipped for a project that already has live video work, so a repeat "generate it" reads the tool's own in-flight answer instead of a false shortfall.
- •A new workspace starts with a signup grant of three hundred credits and its first avatar is free (photo, scenes, basic voice). A workspace on the grant alone cannot generate video: until it has a paid plan, account seats or an admin credit grant,
generate_video,generate_replication_draft, areplicate_projectwithoutdraft_only, acreate_video_projectwithgenerate_video, and aschedule_postthat would generate answervideo_generation_locked(withnextnaming the checkout tools), whatever the balance. Analysis, drafts, scripts, photos, scenes and voices spend the grant as usual, and once video is unlocked the grant pays for it too. A workspace you add withcreate_workspacestarts at zero. - •Top-ups come in units of one thousand credits, one to twenty units per purchase, and are available to subscribed workspaces only;
create_topup_checkout_sessionreturns the Stripe link. Plans:get_credit_plans(yearly plans grant twelve times the monthly credits up front), thencreate_checkout_sessionwith the plan'sprice_id; for a workspace that already subscribes, the link is Stripe's confirm page, and confirming changes the plan in place: a pricier plan starts a new billing period that day with its full credits, priced at the new plan's price less what the current plan's unspent credits cost (on a subscription that has a promotion code those credits stay in the balance instead), and a cheaper plan takes effect when the current period ends. No money is refunded. Asking for the plan the workspace is already on cancels a change scheduled for the period's end and is otherwise refused. Downgrading a yearly plan is refused and goes through support. The checkout page of a new plan takes a Stripe promotion code, which the person types there; top-up and seat checkouts take none.create_billing_portal_sessionopens subscription management (payment method, invoices, billing details, cancellation; plans change only throughcreate_checkout_session); a cancellation there takes effect at the period end, and access lasts until then. When a renewal is declined, seat-funded accounts keep posting and the plan's monthly credits pause while the renewal is past due or unpaid (get_seat_billingsaysrenewal_declined; for the plan,get_user_profile'ssubscription_status);update_payment_cardreturns a page for a new card, which Pamba puts on every subscription and charges the declined renewals to at once (a card changed in the billing portal does not reach subscriptions that carry their own card). A workspace's seats bill to one card unless the Pamba team split them across cards at the customer's request: thenget_seat_billinglistscards(each card's seats, monthly total and renewal, all renewing on the same day),purchase_account_seatslists the cards a purchase can add to (passsubscription_id), andupdate_payment_cardreplaces one card only (pass thesubscription_idof the card being replaced). Every one of these returns a URL a person completes in a browser; the purchase lands on the workspace when the payment settles, so re-readget_credit_balanceorget_seat_billingafterwards. - •Purchases need the caller to be a billing admin of the workspace; other members get
forbidden. - •A paid-plan gate returns
payment_required: inspiration accounts, ideas and Discover details require an active subscription (a credit plan or account seats), and enabling or firing a campaign requires an active subscription on the workspace owner. Discover shows free workspaces the first rows and blurs the rest;create_video_projectwith anidea_descriptionhas no such gate. - •Booking a call with the Pamba team at pamba.app/book-a-call earns twenty dollars of credits, added by the team after the call.
- •Usage limits are separate from credits: daily ceilings on the operations that cost Pamba compute without charging credits, set far above real use. A workspace with no plan and no account seats may start 100 renders a day (5 running at once), upload 50 videos a day and run 200 AI assists a day (
edit_video,reposition_bullets,generate_project_description,suggest_account_usernames, website analysis, the title a concept save writes, the slide copycreate_slideshowwrites, the rewriteset_draft_scenemakes, and the look description a product's photos write); a workspace with a plan or account seats may start 1,000 renders a day (25 at once), upload 500 videos and run 2,000 AI assists. Limits reset at midnight UTC. A refused call answersstatus: rate_limitedwithretry_at, orstatus: free_tier_exhaustedwhen the free tier's shared daily budget is spent (paid workspaces are never affected). Wait forretry_atinstead of retrying; astart_renderrefused this way has already saved the editor state you passed. Two assists degrade instead of refusing, because the request they ride on must still succeed: past the cap a concept save keeps its title, and a website analysis reportsfailedwith no profile.
What needs a browser or a phone
- •Checkout. Every purchase is a Stripe URL the person opens.
- •Files. Tools take URLs, never an upload body: an ingest tool's
source_urlis any publichttp(s)URL, and every other media field takes a Pamba URL (see Media URLs above).upload_assetstores a URL in the media library (png, jpeg, webp, gif, mp4, quicktime, webm, mp3); avatar and scene tools take image URLs. The library holds up to thirty image and video files (audio does not count) and answerslibrary_fulluntil one is deleted. Asset URLs the tools return are signed and expire within twelve hours: never store one in editor state. - •Visual judgment. Watching generated footage and comparing scene images is the person's call. Hand over the URLs the tools return.
- •Accounts. TikTok, Instagram and Facebook accounts are created, edited and posted from on Pamba-managed iPhones by background device jobs. The client never touches a phone; it schedules the job and polls. An account import is the exception that needs the person: the verification code TikTok or Instagram sends them, passed on within minutes.
Ordering and nuance, by area
These are the rules the assistant follows and the ones people most often get wrong when driving the tools directly.
Projects and generation
- •Two ways to start a project with an avatar:
create_video_projectwithscript(spoken verbatim) or withidea_description(a fresh script is written on every call, so fanning one idea across avatars gives each a distinct script; never copy one generated script to several avatars). Passing both or neither isinvalid_request; a script run that fails isgeneration_failed, and rephrasing the idea usually fixes it.promotional=falsewrites a non-promotional script with no brand weaving. A video is spoken in the language its script is written in: a verbatimscriptkeeps its language, and anidea_descriptionwritten in or naming a language gets a script written in it. Latin-alphabet languages work best. Creation costs nothing;generate_videois the spend. - •The project returns before its concept exists. A background job writes the script split, the default scene and the title within a minute or so; while it runs, review-queue items show
building: trueandget_projectreports the concept asnone. A failed build marks the project failed rather than shipping an empty draft. - •The clip split is automatic, on natural speech boundaries, with durations the project's video model allows. Non-automated creations also pick a default scene automatically from the avatar's labeled library scenes, at random among those that fit the script, so two creates from the same script can differ; when nothing fits, a random face-visible library scene stands in. Override frames only when a specific look is wanted:
set_draft_scenemoves a built script or idea draft onto another scene of the avatar's library (every clip re-deals from that scene and its pose variations at once, and its place and video prompts are rewritten for the new scene in the background, free, until anything generates; a generate that arrives first applies the rewrite before it shoots).preview_script_clipsshows a split without saving anything. - •Authoring and generating are separate steps. Changing frames, scenes, script, concept or timeline is complete when saved; rendering or generating is a further, explicit request. The assistant is told never to queue a spend to "finish" an edit, and a script that drives the tools should not either.
- •A project can exist without an avatar:
create_draft_projectwith no avatar plusset_edited_videoturns a ready-made video into a postable project. The avatar stays unassigned forever; it cannot be added later. - •Video models:
grok-imagine-1.5,seedance,gemini-omni. The default resolves in this order: the project's explicit model, the campaign's per-member model, the avatar'sdefault_video_model, the workspace routing rules (campaign videos only), then the platform default: Gemini Omni for campaign videos and for every video an MCP client or API key creates, while in the Pamba app itself a video created from a script or an idea, and a replication whose avatar speaks a line on camera, currently getsgrok-imagine-1.5, and an experiment currently splits any other video, such as a replication with no line spoken on camera, betweengemini-omniandgrok-imagine-1.5.set_video_modelswitches drafts and projects in bulk and re-splits the stored script under the new model's limits (skipped when every duration is already legal, because a re-split mints new clip rows). Every model authors clips of four to fifteen seconds and shares the four-second floor, and a concept save with a clip outside its model's range is refused whole. - •
get_projectuses sentinel strings:conceptandeditor_state_jsonreadnoneuntil they exist,final_video_duration_secondsreadsunknownuntil the file is probed, andgenerated_atstays empty until every clip has a generated video. Prefer the measured duration over summing clip durations, which are the plan.promotionalreadstrue,falseornot_applicable(verbatim scripts decide nothing). - •
update_projectchanges only the fields passed: name, notes,user_review_state(not_reviewedorapproved),posted_state,user_visibility. Archiving also cancels the project's pending posts.list_projectswithposted_onlymeans the project actually went live, whichposted_statealone does not tell you (a cross-post downgrades a live project toscheduled, and cancelling a pending post resets it toapproved). - •Approving or scheduling is refused with a conflict while the video is still generating, with one exception: clips in their final 60fps upscaling pass (the take is already playable:
active_generation_statusis null whilepreview_video_urlis set) do not block; approve or schedule, and the automatic render waits for the upscaled files before anything posts. - •
generate_clipstakes optional zero-basedclip_indices; on a clip in that upscaling pass it replaces the take: a fresh take starts, the superseded pass finishes and parks in the clip's take history (billed like any completed take, revertable withselect_clip_video). A clip still producing its take keeps that generation.keep_raw_voice=truekeeps the model's own audio and skips the avatar voice dub and the speech trim. - •Refusals from the clip-starting tools:
insufficient_credits,automation_active(a pipeline owns the project),queue_full(try again in a few minutes),work_in_flight(a draft still building, or clips, an edit or a render from a previous generate still running). A pipeline stamp older than two hours is treated as dead, so a crashed run cannot lock a project out forever. - •
duplicate_projectclones a shell (concept and frames, no script, clips or videos);duplicate_project_fullclones an exact independent copy, nothing re-billed. Neither carries scheduled posts, approval state or in-flight generations.
Editing
- •
edit_videois the entry point for timeline edits: pass the intent in natural language and a dedicated editing agent, which sees the full timeline, the concept and the media library, applies validated operations and reportsappliedorno_changeswith what it rejected and why.edit_clip_videosis different: it changes a clip's pixels via video-to-video on Gemini Omni whatever model made the clip, on clips that already have a video and are three to ten seconds long; for a longer clip, passin_pointandout_pointto edit a window, one clip at a time, billed for the window at the Omni rate. Each edit lands as a new take, auto-selected, with the prior take still available. A failed edit leaves the working take untouched and reports onlatest_edit_status. - •
set_editor_statereplaces the whole editor state object. Always read it fromget_project, modify, and write it back; a partial object deletes what it omits. When changing one field of an existing item, copy the item verbatim: an item with the same id inherits its earlier placement and style for fields you leave null, but explicit values always win. - •Editor item shapes: text items place with
x,y,wnormalized zero to one (x0.5 centered,ythe vertical center: a top hook sits near 0.12 to 0.2, a bottom one near 0.8), andstyle.font_sizeis pixels on a 1080 by 1920 reference (default sixty-four, readable minimum twenty-four). Always setxandyor the text renders center-frame. Text wraps only at its own line breaks unlesstext_wrapis true, which makeswthe box width. Preferstyle_presetids fromlist_text_style_presetsover hand-built styles. Media items (and audio items) need a Pamba image, video or audio URL: bring an outside file in withupload_editor_mediaand place the URL it returns (a signed library asset URL is refused). They takewas a width fraction (1.0 fullscreen, about 0.6 for a picture-in-picture, about 0.4 for a logo flash); video items also takespeed0.5 to 2 andvolume, which you set to zero so a demo clip never talks over the presenter. - •Clip ids are re-minted on every concept save. An id held across a save answers "Clips not found in the selected concept"; re-read the project. Changing a clip's starting frame also drops that clip's generated video, which comes back only by reverting to the prior concept version (
list_creative_concepts, thenrevert_creative_concept, which restores script, clips and editor state together and is refused while automation runs). - •
select_clip_videoneeds a completed take of the same project; re-render afterwards to bake the change in. A main-track entry withuse_original_voice: truekeeps the clip's pre-dub audio in renders, and the flag is dropped when the clip re-points to a new generation. - •Captions come from
transcribe_clips, which is English only, so the on-screen captions timed from the speech suit English videos. Word timings arrive in spoken order and must not be re-sorted. - •Renders are automatic when saved edits are newer than the last render: approving, scheduling and leaving the editor re-render, scheduled posts wait briefly for an in-flight render rather than posting stale video, and a sweeper renders recently active projects once they have been quiet a few minutes.
render_state: failedmeans the last attempt for the saved edits failed and only the next edit or commit point retries it. A video supplied directly is recorded as the current render and is never re-rendered over:set_edited_videocopies whatever file it is given, and avideo_urlonupdate_scheduled_post,schedule_instagram_postor the REST schedule route counts only when it is a file from outside the project's own outputs. A url the project itself produced (itsedited_video_urlorstitched_video_url, an earlier render, a file it was given before) is ignored on those post routes, and the pending post keeps following the project's latest render. - •
set_clip_voice_effectsadjusts the acoustic environment baked into generated clips' audio: free, seconds per clip, frames untouched.
Replication and drafts
- •
replicate_projecttakes exactly one source: atiktok_url, aninstagram_url(a reel;inspect_instagram_reelreads a pasted link first), asource_video_urlfrom the workspace, or asource_project_idof one of the workspace's own projects (its rendered video is the reference, so it needs a finished video).draft_only=truebuilds a reviewable draft and stops before clip generation, so video credits are spent only when the draft is generated.max_duration_secondsis a target, not a cap: it shortens or lengthens the replica, and every replica is capped at one hundred sixty seconds whichever model generates it.variation_instructionscap at four thousand characters. A workspace runs ten replication jobs at once; requests past that queue automatically. - •For
source_video_url, use a Pamba-hosted video or a video asset owned by the selected workspace's media library. Upload an external source to that library first; arbitrary remote URLs and local files are refused before replication starts. - •Replicating from a TikTok URL also captures the source into the ideas library, deduplicated on the video URL; a replicated Instagram reel is not captured. Replication plans media from the workspace asset library on its own: an app demo the original cut to becomes a media scene, partial cards and logo flashes become timed overlays on a Media track. A non-promotional replica does not use the brand media library.
- •A hub video judged hard to replicate returns
low_feasibility_warninguntil the call repeats withacknowledge_low_feasibility=true. A video that needs the brand's own digital files returnsmissing_brand_assetsnaming what to upload (upload_asset) rather than starting; the same acknowledgement proceeds anyway and the replica drops those beats. Physical products are never a requirement. - •
get_replication_statusreportsbuild_step(source,analyze,concept,scenes,frames,assemble,done) and, on failure,failure_kind(transient,timeout,safety,quality,content,unknown),retriableand anexthint.retry_draft_buildresumes from the last completed checkpoint, so finished stages are never re-paid; prefer it for transient and timeout failures andrequest_draft_editsfor safety or content failures, because a blocked look keeps getting blocked. A failed request-edits revision restores the draft intact and reportsfailed_revisionwith the preserved feedback. - •An ungenerated replication draft's editor is read-only: direct
set_editor_stateis refused. Its edit surface is the draft itself, through the edit ladder: words only, on one scene,edit_scene_script(free); the whole read,edit_draft_script; one scene should look or play differently,edit_scene(image credits); the whole video's look,regenerate_look_canon; restructure, duration, add or remove scenes,request_draft_edits, whichedit_scenerefuses and which cannot serve script drafts. Scene edits of different scenes run in parallel; same-scene and whole-script edits serialize. Every completededit_sceneis undoable withrevert_scene_edit, per scene, free. - •A draft can complete with some scene frames failed;
regenerate_scene_frameretries them, andgenerate_replication_draftis gated until every scene has a frame. - •
generate_replication_draftapproves the reviewed draft into clip generation plus the final editing pass and render, honoring editor changes present on the draft as deliberate overrides.generate_videoon a draft instead runs the standard automation pipeline and does not carry draft edits as overrides.
Scheduling and posting
- •
schedule_postposts a project's video to TikTok (tiktok_username), to the avatar's Instagram (also_post_to_instagram), or both in one atomic schedule: if either platform has no slot (device busy, no slot left that day), nothing is scheduled and the whole request is rejected.schedule_instagram_postschedules a standalone Reel, and itsshare_to_facebookis the only Facebook path. An Instagram Reel can go out as a trial (schedule_post'sinstagram_trial_reel,trial_reelonschedule_instagram_postandupdate_scheduled_post):release_to_followers_once_it_performs_welllets Instagram share it to everyone if it performs well in its first 72 hours,release_to_followers_neverkeeps it a trial that is never shared to the account's followers; leave it out for a regular reel, andupdate_scheduled_post'sremove_trial_reeltakes a trial off. Instagram shows a trial to non-followers first and keeps it off the profile; it never goes to Facebook (refused withshare_to_facebooktrue), Instagram offers it only to professional accounts with at least 200 followers (an account under 200 is refused withinstagram_trial_reel_ineligible: its last read follower count decides, or, for an account Pamba has not read yet, its profile read when the post is scheduled;list_posting_accountsandget_projectname the accounts known to be under it ininstagram_below_trial_floor; a personal account is refused the same way, and they name the ones Pamba knows ininstagram_personal: switch one to creator withupdate_account_profile'sinstagram_account_typeand the trial can be scheduled as soon as the switch is queued), and a slideshow's carousel has none.update_scheduled_post,cancel_scheduled_postandretry_scheduled_postmanage the queue;list_scheduled_postsandget_scheduled_postread it. Acompletedpost is the phone's word that it posted, and itsverification_statussays whether Pamba then found it on the account's public profile:pendingwhile the checks run (20 minutes after posting, then an hour, another hour and a day later),verifiedonce it matched (its link inposted_tiktok_video_urlorposted_instagram_video_url; an Instagram slideshow post (a carousel, or a reel built from its slides), and an Instagram reel posted before 2026-10-03, readverifiedon the phone's word alone until the link is known),video_not_foundwhen no new post appeared,frame_mismatchwhen a new post appeared that is not this one,errorwhen the check could not finish;verification_messagesays it in one sentence. The check runs once, soverifiedsays the post was found, not that it is still up. The app shows these as Posted, Verified (for an Instagram post, once its link is known), Not visible and Not matched. A failed post whose retry already failed again, in a way that alerted Pamba's engineers, readsbeing_fixedtrue: it is theirs to fix and retry, usually within a few hours, andretry_scheduled_postrefuses it with statusbeing_fixed(the REST route answers 409post_being_fixed). A hold nobody works ends a day after the failure, and the retry is yours again. A failure you remedy yourself (another Instagram song or sound, the slideshow's missing images, the TikTok Shop link, approving the project, reconnecting a signed-out account you connected:account_needs_reconnect, new audio for a video TikTok would mute for copyrighted music:copyrighted_sound_muted, where a TikTok sound added on top keeps the video's own audio, a reel Instagram offered no trial:ig_trial_reel_unavailable, fixed by switching the account to creator withupdate_account_profileor removing the trial withupdate_scheduled_post'sremove_trial_reel) stays yours to retry. A trial reel whose outcome was lost readsbeing_fixedtrue from its first failure, and that hold does not end after a day: it may be live and no lookup can see a trial, so Pamba's engineers check it on the phone and settle it, andretry_scheduled_postrefuses it with statusbeing_fixed. A post is never retried, by anyone, while another post of the same video or slideshow to the same account is scheduled, posting or already posted, so nothing posts twice. And one video or slideshow goes to one account per platform:schedule_post,schedule_instagram_postandupdate_scheduled_postrefuse with statusduplicate_content, andschedule_slideshow_postwith statusrejectedandcodeduplicate_content(over REST,error_codeduplicate_content, andcodeon the slideshow schedule route), a post whose content another account of the workspace has scheduled, is posting or posted on the same platform (a draft-only TikTok post,only_create_draft, never counts: it never goes public): the same project or slideshow, or a file with the same bytes (the same upload twice; a carousel all of whose slides another account's carousel holds, or that holds all of another's). TikTok and Instagram flag the same content on a second account. The same video on TikTok from one account and on Instagram from another is fine, and an upload re-cut, re-encoded or with other words on it is another file. - •Pick a time the phone has free. Each account posts from one Pamba iPhone, and a phone runs one post or task at a time for every account on it (an avatar's TikTok and Instagram accounts usually share one). An exact TikTok time that overlaps another post, a task running on the phone or a maintenance window is refused as
schedule_conflictwith the next free time inmessage; an exact Instagram time there is moved to the next free slot that day (read the returnedscheduled_at) and is refused only when the day has no room left. The refusal carries anextfield pointing atget_account_schedule:schedule_postandschedule_instagram_postanswer it as their status,schedule_slideshow_postas itscode, andupdate_scheduled_postasupdate_failedwithcodeschedule_conflict. That tool (platformtiktokorinstagram,username, optionalfromandtoin UTC, seven days by default and fourteen at most) returnsopenings, the stretches in which a post picked at an exact time is kept as picked (a schedule with automate, or while its video is still being finished, waits at least 30 minutes from the request instead) (whole minutes, both ends included, none beforeearliest_post_at, which moves with the clock: a pick must still be that far ahead when it is sent),busy, what holds the phone (postwith this workspace'spost_id,post_platformandpost_username,task, ormaintenance), andpost_minutes, how long one post holds the phone. Read it before scheduling at exact times. A new account being set up on a phone goes first: a post that comes due while Pamba creates an account on its phone waits for the setup and goes out soon after it, itsscheduled_atmoved to the new time, and the wait costs none of its retries. Each post you schedule holds its phone forpost_minutesfrom its time, so space exact picks on one phone at least that far apart. When a TikTok and an Instagram account share a phone, the Instagram post takes the first free time after the TikTok one that day (Pacific time; right after it when the phone is free), and a day with no room left for it refuses both, so leavepost_minutesfree after a TikTok time that cross-posts; a Facebook share rides the Instagram post. A post you move withupdate_scheduled_postis not blocked by itself or its pending cross-posts; the cross-posts then follow it to the first free time after the new time that day, and one with no room left keeps its old time, so leavepost_minutesfree after the new time for each cross-post on the same phone. A new caption on the TikTok post likewise carries to its Instagram cross-posts in the same status (pending with pending, failed with failed) that still had the old caption; one whose caption no longer matched keeps it, and editing a cross-post never changes the TikTok post. A postschedule_postbooked away from the exact time asked for carriesmoved_from(that time) andmove_reasons, a list oftoo_soon,video_to_make,video_finishing,accounts_setting_upandphone_busyin the order they applied, with a note: tell the user the new time and why. A date-onlyscheduled_atfinds a free slot by itself. The openings are a read, not a booking: another schedule can take the time first, and on rare occasions the fleet-wide cap on posts at one time refuses a pick inside one, again with the next free time. Over REST it isGET /devices/accounts/schedule. - •How often an account should post. An account Pamba created less than 10 days ago does best posting once a day, and any account at most 2 or 3 times a day: past that each post brings diminishing returns and makes TikTok or Instagram likelier to flag the account. Pamba warns and never refuses. A post that makes a new account's 2nd post in a day (the workspace's day, counting its pending, posting and posted posts) or any account's 4th is booked all the same and carries
posting_warningin the result ofschedule_post,schedule_instagram_post,schedule_slideshow_post, andupdate_scheduled_postwhen the edit moves the post: tell the user the warning and offer to move the post to another day.list_accountssetsnew_account_until_utcon each account on the workspace's phones that Pamba created less than 10 days ago, so spread several posts on one account across days before scheduling them. Over REST the schedule and edit responses carryposting_warningas{ code, message, day, posts_that_day, posts_per_day },codebeingnew_account_posts_per_dayorposts_per_day. - •A project with an avatar may only post to a TikTok account linked to that avatar. A project with no avatar can post to any account on the workspace's fleet, linked or unassigned; posting to an avatar's account attributes the analytics to that avatar, posting to an unassigned account attributes them to none.
get_project'sposting_accounts(andget_slideshow's, for a slideshow) lists the accounts a schedule may name, the choices the app's schedule dialog offers, andlist_posting_accountslists every avatar's and the no-avatar pool at once: read one beforeschedule_post. A listed TikTok account that is not signed in on one of the workspace's phones, or one with an open suspension, is still refused. - •Posting a video you already have (nothing generated, rendered or credit-metered):
create_draft_projectmakes an empty project with no avatar, so it can post to any account on the fleet;set_edited_videoattaches the file from a publicly reachable video url and records it as the project's completed render; thenschedule_postorschedule_instagram_postposts it. There is no upload body over MCP: a file on the client's machine is staged with the REST upload (POST /uploads/videos, multipart, the same API key) and its returned url passed toset_edited_video. To attribute an uploaded video's analytics to an avatar, create the project in the app's Upload button or with the REST create call and its avatar field, then attach and schedule from here; the avatar choice is permanent.set_edited_videois refused while automation runs on the project or a replication draft is locked, and a scheduled post for the project picks up the new video. - •What
schedule_postposts depends on the project: a project with a concept whose clips have no video yet is generated and rendered first (the result saysmode: generate_then_post, credits are spent); a project whose video was supplied (set_edited_video, the app's Upload button) posts that video as is (mode: post_project_video, nothing generated); a project with neither a video nor a concept is refused asnothing_to_post. The RESTautomateflag follows the same rule: it is 400 on a project with no concept to generate from.generate_videofollows it too: a project whose video was supplied, or one with no concept at all, is refused asnothing_to_generateinstead of starting a pipeline that has nothing to build. - •A post goes out only if its project is approved at its slot.
schedule_postsays where that stands in its result'sapprovalfield:approved_by_schedulewhen it posts a video that already exists (the schedule approves the project, nothing more is owed), andrequired_before_slotingenerate_then_postmode, where the schedule does not approve a video that does not exist yet and someone must approve the rendered video before the slot.update_projectwithuser_review_state=approvedapproves, with or without a schedule; approving is refused while the video is still generating. A post that failed at the gate is recovered by approving the project and then callingretry_scheduled_post. Automated pipelines (campaigns, content pushes) generate, render and schedule but never approve on their own, so a scheduled post whose project nobody approved fails at its slot with the message "Project not approved at scheduled time". That is the review step working, not an outage. - •Captions:
generate_project_descriptionwrites a hook line plus exactly five hashtags from the script and company profile, but only returns the text; pass it as the caption yourself. A TikTok caption with one of the commercial-disclosure hashtags#ad,#ads,#sponsored,#partnershipor#paidpartnershipis posted with TikTok's commercial content disclosure on, as Branded content ("You are promoting another brand or third-party"), so TikTok labels it "Paid partnership" and Pamba cannot take the label off once it is live. TikTok publishes no post with such a hashtag without the disclosure.generate_project_descriptionnever writes one: whether a post is an ad is the user's call. An Instagram caption, a reel's or a carousel's, holds at most 2,200 characters and 5 hashtags: Instagram keeps no more than 5 hashtags on a post, so a longer list is refused rather than posted with the rest stripped to plain words. - •When the avatar has no account on a platform yet,
schedule_postwithawait_new_account=true(TikTok) orawait_new_instagram_account=true, orschedule_instagram_postwithawait_new_account=true, persists the post as waiting;purchase_account_seatswithlink_avatar_project_idthen buys the account, and once it is created the waiting post books a real slot and goes out with no further action, independently per platform. - •TikTok Shop. A TikTok account enrolled in TikTok Shop can link one product of its shop to each post, chosen per post (there is no default product).
get_tiktok_shopreads the shop as the account's phone last saw it (linked, the showcase, the catalog's products with their ids andshowcase_state);sync_tiktok_shopreads it again on the phone, which takes a few minutes. The account's daily phone visit also looks for the Shop tab and reads the shop by itself when the tab appears or goes, so an account TikTok enrolls shows up without a sync. Passtiktok_product_id(and optionallytiktok_product_link_name, at most 30 letters, numbers, spaces, apostrophes or hyphens) toschedule_postorupdate_scheduled_post;remove_tiktok_producttakes it off a pending or failed post, and a post moved to another account drops a product it does not restate. Only a video post links a product; a slideshow cannot. A post links from the showcase only, so a product not in it is queued for adding the moment the post is scheduled (add_tiktok_showcase_productsdoes the same on its own), and the post goes out only after the phone can have added it: an exact time before that is refused with statustiktok_product_not_in_showcase_yetandearliest_at_utc, and a date-only time is given a slot after it. The phone reads a product's title off the screen, so a long one reads cut short with … at its end;rename_tiktok_shop_productgives a product itsdisplay_title, the name to show for it (the phone keeps finding it by its title, and a read of the shop never changes the name). The phone reads each of the showcase and the catalog up to about 80 products; a list it could not read whole (longer than that, or with a product the phone saw but could not read) readsshowcase_completeorcatalog_completefalse, and the lists then hold part of the shop. The phone adds the link before its Post tap, and a post whose link cannot be added fails rather than go out without it. TikTok caps a new shop's shoppable videos (shoppable_videos_left, as the latest post that linked a product left it). - •AI label.
ai_label: trueonschedule_postlabels the video as AI-generated on every platform that call schedules (TikTok's "AI-generated content" label, Instagram's "AI info" label);schedule_instagram_posttakes it for the reel, andupdate_scheduled_postturns it on or off for one pending or failed post. TikTok and Instagram video posts only: a slideshow post and a Facebook post refuse it. The phone sets the label before its Post or Share tap, and a post it cannot label fails and is retried rather than go out unlabeled. Pamba cannot take the label off once the post is live, so set it only when the user asks. - •First-frame cover. Left alone, TikTok and Instagram pick a video's cover from a frame a few seconds in.
first_frame_cover: trueonschedule_postmakes the video's first frame, where its burned-in hook is, the cover on every platform that call schedules;schedule_instagram_posttakes it for the reel, andupdate_scheduled_postsets it (true) or leaves the cover to the platform again (false) for one pending or failed post. TikTok and Instagram video posts only: a slideshow post and a Facebook post refuse it. The phone sets the cover in the app's Edit cover before its Post or Share tap, and a post it cannot set it on fails and is retried rather than go out with another cover. - •If a schedule is rejected, read the reason and offer the valid accounts or another time; do not retry blind.
Slideshows
- •A slideshow is a TikTok photo post or an Instagram carousel (or, with
as_reel, one reel Instagram builds from the slides): up to twenty pictures with words burned in, and one sound per platform under the whole post: a TikTok sound for the photo post, an Instagram track for the Instagram post. It is made from pictures the workspace already holds — nothing about a slideshow spends credits, and there is no slide image generation. Get the pictures in first:upload_assetwith a public url (orlist_assetsfor ones already there), thencreate_slideshowwithslide_images(one Pamba-hosted url per slide, in order) andlines(write_with_ai=falsekeeps them verbatim; no lines gives picture-only slides). Both are strings: a JSON array serialised as a string, or one entry per line; the JSON array itself is taken too. A slide with a picture but no line has no text element. - •The tools are in the
contenttoolset (list_slideshows,get_slideshow,create_slideshow,update_slide,add_slide,remove_slide,reorder_slides,add_slide_image,update_slide_image,remove_slide_image,suggest_slide_lines,search_tiktok_sounds,set_slideshow_sound,search_instagram_audio,set_slideshow_instagram_sound,schedule_slideshow_post,get_slideshow_scheduled_post,duplicate_slideshow,export_slideshow,update_slideshow). Every edit re-burns the slide;get_slideshowreports each slide'sstatus(readyonce burned) and itsimage_url. - •Sound:
search_tiktok_soundswith noqueryreturns TikTok's Hot chart (sourcehot, in chart order, the editor's default listing); with aqueryit pages TikTok's own library (cursorfrom the previous page'snext_cursor), andset_slideshow_soundpicks one for the whole post bytiktok_music_id(the search result'smusic_id); the search is a plain read, not one of the capped AI assists. Searches that reach TikTok run at most 5 a second, 30 a minute and 1,000 a day per workspace (a repeat the day's cache answers is free); past that the tool answersrate_limitedwithretry_at(midnight UTC once the day's are used), and the REST route a 429 with aRetry-Afterheader. Every result carriescommerce_right: whether TikTok clears the sound for commercial use, which a Business account needs to post with it (its sound page shows no Use sound otherwise), so prefer a cleared sound for such an account. - •Instagram sound: the Instagram post's sound is picked apart from the TikTok one, because the two platforms' libraries are different.
search_instagram_audiowith noqueryreturns Instagram's Trending chart (sourcetop, read from a US account's picker); with aqueryit returns Instagram's own results for the words, ten at most with no further page, and the same per-workspace rate and daily limit as the TikTok search.set_slideshow_instagram_soundpicks one byinstagram_audio_id(the result'saudio_id;noneclears it). The track starts where Instagram's picker starts it (highlight_start_seconds), and the phone picks it in Instagram's own music picker when the Instagram post goes out. One it cannot find there goes out as the same song by the same artist at another length, else as a song Instagram picks, andget_scheduled_postandlist_scheduled_postsname it inaudio_fallback. The searches run on accounts outside the US, which list some songs US Instagram lacks, so a song a Pamba phone did not find, posting from an account Pamba knows is not a Business account (a Business account's picker lists only commercial music), is recorded and left out of every later search and of the chart. A pending or failed post still using such a song readsinstagram_song_unavailabletrue onget_scheduled_postandlist_scheduled_posts: set another song before it goes out to choose it yourself. A pick the chart or the day's searches did not list is looked up on Instagram's audio page, and that lookup counts against the same per-workspace rate as a search (not the daily limit, which counts searches only). No provider says which songs an Instagram Business account may use, so the whole library is listed. When Instagram's music search or audio page is not answering, the tool answerssearch_unavailableand the REST route a 503. - •Posting:
schedule_slideshow_postschedules the slides on a Pamba-managed iPhone and approves the slideshow; it is refused while any slide still has no picture. A TikTok photo post takes a single slide; an Instagram carousel or reel (platforminstagram or both) needs at least 2. Withplatformtiktok (the default:tiktok_username,scheduled_at,caption; the caption is the post's description, capped at TikTok's 4,000 characters with the same hashtag rules as a video, and the post has no separate title) it is a public photo post carrying the slideshow's sound; withplatforminstagram (instagram_username, omitted when the avatar has one Instagram account;scheduled_at;caption, at most 2,200 characters and 5 hashtags, no @) it is a public carousel carrying the slideshow's Instagram sound, each slide fitted whole into Instagram's square or 3:4 feed frame (square when the slides are square or wider), and it is refused until the slideshow has one (set_slideshow_instagram_sound): without a track Instagram does not treat the carousel as a reel and shows it only to followers, and the track cannot be cleared while an Instagram post waits;as_reel=trueposts it instead as one reel Instagram builds from the slides, each 4 seconds with the same track under it (which the reel needs too), in the full 9:16 frame with the first slide as its cover (refused withplatformtiktok; withplatformboth the TikTok photo post is unchanged); withplatformboth (tiktok_username, andinstagram_usernameas above) the two are booked together in one plan, both or neither, under onecaptionthat must pass both platforms' rules, and the result'spostslists each. A slideshow posts once per platform.get_slideshow_scheduled_postfollows them (postsholds one per platform:pending,in_progress,completed,failed), andcancel_scheduled_postwith a post's id cancels it while it is still pending. A TikTok photo post is verified against the account's profile and gets analytics like a video. An Instagram carousel is verified on the phone's word (the phone reads it as the profile's newest post), and the account's hourly analytics refresh then links it to its live post (posted_url, a/p/link) and tracks its likes and comments; Instagram publishes no views for a carousel. A slideshow's reel is verified the same way, then linked among the account's reels (a/reel/link) with its public views; each Instagram post inpostscarriesas_reel.
Avatars and voices
- •The wizard, in order:
create_avatar(blocks until the candidate scenes exist and charges seventy-five credits: one appearance plus four scenes), then any ofdiscard_wizard_scene,generate_wizard_scenes(fifteen credits a scene) andupdate_wizard_appearance(regenerates the look) beforeaccept_avatar_appearancelocks the appearance, thenselect_avatar_voice, which finishes the wizard.get_avatar_wizardpolls and already lists the free basicvoice_options;reroll_preset_voicesswaps in three other free picks (directionaccepts onlydeeperorhigher).generate_avatar_voices(premium clones, one to three, one thousand five hundred credits each) only when a premium voice is wanted. Completion auto-starts pose and angle variations for every kept scene, free on the workspace's first avatar and charged per image after, so do not also callgenerate_scene_variationson a fresh avatar. The first kept scene becomes the profile image. - •Voices come in exactly two kinds: free basic voices (called "preset" in tool names for historical reasons) and paid premium clones (
generate_premium_voice, cloned from a generated speaking clip on Seedance by default).get_preset_voicesthenapply_preset_voicechanges an existing avatar's basic voice; browsing and rerolling is free. - •
update_avatar_settingsreplaces whole sets:tiktok_usernames,tagsandwarming_search_termsare overwritten with what you pass (an empty list clears, and warming then falls back to niche terms), and the TikTok accounts must already exist on a workspace device. One exception keeps a new account from being dropped: a TikTok accountget_avatarlists withname_pending(its picked username is still being applied) stays linked while its rename runs and for an hour after it lands, whatever set you pass, and the set names it by its picked username;unlink_accountremoves it.default_video_modeltakesdefaultto clear back to the workspace routing rules. - •Scene library: every scene and library frame carries vision-derived
content_labelsfrom a fixed vocabulary plus ascene_description; match those against a clip's needs rather than picking by name.generate_scene_frames(one to ten, default three) lands frames inactive; activating one withupdate_scene_frameauto-generates six pose variations (ninety credits) when it has none, andupload_scene_frameis stored active and does the same.delete_scene_framesalso deletes a scene's variations, and the profile frame cannot be deleted; set another first. Replication-generated scenes stay out of the avatar's active library on purpose. - •
edit_imageedits any Pamba-hosted image with a text instruction (fifteen credits) and returns a new URL; on a registered frame the result is itself usable as a starting frame.save_scene_variationkeeps that result as a variation (original untouched),replace_scene_imagepoints the frame at it instead, losing the original.promote_scene_variationswaps a variation with the scene's reference, so promoting it back undoes the swap. - •Camera styles are
selfie,tripod,tripod_full_body_visibleandpodcaston the avatar tools;generate_starting_framesspells the full-body styletripod_full_body, and the other spelling falls through to selfie there. - •
import_avatarcreates an avatar from a photo URL withgenderMALEorFEMALEand a free basic voice;redesign_avatarapplies free-form appearance or voice changes and blocks until they land.track_external_tiktok_accountattaches an account you post to from your own phone, for analytics only: posting and warming stay unavailable for it. A free workspace (signup credits only) can connect up to five such accounts; the sixth answersconnected_account_limit, and any plan, account seat or credit purchase lifts the limit. - •Operator-only tools are listed only to Pamba staff. A customer workspace or a connected chat app never sees them, and calling one by name is an unknown tool: the reference-frame tools (
create_reference_frame,update_reference_frame,delete_reference_frame),create_social_account,get_account_creation_status,resume_account_creation,generate_image, the writer-engine controls (run_content_engine,push_content_batch,apply_script_revision,set_script_starting_frame,decide_learning_item,set_autonomy_dial,set_batch_share_page,send_writer_chat_message), and the engine's spend bookkeeping (log_llm_usage, andget_llm_usage_summary, which reports the model spend at Pamba's cost).control_stage_runis listed to everyone, but cancelling a run, and retrying some runs, answersoperator_onlyfor a customer workspace.
Accounts, seats and devices
- •
list_accountsis the inventory of every TikTok, Instagram and Facebook account on the workspace's fleet, including accounts assigned to no avatar (their avatar fields are null). Status isposting,track_onlyorarchived; health flags includeBANNED,SHADOWBAN_RISK(after the account's first three weeks of tracking),NOT_RECOMMENDEDandSUSPENDED. - •
set_account_ordersaves the order the workspace's Accounts page lists accounts in, for everyone in the workspace, andlist_accountsreports each account'spositionin it. A save replaces the whole order, so moving one account means sending every account in its new place; accounts left out, and accounts added later, follow in the default order (open issues first, then the most viewed), and under a saved order archived accounts are listed last. An empty list goes back to that default. - •Managed account seats cost one hundred dollars a month each, every two include a dedicated phone, and every TikTok plus Instagram pair across the subscription prices its second account at fifty dollars, re-priced when seats are added or cancelled. A paid purchase also pairs with seats already on the subscription it raises, the newest one that is active and not set to cancel:
purchase_account_seatscalled with no seat counts returnsunpaired_seats, per platform the seats on that subscription with no partner yet, and the next paid purchase pairs up to that many seats of the other platform with them. One Instagram seat next to one unpaired TikTok adds fifty dollars a month, not one hundred; two Instagram seats next to it add one hundred fifty. Only whatunpaired_seatslists pairs this way: an account with no seat, a seat on a free-seat grant (free_seats_remaining) or on another subscription, and a seat cancelled withcancel_account_seat(even while it posts until its period ends) pair with nothing, and when no subscription can be raised, the purchase starts a new one where only its own seats pair. Any quantity up to a thousand accounts per checkout can be bought; the seats the phones cannot back yet stay being set up until the team adds phones. While no Pamba phone is free,purchase_account_seatsreportshigh_demandtrue, and a checkout with more seats on a platform thanopen_slotslists (what the workspace's own phones still take) carrieshigh_demand_notice: those new accounts may take up to 3 days to be created (for purposeconnect, the accounts may wait up to 3 days for a phone to sign in on), and the user hears so before paying. Facebook has no seat of its own; it rides Instagram cross-posting.purchase_account_seatsreturns a checkout URL: a purchase that raises an existing subscription gets Stripe's confirm page raising its quantity with proration, and one that starts a new subscription gets a new checkout. When Stripe cannot list the workspace's seat subscriptions or open the confirm page, the tool answerspurchase_unavailablewith a message to try again, and nothing is charged or started. A checkout paid by bank transfer completes before its payment clears (usually up to four business days): until then its seats are listed underwaiting_for_payment, nothing is created for them, and they move tobeing_set_uponce Stripe confirms the payment; a payment that fails drops them. Do not buy again while seats are waiting for their payment. - •A purchase never adopts a spare account already sitting on the workspace's phones. Check for spares first: an unassigned spare links to an avatar free with
reassign_accountand nofrom_avatar_project_id(TikTok or Instagram; no password, no phone work). The same tool moves an assigned account whenfrom_avatar_project_idnames its current avatar; without it an assigned account is never moved. A TikTok or Instagram account can post for several avatars (a Facebook account follows its Instagram account):link_account_to_avataradds one without taking the account from the others, so a video for a second avatar can go to an account the first one already uses instead of a new purchase.unlink_accountis the reverse: it drops one avatar's binding, and an account no other avatar links is a spare again, still signed in on its phone, with its status and history. - •A bought seat waits for its username before creation starts.
suggest_account_usernamesreturns a checked, currently free idea per waiting seat (names for a waiting order are prepared in the background, so a call usually answers at once; otherwise a few seconds each, so for a large order passbatch_size, for example 8, and call again withexcludeset to the names already offered; a batch answers within 90 seconds),check_account_usernameverifies a pick (availability is a hint, not a reservation),set_account_usernamesaves it and starts that seat's creation, oruse_default_name=truecreates with a platform default. Instagram gets the typed name at signup; TikTok assigns its own handle and applies the pick as a rename right after, which spends TikTok's one username change per thirty days; until the rename lands (usually a few minutes) the account stays offlist_accounts'accounts, listed underaccounts_being_namedwith its pick, and its seat shows inpurchase_account_seats'being_set_upat stageapplying_username. A name that fails when applied falls back to close variations, then keeps the platform handle; the account-ready email and Home item then say which pick was not used, andlist_accountscarries it aspicked_username_not_appliedfor thirty days or until the account is renamed. Progress shows per account onlist_accountsuntil the account is ready. - •
cancel_account_seatkeeps the account posting until the paid period ends, then stops posting and billing, no refund;reinstate_account_seatundoes it before that date at no cost. Once a workspace holds no seats, the phones its seats came with are signed out and returned to the pool three days after its last seat subscription ends, even while a credit plan runs. When a whole seat subscription ends (its seats cancelled, or Stripe gave up on a failed payment), its accounts stop posting at once but stay on their phone for those three days:get_seat_billinglists them underrestore_offers, andrestore_account_seatsreturns a checkout that brings them all back at the price that subscription billed (an account the workspace had paused itself comes back paused); after that, resubscribing can't bring them back. An offer'spayment_failedis true when Stripe ended the subscription because its renewal payment didn't go through; Pamba then voids that subscription's unpaid invoices, so the old bill can't be paid for nothing.get_seat_billingshows the next renewal's total per seat.recreate_social_accountreplaces a seat-funded Instagram account with a new one on the same phone and seat (once every 10 days per seat, admins only; the old account keeps counting in the workspace's analytics with nothing new read for it, flaggedarchived, its videos are not deleted and Pamba keeps its credentials in case they are ever needed; its pending posts move to the new account, or withmove_scheduled_posts: falseare cancelled when the new account lands and their videos stay to schedule again);get_account_recreationsays whether an account can be recreated now and how a recreation is going. A TikTok account cannot be recreated by the workspace (unsupported_platform): only Pamba's team replaces one. While any recreation runs,list_accountsleaves the old account out and lists it underrecreations_in_flight. - •
import_social_accountbrings a TikTok or Instagram account the user already owns onto Pamba: a seat still waiting for an account takes it at the normal seat price, one bought to connect before one bought to create (no_open_seatmeans buy seats withpurchase_account_seatsand purposeconnectfirst: the same prices and pair discount, no usernames asked, and each seat waits inbeing_set_up, purposeconnect, until an import fills it, so ten accounts are paid for once and connected one by one, whenever the user is ready), and one of the workspace's phones signs it in with the handle, password and, when it is not the handle, the email or phone the user signs in with. Accounts that sign in only with Google or Apple need a password set in the app first. The sign-in usually stops on a verification code the platform sends the user: pollget_account_import_statusevery few seconds, and the moment itscode_requestis set (kindemail, sms, authenticator or approve_on_device, the maskeddestination,wrong_codeafter a refused code,expires_at) ask the user for the code and pass it tosubmit_account_import_code; codes expire within minutes, andresend_account_import_codeasks the phone to send a new one (afterresend_available_at: the apps hold their own resend about a minute). For an email or text code the app also asks on the user's own phone whether the sign-in is theirs, and approving there works with no code.password_rejectedtrue means the app said the password was wrong and sent the code to an address it chose: the user enters it only if the address is theirs, and if it is not, the handle reached someone else's account (cancel_account_importand start again with the right handle, or, once the code wait ends and the import readsneeds_customer,retry_account_importwith the rightusername).needs_customercarries afailurethe user must fix (a wrong password, a code never given, too many tries, a suspended account, orpasskey_required: TikTok only lets the account in with a passkey on the user's own phone, which they remove in TikTok under Settings and privacy, Account, Passkey), thenretry_account_importwith the new password, login or handle (username: a mistyped handle readsaccount_not_found; a retry after five sign-in attempts hands the import to Pamba's team instead).failure.codewrong_accountmeans the user's login opened another of their accounts, named inopened_username, which the phone has already signed back out: ask whether it is the one they meant, and if soretry_account_importwithusernameset to it (the same login and password), otherwise with theusernameand login of the account they meant (a reconnect leavesopened_usernameempty and keeps its handle);with_teammeans Pamba's team is finishing the sign-in by hand and settles any code it needs with the user directly.cancel_account_importstops an import and frees its seat; a reconnect is refused (reconnect_not_cancellable) while its account still fills its seat, and Pamba closes one 3 days after its seat ended, when the seat can no longer be bought back. Pamba changes nothing on an imported account by itself (no AI-comment filter, no AI-creator label, no rename); it warms like every account on a phone. If TikTok or Instagram later signs it out of its phone (a password change, or the app ending its session), its import reopens asneeds_customerwithfailure.codesigned_outand the user is emailed: untilretry_account_importreconnects it (the stored password unless the user gives a new one, then the code the app sends, as on the first connect) it can't post or warm,schedule_post,schedule_instagram_post,schedule_slideshow_postandpost_instagram_storyrefuse it withaccount_needs_reconnect, its scheduled posts fail with that code (retry them once it is reconnected), andlist_announcementsleads with a warning (kindwarning, labelSigned out) naming it. An import connects only the account it names: Instagram also signs in every account that shares a Meta Accounts Center with it, and Pamba never lists, warms or posts from those; connecting one takes its own seat and import. - •A workspace that only buys accounts and posts its own videos runs this order, and nothing in it spends credits:
list_accountsto rule out a spare,purchase_account_seats(passlink_avatar_project_idwhen the account is for an avatar) and the person pays at the checkout URL,suggest_account_usernamesthenset_account_usernameper seat (creation starts only once a seat has a name),list_accountsuntil the account readsposting, thencreate_draft_project,set_edited_videoandschedule_postwith the new username (see Scheduling and posting). To queue the post before the account exists, the project needs the avatar the purchase links to, andschedule_posttakesawait_new_account=truein place of a username. - •
follow_accountshas a TikTok or Instagram account on a Pamba phone follow a list of usernames or profile links. An account's lists keep to a daily limit, because TikTok and Instagram can flag an account that follows too much: none in its first seven days on a Pamba phone (counted from its first warming session or follow list), so the first follow lands once the account is a week old, then one a day at most, however old the account. Warming's own follows are separate and do not count toward it.get_account_followsreports the limit today asdaily_limit(withstarts_at_utcwhile a new account's first days last). A list waits for the limit, and a waiting list's next session time says when it continues. The phone follows one account per session, at a different time each day between 8 AM and 1 AM Pacific, around the account's posts and warming, and at most fifty wait at once; a session that followed no one (already followed, not found) leaves the day's follow for the next session, at least three hours later (up to half an hour more). A request while a list is running joins it (up to a hundred accounts on one list in all; a list being stopped takes nothing new, so the request opens the next list), and a new list starts no sooner than three hours after the account's last session. A profile the account already follows is left alone, and the account never follows itself. It runs in the background:get_account_followsshows the running list with each account's outcome (followed,requestedfor a private account,already_following,not_found,failed(where a mistyped or deleted username usually lands, with a reason to check it),cancelledwhen a stop reached it first, orskippedwhen the request failed before reaching it), andcancel_account_followsstops what is still waiting; a session already on the phone finishes its one account first. - •
delete_account_postsdeletes published posts from an account on a Pamba phone, videos and slideshows alike (TikTok videos and photo posts; Instagram reels, carousels and pictures), up to twenty per request and fifty waiting per account: it removes them from the platform itself, so confirm the exact posts first. Name each by itspost_idor by its link: a project'sposted_tiktok_video_urlorposted_instagram_video_urldeletes that project's post, and a slideshow post's posted link deletes that slideshow post.list_account_postslists the account's posts newest first with each one'spost_id, itskind(video,slideshoworpicture) and its deletion state (pending,deleting,deleted,not_foundwhen the post was already gone,not_confirmedwhen the phone could not prove the post on screen was the one asked for and deleted nothing,delete_unconfirmedwhen the phone may have deleted it but its link did not show it gone (the delete was confirmed, or the post was in a session nobody heard back from), which is not final: Pamba checks the account's own listing about fifteen minutes after the session and settles the postdeletedonce the account no longer lists it, orfailedwhen it still shows it (a post the listing cannot see, such as an Only-you TikTok post or an Instagram reel off the profile grid, is settled by Pamba's team instead),failed,cancelledorskipped). A post the phone reporteddeletedthat the account still lists on both checks turnsfailedtoo. The phone deletes five per session, around the account's posts and warming; TikTok and Instagram keep a deleted post 30 days in Recently deleted, where only someone on the phone can restore it. Withpost_ids(ids or links) it returns only those posts, and still returns a deleted post the platform no longer lists, with its state.cancel_post_deletionstops what is still waiting; a session already on the phone finishes its own few first. In the app it is Delete from TikTok or Delete from Instagram on a posted post (the project's More menu, and the post's row and calendar card on the Schedule page, slideshow posts included). - •
list_commentslists the comments on the workspace's own TikTok and Instagram videos from the last sixty days, each top-level comment with its replies and its video: newest thread first, or withsortthe most liked first (most_liked) or in the order TikTok or Instagram itself ranks the video's comments as of Pamba's last read (top). Comments are read about every fifteen minutes once a video's comment count grows, so a new one shows within about an hour;synced_atsays how fresh the list is.questions_only=truekeeps the comments that ask the creator something or ask for something the video offered,mine=truekeeps the threads the workspace's accounts took part in, andqsearches the text, the authors and the replies.about_aimarks a comment that says or asks whether the video or the person in it is AI or not real, and each TikTok account on the workspace's phones carriesai_comment_block_stateandauto_block_ai_comments: when such comments sit on an account whose filter isfailed, oroffwithauto_block_ai_commentstrue (false means the user allowed AI comments),update_account_profilewithdisable_ai_commentsandauto_block_ai_commentsboth true turns on TikTok's filter for them, as the Comments tab's Block AI comments line does.list_comment_videosgives the same comments per video, newest activity first, with how many match and how many are questions, for going through them one video at a time; it also lists every post from the last seven days before its first comment, so the account can leave that first comment withcomment_on_video.reply_to_commentanswers a top-level comment andcomment_on_videoadds a new comment to one of the workspace's own videos, from any of the workspace's accounts on that platform (account, the video's own by default); either is typed within minutes on that account's phone, or atscheduled_for(an ISO-8601 time with its offset, from a minute to thirty days ahead), so only an account on the workspace's phones can send (theaccountslist says whichcan_reply), up to one hundred fifty characters on TikTok and two thousand two hundred on Instagram, and at most thirty in any rolling day per account. On TikTok an @username in the text is picked from TikTok's own list as the phone types it, so it posts as a tappable mention showing that account's display name; a username TikTok does not offer fails the comment unsent (failed, with a reason naming it), since typed as it is it would not link. Instagram links a typed @username by itself. TikTok and Instagram lock an account that comments on other accounts' videos too early or too often for suspicious activity, so on another account's video (another of the workspace's), an account Pamba created comments only after its first seven days (statusnew_account), and any account at most the workspace'scross_account_per_dayin any rolling day (one unless the Pamba team raised it;cross_account_daily_limit); each account inaccountsthat can reply carriescross_account_blocked_reasonandcross_account_available_atwhile it is held, and its own videos are never held. Every limit counts at the time the comment goes out, against the account's comments before and after it, so a refusal'savailable_atpassed asscheduled_forqueues it, and a workspace spreads comments across days by scheduling them. What an account is asked to do now on one video, comments, replies, likes and pins alike, goes out together in one phone session, as a creator does it in one sitting: each request waits two minutes for the next, the run goes out at most ten minutes after its first, and a session takes up to ten; requests givenscheduled_forgo out at their own times, so the same time groups them and different times keep them apart.comment_on_videowithpintrue has an Instagram reel's own account pin the new comment once it is live.like_commentlikes a top-level comment from one of the workspace's accounts (the video's own by default on its own videos) andpin_commentpins one on the workspace's own Instagram reel from the reel's account (Instagram keeps up to two pinned comments per post; TikTok no longer lets creators pin comments,pin_not_available); both are typed on the phone like a comment, now or atscheduled_for, thirty a day per account together, never counted against the comment limits; a like from an account that does not own the video (another of the workspace's accounts' videos) keeps to the workspace'scross_account_likes_per_dayin any rolling day (one unless the Pamba team raised it;cross_account_daily_limit, withavailable_at), each account inaccountscarryingcross_account_like_blocked_reasonandcross_account_like_available_atwhile it is held, so likes in bulk are spread across days by giving each itsscheduled_for; andlist_commentsshows them in each thread'sactions(list_outgoing_commentslists them withactionlike or pin; it lists comments alone by default). To reply in advance, passreply_to_commentthe outgoing id of one of the workspace's own comments that is not live yet: the reply waits for it, and up to three replies can wait behind one comment, going out one at a time in the order they were asked for, each once the one before it is live and fifteen to forty-five minutes after it was sent (reply_to_outgoing_idnames the comment it answers andwaiting_for_idthe one it waits for). Once a comment has replies in advance behind it (on their way or live), another reply to it, by its outgoing id or by its comment id once it is live, joins the end of that line. If a comment before them fails, is cancelled or still does not show two days after it was sent, the replies behind it are cancelled too; a fourth reply answerschain_full, and a reply to a comment that will not go live answersparent_not_live.list_outgoing_commentsfollows each one:queued,sending,posted(the phone sent it, or Pamba lost the phone's answer; a read of the video settles which),liveonce a read of the video shows it,not_visiblewhen no read has six hours later, orfailed;cancel_outgoing_commentwithdraws one while it is still queued, with the replies waiting behind it. - •
update_account_profileedits display name, handle, picture and bio on the hosting phone. Bios are capped at one hundred sixty characters on TikTok and one hundred fifty on Instagram; a URL typed into a bio is plain text, the link field is separate and untouched. On TikTok the phone picks each @handle in a bio from TikTok's mention suggestions, so it lands as a tappable mention that TikTok shows as @ and that account's display name; a handle TikTok offers no account for fails the bio field with the error code bio_mention_not_found, and a mention the phone could not show links the account asked for (a pick on a suggestion whose caption TikTok cut short, or a bio TikTok already held whose mentions are not drawn as links) with bio_mention_unconfirmed; an email address stays text.list_accountsreports each account's current bio, whichever is newer of the one Pamba last set and the one last read off the phone (on TikTok, a read that is the bio Pamba set with each mention shown as @ and a display name still reports the bio as set, with the handles an edit sends again); every linked account's bio is read once a day, so an in-app change shows within a day. Only the fields an edit asked for count as outcomes: a bio-only edit reports one operation, not three. On TikTok the phone gets time for each field and each @handle an edit asks for; a field it had no time left to start comes back not applied with the error code field_out_of_time, beside the fields it did apply. An Instagram bio with a link, put on an account Pamba created less than seven days ago, still goes through, and the result carries awarning: Instagram often restricts link sharing on accounts that add a link this early. Aqueuedanswer, from this tool or fromenable_instagram_ai_creatoranddisable_instagram_ai_creator, carries the edit'sjob_id, whichget_account_profile_editreads to its outcome. - •
update_account_profilealso switches an Instagram account between personal and creator withinstagram_account_type, sets its profile category withinstagram_category(any case, one of Digital creator, Artist, Musician/band, Blogger, Clothing (Brand), Community, Education, Entrepreneur, Health/beauty, Writer, Personal blog, Product/service, Gamer, Restaurant, "Beauty, cosmetic & personal care", Grocery Store, Photographer, Shopping & retail, Reel creator, Gaming video creator, Social Media Agency, Camera/photo, Computer Company, Makeup Artist or Creator) and whether the profile shows it withinstagram_show_category, sent in a call of their own with no other field: the account type is its own job on the phone, answeredqueuedwith ajob_idthatget_account_profile_editreads (its kind is instagram_account_type, its fields account type, category and show category). Pamba never switches an account to business, since Business accounts can't use most of Instagram's licensed music:businessis refused with the error code instagram_account_type_invalid, and an account that is a Business account already is never switched to creator (instagram_account_business) but can go to personal or change its category; when the phone finds a Business account Pamba had not read yet, the job fails with ig_account_business and nothing changes.creatoron an account that is creator or business while its switch to personal still waits for the phone, never yet sent to it, withdraws that switch instead: the call answerswithdrawnwithwithdrawn_job_idsand the account stays as it is (a category or display in the same call is queued as its own change); a switch to personal already sent to the phone is refused with change_in_progress, and on a creator account after an earlier type switch of it ended unread the call is queued over the waiting switch instead (it answersqueued), for the phone to read the type the account has. A personal account, or onelist_accountsgives noinstagram_account_typefor, switched to creator takes the category Digital creator unless the call (or a change already queued) names one, and a hidden display unless it names one; an account that is creator or business already changes only the fields the call names. A category or its display alone needs an account that is creator or business, or has a switch to creator queued (one Pamba knows is personal, or with a switch to personal queued, is refused with the error code instagram_account_not_professional; one whose type Pamba has not read goes to the phone, whose job fails with ig_account_not_professional when the account is personal), a category Pamba does not offer answers instagram_category_invalid with the list, and a call for TikTok is refused, since TikTok's only switch is to a Business account, which limits it to TikTok's commercial music library. Switching makes the profile public, and Instagram also turns on stricter filtering for professional accounts, which hides more comments and message requests; going back to personal turns its insights off.list_accountsreports each Instagram account'sinstagram_account_type,instagram_categoryandinstagram_show_category, the newer of what Pamba last set and what the hourly analytics refresh last read. Instagram trial reels need a creator or business account with at least two hundred followers. - •Pamba-created TikTok accounts block AI comments automatically once linked to an avatar: an account linked at creation gets the filter after its first post is live, one linked later gets it queued at link time, and an unassigned account is never filtered.
disable_ai_commentsturns it off per account.get_avatarreports the state per account asapplied,queued,scheduled,failedoroff, and null when the account is not on one of the workspace's phones. - •
enable_instagram_ai_creatoranddisable_instagram_ai_creatorturn the label on and off; each leaves a label already where it asks untouched, and a change still queued for a busy phone takes the newest call's direction. While the phone is applying one direction, a call for the other is refused withchange_in_progress; call again once it settles.list_accountsreports each Instagram account'sai_creator_label_state:turning_onorturning_offwhile the phone is queued or running to change it, thenonoroff,failedwhen the newest attempt to turn it on failed, orturn_off_failedwhen the newest attempt to turn it off failed (the label is still on); each TikTok account carries its AI-comment filter asai_comment_block_state. Both are empty for an account on none of the workspace's phones. - •Warming (human-like feed browsing) is always on for every device-hosted account and cannot be turned off from the tools. Every account warms once a day under its own config (
get_account_warming_config,set_account_warming_search_terms), whichever avatars link it. An avatar's config (get_warming_config, terms viaupdate_avatar_settings) is the one its accounts start from: an edit there is written onto every account the avatar links, shared ones included, and an account linked to its first avatar takes that avatar's settings. A linked account warms while every link of it posts and at least one linking avatar is active. Terms cap at twenty-five of eighty characters, and a save carrying a term with "porn" is refused with a message naming it, since TikTok and Instagram show no results for it; without explicit terms, sessions fall back to terms generated from the workspace niche (search_terms_sourceniche), while an empty list saved withuse_niche_termsfalse is kept as the owner's own and its sessions search nothing (search_terms_sourcenone;use_niche_termstrue with an empty list goes back to the niche terms). A term TikTok answers with its guidelines page on the phone leaves the account's terms, the terms of the avatars linking it and of every account those avatars link, and the niche terms by itself, and the workspace gets a Home item at once and an email about two hours later; a "No results found" on either app removes nothing. TikTok and Instagram sessions both search those terms and judge what they watch against the workspace niche, and a session that browses the feed follows the creator of an in-niche video now and then: at most one follow per account per day. A session that searches gives at most 3 likes in all, follows no one and shares nothing. The workspace's defaults, which a new avatar and a new TikTok or Instagram account with no avatar start with (an account added to an avatar takes the avatar's setting), areupdate_workspace_settingswarming_searchesandwarming_follows(list_workspacesreports both); either needsapply_warming_to_existing_accounts: true also writes it onto every existing account and avatar, false changes the default for new ones only, and without it the call changes nothing and answersneeds_choice. Warming keeps running either way.set_account_warming_switchessets one account's own switches:follows_enabledfalse and its sessions follow no one,searches_enabledfalse and they never search (the first week's search included) while its terms are kept for when searches are back on;get_account_warming_configreports both.update_avatar_settingswithwarming_searches_enabledorwarming_follows_enabledsets them for every account an avatar links, shared ones included, and for an account it links later that no other avatar links;get_warming_configreports what the avatar's last edit set, as it does its terms. An account searches in one session per warming day at most (a warming day starts at 8 AM Pacific), whatever its search chance or a boost's: once a session has started a search, even one the app answers with nothing, the day's other sessions browse without one, and a day may have none. For seven days from an account's first completed session, the longest session of each warming day opens with that search whatever the search chance, and the day's other sessions do not search. By default an account warms three five-minute sessions a day.start_account_warming_boostwarms one account harder forduration_hours(1 to 336), then it goes back to its own pace by itself:sessions_per_day(1 to 5; needs at least 24 hours) applies from the next daily booking at 10:00 UTC,search_probability(0 to 1) from the next session, still one search a day at most, and you pass either or both. A new boost replaces a running one,get_account_warming_boostreads it andend_account_warming_boostends it early. It works for assigned and unassigned accounts alike, never changes the config or its terms, and renaming the account ends it.cancel_warming_sessionworks only on pending sessions.get_account_activityis one feed per account of what the phone did for it, newest first: warming sessions (status, length, videos watched, likes, comment reads, creators followed, the search term, a few sample screenshot URLs), daily TikTok health checks, posts, profile edits, finished follow requests and post deletions, and the comments and replies the account posted with every screenshot the phone took of each; pass a page'snext_beforeback asbeforeto read further back, and an emptynext_beforeends the feed. - •Every device-held linked TikTok account gets one account-health check a day. Findings open incidents (
ACCOUNT_WARNING,VIDEO_REMOVED,VIDEO_NOT_RECOMMENDED), shown as health flags and cards and surfaced on Home, and emailed to the workspace about two hours later; these kinds never pause the account.get_tiktok_account_healthreturns the latest screenshots and open issues with each appeal's progress;request_tiktok_appealrecords the decision to appeal a removed or restricted video or an account warning, one appeal per issue, and nothing is appealed without it unless the account's auto-appeal is on (set_tiktok_auto_appeal, reported byget_tiktok_account_healthasauto_appeal): then every open issue is appealed when it goes on, and each new one as the daily check finds it. The account's phone then files the appeal itself, submitting only once a TikTok screen prints that video's posted time (a video it cannot pin down is filed by the Pamba team by hand; anACCOUNT_WARNINGis appealed through the video TikTok removed with it: appealing it also appeals the one removed video the same daily check found, and one verdict decides both; with none or several, the Pamba team files it by hand), and reads TikTok's verdict off the account's notifications once a day until it answers:appeal_verdictAPPROVED closes the issue as restored, REJECTED keeps it open. An appeal TikTok has not answered four days after filing sends the phone back to the video to read TikTok's answer on its page. A removed video reappearing also closes its issue and approves its appeal, a video the phone finds no longer restricted when it goes to file closes its issue as restored, other issues close after two clean daily checks, except one whose appeal is still being filed or still waits for TikTok's verdict (up to 21 days after filing). A video the workspace deletes through Pamba (delete_account_posts) takes the open issues that predate the deletion with it once the deletion confirms it gone (closed asDELETED): its appeal stops wherever it stood, and nothing is filed, read or rechecked for it. AnACCOUNT_WARNINGTikTok gave for that video stays open; if its appeal was not filed yet, the Pamba team checks whether TikTok still takes it. When Pamba replaces an account with a new one, every open issue of the old account closes (closed_byMANUAL) and its appeals stop.close_account_incidentdismisses an issue for good. - •Accounts suspended by Meta open a
SUSPENDEDincident that pauses posting and warming and rejects scheduling until a session runs clean or the incident is closed withclose_account_incident, only after the account is verified restored. An account Pamba confirmed TikTok or Instagram banned carries aBANNEDhealth flag and incident: it can no longer post (Pamba still accepts posts for it, so never schedule one there), Pamba replaces it with a new account on its seat at no extra cost, and only Pamba closes the incident (close_account_incidentanswerspamba_closes), withclosed_byRESTOREDwhen the account comes back orMANUALonce a new account replaces it. While any account is banned,list_announcementsleads with a warning (kindwarning, labelBanned) naming them, the strip shown across the top of the app; aSigned outwarning about accounts to reconnect comes after it. A ban outranks aSUSPENDEDincident on the same account: don't suggest an appeal or close the suspension. Instagram can also restrict one feature of an account that keeps working ("You can't share links" until a date): the phone closes Instagram's restriction page and Pamba opens aFEATURE_RESTRICTEDincident whose detail carries the restriction and itsends_on. It never pauses posting or warming, shows through its end date and closes the day after.reconcile_tiktok_renamerepairs an account renamed on TikTok itself, moving the avatar's active account and all forward-looking drafts, plan and scheduling to the new handle; old posts stay under the old handle.
Ideas, discover and research
- •
list_ideasandget_idearead the library (twenty-five per page, sortable by date, views and engagement ratios); every hub video carries a replicationfeasibility_verdict(pass,fail,unjudged) with the judge's reason, andexclude_low_feasibility=truehides failed ones while unjudged stay visible.get_idealistsrequired_brand_assetswithin_libraryper kind, which tells you before replicating whether an upload is needed. A workspace holds up to one hundred ideas. - •Research needs an active subscription, a credit plan or account seats; free workspaces browse but every addition (
create_idea,branch_idea,add_tracked_accounts,generate_script_from_idea) answerspayment_required. Saving a video that is already analyzed is allowed on every plan. The inspiration-account cap scales with the plan tier. Tracking an account feeds its breakout videos into the create page's For You blend once the feasibility judge passes them;remove_tracked_accountcannot remove an account linked to one of the workspace's avatars. - •
search_tracked_videossearches the workspace's own accounts by default (avatar-linked, signed in on its phones, or with a post it scheduled); passinclude_research_accounts=truefor the inspiration accounts. Ground recommendations there rather than in memory.generate_script_from_ideawrites a fresh script, thirty to forty-five seconds unless the idea asks for another length and in the idea's language, and does not save it;save_idea_scriptorcreate_video_projectdoes. - •Discover:
get_trending_videos(by default only avatar-replicable content, screened for promotion carriage;include_unproducible=truereveals everything),get_niche_feed(returnsniche_statuspendingorno_nichefor an empty feed),search_viral_videos(paid only; falls through to a live TikTok search when the corpus is thin, with a daily budget reported aslive_searches_remaining_today),get_breakout_creators. To act:use_discover_videoputs a video on the Ideas board (idempotent),bookmark_discover_videosaves it,track_video_authoradds the creator as an inspiration account.browse_picker_videosis the create page's shelf; a row whosevideo_urlis null is an un-enriched Discover row, so prepare it withuse_discover_videofirst.
Content review, knowledge and automation
- •Campaigns are autonomous cycles that plan, write, generate and queue posts for their member avatar and account bindings on a schedule, gated by review windows unless auto-approve is on. Schedules run in the workspace timezone and plans are ready for review by nine in the morning local time by default. Every workspace has a Default campaign that owns unassigned members and cannot be deleted;
create_campaigncopies its schedule and starts disabled with no members;assign_avatar_to_campaignis a complete move.enable_campaignspends credits on every future cycle untildisable_campaign, and both need an active subscription on the workspace owner.run_campaign_nowplans the gap days up to the next scheduled cycle without stealing that cycle's window. - •
preview_content_planis a dry run that creates nothing;plan_content_batchplans (or re-plans an unapproved batch viabatch_id);get_content_planexplains, per avatar, why each got its slots;edit_plan_slotsmoves, removes, swaps, adds or pauses.approve_content_planorapprove_all_content_plansis where credit spend starts, and approval is refused while the plan has error-severity violations.set_mix_targetsreplaces all targets, so readget_content_strategyfirst.delete_planonly removes a planning or brief-pending batch and never touches projects. - •
push_content_batchis safe by default: withoutpush_now=trueor apreflight_idit only runs the preflight. Withpush_now, each pushed approved script becomes a fully automated project that generates and schedules, and spends video credits.decide_content_scriptwith abatch_idand noscript_idapproves every undecided script;require_green=trueskips scripts with failing checks.send_writer_chat_messageanswers asynchronously: read the thread withget_content_script(view=writer_chat), thenapply_script_revision. - •Knowledge base: patterns (a pattern's category is its canonical format;
lipsyncpatterns are classification-only, the planner never allocates them), principles, playbooks and term lists (tiered pools of real terms the writer draws from:proven,testingandexploratorytiers are writer-eligible,candidateandrisk_flaggedterms are not). The writer's references are chosen automatically at claim time from pattern links; curate them withmanage_pattern_linkand preview withget_pattern_references. - •
get_studio_overviewis the one read for the Drafts and Videos tabs. Always passstatuses:draftsis the Drafts population (concept-stage items awaiting generation), the others (queue,failed,approved,scheduled,posted,archived) are the Videos tab's filter, and posted history and archived projects are reachable only here. Omittingstatusesreturns the classic queue capped at fifty with drafts sorted below everything else, which hides them on a busy workspace.sort(newest,oldest,posttime) decides which items make the window and requiresstatuses; a typo in either errors rather than defaulting.view=homealso returns the getting-live setup, whereready_to_post(notaccount_connected) says whether posting would actually work.
Analytics
- •
get_analytics_summary(daysone to three hundred sixty-five, default thirty;platformtiktok,instagramorfacebook, default TikTok; optionalavatar) gives views and followers per platform, broken down by up to twenty avatars. An inactive avatar's accounts stay in it as an archived account does, markedarchived: their old views keep counting and nothing new is read for them until the avatar is active again.search_tracked_videosis per-video TikTok performance,list_social_videosper-video Instagram and Facebook performance,get_tracked_account_metricsan account's lifetime totals and cadence. - •An Instagram slideshow or picture (
media_kindphoto) has no public view count: Instagram shows its views only to the account that posted it, so the account's Pamba phone reads them off the post's own insights, about three days after posting and a final time about four weeks after, andviews_read_atsays when. Every postlist_social_videos,search_tracked_videosandget_post_analyticsreturn carriesviews_source, where its views come from:public(the count the platform shows publicly, read by Pamba's hourly scrape: every TikTok and Facebook post, an Instagram reel, a slideshow posted as one included) orinsights(read off the post's insights by the account's phone: every other slideshow, and every picture). Aninsightspost with noviews_read_athas not been read yet: its views, 0 in a list and null onget_post_analytics, mean not known yet rather than zero views (the app shows a ? there). Its likes and comments come from the hourly read like a reel's. - •
get_post_analytics(platformtiktokorinstagram,video_idthe TikTok video id or the Instagram shortcode) is one post's page: its counts with their daily history and its audience (gender, age from 18 (no age under 18 is ever served), top locations, new vs returning viewers, followers vs not, watch time, finish rate, and its retention curve: the percent still watching at each second, with TikTok's average share watched and the moment most viewers stopped, or Instagram's skip rate) and its engagement (the likes, comments, shares, saves and Instagram's reposts as the app counts them; when in the video viewers liked it, at each second, on the app's own scale: TikTok's chart runs to 100% at its most liked moment, Instagram's gives each moment's share of the likes; TikTok's most liked moment and the words its comments use most; the like, comment, share, save and repost rates, Instagram's own, or for TikTok, which prints none, the read's counts over its views withrates_from_countstrue), andretention_moments, the percent still watching at 5 s, 10 s, halfway and the end with the skip rate, aslist_post_analyticsgives them, read by the account's phone off TikTok's Video analytics or Instagram's reel insights, with the screenshots behind each read. A post is first read once it has 200 views, at any age (or three days after posting with 100), and again as it passes 1,000, 5,000, 10,000 views and every doubling after, at most ten posts a day per account;next_readsays when.list_post_analytics(platformall,tiktokorinstagram,days1-365 (default 30),sortnewest,retention_5s,retention_end,skip_rate,like_rate,comment_rate,share_rateorsave_rate,limit1-100) lists the posts with a read, each read at a glance: the percent still watching at 5 s, 10 s, halfway and at the end (one second before it on a post up to 20 seconds long, the curve's second-to-last measured point on a longer one, since TikTok's chart falls to about zero in its last second), the skip rate (the app's own where it prints one, Instagram; otherwise the share gone in the first 3 seconds of the curve, withskip_rate_from_curvetrue), the share watched and the finish rate, and its engagement: the likes, comments, shares, saves and (Instagram) reposts the read counted, the share of viewers who did each (Instagram's own rates; TikTok prints none, so there each is the read's count over its views, withrates_from_countstrue) and TikTok's most liked moment. Each post also carries the listing's own likes, comments, shares and saves. These are the Retention and Engagement columns of All Videos. Each row'sretentionis left empty there (get_post_analyticshas the curve), andtotalsays how many matched.get_account_audienceis the account's own viewers (TikTok Studio, 28 days) and followers breakdowns, read about once a week, with its latest daily health checks' screenshots; both apps show a followers breakdown only from 100 followers.get_audience_summary(segmentviewersorfollowers,platformall,tiktokorinstagram) is the workspace's audience across all its accounts on Pamba phones, each account counted by its size: viewers are TikTok Studio's (28 days) plus Instagram reels read in the last 28 days, followers are each app's followers breakdown; it lists the accounts folded in and when each was read, and is rebuilt as reads land. These are the platforms' own estimates, as printed. - •The numbers are snapshots and the surfaces end their windows and total differently, so do not expect them to reconcile to the view. The summary tool and the app's dashboard read the same daily rows, each dated on its workspace's calendar; the summary ends its window on today in UTC, the dashboard on today in the viewer's timezone.
get_tracked_account_metricsdates its per-day series on the workspace's calendar too. The dashboard sums daily deltas, while per-account metrics sum lifetime view counts. A TikTok video's first snapshot carries everything it earned before Pamba first read it, and those counts land on the day the video was posted when Pamba first read it within 90 days of posting; a video it starts tracking later adds only its later growth. On every platform, the views a reading finds two or more days after a post's previous one (an account not read while its avatar was inactive, a scrape outage) are spread evenly over those days rather than landing on the day the reads resumed. Accounts assigned to a deactivated avatar keep posting and accruing views but do not appear in avatar-scoped dashboards. A TikTok rename keeps one account row: the hourly refresh follows the account through its stable id (or one of its own videos) and moves the row to the new handle, so both handles' videos stay together; a rename it cannot follow leaves the old row failing until it is reconciled by hand. Instagram's headline views are the play count the app shows, and the first observation of a reel attributes its whole lifetime to one day.
Workspace, members, onboarding and support
- •
update_workspace_settingsis admins only; settingwebsite_urlre-scrapes the site and replaces the stored company profile (and the niche, unless it was hand-written).update_company_profileedits the brief field by field and leaves the others alone; an empty string clears a field. Name, niche and profile feed the model's own context, from the next connection onward.list_workspacesreturns at most twenty workspaces andlist_workspace_membersone hundred. - •
create_workspacewithwebsite_urlsets a workspace up like an onboarded one in one call (brief, name, media library, niche feed, three matched avatars; the site read takes about thirty seconds); passniche_description,what_they_doandnameinstead when there is no site (withoutwhat_they_dothe brand stays unconfirmed and the result says how to finish it). A new workspace has its own plan and starts with zero credits, and the connection stays bound to the workspace of its key. If setup fails after creation the error carries theworkspace_id: finish or delete it, never create a second.delete_workspaceis a soft delete and cannot remove the user's default workspace. - •Onboarding state (
get_onboarding_state) runs website, brand, media, first video, avatar, plan, device; thelightflow of an added workspace ends afterset_onboarding_brandandcomplete_onboarding.set_onboarding_websiteis best-effort (an unreachable site still records the URL and advances) and kicks a background media capture into the asset library (media_capture_status).list_onboarding_presenter_optionsreturns an empty list while the niche match is still running, so poll again rather than treating it as no avatars.select_onboarding_presenterpicks a matched starter avatar for free;start_onboarding_avatargenerates one and spends image credits.create_onboarding_concept_projectsis free and idempotent. The device half must be resolved (purchased or skipped) beforecomplete_onboarding, which refuses otherwise.set_onboarding_referralaccepts only its listed sources, with free text indetailunderother. A user with no credits and no avatars right after signing up has a torn bootstrap;heal_signup_bootstrapre-runs the missing grants idempotently. - •
contact_supportposts into the user's private support conversation with the Pamba team (up to five thousand characters, plus up to four public image links inscreenshot_urls, PNG, JPEG or WebP, up to ten megabytes each); a user can send ten messages a minute and a hundred a day across every door, emails to support or to a team member included, and upload fifty screenshots a day. Acontact_emailstays on the conversation for later replies until another replaces it, and the result names the address replies go to. The team answers in the app's Support tab and by email, andget_support_messagesreads the conversation: who wrote each message, the text, screenshot links valid for an hour, andunread_count. Reading the newest page counts as the user seeing the replies, so the reply email is skipped. Over this transport no chat transcript is shared with the team, so put the context in the message.list_api_keys,create_api_keyandrevoke_api_keymanage keys; a revoked key's MCP connection fails at its next call.create_api_keyreturns the new secret in its result, which over a hosted client lands in a transcript, so create the key for an MCP connection in the app and keep the tool for keys the agent itself will hand to a system. That includes the keycreate_api_keymakes withkey_workspace_idfor a workspace the connection's key created: it lands in the transcript too, so it suits a system integration rather than a person's own connection. - •Content rules: Pamba's Acceptable Use Policy is the public page
https://pamba.app/acceptable-use-policy; point people there for what is allowed, why a generation was refused by safety filters, and what happens to accounts that break the rules.
Security model
- •A workspace API key resolves to one user in one workspace, where workspace-bound tools run. It makes keys only there and in the workspaces it created itself (
create_api_keywithkey_workspace_id); a chat app's connection makes keys only in the workspace the call runs in. What acts on the person reaches past the key's workspace, as it does in the app:list_api_keysandrevoke_api_keycover their keys everywhere, anddelete_workspaceand the REST/workspaces/{workspaceId}/…routes (settings, members, invitations) act on any workspace they administer. An OAuth token resolves to one user and an explicit set of approved workspaces; each tool call resolves one approved workspace and verifies current membership before execution. Ownership checks are the same the app enforces: an id from another workspace answersnot_found, never data. Admins-only settings answerforbiddenfor members. Operator endpoints behind Pamba's admin key are not reachable through this server at all; the admin key is not a credential here. - •Rotate a key by creating a new one and revoking the old; connections are stateless, so the next call after revocation is the one that fails. Revoking a key leaves the keys it made working, and the new key cannot make keys for the workspaces the old one created: keep a key made inside each of those, or make one later in that workspace's settings.
- •If a key leaks, revoke it, then clear what it made, since revoking removes none of it. Keys:
GET /api-keyslists every key you own with itsworkspace_idand when it was made and last used (list_api_keysshows the fifty newest and counts them all; a workspace's settings list only that workspace's keys). Revoke each one made since the leak, judging by date rather than name, since a key's name is whatever its maker typed, or revoke them all and make new ones. Members: a key can invite people into any workspace you administer, and an invitation link admits whoever accepts it, so check the members and pending invitations of each of those in its settings in the app, and remove what you did not add (over MCP,list_workspace_membersandlist_workspace_invitationsread only the workspace the connection runs in); check the key's own workspace's share links too (list_share_links). Workspaces:GET /workspaceslists every one you belong to with its owner (list_workspacesshows twenty and counts them all); delete any you own and do not recognize, and ask the admins of one you do not own to remove you. A leaked key could also have revoked your other keys or deleted a workspace you administer, never your default one.
Protocol details
- •Streamable HTTP, stateless: every POST is independent and carries its own credential, there is no session id, and no server-to-client stream (GET and DELETE answer 405). A deploy between two calls is invisible to the client.
- •One JSON-RPC message per POST, at most one megabyte (enough for a full editor state; media never travels in a message) and at most sixty-four levels of nesting; a larger body is answered with HTTP 413 and a deeper one with HTTP 400, each with a JSON-RPC error. Batches are refused. Responses are
application/json; the server never opens an event stream. Sixteen tool bodies run at once across every connection and four per workspace: a call past the workspace's share answersstatus: busyat once, and one past the overall bound waits up to thirty seconds for a slot before answering the same, in both cases with nothing run, so a saturated server never hangs a client and one workspace's fan-out never starves another's. Protocol versions2025-06-18and2025-11-25are accepted; anything else, including2025-03-26(whose transport requires batches), negotiates to2025-06-18. - •Capabilities: tools, prompts and resources, none with change notifications; the listing changes only with a deploy. Regenerate the reference in your own docs from
tools/listif you mirror it. - •JSON-RPC errors:
-32700malformed JSON,-32600invalid request or batch,-32601unknown method,-32602unknown tool, tool outside the scope, bad arguments, unknown prompt or a missinguri,-32002resource not found (thedatanames the uri),-32603internal error. Auth failures are HTTP 401 before any message is read; a badtoolsets,readonlyormax_creditsvalue on the URL is HTTP 400 with a JSON-RPC error body.
Still stuck? Message the team
