The same engine you drive through the web UI, exposed as JSON over HTTPS. Build CI gates. Ship agents. Stop checking screenshots.
$ curl https://api.prior.run/api/v1/ads/compare -H "Authorization: Bearer $PR_KEY" -d '{"image_a": "…", "image_b": "…", …}' // running ··························· ← { "memo_id": "comp_b81b0b93", "status": "complete", "memo": { verdict: { winner: "A" }, confidence_level: "Moderate", verdict_headline: "We prefer Design A" … } }▍
https://api.prior.runhttp://localhost:8000Authorization: Bearer pr_live_••••••••••••Generate at /settings. Plaintext shown once.
Every product memo the web UI produces — verdict, reactions, quotes, audience preference, risk flags — in one JSON response.
/api/v1/design/review↳ single design01/api/v1/design/compare↳ two variants02Scroll-stop, hook clarity, brand recall. Platform-aware when you pass run_platform=meta | tiktok | google. Inspiration drafts bundle action items into one new image + body copy + headline + CTA — CTA is auto-snapped to the platform's allowed list. Creative-from-fieldnotes turns a focus-group room's consensus / tension / surprise notes into three archetype variants (quote · editorial · bold_graphic) — no memo required; the hook always lifts a verbatim phrase from the transcript.
/api/v1/ads/single↳ one creative01/api/v1/ads/compare↳ two head-to-head02/api/v1/ads/inspiration↳ draft from recs · single + compare03/api/v1/ads/inspiration/{id}↳ latest draft04/api/v1/ads/creative-from-fieldnotes↳ 3 variants from a focus-group's field notes05/api/v1/ads/creative-flatten↳ composite overlay onto a bare image06Synthetic personas walk a real website and produce the same memo shape as image audits. Pass mode=explore for free roam, flow for a guided funnel, or quiz for a verdict-pressure walk. Credits-charged per run. Long-running — the endpoint blocks until synthesis is complete (~5–10 min).
/api/v1/url/audit↳ walk one live URL · mode = explore | flow | quiz01/api/v1/url/compare↳ two URLs head-to-head · same mode enum02/api/v1/url/audit/cost↳ credit cost preview03/api/v1/url/compare/cost↳ credit cost preview04Mine the open web for what real people say about a brand. Asynchronous — POST returns a job_id immediately, poll until status='completed' (~15–25 min), then GET the corpus.
/api/v1/mood↳ kick off pipeline (returns job_id)01/api/v1/mood/jobs/{id}↳ poll job status02/api/v1/mood↳ list caller's reports03/api/v1/mood/{id}↳ full corpus JSON04/api/v1/mood/{id}/cohorts↳ list cohort_ids for spawn05/api/v1/mood/{id}/regenerate↳ fresh mine, same URL06/api/v1/mood/{id}/spawn-audiences↳ panel → synthetic audiences07Create returns a memo_id immediately. Poll until status = complete — typically 75–120s for ads, 90–180s for non-ads. GET /memo/{id} accepts either the internal memo UUID or the share_token returned at creation — both resolve to the same memo.
/api/v1/memo/{id}↳ full memo JSON · accepts memo UUID or share_token01/api/v1/ads/inspiration/{id}↳ latest ads inspiration draft02/api/v1/audience-templates↳ list built-in audience templates03/api/v1/audiences↳ list caller's saved custom audiences (id + name)04/api/v1/audiences/{id}↳ rename a saved custom audience05/api/v1/audiences/{id}↳ delete a saved custom audience06Follow-up Q&A with synthetic personas — either one persona on a memo, or the whole focus-group room for a saved custom audience. Capped per (memo, persona, viewer) and per audience to keep the panel honest.
/api/v1/persona/interview↳ ask one persona on a memo (capped per viewer)01/api/v1/persona/interview/history↳ transcript + remaining budget02/api/v1/persona/audience-panel↳ open focus-group room for a saved audience03/api/v1/persona/audience-ask↳ ask the whole room one question (fans out)04/api/v1/persona/audience-synthesis↳ transcript → themes + quotes + dissent0501curl -X POST https://api.prior.run/api/v1/ads/compare \02 -H "Authorization: Bearer $PRIORRUN_API_KEY" \03 -H "Content-Type: application/json" \04 -d '{05 "image_a": "https://cdn.brand.com/hero-a.png",06 "image_b": "https://cdn.brand.com/hero-b.png",07 "campaign_context": "Gen Z skincare, TikTok awareness.",08 "run_platform": "tiktok"09 }'
01{02 "memo_id": "comp_b81b0b93",03 "status": "pending",04 "url": "https://prior.run/ads/memo/comp_b81b0b93"05}
01curl https://api.prior.run/api/v1/memo/comp_b81b0b93 \02 -H "Authorization: Bearer $PRIORRUN_API_KEY"0304# → { memo_id, status: "complete", memo: { verdict,05# quotes, action_items, lens_highlights, ... } }
Images
Base64, data URL, or https. Max 10 MB.
Dedup
Duplicate or near-duplicate images rejected (400).
Text limits
campaign_context + hypothesis: 500. custom_audience: 2500. creative_name: 60. metric: 120. Sanitized for injection.
Audiences
Every memo endpoint (design/ads/url) accepts audience_template (built-in key) or custom_audience_id (saved audience UUID). custom_audience_id wins when both are set.
Live URLs
https only, max 2048 chars. url_a ≠ url_b for compare.
Mood
Async pipeline. POST returns job_id · poll /mood/jobs/{id} until status=completed.
Auth
Bearer pr_live_… . Keys are user-scoped.
Polling
Create returns memo_id · poll GET /memo/{id} until status=complete.
Rate limits
Per-key request rate and concurrent-job caps apply. Bursts → 429 with Retry-After. Upgrade plan to raise the ceiling.
Polling cadence
Poll GET /memo/{id} every ~5s. Stop at status=complete or status=failed. Don't re-submit on 504 — just re-poll.
Key lifecycle
Keys are user-scoped, shown in plaintext once at creation. Rotate or revoke any time at /settings. Old keys 401 instantly.
↳ Duplicate image submissions inside the same compare body are rejected with 400 — treat this as built-in idempotency for re-submits within a short window.
[ end of specification ]