{"openapi":"3.1.0","jsonSchemaDialect":"https://json-schema.org/draft/2020-12/schema","info":{"title":"Havadis API","version":"1.0.0","description":"Keyed REST façade over Havadis content generation. Authenticate with `Authorization: Bearer havadis_<prefix>_<secret>`. Errors use a closed envelope with stable `code` values."},"servers":[{"url":"https://api.gethavadis.co"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","bearerFormat":"havadis_<prefix>_<secret>"}},"responses":{"Error":{"description":"Error envelope","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"type":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"retry_after_seconds":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["type","code","message"]},"request_id":{"type":"string"}},"required":["error"]}}}}},"x-error-codes":["invalid_request","invalid_cursor","unauthorized","scope_denied","forbidden","brand_not_found","not_found","channel_not_supported","rate_limit_exceeded","daily_spend_cap_exceeded","insufficient_credits","owner_insufficient_credits","api_key_limit_reached","idempotency_key_required","idempotency_error","idempotency_in_flight","internal_error"]},"paths":{"/api/v1/me":{"get":{"operationId":"me.get","summary":"Identity, effective scopes and limits of the calling key","description":"No scope required beyond a valid key.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"tenant":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"plan":{"type":"string"}},"required":["id","name","slug","plan"]},"api_key":{"type":"object","properties":{"prefix":{"type":"string"},"label":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}},"required":["prefix","label","scopes"]},"limits":{"type":"object","properties":{"rate_limit_per_minute":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991},"daily_credit_cap":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["rate_limit_per_minute","daily_credit_cap"]}},"required":["tenant","api_key","limits"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/credits":{"get":{"operationId":"credits.get","summary":"Credit pool snapshot of the workspace owner's account","description":"Requires scope: `credits:read`.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"balance":{"anyOf":[{"type":"number"},{"type":"null"}]},"is_unlimited":{"type":"boolean"},"plan":{"type":"string"},"daily_credit_cap":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["balance","is_unlimited","plan","daily_credit_cap"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands":{"get":{"operationId":"brands.list","summary":"Brands owned by the calling tenant","description":"Requires scope: `brands:read`.","security":[{"apiKey":[]}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"website":{"type":"string"},"industry":{"type":"string"},"description":{"type":"string"},"created_at":{"type":"string"}},"required":["id","name","website","industry","description","created_at"]}}},"required":["data"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}":{"get":{"operationId":"brands.get","summary":"One owned brand","description":"Requires scope: `brands:read`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"website":{"type":"string"},"industry":{"type":"string"},"description":{"type":"string"},"created_at":{"type":"string"}},"required":["id","name","website","industry","description","created_at"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/contents":{"get":{"operationId":"contents.list","summary":"Keyset-paged contents, drafts included","description":"Requires scope: `content:read`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["draft","published","all"],"default":"all"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from next_cursor. A malformed cursor is a 400."},{"name":"include_total","in":"query","required":false,"schema":{"type":"integer","enum":[0,1],"default":0}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"content_type":{"type":"string"},"status":{"type":"string","enum":["draft","published"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"published_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"cover_image_url":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["id","slug","title","content_type","status","created_at","updated_at","published_at","cover_image_url"]}},"has_more":{"type":"boolean"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}]},"total":{"type":"integer","minimum":-9007199254740991,"maximum":9007199254740991}},"required":["data","has_more","next_cursor"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/contents/{idOrSlug}":{"get":{"operationId":"contents.get","summary":"Full content (body + SEO/AEO/GEO), ETag/If-None-Match aware","description":"Requires scope: `content:read`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"idOrSlug","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"slug":{"type":"string"},"title":{"type":"string"},"content_type":{"type":"string"},"status":{"type":"string","enum":["draft","published"]},"created_at":{"type":"string"},"updated_at":{"type":"string"},"published_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"cover_image_url":{"anyOf":[{"type":"string"},{"type":"null"}]},"summary":{"type":"string"},"body":{"type":"string"},"hashtags":{"type":"array","items":{"type":"string"}},"seo_metadata":{"type":"object","properties":{"meta_title":{"type":"string"},"meta_description":{"type":"string"},"keywords":{"type":"array","items":{"type":"string"}},"slug":{"type":"string"}},"required":["meta_title","meta_description","keywords","slug"]},"aeo_metadata":{"type":"object","properties":{"featured_snippet_target":{"type":"string"},"faq_items":{"type":"array","items":{"type":"object","properties":{"question":{"type":"string"},"answer":{"type":"string"}},"required":["question","answer"]}}},"required":["featured_snippet_target","faq_items"]},"geo_metadata":{"type":"object","properties":{"citations":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"claim":{"type":"string"}},"required":["source","claim"]}},"structured_data":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["citations","structured_data"]}},"required":["id","slug","title","content_type","status","created_at","updated_at","published_at","cover_image_url","summary","body","hashtags","seo_metadata","aeo_metadata","geo_metadata"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/contents/{contentId}/publish":{"post":{"operationId":"contents.publish","summary":"Publish to the customer's own site (custom_website)","description":"Requires scope: `content:write`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"contentId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string","description":"v1 supports 'custom_website' only."},"title":{"type":"string"},"contentHtml":{"type":"string"},"coverImageUrl":{"type":"string"}},"required":["channel"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"published":{"type":"boolean"},"warnings":{"type":"array","items":{"type":"string"}}},"required":["published","warnings"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/contents/{contentId}/unpublish":{"post":{"operationId":"contents.unpublish","summary":"Take content off the custom_website channel","description":"Requires scope: `content:write`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"contentId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"channel":{"type":"string"}},"required":["channel"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"published":{"type":"boolean"},"warnings":{"type":"array","items":{"type":"string"}}},"required":["published","warnings"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/jobs":{"post":{"operationId":"jobs.create","summary":"Queue a content generation job (async — poll jobs.get)","description":"Requires scope: `jobs:write`. Spends credits (all-or-nothing at execution). The `Idempotency-Key` header is REQUIRED; retries replay the stored result.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contentTypes":{"minItems":1,"maxItems":7,"type":"array","items":{"type":"string","enum":["blog","linkedin","instagram","pinterest","x_thread","viral_content","ad_creative"]}},"brief":{"type":"string","minLength":10,"maxLength":50000},"styleUrls":{"default":[],"maxItems":10,"type":"array","items":{"type":"string","format":"uri"}},"researchUrls":{"default":[],"maxItems":10,"type":"array","items":{"type":"string","format":"uri"}},"keywords":{"default":[],"maxItems":20,"type":"array","items":{"type":"string","minLength":1}},"targetPersonaId":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"instructions":{"default":"","type":"string","maxLength":2000},"language":{"type":"string","minLength":2,"maxLength":5},"wordCountRange":{"default":null,"anyOf":[{"type":"string","enum":["short","medium","long","unlimited"]},{"type":"null"}]},"aiModelKey":{"default":null,"anyOf":[{"type":"string","pattern":"^[a-z0-9][a-z0-9_]{1,63}$"},{"type":"null"}]},"suggestionId":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"origin":{"default":null,"anyOf":[{"type":"string","enum":["manual","suggestion","search_console","bulk_plan","ai_visibility","meta_ads"]},{"type":"null"}]},"useCaseId":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"recreatedFromJobId":{"default":null,"anyOf":[{"type":"string"},{"type":"null"}]},"viralOptions":{"default":null,"anyOf":[{"type":"object","properties":{"mediums":{"minItems":1,"type":"array","items":{"type":"string","enum":["image","video"]}},"conceptCount":{"type":"integer","minimum":3,"maximum":8}},"required":["mediums","conceptCount"]},{"type":"null"}]},"adOptions":{"default":null,"anyOf":[{"type":"object","properties":{"objective":{"type":"string","enum":["awareness","consideration","conversion"]},"conceptCount":{"type":"integer","minimum":2,"maximum":6},"directive":{"default":null,"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"required":["objective","conceptCount"]},{"type":"null"}]},"generateCoverImage":{"default":false,"type":"boolean"},"coverImageReferenceUrl":{"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"coverStyleTemplateKey":{"default":null,"anyOf":[{"type":"string","enum":["editorial_photo","minimal_3d","flat_illustration","gradient_abstract","soft_pastel","organic_natural","cinematic_moody","neon_tech"]},{"type":"null"}]}},"required":["contentTypes","brief"]}}}},"responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"}},"required":["id","status"]}}}},"default":{"$ref":"#/components/responses/Error"}}},"get":{"operationId":"jobs.list","summary":"Keyset-paged jobs","description":"Requires scope: `jobs:read`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque keyset cursor from next_cursor. A malformed cursor is a 400."}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"content_types":{"type":"array","items":{"type":"string"}},"platforms":{"type":"array","items":{"type":"object","properties":{"content_type":{"type":"string"},"status":{"type":"string"},"content_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"failure_reason":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["content_type","status","content_id","completed_at","failure_reason"]}},"origin":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string"}},"required":["id","status","content_types","platforms","origin","created_at"]}},"has_more":{"type":"boolean"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["data","has_more","next_cursor"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/jobs/cost-preview":{"post":{"operationId":"jobs.costPreview","summary":"Free per-model cost preview for a job shape","description":"Requires scope: `jobs:read`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contentTypes":{"minItems":1,"maxItems":5,"type":"array","items":{"type":"string","enum":["blog","linkedin","instagram","pinterest","x_thread","viral_content","ad_creative"]}}},"required":["contentTypes"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"costs":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"number"}}},"required":["costs"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/jobs/{jobId}":{"get":{"operationId":"jobs.get","summary":"One job with per-platform state","description":"Requires scope: `jobs:read`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"jobId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"content_types":{"type":"array","items":{"type":"string"}},"platforms":{"type":"array","items":{"type":"object","properties":{"content_type":{"type":"string"},"status":{"type":"string"},"content_id":{"anyOf":[{"type":"string"},{"type":"null"}]},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}]},"failure_reason":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["content_type","status","content_id","completed_at","failure_reason"]}},"origin":{"anyOf":[{"type":"string"},{"type":"null"}]},"created_at":{"type":"string"}},"required":["id","status","content_types","platforms","origin","created_at"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/topics/suggest":{"post":{"operationId":"topics.suggest","summary":"Queue topic discovery (async — results land in topics.list)","description":"Requires scope: `topics:write`. Spends credits (all-or-nothing at execution). The `Idempotency-Key` header is REQUIRED; retries replay the stored result.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","maxLength":255}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"language":{"type":"string","enum":["en","tr","de","fr","es","it","pt","nl","ar","ja","ko","zh"]},"contentType":{"type":"string","enum":["blog","linkedin","instagram","pinterest","x_thread","viral_content","ad_creative"]},"targetPersonaId":{"anyOf":[{"type":"string"},{"type":"null"}]},"generateCoverImage":{"default":false,"type":"boolean"},"coverImageReferenceUrl":{"default":null,"anyOf":[{"type":"string","format":"uri"},{"type":"null"}]},"coverStyleTemplateKey":{"default":null,"anyOf":[{"type":"string","enum":["editorial_photo","minimal_3d","flat_illustration","gradient_abstract","soft_pastel","organic_natural","cinematic_moody","neon_tech"]},{"type":"null"}]},"viralOptions":{"default":null,"anyOf":[{"type":"object","properties":{"mediums":{"minItems":1,"type":"array","items":{"type":"string","enum":["image","video"]}},"conceptCount":{"type":"integer","minimum":3,"maximum":8}},"required":["mediums","conceptCount"]},{"type":"null"}]},"adOptions":{"default":null,"anyOf":[{"type":"object","properties":{"objective":{"type":"string","enum":["awareness","consideration","conversion"]},"conceptCount":{"type":"integer","minimum":2,"maximum":6},"directive":{"default":null,"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}]}},"required":["objective","conceptCount"]},{"type":"null"}]},"focus":{"anyOf":[{"type":"object","properties":{"source":{"type":"string","const":"ai_visibility"},"promptId":{"type":"string","minLength":1,"maxLength":64}},"required":["source","promptId"],"additionalProperties":false},{"type":"null"}]}},"additionalProperties":false}}}},"responses":{"202":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"run_id":{"type":"string"},"status":{"type":"string"},"content_type":{"type":"string"}},"required":["run_id","status","content_type"]}}}},"default":{"$ref":"#/components/responses/Error"}}}},"/api/v1/brands/{brandId}/topics":{"get":{"operationId":"topics.list","summary":"Topic suggestions for the brand","description":"Requires scope: `topics:read`.","security":[{"apiKey":[]}],"parameters":[{"name":"brandId","in":"path","required":true,"schema":{"type":"string"}},{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","approved","dismissed"]}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":50}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string","enum":["pending","approved","dismissed"]},"title":{"type":"string"},"short_description":{"type":"string"},"rationale":{"type":"string"},"suggested_brief":{"type":"string"},"suggested_keywords":{"type":"array","items":{"type":"string"}},"content_type":{"type":"string"},"language":{"type":"string"},"created_at":{"type":"string"}},"required":["id","status","title","short_description","rationale","suggested_brief","suggested_keywords","content_type","language","created_at"]}}},"required":["data"]}}}},"default":{"$ref":"#/components/responses/Error"}}}}}}