{"name":"Marketing Agent Platform API","version":"0.1.0","description":"Brief in. Campaign out. Live. A 7-phase multi-agent orchestrator.","auth":{"type":"two-factor (api-key + user-id)","apiKey":{"header":"x-api-key","altHeader":"Authorization: Bearer <key>","purpose":"Proves the call comes from a trusted proxy. Stays server-side."},"userId":{"header":"x-user-id","purpose":"Opaque end-user identifier (e.g. Firebase UID). Used as the partition key for the per-user AgentRuntime. Trusted because the calling proxy verifies the user before forwarding.","format":"Printable ASCII, no whitespace, max 128 chars. Lazily creates a runtime on first sight."},"protected":["/api/campaigns","/api/campaigns/:id/pulse","/api/campaigns/:id/cancel","/api/agent/pause","/api/agent/resume","/api/agent/stats","/api/agent/pulse"],"public":["/","/docs","/api/docs"],"errors":{"400":"Missing or invalid X-User-Id.","401":"Missing or invalid X-API-Key.","403":"Resource (campaign) belongs to another user.","404":"Campaign id unknown (do not leak ownership).","409":"Campaign was cancelled mid-pipeline.","429":"Per-user queue full or rate limit exceeded."}},"endpoints":[{"method":"POST","path":"/api/campaigns","description":"Kick off a campaign. Runs the full 7-phase pipeline and returns a CampaignPackage.","body":{"brief":{"id":"string","audience":"string","product":"string","goals":"string[]","tone":"string","platforms":"Platform[]  // instagram | tiktok | x | facebook | linkedin","videoDurationSec":"number  // 1-5 (V1 ceiling)","providers":{"image":"ImageProviderId","video":"VideoProviderId"},"brandKitId":"string"},"brandKit":{"id":"string","logos":"BrandAsset[]","productImages":"BrandAsset[]","colorPalette":"string[]?","usageRules":"string?"}},"responses":{"200":"CampaignPackage (strategy, copy, images, videos, schedule, costSummary, disclaimers)","400":"{ error: string } — validation failed"}},{"method":"GET","path":"/api/campaigns/:id/pulse","description":"Server-Sent Events stream of PulseEvents for the given campaign. Replays history first, then streams live.","responses":{"200":"text/event-stream of PulseEvent JSON objects"}},{"method":"POST","path":"/api/campaigns/:id/cancel","description":"Abort a running campaign at the next phase boundary. Returns spent vs refunded USD.","responses":{"200":"{ cancelled: true, campaignId, spentUsd, refundUsd }","404":"{ error } — campaign is not currently running"}},{"method":"POST","path":"/api/agent/pause","description":"Pause the runtime. In-flight campaigns continue; new submissions queue until resume.","responses":{"200":"{ status: 'paused', queued: number }"}},{"method":"POST","path":"/api/agent/resume","description":"Resume the runtime and drain any queued campaigns sequentially.","responses":{"200":"{ status, drained: number }"}},{"method":"GET","path":"/api/agent/stats","description":"Runtime status, uptime, totals, success rate, total spend.","responses":{"200":"AgentStats { status, startedAt, uptimeMs, totalCampaigns, succeeded, failed, cancelled, queued, running, totalSpendUsd, successRate }"}},{"method":"GET","path":"/api/agent/pulse","description":"Unified Server-Sent Events stream of GlobalPulseEvents across all campaigns plus runtime lifecycle events. Each event includes campaignId (string | null).","responses":{"200":"text/event-stream of GlobalPulseEvent JSON objects"}},{"method":"GET","path":"/api/docs","description":"This document."}],"pulseEventTypes":["agent.started","agent.progress","agent.completed","agent.failed","milestone.reached","asset.produced","cost.incurred","runtime.paused","runtime.resumed","runtime.error","runtime.queued","runtime.dequeued","campaign.started","campaign.completed","campaign.failed","campaign.cancelled"],"limits":{"perUserQueueMax":20,"globalConcurrencyMax":32,"perUserRatePerHour":60,"note":"Configurable via PER_USER_QUEUE_MAX / GLOBAL_CONCURRENCY_MAX / PER_USER_RATE_PER_HOUR env vars."},"providers":{"image":[{"id":"openai/gpt-image-2","gatewayModel":"openai/gpt-image-2","capabilities":{"acceptsReferenceImages":true,"maxResolution":2048,"aspectRatios":["1:1","16:9","9:16"]},"pricing":{"perImageUsd1024":0.04}},{"id":"google/gemini-2.5-flash-image","gatewayModel":"google/gemini-2.5-flash-image","capabilities":{"acceptsReferenceImages":true,"maxResolution":1024,"aspectRatios":["1:1","16:9","9:16","4:3","3:4"]},"pricing":{"perImageUsd1024":0.039}},{"id":"google/gemini-3.1-flash-image","gatewayModel":"google/gemini-3.1-flash-image-preview","capabilities":{"acceptsReferenceImages":true,"maxResolution":4096,"aspectRatios":["1:1","16:9","9:16","4:3","3:4"]},"pricing":{"perImageUsd1024":0.067}},{"id":"google/gemini-3-pro-image","gatewayModel":"google/gemini-3-pro-image-preview","capabilities":{"acceptsReferenceImages":true,"maxResolution":4096,"aspectRatios":["1:1","16:9","9:16","4:3","3:4"]},"pricing":{"perImageUsd1024":0.134}},{"id":"google/imagen-4-fast","gatewayModel":"google/imagen-4.0-fast-generate-001","capabilities":{"acceptsReferenceImages":false,"maxResolution":2048,"aspectRatios":["1:1","16:9","9:16"]},"pricing":{"perImageUsd1024":0.02}},{"id":"google/imagen-4-standard","gatewayModel":"google/imagen-4.0-generate-001","capabilities":{"acceptsReferenceImages":false,"maxResolution":2048,"aspectRatios":["1:1","16:9","9:16"]},"pricing":{"perImageUsd1024":0.04}},{"id":"google/imagen-4-ultra","gatewayModel":"google/imagen-4.0-ultra-generate-001","capabilities":{"acceptsReferenceImages":false,"maxResolution":2048,"aspectRatios":["1:1","16:9","9:16"]},"pricing":{"perImageUsd1024":0.06}}],"video":[{"id":"google/veo-3.1-lite","gatewayModel":"google/veo-3.1-lite-generate-preview","capabilities":{"acceptsReferenceImages":true,"maxResolution":1080,"aspectRatios":["16:9","9:16"],"maxVideoSeconds":5,"audio":true},"pricing":{"perSecondUsd720":0.05,"perSecondUsd1080":0.08,"audio":true}},{"id":"google/veo-3.1-fast","gatewayModel":"google/veo-3.1-fast-generate-preview","capabilities":{"acceptsReferenceImages":true,"maxResolution":2160,"aspectRatios":["16:9","9:16"],"maxVideoSeconds":5,"audio":true},"pricing":{"perSecondUsd720":0.1,"perSecondUsd1080":0.12,"perSecondUsd4k":0.3,"audio":true}},{"id":"google/veo-3.1-standard","gatewayModel":"google/veo-3.1-generate-preview","capabilities":{"acceptsReferenceImages":true,"maxResolution":2160,"aspectRatios":["16:9","9:16"],"maxVideoSeconds":5,"audio":true},"pricing":{"perSecondUsd720":0.4,"perSecondUsd1080":0.4,"perSecondUsd4k":0.6,"audio":true}}]},"v1Limitations":["Video duration capped at 5 seconds.","Logos passed as references may distort in generated video frames (no post-gen overlay in V1).","Linear pipeline — no revision/retry loops.","Fully autonomous — no human-in-the-loop checkpoints.","One campaign in flight per user (additional submissions queue).","In-memory state in V1 — Postgres persistence ships in V2."],"docs":{"vision":"/docs/01-vision.md","architecture":"/docs/02-architecture.md","humanReadable":"/docs"}}