Gather Launch API

What this is · Get an API key · Send a brief · The brief · What "clear" means · The clarification loop · Check on a launch · What happens after ready · Bring your own site · Guidance and playbooks · Errors · For Claude sessions calling this API

What this is

Gather Launch takes a brief for a new brand test (like schol or Pinch) and runs it end to end: domain, concept pages, waitlist and Meta sign-up tracking, ads, campaigns, 2-hourly reports, auto-pause and the end-of-test report.

It does about 80% of the work itself. The rest needs a person (creating the Facebook Page, approving the budget, ticking Meta's AI info box), so it queues those tasks for Delbert and carries on when he marks them done.

You send a brief. The service checks it before anything is built. If something is missing or unclear you get questions back; answer them and it checks again. Once the brief is clear it is locked and queued. Nothing is bought, published or spent until Delbert approves the launch.

Get an API key

Send a brief

curl -s -X POST https://gather-launch.vercel.app/api/launches \
  -H "Authorization: Bearer $GATHER_LAUNCH_KEY" \
  -H "Content-Type: application/json" \
  --data @brief.json

The reply is always 202 with the launch id and one of three statuses: needs_clarification (with questions), ready (the brief is locked and queued), or checking (the checker is retrying; poll the launch in a minute).

The brief

FieldTypeRules
brandstringThe brand name used on pages, ads and the Facebook Page.
domain_ideasstring[]1 to 6 domains like getschol.com. The worker buys the first available one, after Delbert approves.
marketstringTwo-letter code. Supported: IN (India), US (United States).
conceptsobject[]1 to 4 concepts. Each one gets its own page, ads and ad set, so they can be compared.
concepts[].slugstringLower-case letters, digits and dashes. Becomes the page path, e.g. /housing.
concepts[].problemstringWho has what problem, in what situation. One sentence.
concepts[].promisestringWhat the product does for them, concretely. No guarantees of outcomes or deadlines.
concepts[].proof{text, source}One real stat or quote, and where it comes from (a link, or a named survey with size and date).
concepts[].categorystring, optionalRegulated area: none, housing, finance, immigration, health, employment. If you leave it out, the checker guesses and asks you to confirm.
budgetperday_usdnumberTotal daily ad budget, 5 to 200. Split evenly across concepts and set as a hard Meta spend cap.
test_daysinteger3 to 21. Every campaign is paused at the end.
reviewersstring[]Who signs off the copy before launch, not counting the owner (e.g. Abhi, Emily).
ownerstringWork email of the person who owns the test and gets the report.
notesstring, optionalAnything else the worker or Delbert should know.
siteobject, optionalWho builds the pages. Leave it out and we build them on the shared concept site. { "mode": "own", "urls": { "<concept-slug>": "https://..." } } if the teammate builds their own (see Bring your own site). With your own site, domain_ideas can be left out.

A full example (this brief passes every check as written):

{
  "brand": "schol",
  "domain_ideas": ["getschol.com", "schol.app"],
  "market": "IN",
  "concepts": [
    {
      "slug": "early-number",
      "problem": "Indian students flying to the US for a master's can't get a US phone number until they land, so banks and landlords can't reach them.",
      "promise": "A US number that works in India before you fly, set up in two minutes.",
      "proof": { "text": "61% of students we surveyed missed a call from a US bank or landlord in their first week.", "source": "Schol survey of 212 Indian students, October 2026" },
      "category": "none"
    },
    {
      "slug": "housing",
      "problem": "Indian students arriving in the US have no credit history or SSN, so landlords turn down their rental applications.",
      "promise": "We help you put together a complete US rental application before you land.",
      "proof": { "text": "58% of students we surveyed were asked for a US credit score they did not have.", "source": "Schol survey of 212 Indian students, October 2026" },
      "category": "housing"
    }
  ],
  "budget_per_day_usd": 40,
  "test_days": 7,
  "reviewers": ["Abhi", "Emily"],
  "owner": "delbert@gatherat.ai",
  "notes": "Same audience as the October schol test."
}

A brief that can't be read at all (wrong types, no concepts, more than four, bad or duplicate slugs) gets a 400 with an issues list instead of questions. Fix those and send it again.

What "clear" means

Every brief goes through three layers before the Mac worker can see it.

The brief is clear when every check passes or you have answered "keep it" to the ones that allow it. Rewriting a field clears any "keep it" on that field, so the new text is checked again.

The clarification loop

A needs_clarification reply looks like this:

{
  "id": "jd78e9360v8vt4k1kmrnyqyakn8gagqm",
  "status": "needs_clarification",
  "questions": [
    {
      "id": "housing.promise.guarantee",
      "field": "concepts[1].promise",
      "question": "Concept \"housing\": this promise makes a guarantee (\"within 15 days\"): \"We get your lease approved, completed within 15 days.\". Rewrite it without promising an outcome or a deadline.",
      "why": "We can't keep guarantees in a fake-door test, and Meta rejects ads that over-promise."
    },
    {
      "id": "housing.category",
      "field": "concepts[1].category",
      "question": "Concept \"housing\": which regulated area is this in, if any? Our best guess is \"housing\".",
      "options": ["none", "housing", "finance", "immigration", "health", "employment"],
      "why": "Housing, finance and employment need a Meta special ad category and their own campaign; immigration and health need extra care in the copy."
    }
  ]
}

Answer any or all of them:

curl -s -X POST https://gather-launch.vercel.app/api/launches/<id>/answers \
  -H "Authorization: Bearer $GATHER_LAUNCH_KEY" \
  -H "Content-Type: application/json" \
  --data '{ "answers": { "housing.promise.guarantee": "We help you put together a complete US rental application before you land.", "housing.category": "housing" } }'

The reply has the same shape: more questions, or ready. If an answer couldn't be used it is listed in answer_errors (unknown id, not one of the options, not a number) and the question is asked again. When two questions point at the same field, the first rewrite wins and the new text is checked again.

Check on a launch

curl -s https://gather-launch.vercel.app/api/launches/<id> -H "Authorization: Bearer $GATHER_LAUNCH_KEY"

Returns status, the brief, open questions, the worker's steps, waiting_on_delbert (open human tasks), results (domain, pixel, campaign ids, report) and recent history. People can see the same thing at https://gather-launch.vercel.app/launches/<id>. Both work when Delbert's Mac is off.

StatusMeaning
checkingThe brief is being checked, or the judge was unreachable and is being retried (30 s, 2 min, 10 min).
needs_clarificationQuestions are waiting for you.
readyAll clear. The brief is locked and can't change.
queuedWaiting for the Mac worker. A brief sent while the Mac sleeps waits here and is never lost.
runningThe worker is building: domain, pages, tracking, creative, paused campaigns.
waitingondelbertBlocked on a task only a person can do. See waiting_on_delbert.
awaitinglaunchapprovalEverything is built and paused. Delbert approves the budget and copy before anything goes live.
liveAds are running. Reports every 2 hours; auto-pause at the budget cap and at the end of the test.
doneThe test ended and the report names the winning concept.
failedStopped. fail_reason says why.
cancelledCancelled from the status page.

What happens after ready

Tasks only a person can do are queued for Delbert at /tasks, with a notification in Claude Code: create the Facebook Page and Instagram account, confirm Meta domain verification, tick AI info on each ad, CAPTCHAs, a card on a new ad account, and the judgment calls (copy sign-off, budget, regulated areas, picking the winner).

Bring your own site

Teammates can build the concept pages themselves, on any stack. gather-launch still does the counting and the Meta Leads, so nobody handles a Meta token and the numbers match every other launch.

<!-- In <head> of every concept page -->
<script src="https://gather-launch.vercel.app/t.js" data-brand="<brand-slug>" defer></script>

<!-- The sign-up form: mark it and keep normal email/phone inputs -->
<form data-gather-lead>
  <input type="email" name="email" required>
  <input type="tel" name="phone">            <!-- optional -->
  <button type="submit">Join the waitlist</button>
</form>
<button data-gather-cta="hero">Join the waitlist</button>

<!-- Phone-only forms work too: just the type="tel" input -->

<!-- Or from your own code, after your submit succeeds -->
<script>
  await GatherLaunch.lead({ email, phone }); // resolves {ok, eventId}
</script>

Guidance and playbooks

Every response carries a guidance block: the rules behind each open question, and once the brief is ready the playbooks for what comes next (copy rules, and for your own site the site and tracking rules). Each rule says why, from what we learned on Pinch and schol.

The full playbooks need no key: GET https://gather-launch.vercel.app/api/playbooks lists them, GET https://gather-launch.vercel.app/api/playbooks/<topic> returns one, /api/playbooks/all returns everything. Read them before building pages or creative.

Writing the brief (brief). A brand test compares 1 to 4 concepts. Each concept is one problem, one promise and one piece of real proof.

Copy rules (pages and ads) (copy). Honest, specific, and safe for Meta review. These apply to every line a visitor or reviewer sees.

Regulated areas (regulated). Housing, finance and employment are Meta special ad categories; immigration and health are sensitive.

Tracking and Meta Leads (tracking). Count leads ourselves, send Meta a deduplicated Lead from browser and server, and never let a test count.

Bringing your own site (own_site). Build the pages however you like (Next, Framer, Webflow, plain HTML). Add one script tag and mark the sign-up form; gather-launch does the counting and the Meta Leads.

Ad creative (creative). Static ads in 4:5 and 9:16 per concept; video ads in their own ad sets with their own budget.

Campaigns (campaigns). Built PAUSED with a hard spend cap; launched only on Delbert's approval.

Reporting (reporting). Every 2 hours to the Gather Dashboard, using the standard metric names.

Errors

CodeMeaning
400The brief or the answers body can't be read. issues or error says what to fix.
401Missing, unknown or revoked API key.
404No launch with that id.
409The launch isn't waiting for answers (it is already locked, or still checking).
413Body over 64 KB.

For Claude sessions calling this API

If you are a Claude session launching a test for someone, follow this loop. The person you are working with is the source of truth for the copy; you are the go-between.

# The whole loop, by hand
ID=$(curl -s -X POST https://gather-launch.vercel.app/api/launches -H "Authorization: Bearer $GATHER_LAUNCH_KEY" \
  -H "Content-Type: application/json" --data @brief.json | jq -r .id)
curl -s https://gather-launch.vercel.app/api/launches/$ID -H "Authorization: Bearer $GATHER_LAUNCH_KEY" | jq '{status, questions}'
curl -s -X POST https://gather-launch.vercel.app/api/launches/$ID/answers -H "Authorization: Bearer $GATHER_LAUNCH_KEY" \
  -H "Content-Type: application/json" --data '{"answers": {"<question id>": "<answer>"}}'