{"openapi":"3.1.0","info":{"title":"Coppica API","version":"v1-alpha","description":"Programmatic access to Coppica’s learning loop: generate persuasion-engineered copy, then report real-world outcomes against the exact output that produced them so every future generation is informed by what actually converted. Authenticate with a Bearer API key (cpk_...). Human docs: https://coppica.com/docs/api"},"servers":[{"url":"https://coppica.com/api/v1"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Reference","description":"Bot catalog and the authenticated identity."},{"name":"Clients","description":"Client records the key can access."},{"name":"Generation","description":"Run bots and poll results."},{"name":"Learning loop","description":"Extract techniques and report outcomes."},{"name":"Resources","description":"Campaigns, ideas, tasks, avatars, offers, stories."},{"name":"Webhooks","description":"Event subscriptions."}],"paths":{"/bots":{"get":{"tags":["Reference"],"summary":"List available bot types","responses":{"200":{"description":"Bots grouped with display names and categories.","content":{"application/json":{"schema":{"type":"object","properties":{"bots":{"type":"array","items":{"$ref":"#/components/schemas/Bot"}}},"required":["bots"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/me":{"get":{"tags":["Reference"],"summary":"Current identity, plan, and credit balance","responses":{"200":{"description":"The authenticated user.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Identity"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients":{"get":{"tags":["Clients"],"summary":"List accessible clients","responses":{"200":{"description":"Clients the key can access.","content":{"application/json":{"schema":{"type":"object","properties":{"clients":{"type":"array","items":{"$ref":"#/components/schemas/Client"}}},"required":["clients"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Clients"],"summary":"Create a client","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"business_name":{"type":"string"},"contact_name":{"type":"string"},"email":{"type":"string"},"website":{"type":"string"}},"required":["business_name"]}}}},"responses":{"201":{"description":"Created client.","content":{"application/json":{"schema":{"type":"object","properties":{"client":{"$ref":"#/components/schemas/Client"}},"required":["client"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}":{"get":{"tags":["Clients"],"summary":"Client detail + intake summary","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The client, with its permission level and intake.","content":{"application/json":{"schema":{"type":"object","properties":{"client":{"$ref":"#/components/schemas/Client"}},"required":["client"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"tags":["Clients"],"summary":"Update intake fields","description":"Updates an EXISTING intake form. Returns 404 if the client has not completed in-app intake. Body: { source, intake: { <field>: <value> } }.","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string"},"intake":{"type":"object","additionalProperties":true}},"required":["source","intake"]}}}},"responses":{"200":{"description":"Updated client.","content":{"application/json":{"schema":{"type":"object","properties":{"client":{"$ref":"#/components/schemas/Client"}},"required":["client"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/campaigns":{"get":{"tags":["Resources"],"summary":"List campaigns","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","description":"Max rows to return (1–50, default 50).","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":50}}],"responses":{"200":{"description":"Campaigns for the client.","content":{"application/json":{"schema":{"type":"object","properties":{"campaigns":{"type":"array","items":{"$ref":"#/components/schemas/Generic"}}},"required":["campaigns"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Resources"],"summary":"Create a campaign","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"201":{"description":"Created campaign.","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/Generic"}},"required":["campaign"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/campaigns/{campaignId}":{"get":{"tags":["Resources"],"summary":"Campaign detail","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The campaign.","content":{"application/json":{"schema":{"type":"object","properties":{"campaign":{"$ref":"#/components/schemas/Generic"}},"required":["campaign"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/campaigns/{campaignId}/graph":{"get":{"tags":["Resources"],"summary":"Read the campaign graph (nodes + edges)","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The campaign graph.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Resources"],"summary":"Write the campaign graph","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Updated graph.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/campaigns/{campaignId}/nodes/{nodeId}":{"patch":{"tags":["Resources"],"summary":"Update a graph node","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"nodeId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Updated node.","content":{"application/json":{"schema":{"type":"object","properties":{"node":{"$ref":"#/components/schemas/Generic"}},"required":["node"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"tags":["Resources"],"summary":"Delete a graph node","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"nodeId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted node id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/campaigns/{campaignId}/edges":{"post":{"tags":["Resources"],"summary":"Connect two graph nodes","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"201":{"description":"Created edge.","content":{"application/json":{"schema":{"type":"object","properties":{"edge":{"$ref":"#/components/schemas/Generic"}},"required":["edge"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/campaigns/{campaignId}/edges/{edgeId}":{"delete":{"tags":["Resources"],"summary":"Delete a graph edge","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"edgeId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted edge id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/campaigns/{campaignId}/layout":{"patch":{"tags":["Resources"],"summary":"Update graph layout","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"campaignId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Updated layout.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/campaigns/from-graph":{"post":{"tags":["Resources"],"summary":"Materialize a campaign from a graph","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"201":{"description":"Created campaign from graph.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/ideas":{"get":{"tags":["Resources"],"summary":"List ideas","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Ideas for the client.","content":{"application/json":{"schema":{"type":"object","properties":{"ideas":{"type":"array","items":{"$ref":"#/components/schemas/Generic"}}},"required":["ideas"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Resources"],"summary":"Create an idea","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"}},"required":["title"]}}}},"responses":{"201":{"description":"Created idea.","content":{"application/json":{"schema":{"type":"object","properties":{"idea":{"$ref":"#/components/schemas/Generic"}},"required":["idea"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/ideas/{ideaId}":{"patch":{"tags":["Resources"],"summary":"Edit or promote an idea","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"ideaId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"action":{"type":"string","enum":["promote"]}},"additionalProperties":true}}}},"responses":{"200":{"description":"Updated idea.","content":{"application/json":{"schema":{"type":"object","properties":{"idea":{"$ref":"#/components/schemas/Generic"}},"required":["idea"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/tasks":{"get":{"tags":["Resources"],"summary":"List tasks","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Tasks for the client.","content":{"application/json":{"schema":{"type":"object","properties":{"tasks":{"type":"array","items":{"$ref":"#/components/schemas/Generic"}}},"required":["tasks"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Resources"],"summary":"Create a task","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string"},"description":{"type":"string"}},"required":["title"]}}}},"responses":{"201":{"description":"Created task.","content":{"application/json":{"schema":{"type":"object","properties":{"task":{"$ref":"#/components/schemas/Generic"}},"required":["task"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/avatars":{"get":{"tags":["Resources"],"summary":"List avatars","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Audience avatars for the client.","content":{"application/json":{"schema":{"type":"object","properties":{"avatars":{"type":"array","items":{"$ref":"#/components/schemas/Generic"}}},"required":["avatars"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/offers":{"get":{"tags":["Resources"],"summary":"List offers","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Offer architectures for the client.","content":{"application/json":{"schema":{"type":"object","properties":{"offers":{"type":"array","items":{"$ref":"#/components/schemas/Generic"}}},"required":["offers"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/stories":{"get":{"tags":["Resources"],"summary":"List stories","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Stories for the client.","content":{"application/json":{"schema":{"type":"object","properties":{"stories":{"type":"array","items":{"$ref":"#/components/schemas/Generic"}}},"required":["stories"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Resources"],"summary":"Add a story","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"201":{"description":"Created story.","content":{"application/json":{"schema":{"type":"object","properties":{"story":{"$ref":"#/components/schemas/Generic"}},"required":["story"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/avatars/{avatarId}":{"get":{"tags":["Resources"],"summary":"Avatar detail","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"avatarId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The avatar.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"tags":["Resources"],"summary":"Refine an avatar","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"avatarId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Refined avatar.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/offers/{offerId}":{"get":{"tags":["Resources"],"summary":"Offer detail","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"offerId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The offer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"tags":["Resources"],"summary":"Refine an offer","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"offerId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Refined offer.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/stories/{storyId}":{"get":{"tags":["Resources"],"summary":"Story detail","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"storyId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The story.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/outputs":{"get":{"tags":["Generation"],"summary":"List bot outputs","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","description":"Max rows to return (1–50, default 50).","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":50}},{"name":"since","in":"query","description":"ISO-8601 timestamp — return only rows after it (incremental polling).","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"finalized","in":"query","required":false,"schema":{"type":"boolean"},"description":"Only approved-to-deploy copy (orders by finalized_at)."},{"name":"bot_type","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Bot outputs, newest first.","content":{"application/json":{"schema":{"type":"object","properties":{"outputs":{"type":"array","items":{"$ref":"#/components/schemas/Output"}}},"required":["outputs"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/outputs/{outputId}":{"get":{"tags":["Generation"],"summary":"Output detail","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"outputId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The output.","content":{"application/json":{"schema":{"type":"object","properties":{"output":{"$ref":"#/components/schemas/Output"}},"required":["output"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"tags":["Generation"],"summary":"Update an output (review stage / deployment status)","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"outputId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Updated output.","content":{"application/json":{"schema":{"type":"object","properties":{"output":{"$ref":"#/components/schemas/Output"}},"required":["output"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/outputs/{outputId}/append":{"post":{"tags":["Generation"],"summary":"Append a dated addendum to a strategic doc","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"outputId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Addendum appended.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/outputs/{outputId}/diagnose":{"post":{"tags":["Generation"],"summary":"Diagnose which techniques an output used","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"outputId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Diagnosis.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/rank-outputs":{"post":{"tags":["Generation"],"summary":"Rank candidate outputs head-to-head","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Ranking.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/pixel-snippet":{"get":{"tags":["Deploy & track"],"summary":"Get the conversion-pixel install snippet for a client","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The pixel <script> tag (client UUID pre-filled), its src, and an install note.","content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","format":"uuid"},"src":{"type":"string"},"snippet":{"type":"string"},"install":{"type":"string"}},"required":["client_id","snippet"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/tracking-links":{"post":{"tags":["Deploy & track"],"summary":"Build a UTM tracking link for an output","description":"Generator (not stored). Returns a URL with utm_source=coppica, utm_medium=ai-copy, utm_content=<output_id>, and optional utm_campaign. The output must belong to the client.","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"output_id":{"type":"string","format":"uuid"},"destination_url":{"type":"string","format":"uri"},"utm_campaign":{"type":"string","maxLength":100}},"required":["output_id","destination_url"]}}}},"responses":{"200":{"description":"The tagged tracking URL + the UTM parameters used.","content":{"application/json":{"schema":{"type":"object","properties":{"tracking_url":{"type":"string"},"output_id":{"type":"string","format":"uuid"},"utm":{"type":"object","additionalProperties":true}},"required":["tracking_url","output_id"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/outputs/{outputId}/conversions":{"get":{"tags":["Deploy & track"],"summary":"Aggregated conversion performance for an output","description":"Sums conversion_events tied to the output across ALL sources (pixel, api_outcome, ga4, meta_ads, stripe, manual, …).","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"outputId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Conversion summary for the output.","content":{"application/json":{"schema":{"type":"object","properties":{"output_id":{"type":"string","format":"uuid"},"total_conversions":{"type":"integer"},"total_value":{"type":"number"},"by_type":{"type":"object","additionalProperties":true},"by_source":{"type":"object","additionalProperties":true},"last_conversion_at":{"type":["string","null"],"format":"date-time"},"truncated":{"type":"boolean"}},"required":["output_id","total_conversions","total_value"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/attribution-summary":{"get":{"tags":["Deploy & track"],"summary":"Naive vs canonical attribution headline (\"many sources, one narrative\")","description":"Compares the naive multi-source conversion view against Heimdall's deduped canonical view (identity graph + reconciliation): dedup_ratio, revenue_overcount_ratio, clean vs review_pending counts. window_days defaults to 90.","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"window_days","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":365,"default":90}}],"responses":{"200":{"description":"Attribution comparison summary.","content":{"application/json":{"schema":{"type":"object","properties":{"window_days":{"type":"integer"},"naive":{"type":"object","properties":{"conversions":{"type":"integer"},"revenue":{"type":"number"}}},"canonical":{"type":"object","properties":{"conversions":{"type":"integer"},"revenue":{"type":"number"}}},"dedup_ratio":{"type":["number","null"]},"revenue_overcount_ratio":{"type":["number","null"]},"reconciliation":{"type":"object","properties":{"clean":{"type":"integer"},"review_pending":{"type":"integer"}}},"sources_seen":{"type":"array","items":{"type":"string"}},"reconciliation_version":{"type":"integer"},"revenue_truncated":{"type":"boolean"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/canonical-conversions":{"get":{"tags":["Deploy & track"],"summary":"Heimdall deduped conversion ledger (reconciled, PII-free)","description":"Each row is one reconciled economic event — raw conversions from multiple sources collapsed into one via the identity graph + Fellegi-Sunter clustering, with per-source agreement, dissent, break_status, and an attribution_confidence score. Customer PII is never returned.","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200,"default":50}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0}},{"name":"since","in":"query","required":false,"schema":{"type":"string","format":"date-time"}},{"name":"event_type","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deduped canonical conversion ledger.","content":{"application/json":{"schema":{"type":"object","properties":{"canonical_conversions":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"occurred_at":{"type":"string","format":"date-time"},"amount":{"type":["number","null"]},"currency":{"type":"string"},"event_type":{"type":"string"},"sources":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"confidence":{"type":["number","null"]},"amount":{"type":["number","null"]}}}},"source_count":{"type":"integer"},"attribution_confidence":{"type":"number"},"dissent_severity":{"type":"number"},"break_status":{"type":"string"},"matched_event_count":{"type":"integer"}}}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"total":{"type":"integer"},"has_more":{"type":"boolean"}}},"reconciliation_version":{"type":"integer"}}}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/performance-brief":{"get":{"tags":["Deploy & track"],"summary":"Heimdall performance brief (cached, stale-while-revalidate)","description":"The most recent performance brief over the client's reconciled conversion data. Returns the cached brief plus a `stale` flag; if missing or >24h old it queues a background refresh (cheap no-op if the data is unchanged). available:false + regenerating:true means one was just queued — poll again shortly.","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The cached brief (with stale/regenerating flags), or available:false.","content":{"application/json":{"schema":{"type":"object","properties":{"available":{"type":"boolean"},"brief":{"type":"object","additionalProperties":true},"generated_at":{"type":["string","null"],"format":"date-time"},"model":{"type":["string","null"]},"stale":{"type":"boolean"},"regenerating":{"type":"boolean"},"message":{"type":"string"}},"required":["available"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Deploy & track"],"summary":"Force a fresh performance brief (execute scope)","description":"Queues an immediate fresh brief, bypassing the 24h freshness window — the \"specifically requested\" path. A paid Opus generation. Returns 202 + a job_id; poll GET for the result (typically 1-4 minutes).","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"202":{"description":"Brief generation queued.","content":{"application/json":{"schema":{"type":"object","properties":{"queued":{"type":"boolean"},"job_id":{"type":["string","null"]},"message":{"type":"string"}},"required":["queued"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/drafts":{"get":{"tags":["Generation"],"summary":"List drafts","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Drafts for the client.","content":{"application/json":{"schema":{"type":"object","properties":{"drafts":{"type":"array","items":{"$ref":"#/components/schemas/Generic"}}},"required":["drafts"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/drafts/{draftId}":{"get":{"tags":["Generation"],"summary":"Draft content","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"draftId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The draft.","content":{"application/json":{"schema":{"type":"object","properties":{"draft":{"$ref":"#/components/schemas/Generic"}},"required":["draft"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"patch":{"tags":["Generation"],"summary":"Update a draft","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"draftId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Updated draft.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/workflows":{"post":{"tags":["Generation"],"summary":"Run a multi-stage workflow (ad-set, iterate-on-winner)","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"202":{"description":"Workflow started; poll the returned workflow_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/workflows/{workflowId}":{"get":{"tags":["Generation"],"summary":"Poll workflow status","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"workflowId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The workflow.","content":{"application/json":{"schema":{"type":"object","properties":{"workflow":{"$ref":"#/components/schemas/Generic"}},"required":["workflow"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/bots/{botType}/run":{"post":{"tags":["Generation"],"summary":"Run a bot (async)","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"botType","in":"path","required":true,"schema":{"type":"string"},"description":"e.g. PERSUASION_MAP, MIMIR."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"user_message":{"type":"string","description":"Optional steer for the run."},"channel":{"type":"string","description":"Asset channel hint (any in-app channel slug). Legacy aliases (meta_ads/google_ads/tiktok_ads/email) also accepted.","enum":["facebook_ad","tiktok_ad","google_search_ad","google_display_ad","email_single","email_sequence","landing_page","sales_page","vsl","advertorial","organic_social","blog_post","sms","direct_mail","linkedin_ad","linkedin_organic","amazon_listing","podcast_ad","webinar_registration","other","meta_ads","google_ads","tiktok_ads","email"]},"funnel_stage":{"type":"string","enum":["cold_traffic","retargeting","warm","reactivation"]},"format":{"type":"string","description":"Creative-format hint (any in-app creative-format slug). Legacy aliases also accepted.","enum":["ugly_ad","bold_typography","native_social_post","breaking_news","screenshot_format","meme_template","comment_review","handwritten_note","native_ad_style","hero_layout","carousel","split_screen","infographic","talking_head","screen_recording","simple_animation","faceless","ugc_style","founder_style","podcast_clip","street_interview","cartoon_animation","ugly_video","text_on_broll","production_heavy","reaction_video","green_screen","presentation","whiteboard","meta_ad","google_responsive_search","email","landing_page","sms","primary_text","headline","description","full_ad_set"]},"iteration_context":{"type":"string","maxLength":4000,"description":"Free text explaining why new copy is needed."},"reference_output_id":{"type":"string","format":"uuid","description":"Output to iterate on."},"idempotency_key":{"type":"string","maxLength":255,"description":"Retry-safety key; a repeat with the same (client, bot, key) returns the original run."},"label":{"type":"string","maxLength":200,"description":"Human-readable label for this run. Becomes the title of the auto-promoted draft; without it, drafts fall back to \"<Bot> · <short id>\". Alias: session_label."},"session_label":{"type":"string","maxLength":200,"description":"Alias for label."}}}}}},"responses":{"202":{"description":"Accepted — poll poll_url until status is complete.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunAccepted"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/jobs/{outputId}":{"get":{"tags":["Generation"],"summary":"Poll a bot run","parameters":[{"name":"outputId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Job status; output_text is populated once status is complete.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatus"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/extract":{"post":{"tags":["Learning loop"],"summary":"Extract persuasion techniques from arbitrary copy","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractRequest"}}}},"responses":{"200":{"description":"Extracted techniques. When persist=true, output_id is returned so you can later report outcomes against it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/outcomes":{"post":{"tags":["Learning loop"],"summary":"Report an outcome against an output_id (the flagship loop primitive)","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutcomeRequest"}}}},"responses":{"200":{"description":"Idempotent replay — the same (output_id, external_id) was already reported. Same body shape as 201.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutcomeResult"}}}},"201":{"description":"Outcome recorded; weight update queued asynchronously.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutcomeResult"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/clients/{clientId}/outcomes":{"get":{"tags":["Learning loop"],"summary":"Audit log of outcomes this key reported","parameters":[{"name":"clientId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"limit","in":"query","description":"Max rows to return (1–50, default 50).","required":false,"schema":{"type":"integer","minimum":1,"maximum":50,"default":50}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0}}],"responses":{"200":{"description":"Outcomes reported by this key for the client.","content":{"application/json":{"schema":{"type":"object","properties":{"outcomes":{"type":"array","items":{"$ref":"#/components/schemas/Generic"}},"pagination":{"type":"object","properties":{"limit":{"type":"integer"},"offset":{"type":"integer"},"returned":{"type":"integer"}}}},"required":["outcomes"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/webhooks":{"get":{"tags":["Webhooks"],"summary":"List webhook subscriptions","responses":{"200":{"description":"Your webhook subscriptions (URLs masked).","content":{"application/json":{"schema":{"type":"object","properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}},"required":["webhooks"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"post":{"tags":["Webhooks"],"summary":"Create a webhook subscription","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookCreate"}}}},"responses":{"201":{"description":"Created. For generic webhooks the signing secret is returned once.","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"}},"required":["webhook"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}},"/webhooks/{webhookId}":{"patch":{"tags":["Webhooks"],"summary":"Update a webhook","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"responses":{"200":{"description":"Updated webhook.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook","parameters":[{"name":"webhookId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Generic"}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"A Coppica API key, e.g. `Authorization: Bearer cpk_...`. Keys carry read/write/execute scopes."}},"schemas":{"Error":{"type":"object","description":"Standard error envelope. Branch on `code`, never the human `error` string.","properties":{"error":{"type":"string","description":"Human-readable, sanitized message."},"code":{"type":"string","description":"Stable machine-readable code.","examples":["invalid_request","invalid_client_id","missing_authorization","invalid_api_key","missing_scope","client_access_denied","spending_cap_exceeded","not_found","rate_limited","server_error"]}},"required":["error","code"]},"Bot":{"type":"object","properties":{"bot_type":{"type":"string"},"display_name":{"type":"string"},"category":{"type":"string","enum":["strategy","writing","other"]}},"required":["bot_type","display_name","category"]},"Identity":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"display_name":{"type":["string","null"]},"plan":{"type":["string","null"]},"credits":{"type":"object","properties":{"balance":{"type":"number"},"monthly_remaining":{"type":"number"},"purchased":{"type":"number"}}},"scopes":{"type":"array","items":{"type":"string","enum":["read","write","execute"]}},"spending_cap":{"type":["number","null"]}},"required":["user_id","scopes"]},"Client":{"type":"object","description":"A client record. Includes permission + intake on the detail endpoint.","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string"},"permission":{"type":"string","description":"Caller’s permission level (detail endpoint only)."},"intake":{"type":["object","null"],"additionalProperties":true}},"required":["id"],"additionalProperties":true},"Output":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"client_id":{"type":"string","format":"uuid"},"bot_type":{"type":"string"},"status":{"type":"string","enum":["processing","complete","needs_revision"]},"session_label":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"}},"required":["id","bot_type","status","created_at"],"additionalProperties":true},"RunAccepted":{"type":"object","properties":{"output_id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["processing","complete"]},"poll_url":{"type":"string","description":"GET this to poll the run, e.g. /api/v1/jobs/{outputId}."}},"required":["output_id","status","poll_url"]},"JobStatus":{"type":"object","properties":{"output_id":{"type":"string","format":"uuid"},"bot_type":{"type":"string"},"status":{"type":"string","enum":["processing","complete","needs_revision","failed","error"]},"output_text":{"type":["string","null"],"description":"Null until status is complete."},"tokens_input":{"type":"integer"},"tokens_output":{"type":"integer"},"credits_spent":{"type":["number","null"],"description":"Credits consumed by this run. Null until status is complete."},"intake_completeness":{"type":["number","null"],"description":"Fraction (0–1) of the 15 intake fields populated."},"warnings":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"required":["output_id","bot_type","status"]},"ExtractRequest":{"type":"object","properties":{"client_id":{"type":"string","format":"uuid"},"text":{"type":"string","description":"The copy to analyze."},"context_hint":{"type":"string","maxLength":500,"description":"Optional context, e.g. \"a Facebook ad for a chiropractor\"."},"label":{"type":"string","description":"Optional label for the stored output."},"persist":{"type":"boolean","default":true,"description":"Store a bot_outputs row so you can report outcomes against the returned output_id."}},"required":["client_id","text"]},"ExtractResult":{"type":"object","properties":{"output_id":{"type":"string","format":"uuid","description":"Present only when persist=true."},"elements":{"type":"array","items":{"type":"object","additionalProperties":true}},"elements_count":{"type":"integer"},"credits_spent":{"type":"number","description":"Credits consumed by this extraction."},"persisted":{"type":"boolean"}},"required":["elements","elements_count","persisted"]},"OutcomeRequest":{"type":"object","properties":{"output_id":{"type":"string","format":"uuid"},"type":{"type":"string","enum":["conversion_purchase","conversion_lead","conversion_signup","conversion_custom","engagement_positive","engagement_negative","thumbs_up","thumbs_down"]},"value":{"type":"number","description":"Dollar value for conversions."},"external_id":{"type":"string","description":"Your stable event id for idempotency (normalized lowercase + trimmed)."},"occurred_at":{"type":"string","format":"date-time","description":"Historical timestamp, up to 1 year back."},"metadata":{"type":"object","additionalProperties":true}},"required":["output_id","type"]},"OutcomeResult":{"type":"object","properties":{"outcome_id":{"type":"string","format":"uuid"},"output_id":{"type":"string","format":"uuid"},"type":{"type":"string"},"weights_updated":{"type":"integer","description":"Always 0 on the synchronous response; the update runs async."},"weight_update_queued":{"type":"boolean"},"status":{"type":"string"},"echo":{"type":"object","properties":{"output_id":{"type":"string"},"type":{"type":"string"},"value":{"type":["number","null"]},"external_id":{"type":["string","null"]},"anomaly_flagged":{"type":"boolean"}}}},"required":["outcome_id","output_id","type","weight_update_queued","status"]},"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"provider":{"type":"string","enum":["generic","slack"]},"label":{"type":["string","null"]},"events":{"type":"array","items":{"type":"string"}},"enabled":{"type":"boolean"},"masked_url":{"type":"string","description":"URL with the host/path partially masked."},"secret":{"type":"string","description":"Signing secret — returned only once, on create, for generic webhooks."},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","provider","events","enabled"]},"WebhookCreate":{"type":"object","properties":{"webhook_url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["bot.complete","pipeline.complete","intake.submitted","document.shared","draft.ready","client.annotation","client.approval","conversion.recorded","task.assigned","output.finalized","workflow.node_complete","workflow.complete"]}},"provider":{"type":"string","enum":["generic","slack"],"default":"generic"},"label":{"type":"string"}},"required":["webhook_url","events"]},"Generic":{"type":"object","additionalProperties":true}},"responses":{"Unauthorized":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"Wrong scope, client access denied, or spending cap exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Resource not found (also returned when access is denied).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"RateLimited":{"description":"Rate limit exceeded.","headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait before retrying."},"RateLimit-Limit":{"schema":{"type":"integer"},"description":"Max requests in the window."},"RateLimit-Remaining":{"schema":{"type":"integer"},"description":"Requests left in the window."},"RateLimit-Reset":{"schema":{"type":"integer"},"description":"Seconds until the window resets."}},"content":{"application/json":{"schema":{"type":"object","description":"The 429 body carries code plus a message and retryAfterMs.","properties":{"error":{"type":"string"},"code":{"type":"string","const":"rate_limited"},"message":{"type":"string"},"retryAfterMs":{"type":"integer"}},"required":["error","code"]}}}}}}}