# Creator Harbor > Creator Harbor makes vertical (9:16) UGC-style video ads: an AI actor talks to a phone camera about a product, with captions burned in. Give it a product page link; it writes the script, renders the video and returns an MP4. Pricing: per second of video by engine, 1 credit = $0.01: natural 45 credits (a 10 s ad is 450), precise 15 credits (a 10 s ad is 150), seedance 40 credits (a 10 s ad is 400). Credits are charged when an ad starts and refunded automatically if it fails; only failures are refunded, not results someone doesn't like. New accounts get 400 free credits for a first ad once they confirm their email address (not for throwaway inboxes); free takes are a watermarked preview on the precise engine and don't represent the quality of paid ads (natural engine). More credits come in packs bought by the user at https://creatorharbor.app/app/account ($10 = 1,000, $29 = 3,000, $79 = 8,500, $199 = 22,000; they never expire); agents can't buy them. ## Auth Two options: - OAuth 2.1 (for MCP clients). Discovery starts from the 401 on https://creatorharbor.app/api/mcp (RFC 9728 metadata at https://creatorharbor.app/.well-known/oauth-protected-resource/api/mcp). Client ID Metadata Documents and dynamic registration are both supported. The user signs in and approves on https://creatorharbor.app. Scopes beyond reading and the free tools: `spend` (make_ad, make_ads_batch, make_static_ads, make_short, make_clips, translate_video, run_story_step, approve_short, discard_short, retry_video), `post` (post_video, cancel_post, reschedule_post, share_video), `series` (create_series, update_series, create_autopilot, update_autopilot); a tool outside the sign-in's scopes fails with scope_missing; ask for none and you get all, the user approving. The access token also works as a Bearer for GET on /api/v1 (video_url, download_url and the like), not for writes. - API keys (for scripts and headless agents). Create one at https://creatorharbor.app/app/keys and send `Authorization: Bearer `. Works for MCP and REST. ## MCP Remote MCP server (Streamable HTTP, 2025 and 2026-07-28 protocols): https://creatorharbor.app/api/mcp Claude Code: `claude mcp add --transport http creatorharbor https://creatorharbor.app/api/mcp`, then run /mcp to sign in. Headless: add `--header "Authorization: Bearer "`. Tools: list_options, quote (any paid job's price: kind ad, ads_batch, short, clips, translate, story_step or statics, with that tool's args), quote_ad, draft_script (free: the words to agree on before paying, optionally to a template), make_ad, make_ads_batch (variants to test), get_ad (wait=true long-polls), list_ads, make_static_ads, get_static_ads, draft_short (free: a Short's plan), make_short, get_short, list_shorts, redo_short_picture, approve_short, discard_short, retry_video, share_video, get_brand_kit, set_brand_color, create_story, draft_story_concepts, pick_story_concept, run_story_step, get_story, list_stories, create_series, list_series, update_series, create_autopilot, list_autopilots, update_autopilot, find_trending_shorts, explain_video, save_video, list_saved_videos, explain_saved_video, import_video, get_import, make_clips, get_clips, edit_clip (re-edit a clip by plain instruction, free), get_clip_edit, translate_video, list_social_accounts, post_video, list_posts, cancel_post, reschedule_post, open_upload_panel (hosts with MCP Apps: the user picks a local MP4/MOV and it uploads, free; the panel tells you the key), get_uploaded_video (did an upload finish, its duration and clip quote), preview_image (a small private picture of your own ad, Short scene or clip, returned as an image), rate_video (good or bad, and what was off: we read ratings when we review models and fixes), get_balance. The flow (also in the server's instructions): list_options, then a free draft (draft_script, draft_short), then quote and tell the user the price; create with expected_credits set to the quoted credits (a changed price fails with price_changed, never charged) and a request_id; poll get_* with wait=true; give the user video_url. Tool errors carry the same JSON as REST errors, { "error": { "code", "message" } } (codes below, plus scope_missing and internal). ## REST API Machine-readable OpenAPI 3.1 specification: https://creatorharbor.app/openapi.json (public, no key needed). Import it into an API client or use it to generate a client. It documents the REST endpoints below, including upload parts and file downloads. MCP tools have their own schemas on the MCP server. - GET https://creatorharbor.app/api/v1/catalog: actors, formats, caption styles, lengths and price. No key needed. - GET https://creatorharbor.app/api/v1/me: { credits, watermarked, rendering_open } - GET https://creatorharbor.app/api/v1/me/credits: { credits, history: [{ at, amount, what }] }, the last 100 entries newest first: each render (negative), refund, pack and gift - POST https://creatorharbor.app/api/v1/scripts: draft the script from the page, free (limited per hour), to show the user before paying. Body: product_url, product_name, actor, format, duration_s (as below). Returns { hook, script, words, fits_words: [min, max], duration_s, from_page, policy_warnings: [{ phrase, why }] }; from_page false means the page couldn't be read and the script came from product_name. policy_warnings: phrases Meta, TikTok and YouTube usually reject (cures, guarantees, weight-loss or income claims, personal attributes); show them and offer a rewrite. Pass the agreed text as script below. Hooks to test: add hooks: 2 or 3 (and optionally your own script) to also get alt_hooks, other first sentences, and scripts, each full script with one. Make one ad per script (and per actor) and compare. - POST https://creatorharbor.app/api/v1/ads: start an ad. JSON body: - product_url (required): the product page - product_name: optional; without it the finished ad is named after the product as read from its page (the domain until then) - actor: maya | dan | renee | tom | wei | ama | helen | callum | priya | marcus | sofia | kenji | grace | omar | zoe | jamal | linh | frank | aisha | diego | emma | raj | nia | lucas, or one of your own (my-…) from GET https://creatorharbor.app/api/v1/actors (default maya) - voice: one of your own cloned voices (my-voice-…, in GET https://creatorharbor.app/api/v1/actors as voices), spoken on the precise engine with the actor lip-synced to it, in any language (omit for the actor's voice) - format: selfie | product | unboxing | review | problem | app (default selfie) - duration_s: 5 | 10 | 15 | 20 | 30 (default 10). 20 and 30 s ads are cut from several shots of the actor (a 3-second hook, the middle, the call to action, each its own take, cut where the words end): natural engine and paid accounts only. They're priced at 55 credits a second of what the video model bills, every shot at least 5 s (20 s: 1210 credits, 30 s: 1760 credits); a new hook on one (only its opening shot made again) is 275 - captions: hormozi | minimal | box | yellow | karaoke | marker | pop | neon | subtle | fire (default hormozi) - engine: natural | precise | seedance (default natural). natural moves like a real person, but the model sets the timing and voice; precise says the script word for word in the actor's fixed voice and ends cleanly, with less body movement; seedance makes a new person each take from the actor's description, not their photo (English, stock actors only, not format app) - language: en (English) | es (Spanish) | pt (Portuguese) | fr (French) | de (German) | it (Italian) | nl (Dutch) | pl (Polish) | tr (Turkish) | sv (Swedish) | id (Indonesian) | ro (Romanian) | ru (Russian) | uk (Ukrainian) | vi (Vietnamese) | ja (Japanese) | ko (Korean) | zh (Chinese (Simplified)) | hi (Hindi) | ar (Arabic) | th (Thai) (default en): the script, voice and captions. Other languages than English use the precise engine (the default for them; natural is refused) - ai_label: true | false (default true): a small "AI-generated" label in a top corner, in the ad's language, for places that require one on ads with AI actors (e.g. New York) - product_image_url: https link to a product photo, or for format app a screenshot of the app (optional; otherwise the page's own image) - script: exact words to say (optional; otherwise written from the page) - say_as: how to say tricky words, e.g. {"Hatoba": "Ha-TOE-ba"} (up to 5). Only the voice hears the respelling; captions keep the real spelling - music: none | upbeat | chill | warm | tech | luxe (default none): a music bed under the speech, quieter while the actor talks, made for the ad by an AI music model (Lyria 3), never a scraped track; 11 credits more. If it can't be made, the ad comes without it and those credits are refunded (refunded_credits) - lower_half_video: your video's key (from the video upload under Clips below, or imported from a link), with lower_half_rights: true to confirm you own it or have the rights to use it: B-roll or a screen recording fills the bottom half under the talking actor, captions on the seam (the split look); whole over a blurred fill, looped if shorter, its sound left out. Free - webhook_url: optional https URL that gets a POST when the ad finishes (see Webhooks) - template: offer_demo | problem_demo | letter | asmr | unboxing | before_after | three_reasons | comparison | founder (optional): a proven ad structure (GET /api/v1/catalog templates lists each with its format, captions, hook type and questions). Without a script, the one written follows it; draft it first with POST /api/v1/scripts (same template and answers) to read it free - answers: { question id: answer } for the template's questions (each optional, up to 200 characters); what's left out comes from the page Send `Idempotency-Key: ` to make retries safe: same key and body returns the original ad (200), a different body is 409. It works the same on translate, story steps, series, autopilots and posts (a retry returns what the first try made, charged and posted once); MCP tools that charge or post take it as request_id. expected_credits: the price you showed the user (optional). If it isn't the price now, nothing is charged and the answer is 409 price_changed. Works the same on shorts, clips, translate and story steps, and on the MCP tools that charge. Returns 201 with the ad object. Paid ads are checked before captions, at no cost to you: the words heard against the script, and the picture by an AI watcher (a warped face or hands, garbled writing or logos, the wrong product, a broken picture). A take that fails either gets one more take; one that doesn't say the script twice fails and is refunded. Free previews aren't checked. - GET https://creatorharbor.app/api/v1/ads/{id}?wait=25: the ad. `wait` long-polls up to 25 s until it finishes. status: queued | running (step: script | video | captions) | succeeded (hook, hook_type, script, video_url) | failed (error, refunded: true) hook_type: the kind of hook the script opens with, offer | new | price | problem | detail | question (null on ads from before it was recorded) - GET https://creatorharbor.app/api/v1/ads?limit=20: recent ads, newest first. - POST https://creatorharbor.app/api/v1/ads/batch: up to 20 variants to test against each other. The body of POST /api/v1/ads with lists for what to vary: actors (1 to 4), hooks (other opening lines, up to 4; they need a script), formats, engines; every actor × hook × format × engine is its own ad. The whole batch is checked and priced before any ad starts, with one balance check; expected_credits is the batch's total. ?dry_run=1 only prices it: { credits, takes, warnings }. Returns 201 { batch, ads: [...], takes, credits, warnings }. warnings say where variants look alike (hooks sharing most of their words, takes differing only in their words, the same actor and hook on several engines): Meta and TikTok treat near-duplicates as one ad, so vary actors and formats, not just the copy. Renders run one at a time per account. Idempotency-Key replays ad by ad (charged once). If the balance runs out partway, the ads already started stay: 201 with them and error. MCP: make_ads_batch (quote kind ads_batch). - GET https://creatorharbor.app/api/v1/ads/export?batch= (or ?ids=,, or nothing for the latest): up to 20 finished ads as one ZIP for Meta or TikTok Ads Manager: each ad's MP4s named CH___