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
- •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. 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. 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, individual scheduled posts),ideas(the ideas library and tracked inspiration accounts),discover(the viral corpus, niche feed, trends, the source picker),content(script batches, the review desk, 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, 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. Two 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; and the connection's ceiling, where a call estimated abovemax_creditsis refused withstatus: spend_limit_exceeded. Neither 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),forbidden(the caller's workspace role is too low, for example a member trying an admins-only setting, or an operator-only tool),busy,queue_full,work_in_flightandautomation_running(work in flight, wait for it) 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, 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). - •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. - •URLs you pass in are fetched from Pamba's servers. Public
http(s)only; anything resolving to a private or loopback address is refused, and redirects are re-checked. - •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). So a clip can sit in 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 profile edits andget_account_link_statusa link. 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, and update_account_profile when it edits a TikTok profile. 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). Three hundred is below a typical first video (a twenty-five to thirty-five second concept runs about four to five hundred credits), so a first
generate_videowithout a plan or top-up usually answersinsufficient_credits. 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 showing the prorated amount, and confirming changes the plan in place. Downgrading a yearly plan is refused and goes through support.create_billing_portal_sessionopens subscription management; a cancellation there takes effect at the period end, and access lasts until then. 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.
What needs a browser or a phone
- •Checkout. Every purchase is a Stripe URL the person opens.
- •Files. Tools take public
http(s)URLs, never an upload body.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.
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. 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.
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, then Gemini Omni.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). Gemini Omni authors clips of four to ten seconds, the extended models four to fifteen; every model 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 need a durable public URL (a signed asset URL expires; re-host through the project first) and 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. 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 (set_edited_video, or avideo_urlonschedule_post) is recorded as the current render and is never re-rendered over. - •
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, 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. - •Replicating from a TikTok URL also captures the source into the ideas library, deduplicated on the video URL. 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.update_scheduled_post,cancel_scheduled_postandretry_scheduled_postmanage the queue;list_scheduled_postsandget_scheduled_postread it. - •A project with an avatar may only post to a TikTok account linked to that avatar; check
get_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. - •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. - •A post goes out only if its project is approved at its slot. Scheduling through
schedule_postapproves the project;update_projectwithuser_review_state=approvedapproves without scheduling. 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. TikTok captions may not contain the commercial-disclosure hashtags#ad,#ads,#sponsored,#partnershipor#paidpartnership: TikTok's own disclosure gate blocks the post, so the caption validator refuses them up front. - •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. - •If a schedule is rejected, read the reason and offer the valid accounts or another time; do not retry blind.
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.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. - •Operator-only tools exist on the surface because the in-app assistant has them; for a customer workspace they answer
forbidden: the reference-frame tools,create_social_account,get_account_creation_status,resume_account_creation,generate_image, and the writer-engine controls (run_content_engine,control_stage_run,update_engine_prompt,set_autonomy_dial,set_batch_share_page).
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 includeSHADOWBAN_RISK(after the account's first three weeks of tracking),NOT_RECOMMENDEDandSUSPENDED. - •Managed account seats cost one hundred dollars a month each, every three 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. 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. Facebook has no seat of its own; it rides Instagram cross-posting.
purchase_account_seatsreturns a checkout URL; an already subscribed workspace gets Stripe's confirm page raising the quantity with proration. - •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, TikTok through
update_avatar_settings(tiktok_usernames), Instagram throughlink_social_accountwithout a password. - •A bought seat waits for its username before creation starts.
suggest_account_usernamesreturns a checked, currently free idea per waiting seat,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. A name that fails when applied falls back to close variations, then keeps the platform handle. 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.get_seat_billingshows the next renewal's total per seat. - •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. - •
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.list_accountsreports each account's current bio, whichever is newer of the one Pamba last set and the one last read off the phone; 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. - •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_creatoris enable-only and idempotent: once on, the label locks on, and disabling is rejected. - •Warming (human-like feed browsing) is always on for every device-hosted account and cannot be turned off from the tools. Exactly one config governs an account: an avatar-assigned account warms through its avatar's config (
get_warming_config, terms viaupdate_avatar_settings), an unassigned one through its own (get_account_warming_config,set_account_warming_search_terms); assigning an avatar moves ownership and cancels pending account-level sessions. Terms cap at twenty-five of eighty characters; without explicit terms, sessions fall back to terms generated from the workspace niche.cancel_warming_sessionworks only on pending sessions. - •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, emailed to the workspace and surfaced on Home; these kinds never pause the account.get_tiktok_account_healthreturns the latest screenshots and open issues;request_tiktok_appealrecords the decision to appeal a removed or restricted video, after which the Pamba team files it from the phone by hand, one appeal per issue. Outcomes are inferred, never read from TikTok directly: a removed video reappearing closes its issue, warnings close after two clean daily checks.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.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 avatar accounts by default; passinclude_research_accounts=truefor the inspiration accounts. Ground recommendations there rather than in memory.generate_script_from_ideawrites a fresh thirty to forty-five second script 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.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. - •The numbers are snapshots and the surfaces bucket differently, so do not expect them to reconcile to the view. The summary tool buckets days in UTC; the app's dashboard uses the workspace timezone and includes the current partial day. The dashboard sums daily deltas, while per-account metrics sum lifetime view counts. Views a video earns before its first snapshot (about an hour after posting, when TikTok front-loads) never land in a daily bucket. Accounts assigned to a deactivated avatar keep posting and accruing views but do not appear in avatar-scoped dashboards. A TikTok rename starts a new account row, and each era's videos stay on their era's row. 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_descriptionandnameinstead when there is no site. 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_supportemails the Pamba team and allows three messages per workspace and five per user in twenty-four hours, so send one complete message of up to five thousand characters.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. - •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 key or token resolves to one user in one workspace, and every tool runs with that identity. Ownership checks are the same the app enforces: an id from another workspace answers
not_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.
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.
