{"openapi":"3.1.0","info":{"title":"Zenex CMS Management API","version":"1.0.0"},"paths":{"/api/v1/blogs/{blogId}/media":{"post":{"operationId":"upload_image","description":"Upload a public JPEG, PNG, GIF or WebP image as base64 (maximum 700 KiB decoded). Returns a URL usable in coverImage or Editor.js. Do not upload confidential files; images are public even for drafts. Required scope: media:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"mimeType":{"type":"string","enum":["image/jpeg","image/png","image/gif","image/webp"]},"base64":{"type":"string","minLength":4,"maxLength":956000,"pattern":"^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"}},"required":["mimeType","base64"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}":{"get":{"operationId":"get_blog","description":"Read this blog’s public identifier and metadata. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"patch":{"operationId":"update_blog","description":"Update this blog’s name, slug or description. Cannot change ownership. Required scope: blog:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]}},"additionalProperties":false}}}},"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}/posts":{"get":{"operationId":"list_posts","description":"List posts, paginated. Posts include drafts; results are private. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":10000}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":100}},{"name":"status","in":"query","required":false,"schema":{"default":"all","type":"string","enum":["draft","published","all"]}},{"name":"language","in":"query","required":false,"schema":{"type":"string"}},{"name":"categoryId","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":128}},{"name":"tagId","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":128}},{"name":"search","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":200}}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"post":{"operationId":"create_posts","description":"Create posts. Posts default to draft; publishing additionally requires content:publish. Use Editor.js JSON for content. Supports every dashboard block, including tables with header rows. MCP clients: call get_editor_guide for examples. Required scope: content:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"},"content":{"type":"object","properties":{"time":{"type":"number"},"version":{"type":"string","maxLength":32},"blocks":{"maxItems":1000,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","maxLength":128},"type":{"type":"string","minLength":1,"maxLength":64},"data":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}},"tunes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema1"}}},"required":["type","data"],"additionalProperties":false}}},"required":["blocks"],"additionalProperties":false,"description":"Editor.js JSON: {blocks:[{type,data}]}, not a Markdown string. Supports paragraph, header, list, quote, code, table, linkTool, image, raw and delimiter. Call get_editor_guide for exact examples. Tables use data.content as string[][] and data.withHeadings=true for a bold, shaded first row. When supplied to update_posts, content replaces ALL blocks: get_posts first, preserve untouched blocks and their IDs, then submit the complete content."},"language":{"default":"en","type":"string"},"status":{"default":"draft","type":"string","enum":["draft","published"]},"featured":{"type":"boolean"},"excerpt":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"coverImage":{"anyOf":[{"anyOf":[{"type":"string","const":""},{"type":"string","maxLength":2048,"format":"uri"}]},{"type":"null"}]},"authorId":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]},"publishedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"translationGroupId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"metaTitle":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"metaDescription":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"ogImage":{"anyOf":[{"anyOf":[{"type":"string","const":""},{"type":"string","maxLength":2048,"format":"uri"}]},{"type":"null"}]},"ogTitle":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"ogDescription":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"canonicalUrl":{"anyOf":[{"anyOf":[{"type":"string","const":""},{"type":"string","maxLength":2048,"format":"uri"}]},{"type":"null"}]},"keywords":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"categoryIds":{"maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"tagIds":{"maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}}},"required":["title","slug","content"],"additionalProperties":false,"$defs":{"__schema0":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema0"}},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}}]},"__schema1":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema1"}},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema1"}}]}}}}}},"responses":{"201":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}/posts/{id}":{"get":{"operationId":"get_posts","description":"Read one posts record by its internal ID, not its slug. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"patch":{"operationId":"update_posts","description":"Update only supplied fields in posts. Editing a published post or changing publication state additionally requires content:publish. Supplied content replaces the entire document: call get_posts first and preserve untouched blocks. MCP clients: call get_editor_guide for block formats. Required scope: content:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"},"content":{"type":"object","properties":{"time":{"type":"number"},"version":{"type":"string","maxLength":32},"blocks":{"maxItems":1000,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","maxLength":128},"type":{"type":"string","minLength":1,"maxLength":64},"data":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}},"tunes":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema1"}}},"required":["type","data"],"additionalProperties":false}}},"required":["blocks"],"additionalProperties":false,"description":"Editor.js JSON: {blocks:[{type,data}]}, not a Markdown string. Supports paragraph, header, list, quote, code, table, linkTool, image, raw and delimiter. Call get_editor_guide for exact examples. Tables use data.content as string[][] and data.withHeadings=true for a bold, shaded first row. When supplied to update_posts, content replaces ALL blocks: get_posts first, preserve untouched blocks and their IDs, then submit the complete content."},"language":{"type":"string"},"status":{"type":"string","enum":["draft","published"]},"featured":{"type":"boolean"},"excerpt":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"coverImage":{"anyOf":[{"anyOf":[{"type":"string","const":""},{"type":"string","maxLength":2048,"format":"uri"}]},{"type":"null"}]},"authorId":{"anyOf":[{"type":"string","minLength":1,"maxLength":128},{"type":"null"}]},"publishedAt":{"anyOf":[{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},{"type":"null"}]},"translationGroupId":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"metaTitle":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"metaDescription":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"ogImage":{"anyOf":[{"anyOf":[{"type":"string","const":""},{"type":"string","maxLength":2048,"format":"uri"}]},{"type":"null"}]},"ogTitle":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"ogDescription":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"canonicalUrl":{"anyOf":[{"anyOf":[{"type":"string","const":""},{"type":"string","maxLength":2048,"format":"uri"}]},{"type":"null"}]},"keywords":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"categoryIds":{"maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}},"tagIds":{"maxItems":100,"type":"array","items":{"type":"string","minLength":1,"maxLength":128}}},"required":[],"additionalProperties":false,"$defs":{"__schema0":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema0"}},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema0"}}]},"__schema1":{"anyOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"$ref":"#/$defs/__schema1"}},{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"$ref":"#/$defs/__schema1"}}]}}}}}},"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"delete":{"operationId":"delete_posts","description":"Permanently delete posts. Published posts additionally require content:publish. Ask the user before deleting. Required scope: content:delete.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}/categories":{"get":{"operationId":"list_categories","description":"List categories, paginated. Posts include drafts; results are private. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":10000}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"post":{"operationId":"create_categories","description":"Create categories. Posts default to draft; publishing additionally requires content:publish. Use Editor.js JSON for content. Required scope: content:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]}},"required":["name","slug"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}/categories/{id}":{"get":{"operationId":"get_categories","description":"Read one categories record by its internal ID, not its slug. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"patch":{"operationId":"update_categories","description":"Update only supplied fields in categories. Editing a published post or changing publication state additionally requires content:publish. Required scope: content:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"},"description":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"delete":{"operationId":"delete_categories","description":"Permanently delete categories. Published posts additionally require content:publish. Ask the user before deleting. Required scope: content:delete.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}/tags":{"get":{"operationId":"list_tags","description":"List tags, paginated. Posts include drafts; results are private. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":10000}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"post":{"operationId":"create_tags","description":"Create tags. Posts default to draft; publishing additionally requires content:publish. Use Editor.js JSON for content. Required scope: content:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"}},"required":["name","slug"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}/tags/{id}":{"get":{"operationId":"get_tags","description":"Read one tags record by its internal ID, not its slug. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"patch":{"operationId":"update_tags","description":"Update only supplied fields in tags. Editing a published post or changing publication state additionally requires content:publish. Required scope: content:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"delete":{"operationId":"delete_tags","description":"Permanently delete tags. Published posts additionally require content:publish. Ask the user before deleting. Required scope: content:delete.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}/authors":{"get":{"operationId":"list_authors","description":"List authors, paginated. Posts include drafts; results are private. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"page","in":"query","required":false,"schema":{"default":1,"type":"integer","minimum":1,"maximum":10000}},{"name":"limit","in":"query","required":false,"schema":{"default":20,"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"post":{"operationId":"create_authors","description":"Create authors. Posts default to draft; publishing additionally requires content:publish. Use Editor.js JSON for content. Required scope: content:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"bio":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"avatar":{"anyOf":[{"anyOf":[{"type":"string","const":""},{"type":"string","maxLength":2048,"format":"uri"}]},{"type":"null"}]}},"required":["name","slug","email"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}},"/api/v1/blogs/{blogId}/authors/{id}":{"get":{"operationId":"get_authors","description":"Read one authors record by its internal ID, not its slug. Required scope: content:read.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"patch":{"operationId":"update_authors","description":"Update only supplied fields in authors. Editing a published post or changing publication state additionally requires content:publish. Required scope: content:write.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":300},"slug":{"type":"string","minLength":1,"maxLength":200,"pattern":"^[\\p{L}\\p{N}]+(?:[-_][\\p{L}\\p{N}]+)*$"},"email":{"type":"string","maxLength":254,"format":"email","pattern":"^(?!\\.)(?!.*\\.\\.)([A-Za-z0-9_'+\\-\\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"bio":{"anyOf":[{"type":"string","maxLength":10000},{"type":"null"}]},"avatar":{"anyOf":[{"anyOf":[{"type":"string","const":""},{"type":"string","maxLength":2048,"format":"uri"}]},{"type":"null"}]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}},"delete":{"operationId":"delete_authors","description":"Permanently delete authors. Published posts additionally require content:publish. Ask the user before deleting. Required scope: content:delete.","security":[{"bearerAuth":[]}],"parameters":[{"name":"blogId","in":"path","required":true,"schema":{"type":"string"},"description":"Public Blog ID (UUID), not a key"},{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Internal record ID, not slug"}],"responses":{"200":{"description":"Success: data (and pagination on lists)"},"400":{"description":"Invalid input"},"401":{"description":"Invalid, missing, expired or revoked API key"},"403":{"description":"Insufficient scope or wrong blog/origin"},"404":{"description":"Record not found"},"409":{"description":"Duplicate slug/email"},"413":{"description":"Body too large"},"415":{"description":"Expected JSON"},"429":{"description":"Rate limit exceeded; Retry-After: 60"},"500":{"description":"Internal server error"},"503":{"description":"Media storage not configured"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"Zenex API key"}}}}