Every API here is available over the APIs.io API and to AI agents over MCP.
{"openapi":"3.1.0","info":{"title":"AfterLaunch public API","version":"1.0.0","description":"AfterLaunch is the agentic growth engine: continuous measurement of how a product gets found, kept as a record and ranked into briefed growth moves. This API is access to one AfterLaunch product run: read the ranked Feed of prepared growth moves, the automated loops and their autonomy, and drafted outputs; act on moves (ship, skip, edit the draft) and approve a drafted output for dispatch. Administrators may run loops on demand and configure loop autonomy, cadence and scans. Authenticate every request with \"Authorization: Bearer al_...\" (an API key bound to one enrollment). Reads need the read scope; acting on a move and minting a checkout need act; the metered pulls need write; administrator configuration changes need config; tracked questions retain their existing config scope and customer entitlement. A key carrying write satisfies act. Metered actions (run, approve) honour per-tenant daily and monthly spend caps and, for runs, a REQUIRED Idempotency-Key header: reusing a key replays the original result instead of spending again."},"servers":[{"url":"https://afterlaunch.io"}],"components":{"schemas":{"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}},"required":["code","message"]}},"required":["error"]}},"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"AfterLaunch API key, format al_<48 hex chars>."}}},"security":[{"apiKey":[]}],"paths":{"/api/v1/content/calendar":{"get":{"operationId":"getContentCalendar","summary":"Read this product run's calendar, up to 100 saved source drafts and their current canonical Feed state. Requires read. Honour queue_position and needs_data. channel_state is a stored projection; check calendar_sync and linkage before acting. x_production_enabled is the existing twitter_thread switch. Read coverage before planning: unknown or incomplete history is not an empty review pile. No generation or spend.","responses":{"200":{"description":"Up to 200 calendar pieces, ordered by queue position then recency, and up to 100 saved records ordered by source output update time.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","required":["enrollment_id","timezone","calendar","drafts","x_production_enabled","can_record_drafts","coverage"],"properties":{"enrollment_id":{"type":"string","format":"uuid"},"timezone":{"type":"string"},"calendar":{"type":"array","maxItems":200,"items":{"type":"object","required":["id","title","angle","kind","channels","channel_state","evidence","status","queue_position","link","notes","needs_data","updated_at"],"properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"angle":{"type":["string","null"]},"kind":{"type":"string","enum":["opinion","educational","amplify"]},"channels":{"type":"array","items":{"type":"string"}},"channel_state":{"type":"object","description":"Stored per-channel projection, including status and output_id when present. For linked content, the canonical move and calendar_sync expose lifecycle drift. Other channels are preserved."},"evidence":{"description":"The existing JSON evidence for this piece, preserved without rewriting."},"status":{"type":"string","enum":["pool","queued","done","dismissed"]},"queue_position":{"type":["integer","null"]},"link":{"type":["string","null"]},"notes":{"type":["string","null"]},"needs_data":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"}}}},"coverage":{"type":"object","required":["ideas","drafts"],"properties":{"ideas":{"type":"object","required":["returned","total","complete"],"properties":{"returned":{"type":"integer","minimum":0},"total":{"type":["integer","null"],"minimum":0},"complete":{"type":"boolean","description":"Exact response count equals all returned, decoded records. False for unknown counts or truncation. This is a point-in-time read, not a reservation."}}},"drafts":{"type":"object","required":["returned","total","complete"],"properties":{"returned":{"type":"integer","minimum":0},"total":{"type":["integer","null"],"minimum":0},"complete":{"type":"boolean","description":"Exact response count equals all returned, decoded records. False for unknown counts or truncation. This is a point-in-time read, not a reservation."}}}}},"drafts":{"type":"array","maxItems":100,"items":{"type":"object","required":["output_id","idea_id","run_key","channel","title","source_url","why","claim_ids","claims","output_status","status","source_draft","move","prepared_result","legacy_publication_report","drafts_withheld","drafts_match","linkage","linkage_reason","calendar_sync","updated_at"],"properties":{"output_id":{"type":"string","format":"uuid"},"idea_id":{"type":"string","format":"uuid"},"run_key":{"type":"string"},"channel":{"const":"x"},"title":{"type":"string"},"source_url":{"type":["string","null"],"description":"Source evidence; also the exact destination for a classified legacy reply."},"why":{"type":"string"},"claim_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"claims":{"type":"array","items":{"type":"object","required":["id","text","number","caveat"],"properties":{"id":{"type":"string","format":"uuid"},"text":{"type":"string"},"number":{"type":"string"},"caveat":{"type":"string"}}}},"output_status":{"type":"string","description":"Raw source output status. posted alone proves neither founder confirmation nor published words."},"status":{"type":"string","description":"Current canonical move status when linked, otherwise raw output status. Prepared attempt content never implies shipped."},"source_draft":{"type":["object","null"],"properties":{"storage":{"enum":["candidate","output"]},"candidate_id":{"type":["string","null"]},"text":{"type":"string"}},"description":"Current source candidate, or output fallback. Null when drafts are withheld. Not published words."},"move":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"identity_key":{"type":["string","null"]},"source_key":{"type":"string"},"source_output_id":{"type":"string","format":"uuid"},"action_kind":{"type":["string","null"]},"target":{"type":["string","null"]},"status":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"draft_content":{"type":["string","null"]},"draft_kind":{"type":["string","null"],"enum":["full_draft","brief",null]}},"description":"Ownership-bound Feed read, carrying the actual move id. A collection app_url does not open the move in focus."},"prepared_result":{"type":["object","null"],"description":"Current attempt from readPreparedMoveResult, including job/attempt identity, state, prepared_content and recorded published_url. Preparation is not publication; prepared_content is not reported final copy. Private material is withheld at the shared tier boundary."},"legacy_publication_report":{"type":["object","null"],"properties":{"basis":{"const":"human_reported"},"text":{"type":"string"},"url":{"type":"string"}},"description":"Only the old pilot explicit human_reported confirmation and its stored words/link. Never reconstructed from output status or a draft."},"drafts_withheld":{"type":"boolean"},"drafts_match":{"type":["boolean","null"]},"linkage":{"enum":["linked","incomplete","legacy_terminal"]},"linkage_reason":{"type":["string","null"]},"calendar_sync":{"enum":["linked","missing","different_output","lifecycle_differs"],"description":"Comparison with stored channel_state. The move lifecycle is authoritative; this reader does not silently repair completion projections."},"updated_at":{"type":"string","format":"date-time","description":"Source output update time. The move and attempt carry their own timestamps."}}}},"x_production_enabled":{"type":"boolean"},"can_record_drafts":{"type":"boolean","description":"True when access permits filing and X production is disabled or has not been configured. The first draft write can create disabled storage; this read creates nothing. This is not an OAuth connection check."}}},"meta":{"type":"object","properties":{"enrollment_id":{"type":"string","format":"uuid"},"generated_at":{"type":"string","format":"date-time"}},"required":["enrollment_id","generated_at"]}},"required":["data","meta"]}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key does not carry the scope this endpoint requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The key is not bound to the current product run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-key rate limit exceeded. Honour Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"recordContent","summary":"File a research idea, original X post or append-only research outcome. Research records preserve the original question, evidence, hold and lifecycle. The caller supplies the conclusion; it is not automatic verification or permission to draft. Same-key replays preserve receipts; changed results or stale new writes conflict. Research is visible in Memory at /app/knowledge-base?open=research (requires act and current draft access). No generation, spend, posting or lifecycle decision. Stable run_key fingerprints preserve the original request. New drafts require action_kind social_post, one existing idea_id or source_idea, and disabled product X production. If no X loop exists, the first authorised draft write creates a disabled storage row without activating generation or posting. Canonical claim caveats travel with the draft. Filing creates an output, materialises a candidate only if absent, and claims a pending Feed move under the output UUID. Replays preserve edits and terminal history. New drafts are original posts. Explicit adopt_legacy recovers exact saved requests as original posts or replies with their saved X status destination. It refuses changed or unclassified actioned work and retains candidate edits. Review and completion are not part of this endpoint.","requestBody":{"required":true,"content":{"application/json":{"schema":{"oneOf":[{"type":"object","additionalProperties":false,"required":["operation","run_key","source_idea"],"properties":{"operation":{"const":"idea"},"run_key":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[a-zA-Z0-9:_./-]+$"},"source_idea":{"type":"object","additionalProperties":false,"required":["title","needs_data"],"properties":{"title":{"type":"string","minLength":1,"maxLength":300,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"angle":{"type":"string","minLength":1,"maxLength":3000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"link":{"type":"string","format":"uri","maxLength":2048,"pattern":"^https?://","description":"An HTTP or HTTPS address without embedded credentials."},"needs_data":{"type":"boolean","description":"True when this idea needs evidence before publication copy can be prepared."},"channels":{"type":"array","minItems":1,"maxItems":4,"uniqueItems":true,"items":{"enum":["x","linkedin","article","seo"]},"description":"Where the piece should go out. Omitted means x."},"kind":{"enum":["opinion","educational","amplify"],"description":"Omitted means the calendar default, educational."},"score":{"type":"number","minimum":0,"maximum":10,"description":"Priority from 0 to 10, at most two decimals. Omitted means unscored."},"final_text":{"type":"object","additionalProperties":false,"required":["channel","text"],"properties":{"channel":{"enum":["x","linkedin"],"description":"One of this idea's channels."},"text":{"type":"string","minLength":1,"maxLength":20000,"pattern":"^[^\\u2014]*\\S[^\\u2014]*$","description":"The finished post, kept byte for byte (not trimmed). Em dashes are rejected."}},"description":"A post the owner has already finished. The morning slot delivers it exactly as written, with no rewrite. Text AfterLaunch would alter or block is refused."},"desk":{"type":"object","additionalProperties":false,"required":["kind"],"properties":{"kind":{"enum":["post","reply","task","decision","read"],"description":"A post or reply needs final_text and takes its channel from it. A task has no channel; its words are the title. A decision or a read is a thing that needs the owner and is not a post: its words are the title, it takes no slot, and it stays open until ticked."},"slot_at":{"type":"string","format":"date-time","description":"The slot to file it into. Present means the item is filed queued; omitted means the backlog."},"image":{"type":"string","minLength":1,"maxLength":2000,"description":"One line: which image to attach, or its address."},"first_reply":{"type":"string","minLength":1,"maxLength":2000,"description":"X: the reply that carries the link, posted under the original."},"target_url":{"type":"string","format":"uri","maxLength":2048,"pattern":"^https?://","description":"A reply: the thread it answers. A decision or a read: the link it opens."},"due_on":{"type":"string","format":"date","description":"A decision or a read only: the local date it is due on. Omitted means undated."},"why":{"type":"string","minLength":1,"maxLength":200,"description":"A decision or a read only: one line on why it matters."},"step":{"type":"string","minLength":1,"maxLength":200,"description":"A decision or a read only: the step that is the owner's."},"source":{"type":"string","minLength":1,"maxLength":80,"description":"A decision or a read only: who raised it."},"note":{"type":"string","minLength":1,"maxLength":200,"description":"Any kind: one line the owner reads before posting, a \"Your call: ...\" included. Shown under the row on the desk."},"venue":{"enum":["hn","producthunt","reddit","email"],"description":"A task or a decision only: where it goes out when it is not X or LinkedIn. It picks the row's mark; a task or a decision without one is not drawn on the desk."}},"description":"An item for the Posting Desk, which the owner posts by hand. A desk item is kept out of the morning slot, so it goes out once."},"series":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120,"description":"Matched among running series, case and spacing aside."},"kind":{"enum":["major_drop","minor_drop","posts","free_tool","launch","announcement","experiment_writeup"],"description":"Used only when the series is created. Omitted means posts."},"starts_on":{"type":"string","format":"date","description":"Used only when created. Omitted means the desk slot's date, else today."},"ends_on":{"type":"string","format":"date","description":"Used only when created. Omitted means open-ended."},"why":{"type":"string","minLength":1,"maxLength":200,"description":"One line on why the series exists. Required to create one."}},"description":"The run of items this one belongs to (a drop, a run of posts). Matched by name, else created; the idea is filed into it."}}}}},{"type":"object","additionalProperties":false,"required":["operation","run_key","title","text","channel","why"],"properties":{"operation":{"const":"draft"},"run_key":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[a-zA-Z0-9:_./-]+$"},"idea_id":{"type":"string","format":"uuid"},"source_idea":{"type":"object","additionalProperties":false,"required":["title","needs_data"],"properties":{"title":{"type":"string","minLength":1,"maxLength":300,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"angle":{"type":"string","minLength":1,"maxLength":3000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"link":{"type":"string","format":"uri","maxLength":2048,"pattern":"^https?://","description":"An HTTP or HTTPS address without embedded credentials."},"needs_data":{"type":"boolean","description":"True when this idea needs evidence before publication copy can be prepared."}}},"title":{"type":"string","minLength":1,"maxLength":300,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"text":{"type":"string","minLength":1,"maxLength":20000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"channel":{"const":"x"},"action_kind":{"const":"social_post","description":"Required for new drafts. Omission is accepted only to recognise an unchanged old-pilot replay; unclassified legacy pending records are not adopted as posts."},"source_url":{"type":"string","format":"uri","maxLength":2048,"pattern":"^https?://","description":"Source evidence for new original posts. An explicit legacy reply adoption retains this exact X status URL as its destination."},"adopt_legacy":{"type":"object","additionalProperties":false,"required":["output_id","action_kind"],"properties":{"output_id":{"type":"string","format":"uuid"},"action_kind":{"enum":["social_post","community_reply"]}},"description":"Explicit recovery of an existing exact replay, never new content. Omit top-level action_kind and restate the original request. Classification preserves output, idea, original words and any existing move."},"why":{"type":"string","minLength":1,"maxLength":5000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"claim_ids":{"type":"array","maxItems":20,"items":{"type":"string","format":"uuid"},"default":[],"description":"Canonical usable claim IDs from get_claims. Missing, held or malformed claims are refused. Their stored caveats travel with the draft."}},"oneOf":[{"required":["idea_id"],"not":{"required":["source_idea"]}},{"required":["source_idea"],"not":{"required":["idea_id"]}}]},{"type":"object","additionalProperties":false,"required":["operation","run_key","idea_id","expected_updated_at","research"],"properties":{"operation":{"const":"research"},"run_key":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[a-zA-Z0-9:_./-]+$"},"idea_id":{"type":"string","format":"uuid"},"expected_updated_at":{"type":"string","format":"date-time","description":"Pass the calendar value unchanged for a new result; exact replays do not need a fresh timestamp."},"research":{"type":"object","additionalProperties":false,"required":["outcome","summary","method","limitations","sources"],"properties":{"outcome":{"type":"string","enum":["supported","not_supported","inconclusive"]},"summary":{"type":"string","minLength":1,"maxLength":5000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"method":{"type":"string","minLength":1,"maxLength":5000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"limitations":{"type":"string","minLength":1,"maxLength":5000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"sources":{"type":"array","maxItems":50,"items":{"type":"object","additionalProperties":false,"required":["title","url","observed_at"],"properties":{"title":{"type":"string","minLength":1,"maxLength":300,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"url":{"type":"string","format":"uri","maxLength":2048,"pattern":"^https?://","description":"An HTTP or HTTPS address without embedded credentials."},"observed_at":{"type":"string","format":"date-time"}}}}}}}}]}}}},"responses":{"200":{"description":"The current linked record or idea receipt. A legacy terminal replay returns its history without inventing a pending move. No receipt implies posting or focused browser visibility.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"oneOf":[{"type":"object","required":["output_id","idea_id","run_key","channel","title","source_url","why","claim_ids","claims","output_status","status","source_draft","move","prepared_result","legacy_publication_report","drafts_withheld","drafts_match","linkage","linkage_reason","calendar_sync","updated_at"],"properties":{"output_id":{"type":"string","format":"uuid"},"idea_id":{"type":"string","format":"uuid"},"run_key":{"type":"string"},"channel":{"const":"x"},"title":{"type":"string"},"source_url":{"type":["string","null"],"description":"Source evidence; also the exact destination for a classified legacy reply."},"why":{"type":"string"},"claim_ids":{"type":"array","items":{"type":"string","format":"uuid"}},"claims":{"type":"array","items":{"type":"object","required":["id","text","number","caveat"],"properties":{"id":{"type":"string","format":"uuid"},"text":{"type":"string"},"number":{"type":"string"},"caveat":{"type":"string"}}}},"output_status":{"type":"string","description":"Raw source output status. posted alone proves neither founder confirmation nor published words."},"status":{"type":"string","description":"Current canonical move status when linked, otherwise raw output status. Prepared attempt content never implies shipped."},"source_draft":{"type":["object","null"],"properties":{"storage":{"enum":["candidate","output"]},"candidate_id":{"type":["string","null"]},"text":{"type":"string"}},"description":"Current source candidate, or output fallback. Null when drafts are withheld. Not published words."},"move":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"identity_key":{"type":["string","null"]},"source_key":{"type":"string"},"source_output_id":{"type":"string","format":"uuid"},"action_kind":{"type":["string","null"]},"target":{"type":["string","null"]},"status":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"draft_content":{"type":["string","null"]},"draft_kind":{"type":["string","null"],"enum":["full_draft","brief",null]}},"description":"Ownership-bound Feed read, carrying the actual move id. A collection app_url does not open the move in focus."},"prepared_result":{"type":["object","null"],"description":"Current attempt from readPreparedMoveResult, including job/attempt identity, state, prepared_content and recorded published_url. Preparation is not publication; prepared_content is not reported final copy. Private material is withheld at the shared tier boundary."},"legacy_publication_report":{"type":["object","null"],"properties":{"basis":{"const":"human_reported"},"text":{"type":"string"},"url":{"type":"string"}},"description":"Only the old pilot explicit human_reported confirmation and its stored words/link. Never reconstructed from output status or a draft."},"drafts_withheld":{"type":"boolean"},"drafts_match":{"type":["boolean","null"]},"linkage":{"enum":["linked","incomplete","legacy_terminal"]},"linkage_reason":{"type":["string","null"]},"calendar_sync":{"enum":["linked","missing","different_output","lifecycle_differs"],"description":"Comparison with stored channel_state. The move lifecycle is authoritative; this reader does not silently repair completion projections."},"updated_at":{"type":"string","format":"date-time","description":"Source output update time. The move and attempt carry their own timestamps."}}},{"type":"object","required":["idea_id","title","angle","link","needs_data","channels","kind","score","status"],"properties":{"idea_id":{"type":"string","format":"uuid"},"title":{"type":"string"},"angle":{"type":["string","null"]},"link":{"type":["string","null"]},"needs_data":{"type":"boolean"},"channels":{"type":"array","items":{"type":"string"}},"kind":{"type":"string","enum":["opinion","educational","amplify"]},"score":{"type":["number","null"]},"status":{"type":"string","enum":["pool","queued","done","dismissed"],"description":"A new idea is pool. An idempotent replay returns its current state without reopening it."}}},{"type":"object","required":["idea_id","research","needs_data","updated_at","app_url"],"properties":{"idea_id":{"type":"string","format":"uuid"},"research":{"type":"object","additionalProperties":false,"required":["outcome","summary","method","limitations","sources","run_key","request_hash","recorded_at"],"properties":{"outcome":{"type":"string","enum":["supported","not_supported","inconclusive"]},"summary":{"type":"string","minLength":1,"maxLength":5000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"method":{"type":"string","minLength":1,"maxLength":5000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"limitations":{"type":"string","minLength":1,"maxLength":5000,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"sources":{"type":"array","maxItems":50,"items":{"type":"object","additionalProperties":false,"required":["title","url","observed_at"],"properties":{"title":{"type":"string","minLength":1,"maxLength":300,"pattern":"^(?!\\s*$)[^\\u2014]*$","description":"Non-empty prose after trimming. Em dashes are rejected."},"url":{"type":"string","format":"uri","maxLength":2048,"pattern":"^https?://","description":"An HTTP or HTTPS address without embedded credentials."},"observed_at":{"type":"string","format":"date-time"}}}},"run_key":{"type":"string","minLength":1,"maxLength":160,"pattern":"^[a-zA-Z0-9:_./-]+$"},"request_hash":{"type":"string","pattern":"^[a-f0-9]{64}$"},"recorded_at":{"type":"string","format":"date-time"}}},"needs_data":{"type":"boolean"},"updated_at":{"type":"string","format":"date-time"},"app_url":{"type":"string"}}}]},"meta":{"type":"object","properties":{"enrollment_id":{"type":"string","format":"uuid"},"generated_at":{"type":"string","format":"date-time"}},"required":["enrollment_id","generated_at"]}},"required":["data","meta"]}}}},"400":{"description":"Invalid operation, unknown field, value outside its bounds, wrong idea selection, or an absent, held or malformed canonical claim.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key does not carry the scope this endpoint requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The key is not bound to the current product run, or the requested idea/output does not belong to it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Changed replay, ineligible idea, enabled product X production, or incomplete candidate/move/calendar linkage. When already saved, the error includes retained_output_id. Read the calendar before retrying the same run_key; no retained output is deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-key rate limit exceeded. Honour Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The X production state could not be confirmed. Missing storage is created disabled only by an authorised draft write. Idea and research recording do not require that storage.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/content/experiments":{"get":{"operationId":"getExperiments","summary":"Read the growth content experiments already run for this product run, newest first by ran_at. Requires read. Each result is one observation with its stated scope, not a rate. Read-only: this never runs, claims or pays for an experiment. available is false while the experiment records cannot be read yet, and the empty list then means unread, not none.","parameters":[{"name":"idea_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Only experiments run for this calendar idea."},{"name":"experiment_id","in":"query","required":false,"schema":{"type":"string","format":"uuid"},"description":"Only this experiment."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":20}}],"responses":{"200":{"description":"Up to limit experiments for the bound product run.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","required":["available","experiments"],"properties":{"available":{"type":"boolean"},"experiments":{"type":"array","maxItems":50,"items":{"type":"object","required":["id","idea_id","run_id","kind","question","method","prediction","evidence","claim_ids","figure","run_date","spend_usd","ran_at"],"properties":{"id":{"type":"string","format":"uuid"},"idea_id":{"type":["string","null"],"format":"uuid"},"run_id":{"type":["string","null"],"format":"uuid"},"kind":{"type":"string","enum":["claim_lookup","engine_probe","corpus_query"]},"question":{"type":"string"},"method":{"type":["string","null"]},"prediction":{"type":["string","null"]},"evidence":{"type":["string","null"],"description":"The stored evidence prose; every line carries its scope."},"claim_ids":{"type":"array","items":{"type":"string"}},"figure":{"description":"The stored figure specification, or null when the result was not numeric."},"run_date":{"type":["string","null"],"description":"The run local date the result was stored under."},"spend_usd":{"type":"number","minimum":0},"ran_at":{"type":"string","format":"date-time"}}}}}},"meta":{"type":"object","properties":{"enrollment_id":{"type":"string","format":"uuid"},"generated_at":{"type":"string","format":"date-time"}},"required":["enrollment_id","generated_at"]}},"required":["data","meta"]}}}},"400":{"description":"An idea_id or experiment_id that is not a UUID, or a limit outside 1 to 50.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key does not carry the scope this endpoint requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"The key is not bound to the current product run.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-key rate limit exceeded. Honour Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/whoami":{"get":{"operationId":"getWhoami","summary":"Confirm the key works and see what it is bound to, in one call: enrollment_id, key_name, key_prefix and scopes, the product_url this run is about, tier and access_state, trial_ends_at, and onboarding { snapshot_status, current_phase, feed_ready, scanned, message } (feed_ready is false while the Growth Snapshot deep scan is still building). credits is present only when metering is live. The same payload the whoami MCP tool returns, without its text screen. Read-only, zero spend.","responses":{"200":{"description":"What this key is bound to.","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"onboarding":{"type":"object","properties":{"snapshot_status":{"type":"string","enum":["building","ready"],"description":"'building' while the deep scan is still running, 'ready' once it has finished."},"current_phase":{"type":["string","null"],"description":"A short honest label of what the deep scan is doing right now while building; null when ready."},"feed_ready":{"type":"boolean","description":"True once the deep scan (Stage B) has finished and the moves list holds the stronger stage-B moves."}}}}},"meta":{"type":"object","properties":{"enrollment_id":{"type":"string","format":"uuid"},"generated_at":{"type":"string","format":"date-time"}},"required":["enrollment_id","generated_at"]}},"required":["data","meta"]}}}},"401":{"description":"Missing, invalid or revoked API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key does not carry the scope this endpoint requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-key rate limit exceeded. Honour Retry-After.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/feed":{"get":{"operationId":"listFeed","summary":"The ranked backlog of prepared growth moves. Live (pending) moves only by default; resolved moves (shipped, skipped, archived, expir
# --- truncated at 32 KB (197 KB total) ---
# Full source: https://artifacts.apis.io/afterlaunch-io/openapi/_original/afterlaunch-io-api-openapi.json