{
	"openapi": "3.1.0",
	"info": {
		"title": "GenuineAI API",
		"version": "1.0.0",
		"description": "The GenuineAI platform API.\n\nAuthenticate with an API key in `X-Api-Key` and name your workspace in `X-Tenant-Id`. Every response is JSON; every error is `application/problem+json` carrying a code from a closed vocabulary. Request bodies are capped at 10mb.\n\nWorkspace isolation is enforced in the database by row-level security, not in application code: a request cannot read another workspace's rows even if the API asks it to.",
		"contact": {
			"name": "GenuineAI support",
			"url": "https://genuinehq.com/contact/",
			"email": "support@genuinehq.com"
		},
		"termsOfService": "https://genuinehq.com/terms/"
	},
	"servers": [
		{
			"url": "https://api.genuineai.app/api/v1",
			"description": "Production"
		}
	],
	"security": [
		{
			"ApiKeyAuth": []
		},
		{
			"BearerAuth": []
		}
	],
	"tags": [
		{
			"name": "Agents",
			"description": "The AI agents a workspace runs — their prompt, model, tools and knowledge."
		},
		{
			"name": "Albums",
			"description": "Collections of media, either curated by hand or defined by a saved filter."
		},
		{
			"name": "Assist",
			"description": "Small single-purpose AI helpers invoked from inside a field or a canvas."
		},
		{
			"name": "Audit",
			"description": "Who changed what, and when."
		},
		{
			"name": "CMS sync",
			"description": "Two-way sync between a site's content and an external CMS."
		},
		{
			"name": "Chat widgets",
			"description": "The embeddable chat widget: its configuration, conversations and captured leads."
		},
		{
			"name": "Content approval flows",
			"description": "The review a page goes through between being drafted and being fit to publish: the steps, what each move is called, and who may make it."
		},
		{
			"name": "Content schemas",
			"description": "The field shapes a page type can be generated into — not page designs."
		},
		{
			"name": "Design categories",
			"description": "The workspace's taxonomy for designs — the terms the design library files and filters by."
		},
		{
			"name": "Designs",
			"description": "Editable multi-layer artwork, its fillable fields and its data-bound charts."
		},
		{
			"name": "Distribution control",
			"description": "The named country sets an asset's public reach is built from, and which of them the whole workspace is held to."
		},
		{
			"name": "Document folders",
			"description": "How the document library is organized: nested folders, and folders that fill themselves from a saved filter."
		},
		{
			"name": "Document relations",
			"description": "Typed links between documents — a translation and its source, a revision and the one it replaces — and the relationship types a workspace defines for them."
		},
		{
			"name": "Documents",
			"description": "The document library — data sheets, decks, manuals and schedules, with the summary and searchable text written for each one on arrival."
		},
		{
			"name": "Downloads",
			"description": "Getting bytes back out: a signed URL for one file, a stream for the kinds a browser shows inline, and a job for a whole selection at once."
		},
		{
			"name": "Extensions",
			"description": "Features built for one workspace that run outside the platform, and the small documents each keeps in the workspace."
		},
		{
			"name": "Faces",
			"description": "Faces detected in a photo. A face is a detection until it is linked to a person — naming and merging are in People.",
			"x-stability": "beta"
		},
		{
			"name": "File analysis",
			"description": "What AI read out of a file — the fields it filled, and the markdown rendition it read them from."
		},
		{
			"name": "File versions",
			"description": "Every save keeps the copy it replaced. Versions are per file, are capped, and count against stored bytes."
		},
		{
			"name": "Files",
			"description": "Everything stored in the workspace: what it is, where it sits, and how it is found. Bytes move through signed URLs, never through the API."
		},
		{
			"name": "Infographics",
			"description": "Generated data graphics: an HTML source and the image rendered from it."
		},
		{
			"name": "Integrations",
			"description": "Connections to third-party products, and the actions each one exposes."
		},
		{
			"name": "Issued share links",
			"description": "Every link the workspace has published outward, whoever made it, with what each one has been used for."
		},
		{
			"name": "Knowledge base records",
			"description": "Reading records across knowledge bases. Writing goes through the base that holds them."
		},
		{
			"name": "Knowledge base schemas",
			"description": "The record shapes form-backed knowledge bases use, including the standard templates a new base starts from."
		},
		{
			"name": "Knowledge bases",
			"description": "The sets of records agents retrieve from."
		},
		{
			"name": "Me",
			"description": "The calling user: who they are, what they may do, and how they have signed in."
		},
		{
			"name": "Media analysis schemas",
			"description": "What the workspace adds to media analysis — the fields the vision model extracts from every analyzed image, over and above the built-in analysis."
		},
		{
			"name": "Media status flows",
			"description": "The statuses media moves through before the whole workspace sees it, and who may move it — the review pipeline behind the media library."
		},
		{
			"name": "Media tag groups",
			"description": "The tag groups the media library files by, including the ones AI analysis fills in — defining them, and replacing the structure wholesale."
		},
		{
			"name": "Media tags",
			"description": "Adding a tag to a group that already exists, done while filing something."
		},
		{
			"name": "Memories",
			"description": "What the assistant remembers about the calling user. Personal, never workspace-wide."
		},
		{
			"name": "Messages",
			"description": "The messages in a conversation, and the endpoint that runs the model."
		},
		{
			"name": "Object lifecycle flows",
			"description": "The states records move through — draft, approved, end-of-life, whatever the workspace defines — and who may move them. Objects created while a flow is active start in its initial state.",
			"x-stability": "beta"
		},
		{
			"name": "Object schemas",
			"description": "The attribute definitions object kinds are described by — the fields a product, a venue or a course carries.",
			"x-stability": "beta"
		},
		{
			"name": "Object sources",
			"description": "The systems that own the product data records are pulled from, with the mapping onto object types and the runs that loaded or refreshed the catalog from them.",
			"x-stability": "beta"
		},
		{
			"name": "Object taxonomies",
			"description": "The classification schemes objects are filed under. Several independent trees coexist, and an object may sit in as many of them as it needs.",
			"x-stability": "beta"
		},
		{
			"name": "Objects",
			"description": "The workspace's own records — products, venues, courses, equipment. Their attributes come from a form rather than from fixed columns, and they link to each other, to files and to classification nodes.",
			"x-stability": "beta"
		},
		{
			"name": "People",
			"description": "The named identities faces are grouped into, and the suggestions that propose each grouping. The detections themselves are in Faces.",
			"x-stability": "beta"
		},
		{
			"name": "Presentation templates",
			"description": "The .pptx files presentations are generated into.",
			"x-stability": "beta"
		},
		{
			"name": "Presentations",
			"description": "Generated decks: plan, generate, edit slide images, rebuild.",
			"x-stability": "beta"
		},
		{
			"name": "Prompt categories",
			"description": "The workspace's taxonomy for prompts — the terms the prompt catalog files and filters by."
		},
		{
			"name": "Prompts",
			"description": "Reusable prompts and the inputs they ask for."
		},
		{
			"name": "Publications",
			"description": "Releasing an asset to a permanent public URL: which version is live, when it is reachable, and from where."
		},
		{
			"name": "Roles",
			"description": "Permission sets, who holds them, and every change made to one."
		},
		{
			"name": "Scheduled jobs",
			"description": "Recurring work the platform runs for a workspace: when each job runs, what a workspace changes about that, and what every run did."
		},
		{
			"name": "Share links",
			"description": "Links that hand files out, or take files in, without an account."
		},
		{
			"name": "Social",
			"description": "Which social accounts are connected, and posting to them immediately or on a schedule."
		},
		{
			"name": "Social calendar",
			"description": "The dated events daily media generation makes graphics for: the ones shared with every workspace, the workspace's own, and the design template each is drawn from."
		},
		{
			"name": "Social connections",
			"description": "Connecting a social account to the workspace and disconnecting it — the credential everyone's posts are published under."
		},
		{
			"name": "Spaces",
			"description": "Shared homes for conversations, with their own membership."
		},
		{
			"name": "Stock photos",
			"description": "Searching a third-party stock photography library, and copying a photo out of it into the workspace. A search result is the provider's, not the workspace's, until it is imported."
		},
		{
			"name": "Storage",
			"description": "What is stored, by whom, and what could be reclaimed — including the duplicate copies and the merge that removes them."
		},
		{
			"name": "Studio",
			"description": "Generating images and infographics as standalone pieces."
		},
		{
			"name": "Tasks",
			"description": "Work items, their review flow, and the routines and autopilot that do them.",
			"x-stability": "beta"
		},
		{
			"name": "Threads",
			"description": "Conversations, who they are shared with, and their live event stream."
		},
		{
			"name": "Uploads",
			"description": "Getting bytes in. Every route here hands back a signed URL to PUT to; the file is not real until it is finalized."
		},
		{
			"name": "Usage",
			"description": "What the workspace has consumed against what its plan allows."
		},
		{
			"name": "Usage breakdown",
			"description": "The itemized record behind the total: who spent what, on which model, in which module."
		},
		{
			"name": "Users",
			"description": "The people in a workspace: their membership, the roles they hold, and the record of both."
		},
		{
			"name": "Voice agents",
			"description": "AI agents that answer a phone number, and the calls they take."
		},
		{
			"name": "Website content",
			"description": "Sites, their page trees, and the AI that drafts and fills them."
		},
		{
			"name": "Wildcards",
			"description": "Named inputs a prompt can ask for, and how each is collected."
		},
		{
			"name": "Workflow instances",
			"description": "Individual runs of a workflow: what each one did, where it got to, and what it is waiting on."
		},
		{
			"name": "Workflows",
			"description": "Multi-step processes: authored, compiled, deployed, then run."
		},
		{
			"name": "Workspace settings",
			"description": "The defaults everything new in the workspace inherits."
		}
	],
	"x-tagGroups": [
		{
			"name": "Core",
			"tags": [
				"Me",
				"Usage"
			]
		},
		{
			"name": "Media library",
			"tags": [
				"Files",
				"Uploads",
				"Stock photos",
				"Downloads",
				"File versions",
				"File analysis",
				"Media analysis schemas",
				"Faces",
				"Albums",
				"People",
				"Media tags",
				"Share links",
				"Publications",
				"Distribution control"
			]
		},
		{
			"name": "AI",
			"tags": [
				"Agents",
				"Threads",
				"Messages",
				"Spaces",
				"Prompts",
				"Prompt categories",
				"Wildcards",
				"Memories",
				"Assist"
			]
		},
		{
			"name": "Documents",
			"tags": [
				"Documents",
				"Document folders",
				"Document relations"
			]
		},
		{
			"name": "Knowledge",
			"tags": [
				"Knowledge bases",
				"Knowledge base records",
				"Knowledge base schemas",
				"Objects",
				"Object taxonomies",
				"Object schemas",
				"Object lifecycle flows",
				"Object sources"
			]
		},
		{
			"name": "Creative",
			"tags": [
				"Designs",
				"Design categories",
				"Studio",
				"Infographics",
				"Presentations",
				"Presentation templates"
			]
		},
		{
			"name": "Website & content",
			"tags": [
				"Website content",
				"Content schemas",
				"Content approval flows",
				"CMS sync",
				"Social"
			]
		},
		{
			"name": "Automation",
			"tags": [
				"Workflows",
				"Workflow instances",
				"Tasks",
				"Scheduled jobs",
				"Integrations",
				"Extensions"
			]
		},
		{
			"name": "Customer channels",
			"tags": [
				"Chat widgets",
				"Voice agents"
			]
		},
		{
			"name": "Administration",
			"tags": [
				"Users",
				"Roles",
				"Workspace settings",
				"Audit",
				"Storage",
				"Usage breakdown",
				"Media tag groups",
				"Media status flows",
				"Issued share links",
				"Social connections",
				"Social calendar"
			]
		}
	],
	"paths": {
		"/admin/access-logs": {
			"get": {
				"operationId": "listAccessLogs",
				"summary": "List the access log",
				"tags": [
					"Audit"
				],
				"description": "Returns the workspace's request log — who called what, when, and with which parameters.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "log_body",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "log_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "log_method",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "log_params",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "log_query",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "log_timestamp",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "log_url",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "log_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "log_user_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/AccessLogEntry"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:log:view"
			}
		},
		"/admin/calendar-events": {
			"get": {
				"operationId": "listCalendarEvents",
				"summary": "List calendar events",
				"tags": [
					"Social calendar"
				],
				"description": "The events daily media generation picks from, earliest first. `ce_source` says where each came from: `system` events are shared with every workspace and can be hidden but not edited, `feed` events come from the workspace's own calendar subscription, and `custom` events were added here. Hidden events are listed too, flagged `ce_hidden`, so they can be restored.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "from",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "date-time"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "to",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "date-time"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/CalendarEvent"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:settings:view"
			},
			"post": {
				"operationId": "createCalendarEvent",
				"summary": "Add a calendar event",
				"tags": [
					"Social calendar"
				],
				"description": "Adds an event of the workspace's own. Pass `ce_template` to have its graphic drawn from that design template.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"ce_summary": {
										"type": "string",
										"minLength": 1,
										"maxLength": 200
									},
									"ce_start": {
										"type": "string",
										"format": "date-time"
									},
									"ce_description": {
										"type": "string",
										"maxLength": 4000
									},
									"ce_location": {
										"type": "string",
										"maxLength": 300
									},
									"ce_end": {
										"type": "string",
										"format": "date-time"
									},
									"ce_template": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"ce_summary",
									"ce_start"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/CalendarEvent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:settings:edit"
			}
		},
		"/admin/calendar-events/{id}": {
			"delete": {
				"operationId": "deleteCalendarEvent",
				"summary": "Delete a calendar event",
				"tags": [
					"Social calendar"
				],
				"description": "Deletes an event the workspace added. Shared and subscribed events are hidden instead.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:settings:edit"
			},
			"patch": {
				"operationId": "updateCalendarEvent",
				"summary": "Edit a calendar event",
				"tags": [
					"Social calendar"
				],
				"description": "`ce_hidden` and `ce_template` apply to any event. The title, dates, location and description can only be changed on an event the workspace added itself. A template assigned here replaces AI image generation for that event: the template's layout, fonts, colors and images stay as approved, and only its text is written.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"ce_summary": {
										"type": "string",
										"minLength": 1,
										"maxLength": 200
									},
									"ce_start": {
										"type": "string",
										"format": "date-time"
									},
									"ce_hidden": {
										"type": "boolean"
									},
									"ce_description": {
										"type": "string",
										"maxLength": 4000
									},
									"ce_location": {
										"type": "string",
										"maxLength": 300
									},
									"ce_end": {
										"type": "string",
										"format": "date-time"
									},
									"ce_template": {
										"type": "string",
										"format": "uuid"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/CalendarEvent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:settings:edit"
			}
		},
		"/admin/delivery-settings": {
			"get": {
				"operationId": "getDeliverySettings",
				"summary": "Get the delivery settings",
				"tags": [
					"Distribution control"
				],
				"description": "The hostname permanent URLs are issued against and the image drawn over watermarked renditions. An unset hostname means the platform default, which is what almost every workspace uses.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"hostname": {
											"type": [
												"string",
												"null"
											]
										},
										"hostname_default": {
											"type": "string"
										},
										"watermark_file": {
											"type": [
												"string",
												"null"
											],
											"format": "uuid"
										},
										"watermark_name": {
											"type": [
												"string",
												"null"
											]
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:settings:view",
				"x-required-plan": "module-publication"
			},
			"patch": {
				"operationId": "updateDeliverySettings",
				"summary": "Update the delivery settings",
				"tags": [
					"Distribution control"
				],
				"description": "Point published URLs at your own subdomain by sending its hostname and a CNAME to the platform hostname; send `null` to go back to the default. A hostname already claimed by another workspace is refused. Changing it moves the URLs shown for every published asset, and the previous hostname keeps resolving so links already in circulation are not broken.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"hostname": {
										"type": "string",
										"maxLength": 253
									},
									"watermark_file": {
										"type": "string",
										"format": "uuid"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:settings:edit",
				"x-required-plan": "module-publication"
			}
		},
		"/admin/geo-restrictions": {
			"get": {
				"operationId": "listGeoRestrictions",
				"summary": "List geo restrictions",
				"tags": [
					"Distribution control"
				],
				"description": "The workspace's named country sets, with how many published assets reference each. Every country in one is blocked. A set marked `geo_workspace_wide` blocks on every published asset whether or not the asset names it.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/GeoRestriction"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:geo-restriction:view",
				"x-required-plan": "module-publication"
			},
			"post": {
				"operationId": "createGeoRestriction",
				"summary": "Add a geo restriction",
				"tags": [
					"Distribution control"
				],
				"description": "Pass `template` to start from one of the shipped catalogs. It fills the countries when you send none of your own, and records which catalog it came from either way. A catalog is copied once and owned by the workspace from that moment; it is never updated for you.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"geo_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 120
									},
									"template": {
										"type": "string"
									},
									"geo_countries": {
										"type": "array",
										"items": {
											"type": "string",
											"minLength": 2,
											"maxLength": 2
										}
									},
									"geo_workspace_wide": {
										"type": "boolean"
									}
								},
								"required": [
									"geo_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/GeoRestriction"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:geo-restriction:edit",
				"x-required-plan": "module-publication"
			}
		},
		"/admin/geo-restrictions/{id}": {
			"delete": {
				"operationId": "deleteGeoRestriction",
				"summary": "Delete a restriction",
				"tags": [
					"Distribution control"
				],
				"description": "Deactivates the restriction and stops it fencing anything. Assets referencing it keep serving.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:geo-restriction:edit",
				"x-required-plan": "module-publication"
			},
			"get": {
				"operationId": "getGeoRestriction",
				"summary": "Get a geo restriction",
				"tags": [
					"Distribution control"
				],
				"description": "One restriction and the countries it blocks, as ISO 3166-1 alpha-2 codes.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/GeoRestriction"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:geo-restriction:view",
				"x-required-plan": "module-publication"
			},
			"patch": {
				"operationId": "updateGeoRestriction",
				"summary": "Edit a geo restriction",
				"tags": [
					"Distribution control"
				],
				"description": "Editing the countries or the workspace-wide flag reaches every asset the restriction governs on the next edge refresh, within about a minute. No asset is rewritten.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"geo_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 120
									},
									"geo_countries": {
										"type": "array",
										"items": {
											"type": "string",
											"minLength": 2,
											"maxLength": 2
										}
									},
									"geo_workspace_wide": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/GeoRestriction"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:geo-restriction:edit",
				"x-required-plan": "module-publication"
			}
		},
		"/admin/geo-restrictions/templates": {
			"get": {
				"operationId": "listGeoRestrictionTemplates",
				"summary": "List starter catalogs",
				"tags": [
					"Distribution control"
				],
				"description": "Shipped country sets for common regimes, offered as a starting point to copy and verify against the workspace's own trade compliance requirements. They are static data, not a maintained authority.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"type": "object",
										"properties": {
											"id": {
												"type": "string"
											},
											"name": {
												"type": "string"
											},
											"countries": {
												"type": "array",
												"items": {
													"type": "string"
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:geo-restriction:view",
				"x-required-plan": "module-publication"
			}
		},
		"/admin/history": {
			"get": {
				"operationId": "listAuditHistory",
				"summary": "List audit history",
				"tags": [
					"Audit"
				],
				"description": "Returns the workspace's audit trail: who changed which record, when, and what the changeset was.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "history_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "history_op",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "history_record",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "history_table",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "history_timestamp",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "history_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "history_user_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/AuditEvent"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:audit:view"
			}
		},
		"/admin/media-duplicates": {
			"get": {
				"operationId": "listMediaDuplicates",
				"summary": "List duplicate media",
				"tags": [
					"Storage"
				],
				"description": "Groups of byte-identical files, with the copy proposed as the one to keep.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"image",
								"video",
								"audio",
								"other"
							],
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 100
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0
						}
					},
					{
						"name": "rule",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"references",
								"metadata",
								"oldest",
								"newest"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"waste",
								"copies",
								"name",
								"recent"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media:deduplicate"
			}
		},
		"/admin/media-duplicates/resolve": {
			"post": {
				"operationId": "resolveMediaDuplicates",
				"summary": "Merge duplicates",
				"tags": [
					"Storage"
				],
				"description": "Re-points everything referencing a removed copy — albums, social posts, presentation files, versions and child files — onto the copy being kept, merges their metadata into it, and then deletes the rest. Nothing is left pointing at a file that has gone.\n\nRemoved copies stay recoverable for the trash retention period. Needs permission both to deduplicate and to delete files.\n\nRequires both `admin:media:deduplicate` and `media:delete`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"groups": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"keep": {
													"type": "string",
													"format": "uuid"
												},
												"remove": {
													"type": "array",
													"items": {
														"type": "string",
														"format": "uuid"
													}
												}
											},
											"required": [
												"keep",
												"remove"
											]
										}
									},
									"merge_metadata": {
										"type": "boolean"
									}
								},
								"required": [
									"groups"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"admin:media:deduplicate",
					"media:delete"
				],
				"x-permission-mode": "all"
			}
		},
		"/admin/media-status-flows": {
			"get": {
				"operationId": "listMediaStatusFlows",
				"summary": "List flows",
				"tags": [
					"Media status flows"
				],
				"description": "Returns the workspace's media status flows, each with its statuses. At most one is active at a time.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sm_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/MediaStatusFlow"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-status-flow:view"
			},
			"post": {
				"operationId": "createMediaStatusFlow",
				"summary": "Create a flow",
				"tags": [
					"Media status flows"
				],
				"description": "Defines the statuses media moves through and who may move it. Answers 409 while an active flow exists — update or delete that one instead.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"states": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"si_label": {
													"type": "string"
												}
											},
											"required": [
												"si_label"
											]
										}
									},
									"transitions": {
										"type": "array",
										"items": {}
									},
									"sm_name": {
										"type": "string"
									},
									"sm_default": {
										"type": "boolean"
									}
								},
								"required": [
									"states"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/MediaStatusFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-status-flow:edit"
			}
		},
		"/admin/media-status-flows/{id}": {
			"delete": {
				"operationId": "deactivateMediaStatusFlow",
				"summary": "Delete a flow",
				"tags": [
					"Media status flows"
				],
				"description": "Stops media being governed. Files keep the status they are in.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-status-flow:edit"
			},
			"get": {
				"operationId": "getMediaStatusFlow",
				"summary": "Get a flow",
				"tags": [
					"Media status flows"
				],
				"description": "Returns the flow with its statuses, its transitions, and the roles each transition requires.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/MediaStatusFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-status-flow:view"
			},
			"put": {
				"operationId": "updateMediaStatusFlow",
				"summary": "Update a flow",
				"tags": [
					"Media status flows"
				],
				"description": "Replaces the flow's statuses and transitions. Files already sitting in a status the new definition drops keep that value until something moves them.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"states": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"si_label": {
													"type": "string"
												}
											},
											"required": [
												"si_label"
											]
										}
									},
									"transitions": {
										"type": "array",
										"items": {}
									},
									"sm_name": {
										"type": "string"
									},
									"sm_default": {
										"type": "boolean"
									}
								},
								"required": [
									"states"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/MediaStatusFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-status-flow:edit"
			}
		},
		"/admin/media-tags": {
			"get": {
				"operationId": "listMediaTagGroups",
				"summary": "List tag groups",
				"tags": [
					"Media tag groups"
				],
				"description": "Returns a library's tag groups and the tags in each, including the groups AI analysis fills in. `scope` picks the library — `media` for the photo library, `docs` for the document library — and defaults to `media`. The two vocabularies are independent even where a group name appears in both.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "mt_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "mt_ai_detection",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "mt_group",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "scope",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"docs"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-tag:view"
			},
			"post": {
				"operationId": "saveMediaTagStructure",
				"summary": "Replace tag groups",
				"tags": [
					"Media tag groups"
				],
				"description": "Send the whole structure — this replaces it rather than merging into it. It replaces one `scope` only, so saving the photo library's groups leaves the document library's alone.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"scope": {
										"enum": [
											"media",
											"docs"
										],
										"type": "string"
									},
									"groups": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"name": {
													"type": "string",
													"minLength": 1
												},
												"tags": {
													"type": "array",
													"items": {}
												}
											},
											"required": [
												"name",
												"tags"
											]
										}
									}
								},
								"required": [
									"groups"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-tag:edit"
			}
		},
		"/admin/roles": {
			"get": {
				"operationId": "listRoles",
				"summary": "List roles",
				"tags": [
					"Roles"
				],
				"description": "Returns the workspace's roles with the permissions each grants, plus `role_users_count` — how many active members currently hold it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "role_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "role_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "role_managed_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "role_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "role_permissions",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Role"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:role:view"
			},
			"post": {
				"operationId": "createRole",
				"summary": "Create a role",
				"tags": [
					"Roles"
				],
				"description": "A role is a set of permissions. What its holders can actually do is that set narrowed by the plan — granting a permission the plan does not include has no effect until the plan does.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"role_name": {
										"type": "string",
										"minLength": 1
									},
									"role_active": {
										"type": "boolean"
									},
									"role_permissions": {
										"type": "array",
										"items": {}
									}
								},
								"required": [
									"role_name",
									"role_active",
									"role_permissions"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Role"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:role:create"
			}
		},
		"/admin/roles/{id}": {
			"get": {
				"operationId": "getRole",
				"summary": "Get a role",
				"tags": [
					"Roles"
				],
				"description": "Returns the role with the permissions it grants. What a member of it may actually do is that set narrowed by the workspace's plan.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Role"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:role:view"
			},
			"patch": {
				"operationId": "updateRole",
				"summary": "Update a role",
				"tags": [
					"Roles"
				],
				"description": "Takes effect for everyone holding the role, on their next request.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"role_name": {
										"type": "string",
										"minLength": 1
									},
									"role_active": {
										"type": "boolean"
									},
									"role_permissions": {
										"type": "array",
										"items": {}
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Role"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:role:edit"
			}
		},
		"/admin/roles/{id}/history": {
			"get": {
				"operationId": "listRoleHistory",
				"summary": "List role history",
				"tags": [
					"Roles"
				],
				"description": "Every recorded change, newest first, each as a per-field `{from, to}` changeset.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"type": "object",
										"properties": {
											"history_id": {
												"type": "string",
												"format": "uuid"
											},
											"history_timestamp": {
												"type": "string",
												"format": "date-time"
											},
											"history_user": {
												"type": [
													"string",
													"null"
												],
												"format": "uuid"
											},
											"history_op": {
												"type": "string",
												"description": "The kind of change — insert, update or delete."
											},
											"history_changeset": {
												"type": "object",
												"description": "One entry per field that changed, keyed by column name.",
												"additionalProperties": {
													"type": "object",
													"properties": {
														"from": {},
														"to": {}
													}
												}
											},
											"history_ref": {
												"type": "object",
												"description": "What the writer noted about the change rather than the columns: the action that made it, or the reason it was made."
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:role:view"
			}
		},
		"/admin/security-events": {
			"get": {
				"operationId": "listSecurityEvents",
				"summary": "List security events",
				"tags": [
					"Audit"
				],
				"description": "Authentication activity across the workspace — sign-in attempts, credential changes, second-factor actions and account blocks, as the identity provider reported them.\n\nEvents are recorded when authentication is processed, which is not always when a person acted: a token exchange renewing a session carries its own timestamp. Filter on `ae_type` to narrow to the events a person caused, and on `ae_success` to separate attempts from outcomes.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "ae_city",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ae_connection",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ae_country",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ae_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "ae_ip",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ae_success",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "ae_timestamp",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ae_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ae_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "ae_user_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/SecurityEvent"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:security-event:view"
			}
		},
		"/admin/share-links": {
			"get": {
				"operationId": "listShareLinks",
				"summary": "List all share links",
				"tags": [
					"Issued share links"
				],
				"description": "Returns every share link in the workspace, whoever made it, with their view, download and upload counts. The link token and password are never returned. To read only your own links, call `GET /share-links` instead — it is scoped to the caller and needs no administrative grant.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "share_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "share_album_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "share_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "share_created_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "share_created_by_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "share_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "share_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "share_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ShareLink"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:share-link:view"
			}
		},
		"/admin/social/{platform}/auth-url": {
			"get": {
				"operationId": "getSocialAuthUrl",
				"summary": "Start a connection",
				"tags": [
					"Social connections"
				],
				"description": "Returns the URL to send the person to. Nothing is connected until the callback comes back.\n\nRequires the `module-social-post` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "platform",
						"in": "path",
						"required": true,
						"schema": {
							"enum": [
								"instagram"
							],
							"type": "string"
						}
					},
					{
						"name": "redirect_uri",
						"in": "query",
						"required": true,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:social:edit",
				"x-required-plan": "module-social-post"
			}
		},
		"/admin/social/{platform}/callback": {
			"post": {
				"operationId": "completeSocialConnection",
				"summary": "Finish a connection",
				"tags": [
					"Social connections"
				],
				"description": "Exchanges the code the platform redirected back with for a stored connection. This is the second half of the flow `auth-url` starts.\n\nRequires the `module-social-post` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "platform",
						"in": "path",
						"required": true,
						"schema": {
							"enum": [
								"instagram"
							],
							"type": "string"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"code": {
										"type": "string"
									},
									"redirect_uri": {
										"type": "string"
									},
									"state": {
										"type": "string"
									}
								},
								"required": [
									"code",
									"redirect_uri"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:social:edit",
				"x-required-plan": "module-social-post"
			}
		},
		"/admin/social/{platform}/disconnect": {
			"delete": {
				"operationId": "disconnectSocialAccount",
				"summary": "Disconnect an account",
				"tags": [
					"Social connections"
				],
				"description": "Publishing to that platform stops working. Posts already published are unaffected.\n\nRequires the `module-social-post` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "platform",
						"in": "path",
						"required": true,
						"schema": {
							"enum": [
								"instagram"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:social:edit",
				"x-required-plan": "module-social-post"
			}
		},
		"/admin/storage/breakdown": {
			"get": {
				"operationId": "getStorageBreakdown",
				"summary": "Get a storage breakdown",
				"tags": [
					"Storage"
				],
				"description": "Grouped by module, file type or user — file count and total size per group.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "group_by",
						"in": "query",
						"required": true,
						"schema": {
							"enum": [
								"module",
								"type",
								"user",
								"origin"
							],
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "module",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"knowledge",
								"chat",
								"chatAi",
								"designs",
								"presentations",
								"prompts",
								"forms",
								"fonts",
								"profile",
								"other"
							],
							"type": "string"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "origin",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"uploaded",
								"generated"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"image",
								"video",
								"audio",
								"pdf",
								"font",
								"document",
								"spreadsheet",
								"presentation",
								"archive",
								"text",
								"other"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:storage:view"
			}
		},
		"/admin/storage/files": {
			"get": {
				"operationId": "listLargestFiles",
				"summary": "List the largest files",
				"tags": [
					"Storage"
				],
				"description": "Returns the files consuming the most storage, largest first — the list to work down when reclaiming space.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "module",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"knowledge",
								"chat",
								"chatAi",
								"designs",
								"presentations",
								"prompts",
								"forms",
								"fonts",
								"profile",
								"other"
							],
							"type": "string"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "origin",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"uploaded",
								"generated"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"image",
								"video",
								"audio",
								"pdf",
								"font",
								"document",
								"spreadsheet",
								"presentation",
								"archive",
								"text",
								"other"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:storage:view"
			}
		},
		"/admin/storage/files/{id}": {
			"get": {
				"operationId": "getStoredFile",
				"summary": "Get a stored file",
				"tags": [
					"Storage"
				],
				"description": "What is claiming this file across the platform, and what else is attached to it — byte-identical copies and saved versions. This is what tells you whether deleting it would actually free space.\n\nUnlike the rest of the API, this is not filtered by who may see the file: it is an accounting view, and a total that hid rows would be the wrong number.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:storage:view"
			}
		},
		"/admin/storage/reclaim": {
			"get": {
				"operationId": "getReclaimableStorage",
				"summary": "Get reclaimable space",
				"tags": [
					"Storage"
				],
				"description": "Duplicate copies beyond the first, and what is sitting in the trash. `trashRetentionDays` is how long a deleted file stays recoverable — 0 means deletion is immediate.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:storage:view"
			}
		},
		"/admin/storage/summary": {
			"get": {
				"operationId": "getStorageSummary",
				"summary": "Get storage usage",
				"tags": [
					"Storage"
				],
				"description": "Bytes stored against bytes granted. `used` counts live files and their version history — the same figure the quota is enforced on, so it is the one to compare against `entitlement`. An entitlement of 0 means the plan grants no storage.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:storage:view"
			}
		},
		"/admin/storage/trend": {
			"get": {
				"operationId": "getStorageTrend",
				"summary": "Get the storage trend",
				"tags": [
					"Storage"
				],
				"description": "Stored bytes over time, for charting growth rather than for reconciling a bill.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "granularity",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"day",
								"month"
							],
							"type": "string"
						}
					},
					{
						"name": "module",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"knowledge",
								"chat",
								"chatAi",
								"designs",
								"presentations",
								"prompts",
								"forms",
								"fonts",
								"profile",
								"other"
							],
							"type": "string"
						}
					},
					{
						"name": "origin",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"uploaded",
								"generated"
							],
							"type": "string"
						}
					},
					{
						"name": "type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"image",
								"video",
								"audio",
								"pdf",
								"font",
								"document",
								"spreadsheet",
								"presentation",
								"archive",
								"text",
								"other"
							],
							"type": "string"
						}
					},
					{
						"name": "tz",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:storage:view"
			}
		},
		"/admin/usage/aggregated": {
			"get": {
				"operationId": "getAggregatedUsage",
				"summary": "Get usage totals",
				"tags": [
					"Usage breakdown"
				],
				"description": "Consumption totalled over a period, for a bill or a budget. For the individual entries behind a total, read the usage entries.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "pivot",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "usage_details",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"contentMediaType": "application/json"
						}
					},
					{
						"name": "usage_param",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "usage_timestamp",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "usage_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:usage:view"
			}
		},
		"/admin/usage/details": {
			"get": {
				"operationId": "getUsageDetails",
				"summary": "Get usage details",
				"tags": [
					"Usage breakdown"
				],
				"description": "The individual entries making up one cell of the pivot, for tracing a number back to its source.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "agent_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "prompt_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "usage_details",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"contentMediaType": "application/json"
						}
					},
					{
						"name": "usage_param",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "usage_timestamp",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "usage_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:usage:view"
			}
		},
		"/admin/usage/entries": {
			"get": {
				"operationId": "listUsageEntries",
				"summary": "List usage entries",
				"tags": [
					"Usage breakdown"
				],
				"description": "Returns individual metered operations — what was run, by whom, and how many credits it consumed.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "usage_details",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"contentMediaType": "application/json"
						}
					},
					{
						"name": "usage_param",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "usage_timestamp",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "usage_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/UsageEntry"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:usage:view"
			}
		},
		"/admin/usage/pivot": {
			"get": {
				"operationId": "getPivotUsage",
				"summary": "Get a usage pivot",
				"tags": [
					"Usage breakdown"
				],
				"description": "Totals grouped both ways at once — by user and model, say — for a table rather than a list.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "group_by",
						"in": "query",
						"required": true,
						"schema": {
							"type": "string",
							"enum": [
								"date",
								"usage_user",
								"agent_name",
								"prompt_name",
								"usage_param"
							]
						}
					},
					{
						"name": "time_granularity",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"enum": [
								"day",
								"week",
								"month"
							]
						}
					},
					{
						"name": "tz",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "usage_details",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"contentMediaType": "application/json"
						}
					},
					{
						"name": "usage_param",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "usage_timestamp",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "usage_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:usage:view"
			}
		},
		"/admin/users": {
			"get": {
				"operationId": "listWorkspaceUsers",
				"summary": "List users",
				"tags": [
					"Users"
				],
				"description": "Everyone holding a membership in the calling workspace. Each row carries both the user account and that membership, so roles and last login come back with it. `external_user` marks an account that belongs to another workspace and is only a guest in this one.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "external_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "memb_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "memb_roles",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "usr_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "usr_email",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "usr_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "usr_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/User"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:user:view"
			},
			"post": {
				"operationId": "createWorkspaceUser",
				"summary": "Add a user",
				"tags": [
					"Users"
				],
				"description": "Adds a person to the workspace and sends them an invitation. A user already known to the platform is attached to this workspace rather than created again.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"usr_name_first": {
										"type": "string",
										"minLength": 1
									},
									"usr_name_last": {
										"type": "string",
										"minLength": 1
									},
									"usr_pass": {
										"type": "string",
										"minLength": 6
									},
									"usr_email": {
										"type": "string",
										"format": "email"
									},
									"usr_active": {
										"type": "boolean"
									},
									"memb_roles": {
										"type": "array",
										"items": {}
									}
								},
								"required": [
									"usr_name_first",
									"usr_name_last",
									"usr_email",
									"usr_active"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:user:create"
			}
		},
		"/admin/users/{id}": {
			"get": {
				"operationId": "getWorkspaceUser",
				"summary": "Get a user",
				"tags": [
					"Users"
				],
				"description": "Returns one member with the roles they hold in this workspace.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/User"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:user:view"
			},
			"patch": {
				"operationId": "updateWorkspaceUser",
				"summary": "Update a user",
				"tags": [
					"Users"
				],
				"description": "This is where a user's roles are set, and so what they may do.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"usr_name_first": {
										"type": "string",
										"minLength": 1
									},
									"usr_name_last": {
										"type": "string",
										"minLength": 1
									},
									"usr_email": {
										"type": "string",
										"format": "email"
									},
									"memb_roles": {
										"type": "array",
										"items": {}
									},
									"usr_active": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/User"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:user:edit"
			}
		},
		"/admin/users/{id}/history": {
			"get": {
				"operationId": "listWorkspaceUserHistory",
				"summary": "List user history",
				"tags": [
					"Users"
				],
				"description": "Every recorded change, newest first, each as a per-field `{from, to}` changeset.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"type": "object",
										"properties": {
											"history_id": {
												"type": "string",
												"format": "uuid"
											},
											"history_timestamp": {
												"type": "string",
												"format": "date-time"
											},
											"history_user": {
												"type": [
													"string",
													"null"
												],
												"format": "uuid"
											},
											"history_op": {
												"type": "string",
												"description": "The kind of change — insert, update or delete."
											},
											"history_changeset": {
												"type": "object",
												"description": "One entry per field that changed, keyed by column name.",
												"additionalProperties": {
													"type": "object",
													"properties": {
														"from": {},
														"to": {}
													}
												}
											},
											"history_ref": {
												"type": "object",
												"description": "What the writer noted about the change rather than the columns: the action that made it, or the reason it was made."
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:user:view"
			}
		},
		"/admin/users/{id}/reset-password": {
			"post": {
				"operationId": "resetWorkspaceUserPassword",
				"summary": "Send a password reset",
				"tags": [
					"Users"
				],
				"description": "Emails the user a reset link. No password is set or returned here.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:user:edit"
			}
		},
		"/admin/workspace-settings": {
			"get": {
				"operationId": "getWorkspaceSettings",
				"summary": "Get the settings",
				"tags": [
					"Workspace settings"
				],
				"description": "Returns the defaults everything new in the workspace inherits — its models, its language, and the behavior that is not per-object.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:settings:view"
			},
			"patch": {
				"operationId": "updateWorkspaceSettings",
				"summary": "Update the settings",
				"tags": [
					"Workspace settings"
				],
				"description": "The defaults new work in this workspace inherits.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"tenant_settings": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:settings:edit"
			}
		},
		"/agents": {
			"get": {
				"operationId": "listAgents",
				"summary": "List agents",
				"tags": [
					"Agents"
				],
				"description": "Returns the agents available to the workspace, including ones published by the platform. An agent the workspace does not own is listed without its prompt or model settings.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "agent_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "agent_audience",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "agent_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "agent_ds",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "agent_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "agent_managed_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "agent_model",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "agent_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "agent_tenant_enabled",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Agent"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"post": {
				"operationId": "createAgent",
				"summary": "Create an agent",
				"tags": [
					"Agents"
				],
				"description": "`agent_model` is restricted: a workspace may use the platform's own `genai-` models, and foundation models only where they have been enabled for it.\n\nKnowledge bases may be set at creation: `agent_ds` names the agent's default set in kebab-case, `agent_tenant_ds` is this workspace's selection of knowledge-base ids. Either can be changed later through the knowledge-bases endpoint.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agent_name": {
										"type": "string",
										"minLength": 1
									},
									"agent_description": {
										"type": "string",
										"minLength": 1
									},
									"agent_model": {
										"type": "string"
									},
									"agent_top_p": {
										"type": "string",
										"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
									},
									"agent_temperature": {
										"type": "string",
										"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
									},
									"agent_active": {
										"type": "boolean"
									},
									"agent_tools": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"agent_audience": {
										"enum": [
											"internal",
											"public"
										],
										"type": "string"
									},
									"agent_ds": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"agent_tenant_ds": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"agent_name",
									"agent_description",
									"agent_model",
									"agent_top_p",
									"agent_temperature"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Agent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "agent:create"
			}
		},
		"/agents/{id}": {
			"delete": {
				"operationId": "deleteAgent",
				"summary": "Delete an agent",
				"tags": [
					"Agents"
				],
				"description": "Soft delete: the agent stops being listed and stops answering, and is not erased.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "agent:delete"
			},
			"get": {
				"operationId": "getAgent",
				"summary": "Get an agent",
				"tags": [
					"Agents"
				],
				"description": "An agent the workspace does not own — one published by the platform — comes back without its prompt or model settings.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Agent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "agent:view"
			},
			"patch": {
				"operationId": "updateAgent",
				"summary": "Update an agent",
				"tags": [
					"Agents"
				],
				"description": "Only the fields present in the body change. The same model restriction as create applies.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agent_name": {
										"type": "string",
										"minLength": 1
									},
									"agent_description": {
										"type": "string",
										"minLength": 1
									},
									"agent_model": {
										"type": "string"
									},
									"agent_top_p": {
										"type": "string",
										"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
									},
									"agent_temperature": {
										"type": "string",
										"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
									},
									"agent_active": {
										"type": "boolean"
									},
									"agent_tools": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"agent_audience": {
										"enum": [
											"internal",
											"public"
										],
										"type": "string"
									},
									"agent_tenant_instructions": {
										"type": "string",
										"maxLength": 20000
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Agent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "agent:edit"
			}
		},
		"/agents/{id}/ds": {
			"patch": {
				"operationId": "updateAgentKnowledgeBases",
				"summary": "Set knowledge bases",
				"tags": [
					"Agents"
				],
				"description": "Two separate things, which is why they are two fields. `agent_ds` is the agent's own default set, named in kebab-case, and can only be changed on an agent this workspace manages. `agent_tenant_ds` is this workspace's selection of knowledge-base ids layered on top of that default — send `null` to drop the override and fall back to the agent's own set.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agent_ds": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"agent_tenant_ds": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Agent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "agent:knowledge:edit"
			}
		},
		"/agents/{id}/history": {
			"get": {
				"operationId": "listAgentHistory",
				"summary": "List agent history",
				"tags": [
					"Agents"
				],
				"description": "Every recorded change, newest first, each as a per-field `{from, to}` changeset.\n\nAgents are audited under the workspace that manages them, so for a platform-published agent this returns only the calling workspace's own overrides — its knowledge-base selection and extra instructions — and not the edit history of the underlying agent.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"type": "object",
										"properties": {
											"history_id": {
												"type": "string",
												"format": "uuid"
											},
											"history_timestamp": {
												"type": "string",
												"format": "date-time"
											},
											"history_user": {
												"type": [
													"string",
													"null"
												],
												"format": "uuid"
											},
											"history_op": {
												"type": "string",
												"description": "The kind of change — insert, update or delete."
											},
											"history_changeset": {
												"type": "object",
												"description": "One entry per field that changed, keyed by column name.",
												"additionalProperties": {
													"type": "object",
													"properties": {
														"from": {},
														"to": {}
													}
												}
											},
											"history_ref": {
												"type": "object",
												"description": "What the writer noted about the change rather than the columns: the action that made it, or the reason it was made."
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "agent:view"
			}
		},
		"/agents/{id}/history/{history_id}/revert": {
			"post": {
				"operationId": "revertAgent",
				"summary": "Revert to a version",
				"tags": [
					"Agents"
				],
				"description": "Puts the agent back to the state a history entry recorded, and audits the restore itself so it can be undone in turn. Only the fields the history view shows are written.\n\nA restore can write less than the version held, and `skipped` says what it left alone and why: a field whose stored value was last written outside the app has no audited value to restore over, and one the workspace may no longer set — a model it is no longer licensed for, a public audience without the chat-widget module — is refused rather than applied.\n\nFor a platform-published agent this restores only the calling workspace's own overrides, the same fields its history returns.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "history_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"restored": {
											"type": "array",
											"description": "Columns written back, by name.",
											"items": {
												"type": "string"
											}
										},
										"skipped": {
											"type": "array",
											"description": "Columns the version carried that were deliberately not written.",
											"items": {
												"type": "object",
												"properties": {
													"field": {
														"type": "string"
													},
													"reason": {
														"type": "string",
														"enum": [
															"unrecorded",
															"not_permitted"
														],
														"description": "unrecorded — the stored value was written outside the app, so there is no audited value to restore over it; not_permitted — restoring it needs a permission or plan the caller no longer has."
													},
													"detail": {
														"type": "string"
													}
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "agent:edit"
			}
		},
		"/agents/{id}/preview-system-prompt": {
			"get": {
				"operationId": "previewAgentSystemPrompt",
				"summary": "Preview the prompt",
				"tags": [
					"Agents"
				],
				"description": "Returns what the agent would actually be sent: its prompt with the workspace's extra instructions and knowledge-base section appended.\n\nFor a platform-published agent the base prompt is withheld — the response is only the parts this workspace contributed.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"systemPrompt": {
											"type": "string"
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "agent:edit"
			}
		},
		"/albums": {
			"get": {
				"operationId": "listAlbums",
				"summary": "List albums",
				"tags": [
					"Albums"
				],
				"description": "Returns albums with a cover preview, how many files each holds and how many child albums it has. A smart album carries the saved search it resolves in `album_query_search`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "album_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "album_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "album_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "album_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "album_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "album_parent",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "album_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "full_text_search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:view"
			},
			"post": {
				"operationId": "createAlbum",
				"summary": "Create an album",
				"tags": [
					"Albums"
				],
				"description": "Creates a curated album, which starts empty — add files to it with `POST /albums/{id}/files`. An album that fills itself from a saved filter is created through `POST /albums/smart` instead.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"album_name": {
										"type": "string",
										"minLength": 1
									},
									"album_description": {
										"type": "string"
									},
									"album_cover_file": {
										"type": "string",
										"format": "uuid"
									},
									"album_metadata": {
										"type": "object"
									},
									"album_acl": {
										"type": "object"
									},
									"album_active": {
										"type": "boolean"
									},
									"album_smart": {
										"type": "boolean"
									},
									"album_query": {
										"type": "string",
										"format": "uuid"
									},
									"album_parent": {
										"type": "string"
									}
								},
								"required": [
									"album_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:create"
			}
		},
		"/albums/{id}": {
			"delete": {
				"operationId": "deleteAlbum",
				"summary": "Delete an album",
				"tags": [
					"Albums"
				],
				"description": "Removes the album. The files it held stay in the library.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:delete"
			},
			"get": {
				"operationId": "getAlbum",
				"summary": "Get an album",
				"tags": [
					"Albums"
				],
				"description": "Returns the album with its resolved cover, its file and child counts, and — for a smart album — the filter it resolves.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:view"
			},
			"patch": {
				"operationId": "updateAlbum",
				"summary": "Update an album",
				"tags": [
					"Albums"
				],
				"description": "Applies the `album_`-prefixed fields present in the body. A smart album's filter is changed through `PATCH /albums/{id}/smart`, not here.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"album_name": {
										"type": "string",
										"minLength": 1
									},
									"album_description": {
										"type": "string"
									},
									"album_cover_file": {
										"type": "string",
										"format": "uuid"
									},
									"album_metadata": {
										"type": "object"
									},
									"album_acl": {
										"type": "object"
									},
									"album_parent": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:edit"
			}
		},
		"/albums/{id}/files": {
			"delete": {
				"operationId": "removeFilesFromAlbum",
				"summary": "Remove files",
				"tags": [
					"Albums"
				],
				"description": "Takes the files out of the album and leaves them in the library.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"file_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:curate"
			},
			"post": {
				"operationId": "addFilesToAlbum",
				"summary": "Add files",
				"tags": [
					"Albums"
				],
				"description": "Adds files to a curated album. Ids that match no file are skipped rather than failing the request, so a partly stale selection still lands.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"file_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:curate"
			}
		},
		"/albums/{id}/smart": {
			"patch": {
				"operationId": "updateSmartAlbumFilters",
				"summary": "Update smart filters",
				"tags": [
					"Albums"
				],
				"description": "Replaces the saved filter a smart album resolves. Membership is recomputed on read, so the change is visible immediately and no files are moved.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"album_name": {
										"type": "string",
										"minLength": 1
									},
									"album_description": {
										"type": "string"
									},
									"query_search": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:edit"
			}
		},
		"/albums/memberships": {
			"get": {
				"operationId": "listAlbumMemberships",
				"summary": "List album membership",
				"tags": [
					"Albums"
				],
				"description": "Returns which files belong to which album, without the file records themselves.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "af_album",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "af_file",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:view"
			}
		},
		"/albums/smart": {
			"post": {
				"operationId": "createSmartAlbum",
				"summary": "Create a smart album",
				"tags": [
					"Albums"
				],
				"description": "A smart album is a saved filter rather than a fixed list: its contents are whatever currently matches, so files join and leave it on their own as the library changes.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"album_name": {
										"type": "string",
										"minLength": 1
									},
									"album_description": {
										"type": "string"
									},
									"query_search": {
										"type": "object"
									}
								},
								"required": [
									"album_name",
									"query_search"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:create"
			}
		},
		"/albums/stats": {
			"get": {
				"operationId": "getAlbumStats",
				"summary": "Get album statistics",
				"tags": [
					"Albums"
				],
				"description": "How many albums the workspace has. For counts within one album, read the album itself — it carries its own file and child counts.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "album:view"
			}
		},
		"/assist/canvas-assistant": {
			"post": {
				"operationId": "runCanvasAssistant",
				"summary": "Ask the canvas assistant",
				"tags": [
					"Assist"
				],
				"description": "Answers a question about what is on a canvas and proposes edits to it, for the assistant that sits inside the design editor.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"instructions": {
										"type": "string"
									},
									"fragment": {
										"type": "string"
									},
									"full_text": {
										"type": "string"
									}
								},
								"required": [
									"instructions"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "assist:run"
			}
		},
		"/assist/captions-generator": {
			"post": {
				"operationId": "generateSocialCaptions",
				"summary": "Suggest social captions",
				"tags": [
					"Assist"
				],
				"description": "Writes caption options for an image or a post, in the voice the workspace's brand knowledge describes.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"platform": {
										"type": "string"
									},
									"photo_description": {
										"type": "string"
									},
									"image_file_id": {
										"type": "string",
										"format": "uuid"
									},
									"instructions": {
										"type": "string"
									}
								},
								"required": [
									"platform"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "assist:run"
			}
		},
		"/assist/magic-write": {
			"post": {
				"operationId": "runMagicWrite",
				"summary": "Write or rewrite text",
				"tags": [
					"Assist"
				],
				"description": "Writes or rewrites a passage in place — the helper behind a single field rather than a conversation. Returns the text only; nothing is saved.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"brief": {
										"type": "string"
									},
									"platform": {
										"type": "string"
									},
									"tone": {
										"type": "string"
									},
									"purpose": {
										"type": "string"
									},
									"currentText": {
										"type": "string"
									}
								},
								"required": [
									"brief"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "assist:run"
			}
		},
		"/assist/photo-selector": {
			"post": {
				"operationId": "selectPhoto",
				"summary": "Pick the best photo",
				"tags": [
					"Assist"
				],
				"description": "Picks the photo that best fits a brief from a candidate set, and says why it chose it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"query": {
										"type": "string"
									},
									"context": {
										"type": "string"
									},
									"limit": {
										"type": "integer",
										"minimum": 1,
										"maximum": 50
									},
									"minQuality": {
										"type": "number",
										"minimum": 1,
										"maximum": 5
									},
									"criteria": {
										"type": "object"
									}
								},
								"required": [
									"query"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "assist:run"
			}
		},
		"/chat-widgets": {
			"get": {
				"operationId": "listChatWidgets",
				"summary": "List chat widgets",
				"tags": [
					"Chat widgets"
				],
				"description": "Returns the workspace's widgets. `widget_key` is the public embed key — it identifies the widget in the snippet on your site and is not a secret.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ChatWidget"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:view",
				"x-required-plan": "module-chat-widget"
			},
			"post": {
				"operationId": "createChatWidget",
				"summary": "Create a chat widget",
				"tags": [
					"Chat widgets"
				],
				"description": "The agent behind a widget must be marked public-facing — a widget is an anonymous surface, and an internal agent is not written to be one, so this refuses rather than exposing it.\n\n`widget_origins` is the list of sites allowed to embed it.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"widget_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 255
									},
									"widget_agent": {
										"type": "string",
										"format": "uuid"
									},
									"widget_origins": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"widget_welcome": {
										"type": "string",
										"maxLength": 2000
									},
									"widget_theme": {
										"type": "object"
									},
									"widget_config": {
										"type": "object"
									},
									"widget_limits": {
										"type": "object"
									}
								},
								"required": [
									"widget_name",
									"widget_agent",
									"widget_origins"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ChatWidget"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:create",
				"x-required-plan": "module-chat-widget"
			}
		},
		"/chat-widgets/{id}": {
			"delete": {
				"operationId": "deleteChatWidget",
				"summary": "Delete a chat widget",
				"tags": [
					"Chat widgets"
				],
				"description": "Soft delete: the widget stops answering on the sites embedding it. Its conversations and captured leads are kept.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:delete",
				"x-required-plan": "module-chat-widget"
			},
			"get": {
				"operationId": "getChatWidget",
				"summary": "Get a chat widget",
				"tags": [
					"Chat widgets"
				],
				"description": "Returns the widget with the agent behind it, its origin allowlist and its theme.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ChatWidget"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:view",
				"x-required-plan": "module-chat-widget"
			},
			"patch": {
				"operationId": "updateChatWidget",
				"summary": "Update a chat widget",
				"tags": [
					"Chat widgets"
				],
				"description": "Applies the `widget_`-prefixed fields present in the body. Changing the origin allowlist takes effect on the next page load; sessions already open are unaffected.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"widget_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 255
									},
									"widget_active": {
										"type": "boolean"
									},
									"widget_agent": {
										"type": "string",
										"format": "uuid"
									},
									"widget_origins": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"widget_welcome": {
										"type": "string",
										"maxLength": 2000
									},
									"widget_theme": {
										"type": "object"
									},
									"widget_config": {
										"type": "object"
									},
									"widget_limits": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ChatWidget"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:edit",
				"x-required-plan": "module-chat-widget"
			}
		},
		"/chat-widgets/{id}/analytics": {
			"get": {
				"operationId": "getChatWidgetAnalytics",
				"summary": "Get widget statistics",
				"tags": [
					"Chat widgets"
				],
				"description": "Conversation and lead counts over the last `days` (30 by default), with the average, median and longest conversation length.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "days",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 90
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:view",
				"x-required-plan": "module-chat-widget"
			}
		},
		"/chat-widgets/{id}/preview-url": {
			"get": {
				"operationId": "getChatWidgetPreviewUrl",
				"summary": "Get a preview link",
				"tags": [
					"Chat widgets"
				],
				"description": "A link that opens the widget on a page of its own, outside any website, for trying it out. It skips the origin allowlist and stops opening conversations after `expires_in` seconds; the conversations it starts carry `preview: true` in their `wses_metadata`.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"url": {
											"type": "string",
											"format": "uri"
										},
										"expires_in": {
											"type": "integer",
											"description": "Seconds the link stays valid."
										}
									},
									"required": [
										"url",
										"expires_in"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:view",
				"x-required-plan": "module-chat-widget"
			}
		},
		"/chat-widgets/{id}/sessions": {
			"get": {
				"operationId": "listChatWidgetSessions",
				"summary": "List conversations",
				"tags": [
					"Chat widgets"
				],
				"description": "Newest first. `has_messages=true` skips sessions where the visitor never wrote, `leads_only=true` keeps only the conversations that captured contact details, `downvoted_only=true` only those with an answer rated not helpful, and `q` searches what was said.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "downvoted_only",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "has_messages",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "leads_only",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "q",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 200
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "wses_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ChatWidgetSession"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:view",
				"x-required-plan": "module-chat-widget"
			}
		},
		"/content-approval-flows": {
			"get": {
				"operationId": "listContentApprovalFlows",
				"summary": "List flows",
				"tags": [
					"Content approval flows"
				],
				"description": "Returns the workspace's content approval flows, each with its steps. Which flow reviews a given site is the site's own setting — see `PUT /sites/{id}/approval-flow` — and sites that have not chosen take the flow marked `sm_default`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sm_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/ContentApprovalFlow"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"post": {
				"operationId": "createContentApprovalFlow",
				"summary": "Create a flow",
				"tags": [
					"Content approval flows"
				],
				"description": "Defines review steps pages can move through before publishing. Pages reaching draft enter at the initial step, and reaching the final step is what marks a page approved. The workspace's first flow becomes the default — governing every site that has not chosen its own — unless `sm_default` says otherwise; marking a later flow default takes the role from the previous holder.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"states": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"si_label": {
													"type": "string"
												}
											},
											"required": [
												"si_label"
											]
										}
									},
									"transitions": {
										"type": "array",
										"items": {}
									},
									"sm_name": {
										"type": "string"
									},
									"sm_default": {
										"type": "boolean"
									}
								},
								"required": [
									"states"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ContentApprovalFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:workflow:edit"
			}
		},
		"/content-approval-flows/{id}": {
			"delete": {
				"operationId": "deleteContentApprovalFlow",
				"summary": "Delete a flow",
				"tags": [
					"Content approval flows"
				],
				"description": "Sites that chose this flow go back to the workspace default; sites governed by it as the default lose review, and approving a page there goes back to being a single step. Pages keep the step they are in.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:workflow:edit"
			},
			"get": {
				"operationId": "getContentApprovalFlow",
				"summary": "Get a flow",
				"tags": [
					"Content approval flows"
				],
				"description": "Returns the flow with its steps, each carrying who may move a page into it and whether doing so asks for a note.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ContentApprovalFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"put": {
				"operationId": "updateContentApprovalFlow",
				"summary": "Update a flow",
				"tags": [
					"Content approval flows"
				],
				"description": "Replaces the flow's steps, their gates included. Pages sitting in a step the new definition drops keep it until something moves them, so their history still reads correctly.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"states": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"si_label": {
													"type": "string"
												}
											},
											"required": [
												"si_label"
											]
										}
									},
									"transitions": {
										"type": "array",
										"items": {}
									},
									"sm_name": {
										"type": "string"
									},
									"sm_default": {
										"type": "boolean"
									}
								},
								"required": [
									"states"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ContentApprovalFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:workflow:edit"
			}
		},
		"/content-schema-libraries": {
			"get": {
				"operationId": "listContentSchemaLibraries",
				"summary": "List libraries",
				"tags": [
					"Content schemas"
				],
				"description": "Every library in the workspace with its schema count and the sites generating from it. Pass `?sitemap=` to also learn which library that site currently uses.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "sitemap",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"post": {
				"operationId": "createContentSchemaLibrary",
				"summary": "Create a library",
				"tags": [
					"Content schemas"
				],
				"description": "Creates a library to group content schemas. A library is a folder, not a namespace — schemas keep working wherever they are filed.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"tgrp_name": {
										"type": "string",
										"minLength": 1
									},
									"sitemap": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"tgrp_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/content-schema-libraries/{id}": {
			"delete": {
				"operationId": "deleteContentSchemaLibrary",
				"summary": "Delete a library",
				"tags": [
					"Content schemas"
				],
				"description": "Soft delete. Sites pointing at the library are released first, so a deactivated library's schemas cannot stay in use through a stale pointer.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:delete"
			},
			"patch": {
				"operationId": "updateContentSchemaLibrary",
				"summary": "Update a library",
				"tags": [
					"Content schemas"
				],
				"description": "Renames or re-describes the library. The schemas it holds are untouched.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"tgrp_name": {
										"type": "string",
										"minLength": 1
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/content-schema-libraries/{id}/duplicate": {
			"post": {
				"operationId": "duplicateContentSchemaLibrary",
				"summary": "Fork a library",
				"tags": [
					"Content schemas"
				],
				"description": "Copies a library and its schemas as an authored one, with no link back to the CMS it came from — so a later schema pull cannot overwrite the copy. This is how a site starts from a mirrored schema set and then diverges from it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"tgrp_name": {
										"type": "string",
										"minLength": 1
									},
									"sitemap": {
										"type": "string",
										"format": "uuid"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/content-schemas": {
			"get": {
				"operationId": "listContentSchemas",
				"summary": "List content schemas",
				"tags": [
					"Content schemas"
				],
				"description": "A content schema is the field shape of a page type — not a page design. Scope with `?group=` for one library, or `?sitemap=` for the library that site generates from. With neither, every schema in the workspace is listed.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "group",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sitemap",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "tpl_component",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "tpl_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "tpl_nestable",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ContentSchema"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"post": {
				"operationId": "createContentSchema",
				"summary": "Create a content schema",
				"tags": [
					"Content schemas"
				],
				"description": "Defines the fields a page type can be generated into. It describes a shape, not a design — nothing here decides how a page looks.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"tpl_group": {
										"type": "string",
										"format": "uuid"
									},
									"sitemap": {
										"type": "string",
										"format": "uuid"
									},
									"tpl_name": {
										"type": "string",
										"minLength": 1
									},
									"tpl_component": {
										"type": "string"
									},
									"tpl_nestable": {
										"type": "boolean"
									},
									"tpl_fields": {
										"type": "array",
										"items": {}
									},
									"tpl_metadata": {
										"type": "object",
										"properties": {
											"metaTitleInstructions": {
												"type": "string",
												"maxLength": 4000
											},
											"metaDescriptionInstructions": {
												"type": "string",
												"maxLength": 4000
											}
										}
									}
								},
								"required": [
									"tpl_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/content-schemas/{id}": {
			"delete": {
				"operationId": "deleteContentSchema",
				"summary": "Delete a content schema",
				"tags": [
					"Content schemas"
				],
				"description": "Removes the schema. Pages that were generated against it keep their content and their component name.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:delete"
			},
			"get": {
				"operationId": "getContentSchema",
				"summary": "Get a content schema",
				"tags": [
					"Content schemas"
				],
				"description": "Returns the schema with its component name and its field definitions.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"patch": {
				"operationId": "updateContentSchema",
				"summary": "Update a content schema",
				"tags": [
					"Content schemas"
				],
				"description": "Changes the schema's fields. Pages already generated against it keep the content they have; only later generations see the new shape.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"tpl_name": {
										"type": "string"
									},
									"tpl_component": {
										"type": "string"
									},
									"tpl_nestable": {
										"type": "boolean"
									},
									"tpl_fields": {
										"type": "array",
										"items": {}
									},
									"tpl_metadata": {
										"type": "object",
										"properties": {
											"metaTitleInstructions": {
												"type": "string",
												"maxLength": 4000
											},
											"metaDescriptionInstructions": {
												"type": "string",
												"maxLength": 4000
											}
										}
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/content-schemas/import": {
			"post": {
				"operationId": "importContentSchemas",
				"summary": "Import content schemas",
				"tags": [
					"Content schemas"
				],
				"description": "Loads schema definitions in bulk, for moving a set between workspaces or seeding a new one.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"data": {
										"type": "string"
									},
									"tpl_group": {
										"type": "string",
										"format": "uuid"
									},
									"sitemap": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"data"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/content-schemas/meta-defaults": {
			"get": {
				"operationId": "getContentSchemaMetaDefaults",
				"summary": "Get meta data defaults",
				"tags": [
					"Content schemas"
				],
				"description": "The instructions the platform writes meta titles and meta descriptions with when a content schema sets none of its own, and the length limits every generated value is clamped to. A schema replaces either block through `tpl_metadata.metaTitleInstructions` / `tpl_metadata.metaDescriptionInstructions`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"title": {
											"type": "object",
											"properties": {
												"instructions": {
													"type": "string"
												},
												"maxLength": {
													"type": "integer"
												}
											}
										},
										"description": {
											"type": "object",
											"properties": {
												"instructions": {
													"type": "string"
												},
												"maxLength": {
													"type": "integer"
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/design-categories": {
			"get": {
				"operationId": "listDesignCategories",
				"summary": "List categories",
				"tags": [
					"Design categories"
				],
				"description": "The workspace's own design categories plus the product-level ones shared with it, in the order they are managed in, each with a count of the designs filed under it.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"categories": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/DesignCategory"
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			},
			"put": {
				"operationId": "replaceDesignCategories",
				"summary": "Replace categories",
				"tags": [
					"Design categories"
				],
				"description": "Send the complete ordered list you want — this is a replacement, not a patch. An entry with an id is renamed in place and takes its position from the array; one without is created; anything you leave out is removed, including from the designs filed under it.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"categories": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"cat_name": {
													"type": "string",
													"minLength": 1,
													"maxLength": 60
												},
												"cat_id": {
													"type": "string",
													"format": "uuid"
												},
												"cat_icon": {
													"type": "string"
												}
											},
											"required": [
												"cat_name"
											]
										}
									}
								},
								"required": [
									"categories"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"categories": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/DesignCategory"
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:category:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs": {
			"get": {
				"operationId": "listDesigns",
				"summary": "List designs",
				"tags": [
					"Designs"
				],
				"description": "Returns designs the caller may see, newest edit first. Version snapshots are never listed, and templates are excluded unless `is_template=true` — which narrows alongside `cat` and `q` rather than replacing them.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cat",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "de_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "is_template",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 1000
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0
						}
					},
					{
						"name": "q",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 200
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/Design"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			},
			"post": {
				"operationId": "createDesign",
				"summary": "Create a design",
				"tags": [
					"Designs"
				],
				"description": "Creates an empty design of the given canvas size. To start from something, use `POST /designs/{id}/copy` or one of the generate endpoints.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"de_name": {
										"type": "string"
									},
									"de_description": {
										"type": "string"
									},
									"de_type": {
										"type": "string"
									},
									"de_canvas_width": {
										"type": "integer",
										"minimum": 1
									},
									"de_canvas_height": {
										"type": "integer",
										"minimum": 1
									},
									"de_canvas_unit": {
										"enum": [
											"px",
											"pt",
											"in",
											"mm",
											"cm"
										],
										"type": "string"
									},
									"de_canvas_dpi": {
										"type": "integer",
										"minimum": 36,
										"maximum": 600
									},
									"de_canvas_background": {
										"type": "object"
									},
									"de_metadata": {
										"type": "object"
									}
								},
								"required": [
									"de_name",
									"de_type",
									"de_canvas_width",
									"de_canvas_height"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Design"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}": {
			"delete": {
				"operationId": "deleteDesign",
				"summary": "Delete a design",
				"tags": [
					"Designs"
				],
				"description": "Deactivates the design. It stops being listed and stops being readable through the API; its versions and layers go with it.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:delete",
				"x-required-plan": "module-design"
			},
			"get": {
				"operationId": "getDesign",
				"summary": "Get a design",
				"tags": [
					"Designs"
				],
				"description": "Returns the design with its canvas, its metadata and its resolved preview file. The layers on it are read through `GET /designs/{id}/layers`.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Design"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			},
			"patch": {
				"operationId": "updateDesign",
				"summary": "Update a design",
				"tags": [
					"Designs"
				],
				"description": "Applies the `de_`-prefixed fields present in the body. This is the canvas and its metadata; the artwork itself is edited through the layer endpoints.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"de_name": {
										"type": "string"
									},
									"de_description": {
										"type": "string"
									},
									"de_type": {
										"type": "string"
									},
									"de_canvas_width": {
										"type": "integer",
										"minimum": 1
									},
									"de_canvas_height": {
										"type": "integer",
										"minimum": 1
									},
									"de_canvas_unit": {
										"enum": [
											"px",
											"pt",
											"in",
											"mm",
											"cm"
										],
										"type": "string"
									},
									"de_canvas_dpi": {
										"type": "integer",
										"minimum": 36,
										"maximum": 600
									},
									"de_canvas_background": {
										"type": "object"
									},
									"de_export_settings": {
										"type": "object"
									},
									"de_metadata": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Design"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/acl": {
			"get": {
				"operationId": "getDesignAccess",
				"summary": "Get who has access",
				"tags": [
					"Designs"
				],
				"description": "Returns who may read and edit this design. An empty result means unrestricted — everyone in the workspace with the design permissions.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			},
			"put": {
				"operationId": "setDesignAccess",
				"summary": "Set who has access",
				"tags": [
					"Designs"
				],
				"description": "An empty object clears the restriction, making it visible to the whole workspace.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"acl": {
										"type": "object"
									}
								},
								"required": [
									"acl"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/ai-fill": {
			"post": {
				"operationId": "proposeDesignFieldValues",
				"summary": "Fill fields with AI",
				"tags": [
					"Designs"
				],
				"description": "Returns proposed values for review — it does not apply them. Committing them goes through the same fill endpoint a person uses, so generated copy is held to the same field whitelist and can never alter the layout. Runs a model, so it consumes credits.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"brief": {
										"type": "string",
										"minLength": 3,
										"maxLength": 4000
									}
								},
								"required": [
									"brief"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:fill",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/brand-restyle": {
			"post": {
				"operationId": "restyleDesignWithBrand",
				"summary": "Apply the brand kit",
				"tags": [
					"Designs"
				],
				"description": "Proposes a coherent restyle — per-layer colors and fonts plus a canvas background — rather than mechanically substituting brand colors. Runs a model, so it consumes credits.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_id": {
										"type": "string"
									},
									"page_ids": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"layer_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"apply": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/bulk-fill": {
			"post": {
				"operationId": "bulkFillDesigns",
				"summary": "Create designs from rows",
				"tags": [
					"Designs"
				],
				"description": "One design per row, each filled from that row's values.\n\nRequires either `design:create` or `design:contribute`.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"rows": {
										"type": "array",
										"items": {}
									},
									"name_field": {
										"type": "string"
									}
								},
								"required": [
									"rows"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"design:create",
					"design:contribute"
				],
				"x-permission-mode": "any",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/categories": {
			"put": {
				"operationId": "setDesignCategories",
				"summary": "Set categories",
				"tags": [
					"Designs"
				],
				"description": "Replaces the design's categories. Categories are the workspace's own taxonomy, defined under `/design-categories`.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"categories": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"categories"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/copy": {
			"post": {
				"operationId": "copyDesign",
				"summary": "Create from a template",
				"tags": [
					"Designs"
				],
				"description": "Copies a template into a new design owned by the caller's workspace. The template is unchanged, and the copy keeps its fillable fields.\n\nRequires either `design:create` or `design:contribute`.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"name": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"design:create",
					"design:contribute"
				],
				"x-permission-mode": "any",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/duplicate": {
			"post": {
				"operationId": "duplicateDesign",
				"summary": "Duplicate a design",
				"tags": [
					"Designs"
				],
				"description": "Copies the design, its layers and its filing into an independent design named \"<name> (Copy)\" unless a `name` is given. The original is unchanged.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"name": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/export": {
			"post": {
				"operationId": "exportDesign",
				"summary": "Export a design",
				"tags": [
					"Designs"
				],
				"description": "Renders it to a downloadable file in the requested format and size.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"format": {
										"type": "string",
										"enum": [
											"png",
											"jpg",
											"svg",
											"pdf"
										]
									},
									"quality": {
										"type": "number",
										"minimum": 0,
										"maximum": 1
									},
									"transparent": {
										"type": "boolean"
									},
									"dpi": {
										"type": "integer",
										"minimum": 36,
										"maximum": 600
									},
									"scale": {
										"type": "number",
										"minimum": 0.05,
										"maximum": 20
									},
									"page_id": {
										"type": "string"
									},
									"pages": {
										"type": "string",
										"enum": [
											"current",
											"all"
										]
									}
								},
								"required": [
									"format"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/export-to-media": {
			"post": {
				"operationId": "exportDesignToMedia",
				"summary": "Export to the library",
				"tags": [
					"Designs"
				],
				"description": "The same render, filed as a library file rather than returned for download.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_id": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/extract-layers": {
			"post": {
				"operationId": "extractDesignLayers",
				"summary": "Extract layers",
				"tags": [
					"Designs"
				],
				"description": "Reverse-engineers a flat image into text blocks with their formatting, graphic overlays and picture regions — the way to get an existing artwork into an editable state. Runs a model.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"file_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/fields": {
			"get": {
				"operationId": "listDesignFields",
				"summary": "List fillable fields",
				"tags": [
					"Designs"
				],
				"description": "What a template lets you change without editing its layout.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/files": {
			"get": {
				"operationId": "listDesignFiles",
				"summary": "List design files",
				"tags": [
					"Designs"
				],
				"description": "Files belonging to this design — the assets placed on it and the previews rendered from it.\n\nRequires any one of `media:view`, `document:view`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "file_hash",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_provider_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_size",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "file_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "repo_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "repo_type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"generated",
								"docs",
								"ds",
								"thread",
								"design",
								"prompt",
								"ppt",
								"ppt_template",
								"form"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/File"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"document:view",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/designs/{id}/fill": {
			"patch": {
				"operationId": "fillDesignFields",
				"summary": "Fill fields",
				"tags": [
					"Designs"
				],
				"description": "Writes values into declared fields only. With `apply_to_variants`, a field key present in several size variants is written to all of them; with `apply_to_kit`, the same happens across the design's kit — one edit updates the date on the flyer, the post and the email page at once. Either way the set stays consistent, and siblings that lack a key are reported, not failed.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"values": {
										"type": "object"
									},
									"apply_to_variants": {
										"type": "boolean"
									},
									"apply_to_kit": {
										"type": "boolean"
									}
								},
								"required": [
									"values"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:fill",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/generate": {
			"post": {
				"operationId": "generateDesignFromTemplate",
				"summary": "Fill a template",
				"tags": [
					"Designs"
				],
				"description": "Spawns a design from an approved template and writes its copy from a brief or from source material — the layout, color and imagery stay exactly as the designer approved them and only the words move. This is `POST /designs/generate` with the layout already decided, and it is the path to prefer whenever a template fits: a brand-approved page beats a generated one. Left unnamed, the design is named from the copy that was written rather than after the template.\n\n`filled` and `unfilled` name the fields in display terms. A field in `unfilled` still shows the template's placeholder text, so ask for those specifics rather than shipping the page as-is; `changed` counts what the write actually altered, and a `changed` of 0 means the design reads exactly like the template.\n\nRequires either `design:create` or `design:contribute`.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"brief": {
										"type": "string",
										"maxLength": 4000
									},
									"content": {
										"type": "object",
										"properties": {
											"text": {
												"type": "string",
												"maxLength": 24000
											}
										}
									},
									"name": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"design:create",
					"design:contribute"
				],
				"x-permission-mode": "any",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/kit": {
			"delete": {
				"operationId": "deleteDesignKit",
				"summary": "Delete a kit",
				"tags": [
					"Designs"
				],
				"description": "Soft-deletes every piece of this design's kit in one call.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:delete",
				"x-required-plan": "module-design"
			},
			"get": {
				"operationId": "listDesignKit",
				"summary": "List kit pieces",
				"tags": [
					"Designs"
				],
				"description": "The sibling designs generated together by `POST /designs/generate-kit`, in channel order (flyer, social, story, email), the caller's own design included. `designs` is empty when this design is not part of a kit.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			},
			"patch": {
				"operationId": "renameDesignKit",
				"summary": "Rename a kit",
				"tags": [
					"Designs"
				],
				"description": "Renames every piece of this design's kit to the given base name with its channel appended (\"Name (Flyer)\", \"Name (Story)\").\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"name": {
										"type": "string",
										"maxLength": 100
									}
								},
								"required": [
									"name"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			},
			"post": {
				"operationId": "addDesignKitPiece",
				"summary": "Add a kit piece",
				"tags": [
					"Designs"
				],
				"description": "Composes one more piece into this design's kit from the content plan stored at generation time — no model runs when the plan is present, so the new piece cannot drift from the others. `output` takes the same shapes as `generate-kit`: a channel role, `{platform}`, `{preset}` or an explicit size. A kit made before plans were stored falls back to one writing call from the stored brief.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"output": {
										"type": "string"
									},
									"format": {
										"type": "object"
									}
								},
								"required": [
									"output"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/layer/{layer_id}/binding": {
			"put": {
				"operationId": "bindDesignChart",
				"summary": "Bind a chart layer",
				"tags": [
					"Designs"
				],
				"description": "Points a chart at data and pulls the current figures in. Send an empty body to unbind — the last fetched numbers stay behind as ordinary editable values.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "layer_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"binding": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/layers": {
			"get": {
				"operationId": "listDesignLayers",
				"summary": "List layers",
				"tags": [
					"Designs"
				],
				"description": "Returns every layer on the design in stacking order, lowest first.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 1000
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/DesignLayer"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			},
			"post": {
				"operationId": "createDesignLayer",
				"summary": "Add a layer",
				"tags": [
					"Designs"
				],
				"description": "Adds a layer to the design. `dl_order` decides what it sits above; omit it and the layer goes on top.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"dl_name": {
										"type": "string"
									},
									"dl_type": {
										"type": "string",
										"enum": [
											"text",
											"image",
											"shape",
											"path",
											"chart",
											"group",
											"video",
											"frame"
										]
									},
									"dl_order": {
										"type": "integer",
										"minimum": 0
									},
									"dl_position": {
										"type": "object"
									},
									"dl_size": {
										"type": "object"
									},
									"dl_content": {
										"type": "object"
									},
									"dl_style": {
										"type": "object"
									}
								},
								"required": [
									"dl_name",
									"dl_type",
									"dl_order",
									"dl_position",
									"dl_size",
									"dl_content"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/DesignLayer"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/layers/{layer_id}": {
			"delete": {
				"operationId": "deleteDesignLayer",
				"summary": "Delete a layer",
				"tags": [
					"Designs"
				],
				"description": "Removes the layer from the design.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "layer_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			},
			"get": {
				"operationId": "getDesignLayer",
				"summary": "Get a layer",
				"tags": [
					"Designs"
				],
				"description": "Returns one layer with its position, its transform and its type-specific content.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "layer_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/DesignLayer"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			},
			"put": {
				"operationId": "updateDesignLayer",
				"summary": "Update a layer",
				"tags": [
					"Designs"
				],
				"description": "Replaces the layer. This is a PUT: fields absent from the body are reset to their defaults, which is what the editor's autosave sends.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "layer_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"dl_active": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/DesignLayer"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/lock": {
			"patch": {
				"operationId": "lockDesign",
				"summary": "Lock or unlock",
				"tags": [
					"Designs"
				],
				"description": "A locked design has its layout frozen: only declared fields can change, for everyone including its author. This is what makes an approved template stay approved.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"locked": {
										"type": "boolean"
									}
								},
								"required": [
									"locked"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/propose-layers": {
			"post": {
				"operationId": "proposeDesignLayers",
				"summary": "Propose layers with AI",
				"tags": [
					"Designs"
				],
				"description": "Suggests layers for the design. Proposals are returned, not saved — the editor adds them as drafts you can accept or discard. Runs a model, so it consumes credits.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"mode": {
										"type": "string",
										"enum": [
											"text",
											"overlay"
										]
									},
									"instructions": {
										"type": "string"
									},
									"page_id": {
										"type": "string"
									}
								},
								"required": [
									"mode"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/refresh-data": {
			"post": {
				"operationId": "refreshDesignData",
				"summary": "Refresh bound data",
				"tags": [
					"Designs"
				],
				"description": "Fetches current figures for every bound chart and writes them back. **No model is involved** — a binding records where the numbers come from, so this is a read and an update, and it costs no credits.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/render-preview": {
			"post": {
				"operationId": "renderDesignPreview",
				"summary": "Render the preview",
				"tags": [
					"Designs"
				],
				"description": "Refreshes the thumbnail shown in listings.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/reset-fill": {
			"post": {
				"operationId": "resetDesignFields",
				"summary": "Reset fields",
				"tags": [
					"Designs"
				],
				"description": "Clears every filled field, returning the design to the template's own copy and imagery.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"keys": {
										"type": "array",
										"items": {}
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:fill",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/resize": {
			"post": {
				"operationId": "resizeDesign",
				"summary": "Resize a design",
				"tags": [
					"Designs"
				],
				"description": "Re-lays the design out at a new size rather than scaling a picture of it.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"platform": {
										"type": "string"
									},
									"preset": {
										"enum": [
											"US Letter",
											"US Legal",
											"Tabloid",
											"A3",
											"A4",
											"A5",
											"Business Card",
											"Postcard",
											"Poster"
										],
										"type": "string"
									},
									"landscape": {
										"type": "boolean"
									},
									"width": {
										"type": "integer",
										"minimum": 1
									},
									"height": {
										"type": "integer",
										"minimum": 1
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/save-as-template": {
			"post": {
				"operationId": "saveDesignAsTemplate",
				"summary": "Save as a template",
				"tags": [
					"Designs"
				],
				"description": "Copies the design into a template others can start from. The original is unchanged.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"name": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/translate": {
			"post": {
				"operationId": "translateDesign",
				"summary": "Translate the text",
				"tags": [
					"Designs"
				],
				"description": "Translates the copy while keeping tone and roughly the same length, so the text still fits its boxes. Runs a model, so it consumes credits.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"language": {
										"type": "string",
										"minLength": 2,
										"maxLength": 60
									},
									"texts": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"id": {
													"type": "string",
													"minLength": 1,
													"maxLength": 64
												},
												"value": {
													"type": "string",
													"minLength": 1,
													"maxLength": 2000
												}
											},
											"required": [
												"id",
												"value"
											]
										}
									}
								},
								"required": [
									"language",
									"texts"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/variants": {
			"get": {
				"operationId": "listDesignVariants",
				"summary": "List size variants",
				"tags": [
					"Designs"
				],
				"description": "Returns the other sizes this design has been resized into, which are separate designs that remember where they came from.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/versions": {
			"get": {
				"operationId": "listDesignVersions",
				"summary": "List versions",
				"tags": [
					"Designs"
				],
				"description": "Returns the design's saved snapshots, newest first, with a preview and a layer count for each.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/DesignVersion"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			},
			"post": {
				"operationId": "saveDesignVersion",
				"summary": "Save a version",
				"tags": [
					"Designs"
				],
				"description": "Takes a snapshot of the design as it stands. Snapshots are what `restore` restores, and they are not created automatically.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"label": {
										"type": "string",
										"maxLength": 120
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/versions/{version_id}": {
			"delete": {
				"operationId": "deleteDesignVersion",
				"summary": "Delete a version",
				"tags": [
					"Designs"
				],
				"description": "Removes one snapshot. The design itself and its other snapshots are untouched.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "version_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/{id}/versions/{version_id}/restore": {
			"post": {
				"operationId": "restoreDesignVersion",
				"summary": "Restore a version",
				"tags": [
					"Designs"
				],
				"description": "Replaces the design's current layers with the snapshot's. Take a version first if the current state is worth keeping — restoring does not snapshot it for you.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "version_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/counts": {
			"get": {
				"operationId": "countDesigns",
				"summary": "Count designs",
				"tags": [
					"Designs"
				],
				"description": "How many designs and how many templates match `cat` and `q`, plus the same pair per category with `cat` left out. This is what a library screen needs to label its tabs and category filters without listing both sides.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cat",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "q",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 200
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"designs": {
											"type": "integer",
											"description": "Matching designs."
										},
										"templates": {
											"type": "integer",
											"description": "Matching templates."
										},
										"categories": {
											"type": "array",
											"items": {
												"type": "object",
												"properties": {
													"cat_id": {
														"type": "string",
														"format": "uuid"
													},
													"designs": {
														"type": "integer"
													},
													"templates": {
														"type": "integer"
													}
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:view",
				"x-required-plan": "module-design"
			}
		},
		"/designs/edit-image": {
			"post": {
				"operationId": "editDesignImage",
				"summary": "Erase or fill an area",
				"tags": [
					"Designs"
				],
				"description": "Send the region to change as a PNG mask; the model regenerates only what the mask covers. Runs a model, so it consumes credits.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_id": {
										"type": "string",
										"format": "uuid"
									},
									"mode": {
										"type": "string",
										"enum": [
											"erase",
											"fill"
										]
									},
									"mask": {
										"type": "string",
										"minLength": 64,
										"maxLength": 1048576
									},
									"prompt": {
										"type": "string",
										"maxLength": 2000
									}
								},
								"required": [
									"file_id",
									"mode",
									"mask"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/generate": {
			"post": {
				"operationId": "generateDesign",
				"summary": "Generate a document",
				"tags": [
					"Designs"
				],
				"description": "Writes a one-page document from a brief or from source material — a story, a post, an announcement — and lays it out at the requested size. Unlike `generate-from-background` the subject is the content: a background image is one optional ingredient, and `format` accepts a paper preset (`US Letter`, `A4`), a social platform, or explicit dimensions in any supported unit.\n\nThe layout comes from a fixed library of archetypes rather than from the model, so the page is set properly whatever the copy turns out to be. Every text slot is returned as a **fill field**, which means the result is immediately usable as a template: save it and fill it for the next story through `PATCH /designs/{id}/fill` or `POST /designs/{id}/bulk-fill`.\n\nWhere an approved template already fits, prefer `POST /designs/{id}/generate` — same request, but a designer's layout instead of an archetype. For a design built *around* a photograph rather than around its words, use `POST /designs/generate-from-background`.\n\n`imagery_used` reports whether a supplied photo was actually placed: a page too full to hold the band composes without it rather than failing.\n\nPass `plan` to lay out a content plan you already have (from `generate-plan`, edited or not) and the writing step is skipped along with its cost.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"format": {
										"type": "object",
										"properties": {
											"preset": {
												"enum": [
													"US Letter",
													"US Legal",
													"Tabloid",
													"A3",
													"A4",
													"A5",
													"Business Card",
													"Postcard",
													"Poster"
												],
												"type": "string"
											},
											"platform": {
												"enum": [
													"Instagram",
													"Instagram Story",
													"Facebook",
													"Twitter",
													"LinkedIn",
													"TikTok",
													"YouTube Thumbnail",
													"Pinterest"
												],
												"type": "string"
											},
											"landscape": {
												"type": "boolean"
											},
											"width": {
												"type": "number",
												"minimum": 0.01
											},
											"height": {
												"type": "number",
												"minimum": 0.01
											},
											"unit": {
												"enum": [
													"px",
													"pt",
													"in",
													"mm",
													"cm"
												],
												"type": "string"
											}
										}
									},
									"brief": {
										"type": "string",
										"maxLength": 4000
									},
									"content": {
										"type": "object",
										"properties": {
											"text": {
												"type": "string",
												"maxLength": 24000
											}
										}
									},
									"archetype": {
										"enum": [
											"customer_story",
											"flyer",
											"stat_sheet",
											"checklist",
											"agenda"
										],
										"type": "string"
									},
									"plan": {
										"type": "object"
									},
									"imagery": {
										"type": "object",
										"properties": {
											"mode": {
												"enum": [
													"none",
													"photo"
												],
												"type": "string"
											},
											"file_id": {
												"type": "string",
												"format": "uuid"
											}
										}
									},
									"name": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/generate-from-background": {
			"post": {
				"operationId": "generateDesignFromBackground",
				"summary": "Create from a background",
				"tags": [
					"Designs"
				],
				"description": "Builds a design **around a photograph**: the image becomes a full-bleed background, and a brand overlay, the logo and the on-image copy are placed onto it. Always a social-platform size.\n\nChoose by the subject. A photograph the design is built on belongs here; words the design is built from belong in `POST /designs/generate`, which takes any canvas size including paper, treats imagery as optional, and returns an editable page rather than a composed picture. Neither substitutes for the other.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_id": {
										"type": "string",
										"format": "uuid"
									},
									"platform": {
										"type": "string"
									},
									"instructions": {
										"type": "string"
									},
									"background_is_clean": {
										"type": "boolean"
									},
									"caption": {
										"type": "string"
									},
									"thread_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"file_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/generate-image": {
			"post": {
				"operationId": "generateDesignImage",
				"summary": "Generate an image",
				"tags": [
					"Designs"
				],
				"description": "With `transparent`, the subject is generated against a backdrop that is knocked out — so it can sit over the design rather than in a box. Runs a model, so it consumes credits.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"prompt": {
										"type": "string",
										"minLength": 3,
										"maxLength": 2000
									},
									"aspect_ratio": {
										"enum": [
											"1:1",
											"2:3",
											"3:2",
											"3:4",
											"4:3",
											"4:5",
											"5:4",
											"9:16",
											"16:9",
											"21:9"
										],
										"type": "string"
									},
									"transparent": {
										"type": "boolean"
									}
								},
								"required": [
									"prompt"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/designs/generate-kit": {
			"post": {
				"operationId": "generateDesignKit",
				"summary": "Generate an asset kit",
				"tags": [
					"Designs"
				],
				"description": "One brief, several designs for the same occasion, each an ordinary layered design ready to edit. An `outputs` entry is a channel role (`flyer`, `social`, `story`, `email`) or a format of its own: `{platform}` for any social preset, `{preset, landscape}` for any paper size, or explicit `{width, height, unit}`. All are generated exactly as `POST /designs/generate` would, from **one shared content plan**, so the date, the offer and the call to action cannot drift between the pieces. Document surfaces (paper, the email column) carry the full plan; social surfaces carry a condensed announcement cut of it.\n\nEvery produced design carries `kit`, `kit_role` and `kit_label` in its metadata, and the response's `kit_id` ties the set together. Each design is an ordinary row afterward — the kit imposes nothing after creation.\n\nRole defaults are US Letter, Instagram, Instagram Story and a 600px email column; `formats` overrides them per role. Pass `plan` (from `generate-plan`, edited or not) to skip the writing step. A leg that fails is reported in `errors` rather than failing the kit.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"brief": {
										"type": "string",
										"maxLength": 4000
									},
									"content": {
										"type": "object",
										"properties": {
											"text": {
												"type": "string",
												"maxLength": 24000
											}
										}
									},
									"outputs": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"formats": {
										"type": "object",
										"properties": {
											"flyer": {
												"type": "object"
											},
											"social": {
												"type": "object"
											},
											"story": {
												"type": "object"
											},
											"email": {
												"type": "object"
											}
										}
									},
									"plan": {
										"type": "object"
									},
									"name": {
										"type": "string",
										"maxLength": 120
									}
								},
								"required": [
									"outputs"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/generate-plan": {
			"post": {
				"operationId": "planDesignDocument",
				"summary": "Plan a document",
				"tags": [
					"Designs"
				],
				"description": "The writing half of `POST /designs/generate` on its own: returns the content plan — headline, pull quote, the figures worth setting large, the sections, the call to action — without building anything. Made for a review step in front of generation, since a long source document is worth agreeing on before a layout is built from it. Hand the plan back to `generate` to lay it out.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"format": {
										"type": "object",
										"properties": {
											"preset": {
												"enum": [
													"US Letter",
													"US Legal",
													"Tabloid",
													"A3",
													"A4",
													"A5",
													"Business Card",
													"Postcard",
													"Poster"
												],
												"type": "string"
											},
											"platform": {
												"enum": [
													"Instagram",
													"Instagram Story",
													"Facebook",
													"Twitter",
													"LinkedIn",
													"TikTok",
													"YouTube Thumbnail",
													"Pinterest"
												],
												"type": "string"
											},
											"landscape": {
												"type": "boolean"
											},
											"width": {
												"type": "number",
												"minimum": 0.01
											},
											"height": {
												"type": "number",
												"minimum": 0.01
											},
											"unit": {
												"enum": [
													"px",
													"pt",
													"in",
													"mm",
													"cm"
												],
												"type": "string"
											}
										}
									},
									"brief": {
										"type": "string",
										"maxLength": 4000
									},
									"content": {
										"type": "object",
										"properties": {
											"text": {
												"type": "string",
												"maxLength": 24000
											}
										}
									},
									"archetype": {
										"enum": [
											"customer_story",
											"flyer",
											"stat_sheet",
											"checklist",
											"agenda"
										],
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/import/figma": {
			"post": {
				"operationId": "importFigmaFrame",
				"summary": "Import a Figma frame",
				"tags": [
					"Designs"
				],
				"description": "Runs inline rather than as a background job: a design is only usable once every layer exists, so it finishes before responding.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"token": {
										"type": "string"
									},
									"file_url": {
										"type": "string"
									},
									"node_id": {
										"type": "string"
									},
									"name": {
										"type": "string"
									},
									"vector_mode": {
										"enum": [
											"raster",
											"path"
										],
										"type": "string"
									}
								},
								"required": [
									"token",
									"file_url"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/import/figma/inspect": {
			"post": {
				"operationId": "inspectFigmaFile",
				"summary": "List Figma frames",
				"tags": [
					"Designs"
				],
				"description": "Lists what can be imported so you can choose before fetching the whole document. The Figma token is used for the request and not stored.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"token": {
										"type": "string"
									},
									"file_url": {
										"type": "string"
									}
								},
								"required": [
									"token",
									"file_url"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/designs/remove-background": {
			"post": {
				"operationId": "removeImageBackground",
				"summary": "Remove a background",
				"tags": [
					"Designs"
				],
				"description": "Cuts the subject out of an image and returns it with a transparent background. The source image is not modified.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"file_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:edit",
				"x-required-plan": "module-design"
			}
		},
		"/document-folders": {
			"get": {
				"operationId": "listDocumentFolders",
				"summary": "List folders",
				"tags": [
					"Document folders"
				],
				"description": "Returns folders with how many documents each holds and how many folders sit inside it. Pass `album_parent=root` for the top level and a folder id to walk down, which is how the tree is drawn a level at a time rather than all at once. A smart folder carries the saved filter it resolves in `album_query_search`.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "album_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "album_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "album_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "album_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "album_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "album_parent",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "album_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "full_text_search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:view",
				"x-required-plan": "module-documents"
			},
			"post": {
				"operationId": "createDocumentFolder",
				"summary": "Create a folder",
				"tags": [
					"Document folders"
				],
				"description": "Creates a folder, which starts empty — put documents in it with `POST /document-folders/{id}/files`. Pass `album_parent` to nest it. A folder that fills itself from a saved filter is created through `POST /document-folders/smart` instead.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"album_name": {
										"type": "string",
										"minLength": 1
									},
									"album_description": {
										"type": "string"
									},
									"album_cover_file": {
										"type": "string",
										"format": "uuid"
									},
									"album_metadata": {
										"type": "object"
									},
									"album_acl": {
										"type": "object"
									},
									"album_active": {
										"type": "boolean"
									},
									"album_smart": {
										"type": "boolean"
									},
									"album_query": {
										"type": "string",
										"format": "uuid"
									},
									"album_parent": {
										"type": "string"
									}
								},
								"required": [
									"album_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:create",
				"x-required-plan": "module-documents"
			}
		},
		"/document-folders/{id}": {
			"delete": {
				"operationId": "deleteDocumentFolder",
				"summary": "Delete a folder",
				"tags": [
					"Document folders"
				],
				"description": "Removes the folder. The documents it held stay in the library, and folders inside it move to the top level.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:delete",
				"x-required-plan": "module-documents"
			},
			"get": {
				"operationId": "getDocumentFolder",
				"summary": "Get a folder",
				"tags": [
					"Document folders"
				],
				"description": "Returns the folder with its file and child counts, the path of folders above it, and — for a smart folder — the filter it resolves.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:view",
				"x-required-plan": "module-documents"
			},
			"patch": {
				"operationId": "updateDocumentFolder",
				"summary": "Update a folder",
				"tags": [
					"Document folders"
				],
				"description": "Applies the `album_`-prefixed fields present in the body. Moving a folder under a new parent is a change to `album_parent` here; a move that would make a folder its own ancestor is refused. A smart folder's filter is changed through `PATCH /document-folders/{id}/smart`.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"album_name": {
										"type": "string",
										"minLength": 1
									},
									"album_description": {
										"type": "string"
									},
									"album_cover_file": {
										"type": "string",
										"format": "uuid"
									},
									"album_metadata": {
										"type": "object"
									},
									"album_acl": {
										"type": "object"
									},
									"album_parent": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/document-folders/{id}/files": {
			"delete": {
				"operationId": "removeDocumentsFromFolder",
				"summary": "Remove documents",
				"tags": [
					"Document folders"
				],
				"description": "Takes the documents out of the folder and leaves them in the library.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"file_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:curate",
				"x-required-plan": "module-documents"
			},
			"post": {
				"operationId": "addDocumentsToFolder",
				"summary": "Add documents",
				"tags": [
					"Document folders"
				],
				"description": "Puts documents in the folder. A document may sit in more than one. Ids that match no document in the library are skipped rather than failing the request, so a partly stale selection still lands.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"file_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:curate",
				"x-required-plan": "module-documents"
			}
		},
		"/document-folders/{id}/smart": {
			"patch": {
				"operationId": "updateSmartDocumentFolderFilters",
				"summary": "Update smart filters",
				"tags": [
					"Document folders"
				],
				"description": "Replaces the saved filter a smart folder resolves. Membership is recomputed on read, so the change is visible immediately and no documents are moved.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"album_name": {
										"type": "string",
										"minLength": 1
									},
									"album_description": {
										"type": "string"
									},
									"query_search": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/document-folders/memberships": {
			"get": {
				"operationId": "listDocumentFolderMemberships",
				"summary": "List folder membership",
				"tags": [
					"Document folders"
				],
				"description": "Returns which documents sit in which folder, without the document records themselves.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "af_album",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "af_file",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:view",
				"x-required-plan": "module-documents"
			}
		},
		"/document-folders/smart": {
			"post": {
				"operationId": "createSmartDocumentFolder",
				"summary": "Create a smart folder",
				"tags": [
					"Document folders"
				],
				"description": "A smart folder is a saved filter rather than a fixed list: its contents are whatever currently matches, so documents join and leave it on their own as the library changes.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"album_name": {
										"type": "string",
										"minLength": 1
									},
									"album_description": {
										"type": "string"
									},
									"query_search": {
										"type": "object"
									}
								},
								"required": [
									"album_name",
									"query_search"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:create",
				"x-required-plan": "module-documents"
			}
		},
		"/document-folders/stats": {
			"get": {
				"operationId": "getDocumentFolderStats",
				"summary": "Get folder statistics",
				"tags": [
					"Document folders"
				],
				"description": "How many folders the workspace has. For counts within one folder, read the folder itself — it carries its own document and child counts.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document-folder:view",
				"x-required-plan": "module-documents"
			}
		},
		"/document-relation-types": {
			"get": {
				"operationId": "listDocumentRelationTypes",
				"summary": "List relationship types",
				"tags": [
					"Document relations"
				],
				"description": "The relationship types documents in this workspace can be linked with, as the administrator defined them. Each carries the label read from the document the link starts at (`rt_name`, \"Translation of\"), the label read from the other end (`rt_inverse_name`, \"Translated as\") and whether it reads the same from both ends (`rt_symmetric`).\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "rt_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/RelationType"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:view",
				"x-required-plan": "module-documents"
			},
			"post": {
				"operationId": "createDocumentRelationType",
				"summary": "Add a relationship type",
				"tags": [
					"Document relations"
				],
				"description": "Defines a relationship type for documents: `rt_name` as the link reads from the document it is made on and `rt_inverse_name` as it reads from the other end. A symmetric type reads the same both ways and carries no inverse name; a directional type without one reuses `rt_name` from both ends. Names are unique within the workspace.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"rt_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 80
									},
									"rt_inverse_name": {
										"type": "string",
										"maxLength": 80
									},
									"rt_symmetric": {
										"type": "boolean"
									},
									"rt_description": {
										"type": "string",
										"maxLength": 300
									}
								},
								"required": [
									"rt_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/RelationType"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:relation-type:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/document-relation-types/{id}": {
			"delete": {
				"operationId": "deleteDocumentRelationType",
				"summary": "Delete a relation type",
				"tags": [
					"Document relations"
				],
				"description": "Removes the type and every link made with it. The documents themselves are untouched.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:relation-type:edit",
				"x-required-plan": "module-documents"
			},
			"put": {
				"operationId": "updateDocumentRelationType",
				"summary": "Replace a relation type",
				"tags": [
					"Document relations"
				],
				"description": "Replaces the type's definition. Links already made with it keep pointing at it, so renaming a type relabels every link at once.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"rt_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 80
									},
									"rt_inverse_name": {
										"type": "string",
										"maxLength": 80
									},
									"rt_symmetric": {
										"type": "boolean"
									},
									"rt_description": {
										"type": "string",
										"maxLength": 300
									}
								},
								"required": [
									"rt_name"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/RelationType"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:relation-type:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/documents": {
			"get": {
				"operationId": "listDocuments",
				"summary": "List documents",
				"tags": [
					"Documents"
				],
				"description": "The document library, with the folders each document sits in and the summary written for it on upload.\n\n`lifecycle` decides which documents are in scope and defaults to `active`: a deprecated document is kept and still downloadable, but it is out of the way and the AI no longer retrieves it, so it stays out of the list unless you ask for `deprecated` or `all`.\n\n`search` matches the name and the summary. `embedding_search` matches on meaning instead, scoring every document against the phrase and ordering by the score, which is what finds a pricing deck that never uses the word \"pricing\". If the embedding cannot be produced the request still filters, falling back to the substring match rather than answering with the whole library.\n\n`folder` narrows to one folder, `tags` to the values of a tag group, and `file_format` to a file name extension. `GET /documents/formats` answers which formats are worth offering.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "embedding_search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "favorite",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_format",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "folder",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "lifecycle",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"active",
								"deprecated",
								"all"
							],
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"pattern": "^-?[0-9]+(\\.[0-9]+)?$",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"pattern": "^-?[0-9]+(\\.[0-9]+)?$",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 200
						}
					},
					{
						"name": "similarityThreshold",
						"in": "query",
						"required": false,
						"schema": {
							"type": "number",
							"minimum": 0,
							"maximum": 1
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "tags",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Document"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:view",
				"x-required-plan": "module-documents"
			}
		},
		"/documents/{id}/deprecate": {
			"post": {
				"operationId": "deprecateDocument",
				"summary": "Deprecate a document",
				"tags": [
					"Documents"
				],
				"description": "Takes a document out of circulation without deleting it. It leaves the library's default listing, and the AI stops retrieving it: its indexed passages are removed, so it can no longer turn up inside an answer.\n\nNothing is destroyed. The file, its versions and its download links are untouched, its converted text is kept, and somebody who names the document directly still gets it. Restore puts it back and re-indexes it.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Document"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/documents/{id}/relations": {
			"get": {
				"operationId": "listDocumentRelations",
				"summary": "List related documents",
				"tags": [
					"Document relations"
				],
				"description": "Every link this document takes part in, in both directions, each resolved to the document on the other end. `label` is the relationship type as it reads from here: a link written as \"A is a translation of B\" lists under B as \"Translated as\". A link to a document the caller may not read is left out.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/DocumentRelation"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:view",
				"x-required-plan": "module-documents"
			},
			"post": {
				"operationId": "createDocumentRelation",
				"summary": "Link a document",
				"tags": [
					"Document relations"
				],
				"description": "Links this document to another one with a relationship type. `direction` is read from this document's side and defaults to `from`: this document is the one the type's label describes (\"this is a translation of `document_id`\"); `to` turns it around (\"`document_id` is a translation of this\"). The caller needs edit on both documents. Linking a pair that is already linked with the same type answers with the existing link; for a symmetric type that holds whichever way round it was written.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"rel_type": {
										"type": "string",
										"format": "uuid"
									},
									"document_id": {
										"type": "string",
										"format": "uuid"
									},
									"direction": {
										"enum": [
											"from",
											"to"
										],
										"type": "string"
									},
									"rel_metadata": {
										"type": "object"
									}
								},
								"required": [
									"rel_type",
									"document_id"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/DocumentRelation"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/documents/{id}/relations/{relation_id}": {
			"delete": {
				"operationId": "deleteDocumentRelation",
				"summary": "Unlink a document",
				"tags": [
					"Document relations"
				],
				"description": "Removes one link. Both documents stay exactly as they were.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "relation_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/documents/{id}/restore": {
			"post": {
				"operationId": "restoreDocument",
				"summary": "Restore a document",
				"tags": [
					"Documents"
				],
				"description": "Puts a deprecated document back into the library and re-indexes it, so the AI can retrieve it again.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Document"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/documents/actions/set-tags": {
			"post": {
				"operationId": "setDocumentTags",
				"summary": "Tag documents",
				"tags": [
					"Documents"
				],
				"description": "Adds and removes tag values across a set of documents in one call. `add` and `remove` are both maps of group name to values; a group the document does not carry is created, and a group left empty is dropped. Ids that name something other than a document in this library are ignored.\n\nThe groups themselves are configured per workspace — see the document tag groups under workspace administration.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"add": {
										"type": "object"
									},
									"remove": {
										"type": "object"
									}
								},
								"required": [
									"file_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:edit",
				"x-required-plan": "module-documents"
			}
		},
		"/documents/formats": {
			"get": {
				"operationId": "listDocumentFormats",
				"summary": "List formats",
				"tags": [
					"Documents"
				],
				"description": "Which file formats the library actually holds and how many of each, so the type filter can offer `pdf` and `pptx` without offering formats the account has none of. A row is a filter: send `format` straight back as `file_format` on `GET /documents`.\n\nOnly the folder and the lifecycle narrow the counts, so a count describes the library rather than the query in front of it. Counting is exact, which means reading every document the caller can see; a library too large to do that inside the server's budget answers with no rows rather than a guess.\n\nRequires the `module-documents` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "folder",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "lifecycle",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"active",
								"deprecated",
								"all"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"formats": {
											"type": "array",
											"items": {
												"type": "object",
												"properties": {
													"format": {
														"type": "string",
														"description": "The file name extension, lower case and without the dot."
													},
													"count": {
														"type": "integer"
													}
												},
												"required": [
													"format",
													"count"
												],
												"additionalProperties": false
											},
											"description": "Ordered by count, most common first."
										},
										"counted": {
											"type": "boolean",
											"description": "False when the library was too large to count in time."
										}
									},
									"required": [
										"formats",
										"counted"
									],
									"additionalProperties": false
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "document:view",
				"x-required-plan": "module-documents"
			}
		},
		"/download-jobs": {
			"post": {
				"operationId": "createDownloadJob",
				"summary": "Start a download job",
				"tags": [
					"Downloads"
				],
				"description": "For selections too large to stream in one response: packs them in the background and returns a job to poll.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"size": {
										"enum": [
											"original",
											"small",
											"medium",
											"large"
										],
										"type": "string"
									}
								},
								"required": [
									"file_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:download"
			}
		},
		"/download-jobs/{id}": {
			"delete": {
				"operationId": "cancelDownloadJob",
				"summary": "Cancel a download job",
				"tags": [
					"Downloads"
				],
				"description": "Stops a download job that has not finished. A job already completed is left alone.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"job_id": {
											"type": "string",
											"format": "uuid"
										},
										"status": {
											"type": "string"
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:download"
			},
			"get": {
				"operationId": "getDownloadJob",
				"summary": "Get a download job",
				"tags": [
					"Downloads"
				],
				"description": "Reports where a download job has got to. Poll it until the status is `completed`, at which point the response carries the URL to fetch.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"job_id": {
											"type": "string",
											"format": "uuid"
										},
										"status": {
											"type": "string"
										},
										"file_count": {
											"type": "integer"
										},
										"download_url": {
											"type": "string",
											"format": "uri",
											"description": "Present once the status is completed."
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:download"
			}
		},
		"/extensions": {
			"get": {
				"operationId": "listExtensions",
				"summary": "List extensions",
				"tags": [
					"Extensions"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe extensions enabled in this workspace, with the scopes each was granted.\n\nRequires the `module-extensions` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "inst_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ExtensionInstall"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "extension:view",
				"x-required-plan": "module-extensions"
			}
		},
		"/extensions/{slug}/state": {
			"get": {
				"operationId": "listExtensionState",
				"summary": "List state documents",
				"tags": [
					"Extensions"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe documents an extension keeps in this workspace, ordered by key. An extension calling with its own key or token sees only its own.\n\nRequires the `module-extensions` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "slug",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"pattern": "^[a-z][a-z0-9-]{1,38}[a-z0-9]$"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "exs_key",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ExtensionStateDocument"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "extension-state:read",
				"x-required-plan": "module-extensions"
			}
		},
		"/extensions/{slug}/state/{key}": {
			"delete": {
				"operationId": "deleteExtensionState",
				"summary": "Delete a state document",
				"tags": [
					"Extensions"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRemoves the document under a key.\n\nRequires the `module-extensions` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "key",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$"
						}
					},
					{
						"name": "slug",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"pattern": "^[a-z][a-z0-9-]{1,38}[a-z0-9]$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "extension-state:write",
				"x-required-plan": "module-extensions"
			},
			"get": {
				"operationId": "getExtensionState",
				"summary": "Get a state document",
				"tags": [
					"Extensions"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nOne document by key. The ETag is its version; send it back as If-Match to update without overwriting a change made since.\n\nRequires the `module-extensions` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "key",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$"
						}
					},
					{
						"name": "slug",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"pattern": "^[a-z][a-z0-9-]{1,38}[a-z0-9]$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ExtensionStateDocument"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "extension-state:read",
				"x-required-plan": "module-extensions"
			},
			"put": {
				"operationId": "putExtensionState",
				"summary": "Write a state document",
				"tags": [
					"Extensions"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nCreates or replaces the document under a key. Send If-Match with the ETag you read to refuse a lost update, or If-Match: * to update only an existing document. Documents are at most 256 KB, and an extension keeps at most 1000 in a workspace.\n\nRequires the `module-extensions` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "key",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"pattern": "^[A-Za-z0-9][A-Za-z0-9._:/-]{0,199}$"
						}
					},
					{
						"name": "slug",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"pattern": "^[a-z][a-z0-9-]{1,38}[a-z0-9]$"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"exs_value": {
										"description": "Any JSON value."
									}
								},
								"additionalProperties": false
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ExtensionStateDocument"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "extension-state:write",
				"x-required-plan": "module-extensions"
			}
		},
		"/file-imports": {
			"post": {
				"operationId": "createFileImport",
				"summary": "Start a cloud import",
				"tags": [
					"Uploads"
				],
				"description": "Starts the import and returns an id to poll. Files transfer in the background.\n\nRequires any one of `media:upload`, `document:upload`, `knowledge-base:upload`, `thread:upload`, `design:edit`, `prompt:edit` or `presentation:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"provider": {
										"type": "string",
										"enum": [
											"dropbox",
											"google-drive"
										]
									},
									"files": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"name": {
													"type": "string"
												},
												"link": {
													"type": "string"
												},
												"driveFileId": {
													"type": "string"
												},
												"accessToken": {
													"type": "string"
												}
											},
											"required": [
												"name"
											]
										}
									}
								},
								"required": [
									"provider",
									"files"
								]
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:upload",
					"document:upload",
					"knowledge-base:upload",
					"thread:upload",
					"design:edit",
					"prompt:edit",
					"presentation:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/file-imports/{id}": {
			"get": {
				"operationId": "getFileImport",
				"summary": "Get a cloud import",
				"tags": [
					"Uploads"
				],
				"description": "Reports how far a cloud import has got and which files have landed. Imports run in the background, so this is polled rather than waited on.\n\nRequires any one of `media:upload`, `document:upload`, `knowledge-base:upload`, `thread:upload`, `design:edit`, `prompt:edit` or `presentation:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:upload",
					"document:upload",
					"knowledge-base:upload",
					"thread:upload",
					"design:edit",
					"prompt:edit",
					"presentation:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files": {
			"get": {
				"operationId": "listFiles",
				"summary": "List files",
				"tags": [
					"Files"
				],
				"description": "Returns files in one repository. `repo_type` selects which — `media` for the shared media library, or the kind of object that owns them (`ds`, `thread`, `design`, `prompt`) together with a `repo_id` naming it. A repository is required: files are always scoped to one rather than listed across the workspace.\n\nEach repository also has its own collection, which is the more direct way to ask — `GET /knowledge-bases/{id}/files`, `GET /threads/{id}/files`, `GET /designs/{id}/files` — and `GET /media-files` lists the media library with album membership and similarity search.\n\nRequires any one of `media:view`, `document:view`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "file_hash",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_provider_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_size",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "file_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "repo_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "repo_type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"generated",
								"docs",
								"ds",
								"thread",
								"design",
								"prompt",
								"ppt",
								"ppt_template",
								"form"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/File"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"document:view",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			},
			"post": {
				"operationId": "createFile",
				"summary": "Create an empty document",
				"tags": [
					"Files"
				],
				"description": "Creates a markdown document to write into. For uploading bytes, start with upload URLs instead.\n\nRequires any one of `media:upload`, `document:upload`, `knowledge-base:upload`, `thread:upload`, `design:edit`, `prompt:edit` or `presentation:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_repo": {
										"type": "object"
									},
									"file_name": {
										"type": "string"
									}
								},
								"required": [
									"file_repo",
									"file_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/File"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:upload",
					"document:upload",
					"knowledge-base:upload",
					"thread:upload",
					"design:edit",
					"prompt:edit",
					"presentation:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}": {
			"delete": {
				"operationId": "deleteFile",
				"summary": "Delete a file",
				"tags": [
					"Files"
				],
				"description": "Recoverable from the trash while its storage objects are still within the retention window.\n\nRequires any one of `media:delete`, `document:delete`, `knowledge-base:delete`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:delete",
					"document:delete",
					"knowledge-base:delete",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			},
			"get": {
				"operationId": "getFile",
				"summary": "Get a file",
				"tags": [
					"Files"
				],
				"description": "Returns one file's record — what it is, where it sits and what is known about it. The bytes are reached through a download URL.\n\nRequires any one of `media:view`, `document:view`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/File"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"document:view",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			},
			"put": {
				"operationId": "updateFile",
				"summary": "Update a file",
				"tags": [
					"Files"
				],
				"description": "Replaces the file's record. This is a PUT: it is the metadata that is being written, never the bytes. Which repository the file belongs to is not editable here — moving it is its own operation, because where a file sits decides who can reach it.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/File"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/analysis": {
			"put": {
				"operationId": "mergeFileAnalysis",
				"summary": "Merge analysis results",
				"tags": [
					"File analysis"
				],
				"description": "Merges values into what AI read out of the file, field by field — fields absent from the body keep the values the analysis gave them.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"analysis": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:edit"
			}
		},
		"/files/{id}/analyze-preview": {
			"post": {
				"operationId": "previewFileAnalysis",
				"summary": "Preview an analysis",
				"tags": [
					"File analysis"
				],
				"description": "A dry run: shows what a profile would produce, and writes nothing to the file.\n\nRequires the `module-custom-analysis` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"form_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"form_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:analyze",
				"x-required-plan": "module-custom-analysis"
			}
		},
		"/files/{id}/copy-to-media": {
			"post": {
				"operationId": "copyFileToMedia",
				"summary": "Copy to the library",
				"tags": [
					"Files"
				],
				"description": "Copies a file into the media library, where albums, faces and tags apply to it. The original stays where it was.\n\nRequires any one of `media:download`, `document:download`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view`, `presentation:view` or `media:upload`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:download",
					"document:download",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view",
					"media:upload"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/download-url": {
			"get": {
				"operationId": "getFileDownloadUrl",
				"summary": "Get a download URL",
				"tags": [
					"Downloads"
				],
				"description": "A signed, expiring URL for the file's bytes.\n\nRequires any one of `media:download`, `document:download`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "size",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"small",
								"medium",
								"large"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "string",
									"format": "uri",
									"description": "A signed URL, valid for a short window. The bytes never pass through the API."
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:download",
					"document:download",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/faces": {
			"get": {
				"operationId": "listFileFaces",
				"summary": "List faces",
				"tags": [
					"Faces"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the faces detected in one photo, most confident first, each with the person it was matched to. `fd_low_quality` marks a face too blurry to match reliably.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Face"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:view"
			}
		},
		"/files/{id}/faces/{face_id}": {
			"delete": {
				"operationId": "deleteFileFace",
				"summary": "Delete a face",
				"tags": [
					"Faces"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRemoves a detection that is not a face, or not one worth keeping. The photo is untouched.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "face_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			},
			"patch": {
				"operationId": "updateFileFace",
				"summary": "Update a face",
				"tags": [
					"Faces"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nAdjusts the detection itself — its box or how it is treated. Who it belongs to is set separately.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "face_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"fd_age": {
										"type": "integer",
										"minimum": 0,
										"maximum": 150
									},
									"fd_gender": {
										"type": "string"
									},
									"fd_expression": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/files/{id}/faces/{face_id}/link": {
			"patch": {
				"operationId": "linkFileFaceToPerson",
				"summary": "Link a face to a person",
				"tags": [
					"Faces"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nLinks this detection to a person. A detection belongs to the file it was found in; the person is a separate resource, and this is the link between them.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "face_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"person_index": {
										"type": "integer",
										"minimum": 0
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/files/{id}/favorite": {
			"patch": {
				"operationId": "toggleFileFavorite",
				"summary": "Favorite or unfavorite",
				"tags": [
					"Files"
				],
				"description": "Flips the caller's own favorite flag on the file. Favorites are per user, not per workspace.\n\nRequires any one of `media:view`, `document:view`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"favorite": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"favorite": {
											"type": "boolean",
											"description": "The state the file is now in."
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"document:view",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/finalize": {
			"put": {
				"operationId": "finalizeFile",
				"summary": "Finalize an upload",
				"tags": [
					"Uploads"
				],
				"description": "Step three. Confirms the bytes arrived, which is what admits the file to the library and starts processing — thumbnails, analysis, indexing. A file that is never finalized never appears.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/File"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/font-data": {
			"get": {
				"operationId": "getFontData",
				"summary": "Stream font bytes",
				"tags": [
					"Downloads"
				],
				"description": "Streams the font's bytes. Fonts come through the API rather than a signed URL so a browser can load them with `FontFace` without a cross-origin round trip.\n\nRequires any one of `media:download`, `document:download`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:download",
					"document:download",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/history": {
			"get": {
				"operationId": "listFileHistory",
				"summary": "List file history",
				"tags": [
					"Files"
				],
				"description": "Completed analysis runs, tag edits, renames and deletions, newest first, reduced to the facts that changed — the full analysis records behind them are not returned here.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:view"
			}
		},
		"/files/{id}/image-data": {
			"get": {
				"operationId": "getImageData",
				"summary": "Stream image bytes",
				"tags": [
					"Downloads"
				],
				"description": "Streams the image through the API rather than redirecting — for callers that cannot follow a signed URL, such as a canvas that would otherwise be tainted by a cross-origin fetch. Ask for a thumbnail or large rendition instead of the original where one exists.\n\nRequires any one of `media:download`, `document:download`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "replica",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 256
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:download",
					"document:download",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/media-tags": {
			"put": {
				"operationId": "setFileMediaTags",
				"summary": "Set media tags",
				"tags": [
					"Files"
				],
				"description": "Replaces the file's tags with what you send.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"mediaTags": {
										"type": "object"
									}
								},
								"required": [
									"mediaTags"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/move": {
			"post": {
				"operationId": "moveFile",
				"summary": "Move a file",
				"tags": [
					"Files"
				],
				"description": "Files the file under a different repository. Everything the move touches is checked: write access to the file, write access to where it is going, and write access to what it is leaving — taking a document out of a knowledge base changes that knowledge base.\n\nRetrieval follows the move: chunks indexed for the old repository answer for the new one from then on. A file that was never indexed does not become searchable by moving it into a knowledge base — reindex it explicitly.\n\nOnly repositories a caller may name are accepted — `library`, `ds`, `thread`, `design` and `prompt`. The rest are stamped by the platform to record how a file came to exist, and are returned but never sent.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_repo": {
										"type": "object"
									}
								},
								"required": [
									"file_repo"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/File"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/publication": {
			"delete": {
				"operationId": "unpublishFile",
				"summary": "Unpublish an asset",
				"tags": [
					"Publications"
				],
				"description": "Deletes the published copy and retires the URL, which then answers 410 rather than 404 so downstream channels can tell a withdrawn asset from one that never existed. The URL is kept, so publishing again revives the same address.\n\nRequires `media:publish`, `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` and `task:form:edit` together.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:publish",
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "all",
				"x-required-plan": "module-publication"
			},
			"get": {
				"operationId": "getPublication",
				"summary": "Get a publication",
				"tags": [
					"Publications"
				],
				"description": "The asset's public life: its permanent URL, which version is live, the availability window, and the distribution rules the edge enforces — including the workspace-wide baseline, which applies whether or not the asset names it.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Publication"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:publish",
				"x-required-plan": "module-publication"
			},
			"post": {
				"operationId": "publishFile",
				"summary": "Publish an asset",
				"tags": [
					"Publications"
				],
				"description": "Releases the current version to its permanent URL, minting the URL on first publish and reusing it forever after. Publishing again re-copies the bytes only when the file changed; a save that changes rules or dates alone updates the edge policy in place. A copy runs in the background; the publication reports `pub_copy_state` until it is live.\n\nRequires `media:publish`, `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` and `task:form:edit` together.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"distribution": {
										"enum": [
											"worldwide",
											"restricted"
										],
										"type": "string"
									},
									"deny": {
										"type": "array",
										"items": {
											"type": "string",
											"minLength": 2,
											"maxLength": 2
										}
									},
									"restrictions": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"start": {
										"type": "string",
										"format": "date-time"
									},
									"end": {
										"type": "string",
										"format": "date-time"
									}
								},
								"required": [
									"distribution"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Publication"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:publish",
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "all",
				"x-required-plan": "module-publication"
			}
		},
		"/files/{id}/reanalyze": {
			"post": {
				"operationId": "reanalyzeFile",
				"summary": "Reanalyze a file",
				"tags": [
					"File analysis"
				],
				"description": "Runs a model — it consumes credits and counts against the expensive rate-limit tier.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:analyze"
			}
		},
		"/files/{id}/references": {
			"get": {
				"operationId": "listFileReferences",
				"summary": "List file references",
				"tags": [
					"Files"
				],
				"description": "Everything holding on to this file — the albums containing it, designs using it in a layer or as a background, social posts that published it, share links exposing it, and the business objects it is attached to. This is what to check before deleting one.\n\nSections the caller may not see come back empty rather than being refused.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:view"
			}
		},
		"/files/{id}/save-as-new": {
			"post": {
				"operationId": "saveFileAsNew",
				"summary": "Save as a new file",
				"tags": [
					"File versions"
				],
				"description": "Saves the current content as a separate file rather than as a version of this one, leaving the original where it is.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"purpose": {
										"type": "string"
									},
									"file_repo": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/similar": {
			"get": {
				"operationId": "listSimilarFiles",
				"summary": "List similar files",
				"tags": [
					"Files"
				],
				"description": "Compares stored embeddings. Returns an empty list when the file has no embedding yet — analysis still pending, or a generated image, which never gets one.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 24
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/File"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:view"
			}
		},
		"/files/{id}/update-url": {
			"put": {
				"operationId": "refreshUploadUrl",
				"summary": "Get a fresh upload URL",
				"tags": [
					"Uploads"
				],
				"description": "Signed URLs expire. Use this to resume an upload whose URL has gone stale.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "string",
									"format": "uri",
									"description": "A fresh signed URL to PUT the bytes to."
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/versions": {
			"get": {
				"operationId": "listFileVersions",
				"summary": "List versions",
				"tags": [
					"File versions"
				],
				"description": "Returns the copies earlier saves replaced, newest first. Versions count against stored bytes and are capped per file.\n\nRequires any one of `media:view`, `document:view`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/FileVersion"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"document:view",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			},
			"post": {
				"operationId": "createFileVersion",
				"summary": "Save as a new version",
				"tags": [
					"File versions"
				],
				"description": "Takes bytes already uploaded as a throw-away file and attaches them to this file as its newest version, in one step, removing the temporary file. This is how an editor saves without leaving a stray upload behind.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "takeOwnership",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"source_file_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"source_file_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/versions/{version_id}": {
			"delete": {
				"operationId": "deleteFileVersion",
				"summary": "Delete a version",
				"tags": [
					"File versions"
				],
				"description": "Versions count against the storage quota, so pruning them frees space.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "version_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/versions/{version_id}/download-url": {
			"get": {
				"operationId": "getFileVersionDownloadUrl",
				"summary": "Get a version URL",
				"tags": [
					"Downloads"
				],
				"description": "Returns a signed URL for one earlier version of a file. It expires shortly; fetch a new one rather than storing it.\n\nRequires any one of `media:download`, `document:download`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "version_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "size",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"small",
								"medium",
								"large"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "string",
									"format": "uri",
									"description": "A signed URL for that version, valid for a short window."
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:download",
					"document:download",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/{id}/versions/{version_id}/revert": {
			"post": {
				"operationId": "revertFileToVersion",
				"summary": "Revert to a version",
				"tags": [
					"File versions"
				],
				"description": "Swaps the current content with the chosen version rather than discarding what was there — the version you were on becomes a version itself, so a revert is undoable.\n\nRequires any one of `media:edit`, `document:edit`, `knowledge-base:write`, `thread:edit`, `design:edit`, `prompt:edit`, `presentation:edit` or `task:form:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "version_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:edit",
					"document:edit",
					"knowledge-base:write",
					"thread:edit",
					"design:edit",
					"prompt:edit",
					"presentation:edit",
					"task:form:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/actions/download": {
			"post": {
				"operationId": "downloadFiles",
				"summary": "Download files as a ZIP",
				"tags": [
					"Downloads"
				],
				"description": "Zips a selection and returns it. Large selections should go through `POST /download-jobs` instead, which does the same work in the background.\n\nRequires any one of `media:download`, `document:download`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"file_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:download",
					"document:download",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/actions/reanalyze": {
			"post": {
				"operationId": "reanalyzeFiles",
				"summary": "Reanalyze files",
				"tags": [
					"File analysis"
				],
				"description": "Queues an analysis run over several files. Returns once queued, not once analyzed.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"file_ids"
								]
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:analyze"
			}
		},
		"/files/actions/reindex": {
			"post": {
				"operationId": "reindexFiles",
				"summary": "Reindex a repository",
				"tags": [
					"Files"
				],
				"description": "Rebuilds the search and retrieval index for a repository. It answers when the reindex is done, and refuses a repository holding more than 99 files rather than running long — the count of what was processed, skipped and what failed comes back in the response.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"repo_type": {
										"enum": [
											"media",
											"generated",
											"docs",
											"ds",
											"thread",
											"design",
											"prompt",
											"ppt",
											"ppt_template",
											"form"
										],
										"type": "string"
									},
									"repo_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"repo_type"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:write"
			}
		},
		"/files/actions/set-media-tags": {
			"post": {
				"operationId": "addMediaTagsToFiles",
				"summary": "Add media tags to files",
				"tags": [
					"Files"
				],
				"description": "Adds to what is already there, rather than replacing it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"mediaTags": {
										"type": "object"
									},
									"remove": {
										"type": "boolean"
									}
								},
								"required": [
									"file_ids",
									"mediaTags"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:edit"
			}
		},
		"/files/actions/transition": {
			"post": {
				"operationId": "transitionFiles",
				"summary": "Change file statuses",
				"tags": [
					"Files"
				],
				"description": "Moves files to another status in the flow that governs them. A move the flow does not allow is refused rather than forced.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"target_state_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"file_ids",
									"target_state_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:edit"
			}
		},
		"/files/face-search": {
			"post": {
				"operationId": "searchFilesByFace",
				"summary": "Search files by face",
				"tags": [
					"Faces"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"threshold": {
										"type": "number",
										"minimum": 0,
										"maximum": 1
									},
									"limit": {
										"type": "string",
										"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
									},
									"offset": {
										"type": "string",
										"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:search"
			}
		},
		"/files/search": {
			"get": {
				"operationId": "searchFiles",
				"summary": "Search files by name",
				"tags": [
					"Files"
				],
				"description": "Name matching for pickers and mentions, limited to files whose text has been extracted — a file with no rendition would add nothing to the message that mentions it. Two sources answer, each behind its own grant and labelled by `source`: the documents a knowledge base indexes, and the document library. An empty query answers with the most recently added.\n\nRequires any one of `media:view`, `document:view`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 25
						}
					},
					{
						"name": "q",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/File"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"document:view",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/files/trash": {
			"get": {
				"operationId": "listTrash",
				"summary": "List the trash",
				"tags": [
					"Files"
				],
				"description": "Each entry says whether it is still recoverable — the underlying storage objects are kept for a retention window, and once that passes the file is gone for good.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/File"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:delete"
			}
		},
		"/files/trash/{id}/recover": {
			"post": {
				"operationId": "recoverFile",
				"summary": "Restore a file",
				"tags": [
					"Files"
				],
				"description": "Restores the file and its thumbnails. Answers **409** if the storage objects are past their retention window — at that point there is nothing left to restore.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:delete"
			}
		},
		"/files/upload-urls": {
			"post": {
				"operationId": "createUploadUrls",
				"summary": "Get upload URLs",
				"tags": [
					"Uploads"
				],
				"description": "Step one of an upload, and it takes a batch. Returns a signed URL per file; PUT the bytes to it, then finalize each one. The bytes go straight to storage and never through the API.\n\nRequires any one of `media:upload`, `document:upload`, `knowledge-base:upload`, `thread:upload`, `design:edit`, `prompt:edit` or `presentation:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"files": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"file_name": {
													"type": "string"
												},
												"file_type": {
													"type": "string"
												},
												"file_size": {
													"type": "string",
													"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
												},
												"purpose": {
													"enum": [
														"media",
														"media-knowledge",
														"knowledge",
														"document",
														"file-repo",
														"chat",
														"font"
													],
													"type": "string"
												},
												"file_repo": {
													"type": "object"
												},
												"file_metadata": {
													"type": "object"
												},
												"mediaTags": {
													"type": "object"
												},
												"album_ids": {
													"type": "array",
													"items": {
														"type": "string",
														"format": "uuid"
													}
												}
											},
											"required": [
												"file_name",
												"file_type",
												"file_size",
												"purpose"
											]
										}
									}
								},
								"required": [
									"files"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/UploadTarget"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:upload",
					"document:upload",
					"knowledge-base:upload",
					"thread:upload",
					"design:edit",
					"prompt:edit",
					"presentation:edit"
				],
				"x-permission-mode": "any"
			}
		},
		"/infographics": {
			"get": {
				"operationId": "listInfographics",
				"summary": "List infographics",
				"tags": [
					"Infographics"
				],
				"description": "Returns the newest revision of each infographic, with how many revisions it has. Earlier ones are read through the versions endpoint.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "file_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 500
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 1000
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0
						}
					},
					{
						"name": "search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 500
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/Infographic"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:view"
			}
		},
		"/infographics/{id}": {
			"delete": {
				"operationId": "deleteInfographic",
				"summary": "Delete an infographic",
				"tags": [
					"Infographics"
				],
				"description": "Removes the image and the HTML it was rendered from — deleting only the picture would leave the source holding storage with nothing pointing at it. Pass `versions=all` to remove every revision.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "versions",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"all"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:delete"
			},
			"patch": {
				"operationId": "renameInfographic",
				"summary": "Rename an infographic",
				"tags": [
					"Infographics"
				],
				"description": "Renames the source and the image together, so the card and both downloads agree. Extensions are kept.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 250
									}
								},
								"required": [
									"file_name"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:edit"
			}
		},
		"/infographics/{id}/acl": {
			"get": {
				"operationId": "getInfographicAccess",
				"summary": "Get who has access",
				"tags": [
					"Infographics"
				],
				"description": "Returns who may read and edit this infographic. An empty result means unrestricted.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:view"
			},
			"put": {
				"operationId": "setInfographicAccess",
				"summary": "Set who has access",
				"tags": [
					"Infographics"
				],
				"description": "Applies to the HTML source as well as the image. Sharing a picture whose source stayed private would hand someone a card they cannot open, edit or export.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"acl": {
										"type": "object"
									}
								},
								"required": [
									"acl"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:edit"
			}
		},
		"/infographics/{id}/download-html": {
			"get": {
				"operationId": "downloadInfographicHtml",
				"summary": "Download the HTML source",
				"tags": [
					"Infographics"
				],
				"description": "Returns the HTML the image was rendered from — the editable source, not the picture.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:view"
			}
		},
		"/infographics/{id}/download-png": {
			"get": {
				"operationId": "downloadInfographicPng",
				"summary": "Download the image",
				"tags": [
					"Infographics"
				],
				"description": "Returns the rendered image. For a fresh render after a data refresh, snapshot it first.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:view"
			}
		},
		"/infographics/{id}/refresh": {
			"post": {
				"operationId": "refreshInfographic",
				"summary": "Refresh the data",
				"tags": [
					"Infographics"
				],
				"description": "Rebuilds the infographic from its stored brief, size and style and adds the result as the newest revision. Only the figures change.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:generate"
			}
		},
		"/infographics/{id}/schedule": {
			"put": {
				"operationId": "setInfographicSchedule",
				"summary": "Set the refresh schedule",
				"tags": [
					"Infographics"
				],
				"description": "Re-reads the data source on a cadence and posts a new revision each time. Only an infographic with a stored brief can be scheduled — without one there is nothing to regenerate from.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"enabled": {
										"type": "boolean"
									},
									"cadence": {
										"enum": [
											"daily",
											"weekly",
											"monthly"
										],
										"type": "string"
									}
								},
								"required": [
									"enabled"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:edit"
			}
		},
		"/infographics/{id}/snapshot-png": {
			"post": {
				"operationId": "snapshotInfographicPng",
				"summary": "Render a PNG",
				"tags": [
					"Infographics"
				],
				"description": "Renders the current HTML and files the image as the newest revision, so the list shows what the editor last saved. Used after an edit uploads new HTML.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"replaces": {
										"type": "string",
										"format": "uuid"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:view"
			}
		},
		"/infographics/{id}/to-design": {
			"post": {
				"operationId": "convertInfographicToDesign",
				"summary": "Convert to a design",
				"tags": [
					"Infographics"
				],
				"description": "Turns a rendered page into something editable: charts and background become an image plate, and each piece of copy becomes a text layer at its measured position, font and color.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/infographics/{id}/versions": {
			"get": {
				"operationId": "listInfographicVersions",
				"summary": "List versions",
				"tags": [
					"Infographics"
				],
				"description": "Returns the earlier revisions of this infographic, newest first.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:view"
			}
		},
		"/integrations": {
			"get": {
				"operationId": "listIntegrations",
				"summary": "List connections",
				"tags": [
					"Integrations"
				],
				"description": "Keys are never included.\n\nRequires the `module-external-data` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "conn_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "conn_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Integration"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "integration:view",
				"x-required-plan": "module-external-data"
			},
			"post": {
				"operationId": "createIntegration",
				"summary": "Create a connection",
				"tags": [
					"Integrations"
				],
				"description": "Credentials are passed to the connector service and are not stored by this API.\n\n`conn_provider` must be the `key` of one of the providers returned by `GET /integrations/providers`. That endpoint also says what the provider needs: send its `credential.fields` as `fields` and its `variables` as `variables`, each keyed by the key given there. A provider that is not in the list is rejected with 422.\n\nRequires the `module-external-data` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"conn_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 120
									},
									"conn_provider": {
										"type": "string"
									},
									"fields": {
										"type": "object"
									},
									"variables": {
										"type": "object"
									},
									"allow_write": {
										"type": "boolean"
									}
								},
								"required": [
									"conn_name",
									"conn_provider",
									"fields"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Integration"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "integration:create",
				"x-required-plan": "module-external-data"
			}
		},
		"/integrations/{id}": {
			"delete": {
				"operationId": "deleteIntegration",
				"summary": "Delete a connection",
				"tags": [
					"Integrations"
				],
				"description": "Revokes the connection at the provider — every key issued through it stops working immediately — and retires the record. Anything relying on it fails from this point.\n\nRequires the `module-external-data` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "integration:delete",
				"x-required-plan": "module-external-data"
			},
			"get": {
				"operationId": "getIntegration",
				"summary": "Get a connection",
				"tags": [
					"Integrations"
				],
				"description": "Returns the connection and its status. Credentials are never returned — they are held outside the database and referenced.\n\nRequires the `module-external-data` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Integration"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "integration:view",
				"x-required-plan": "module-external-data"
			},
			"patch": {
				"operationId": "updateIntegration",
				"summary": "Update a connection",
				"tags": [
					"Integrations"
				],
				"description": "Applies the `conn_`-prefixed fields present in the body. Replacing credentials re-verifies the connection.\n\nRequires the `module-external-data` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"conn_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 120
									},
									"allow_write": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Integration"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "integration:edit",
				"x-required-plan": "module-external-data"
			}
		},
		"/integrations/{id}/operations": {
			"get": {
				"operationId": "searchIntegrationOperations",
				"summary": "Search operations",
				"tags": [
					"Integrations"
				],
				"description": "Searches the operations this connection exposes — the actions an agent can be given through it.\n\nRequires the `module-external-data` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "query",
						"in": "query",
						"required": true,
						"schema": {
							"type": "string",
							"minLength": 1
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "integration:view",
				"x-required-plan": "module-external-data"
			}
		},
		"/integrations/providers": {
			"get": {
				"operationId": "listIntegrationProviders",
				"summary": "List providers",
				"tags": [
					"Integrations"
				],
				"description": "The products a connection can be made to, and what each needs to connect. A static catalog, and deliberately a narrowed view of it: the credential recipe internals are not part of the answer.\n\n`key` is what `POST /integrations` takes as its `conn_provider`. `variables` are the non-secret inputs that provider needs — a subdomain, a region — and `credential.fields` the secrets it authenticates with; both are keyed the way the create body expects them. Read the list rather than hardcoding it: connectors are added between releases.\n\nRequires the `module-external-data` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"examples": {
									"providers": {
										"value": [
											{
												"key": "hubspot",
												"name": "HubSpot",
												"icon": "ph-chart-line-up",
												"description": "CRM contacts, companies and deals from HubSpot.",
												"variables": [],
												"credential": {
													"fields": [
														{
															"key": "token",
															"label": "Private app access token",
															"secret": true
														}
													]
												}
											},
											{
												"key": "wordpress",
												"name": "WordPress",
												"icon": "ph-globe-simple",
												"description": "Posts, pages and comments from a WordPress site (REST API + application password).",
												"variables": [
													{
														"key": "site",
														"label": "Site domain (e.g. blog.example.com)"
													}
												],
												"credential": {
													"fields": [
														{
															"key": "username",
															"label": "WordPress username",
															"secret": false
														},
														{
															"key": "password",
															"label": "Application password",
															"secret": true
														}
													]
												}
											}
										]
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null,
				"x-required-plan": "module-external-data"
			}
		},
		"/knowledge-base-records": {
			"get": {
				"operationId": "searchKnowledgeBaseRecords",
				"summary": "Search all records",
				"tags": [
					"Knowledge base records"
				],
				"description": "Read-only, and flat rather than nested under a knowledge base, because the queries it exists for span several — by name, by category, or by a list of ids. Records are created and edited through their own knowledge base.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "data_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "data_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "data_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "data_repo",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "data_title",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "data_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_category",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ds_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ds_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "dsi_embedding_model",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "summary",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/KnowledgeBaseRecord"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:record:view"
			}
		},
		"/knowledge-base-schemas": {
			"get": {
				"operationId": "listKnowledgeBaseSchemas",
				"summary": "List schemas",
				"tags": [
					"Knowledge base schemas"
				],
				"description": "Returns the record schemas knowledge bases can be built from — the workspace's own and the standard templates the product ships.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "form_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "form_config",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "form_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "form_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "form_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "form_managed_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "form_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "form_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/KnowledgeBaseSchema"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"post": {
				"operationId": "createKnowledgeBaseSchema",
				"summary": "Create a schema",
				"tags": [
					"Knowledge base schemas"
				],
				"description": "Creates an empty schema to define fields on. `POST /knowledge-bases` with `ds_type: form` and no schema named also creates one, already linked to the base.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"form_name": {
										"type": "string",
										"minLength": 1
									},
									"form_description": {
										"type": "string"
									},
									"form_config": {
										"type": "object"
									},
									"form_metadata": {
										"type": "object"
									}
								},
								"required": [
									"form_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBaseSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:schema:edit"
			}
		},
		"/knowledge-base-schemas/{id}": {
			"delete": {
				"operationId": "deleteKnowledgeBaseSchema",
				"summary": "Delete a schema",
				"tags": [
					"Knowledge base schemas"
				],
				"description": "Deactivates the schema. Records already collected with it are unaffected. A schema an active knowledge base is built on cannot be removed: deactivate the base first.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:schema:edit"
			},
			"get": {
				"operationId": "getKnowledgeBaseSchema",
				"summary": "Get a schema",
				"tags": [
					"Knowledge base schemas"
				],
				"description": "Returns the schema with its field definitions. A knowledge base names its schema in `form_id`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBaseSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"patch": {
				"operationId": "updateKnowledgeBaseSchema",
				"summary": "Update a schema",
				"tags": [
					"Knowledge base schemas"
				],
				"description": "Applies the `form_`-prefixed fields present in the body. Records already collected keep the shape they were collected with. A product-shipped template cannot be changed — fork it through the knowledge base that uses it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"form_name": {
										"type": "string"
									},
									"form_description": {
										"type": "string"
									},
									"form_active": {
										"type": "boolean"
									},
									"form_config": {
										"type": "object"
									},
									"form_metadata": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBaseSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:schema:edit"
			}
		},
		"/knowledge-bases": {
			"get": {
				"operationId": "listKnowledgeBases",
				"summary": "List knowledge bases",
				"tags": [
					"Knowledge bases"
				],
				"description": "Returns the workspace's knowledge bases. Where a base is backed by a record schema, the schema's id and name are included as `form_id` and `form_name`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "ds_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "ds_category",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ds_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ds_subcategory",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/KnowledgeBase"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:view"
			},
			"post": {
				"operationId": "createKnowledgeBase",
				"summary": "Create a knowledge base",
				"tags": [
					"Knowledge bases"
				],
				"description": "Names must be unique in the workspace — they are how agents refer to a knowledge base.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"ds_name": {
										"type": "string",
										"minLength": 1
									},
									"ds_description": {
										"type": "string"
									},
									"ds_type": {
										"type": "string",
										"minLength": 1
									},
									"ds_category": {
										"enum": [
											"general",
											"brand-identity",
											"studio"
										],
										"type": "string"
									},
									"ds_subcategory": {
										"enum": [
											"",
											"messaging",
											"visual-identity",
											"other"
										],
										"type": "string"
									},
									"ds_config": {
										"type": "object"
									}
								},
								"required": [
									"ds_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBase"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:create"
			}
		},
		"/knowledge-bases/{id}": {
			"delete": {
				"operationId": "deleteKnowledgeBase",
				"summary": "Delete a knowledge base",
				"tags": [
					"Knowledge bases"
				],
				"description": "Agents pointing at it stop retrieving from it. Check before removing one that is in use.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:delete"
			},
			"get": {
				"operationId": "getKnowledgeBase",
				"summary": "Get a knowledge base",
				"tags": [
					"Knowledge bases"
				],
				"description": "Returns the knowledge base with its type, its category and the form its records are shaped by.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBase"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:view"
			},
			"patch": {
				"operationId": "updateKnowledgeBase",
				"summary": "Update a knowledge base",
				"tags": [
					"Knowledge bases"
				],
				"description": "Applies the `ds_`-prefixed fields present in the body. A base's name must stay unique within the workspace.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"ds_name": {
										"type": "string",
										"minLength": 1
									},
									"ds_description": {
										"type": "string"
									},
									"ds_type": {
										"type": "string",
										"minLength": 1
									},
									"ds_category": {
										"enum": [
											"general",
											"brand-identity",
											"studio",
											"configuration"
										],
										"type": "string"
									},
									"ds_subcategory": {
										"enum": [
											"",
											"messaging",
											"visual-identity",
											"other"
										],
										"type": "string"
									},
									"ds_config": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBase"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:edit"
			}
		},
		"/knowledge-bases/{id}/export": {
			"get": {
				"operationId": "exportKnowledgeBase",
				"summary": "Export records",
				"tags": [
					"Knowledge bases"
				],
				"description": "Returns every record in the base as a file, for moving it elsewhere or keeping a copy.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:export"
			}
		},
		"/knowledge-bases/{id}/files": {
			"get": {
				"operationId": "listKnowledgeBaseFiles",
				"summary": "List knowledge base files",
				"tags": [
					"Knowledge bases"
				],
				"description": "The documents this knowledge base indexes. Reading them is reading the knowledge base, so its own access rules apply on top of each file's.\n\nRequires any one of `media:view`, `document:view`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "file_hash",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_provider_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_size",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "file_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "repo_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "repo_type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"generated",
								"docs",
								"ds",
								"thread",
								"design",
								"prompt",
								"ppt",
								"ppt_template",
								"form"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/File"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"document:view",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/knowledge-bases/{id}/fork-form": {
			"post": {
				"operationId": "forkKnowledgeBaseSchema",
				"summary": "Fork the record schema",
				"tags": [
					"Knowledge bases"
				],
				"description": "A knowledge base built from a standard template shares that template. This copies it into one the workspace owns and re-points the knowledge base and its existing records at the copy — so the shape can be changed without affecting anyone else, and without a later template update overwriting the changes. A few templates are fixed: where a knowledge base is presented on a screen built for its fields, the copy is refused.\n\nRequires both `knowledge-base:edit` and `knowledge-base:schema:edit`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"knowledge-base:edit",
					"knowledge-base:schema:edit"
				],
				"x-permission-mode": "all"
			}
		},
		"/knowledge-bases/{id}/import": {
			"post": {
				"operationId": "importKnowledgeBase",
				"summary": "Import records",
				"tags": [
					"Knowledge bases"
				],
				"description": "Bulk load. The payload is size-capped — split a large import rather than sending it in one call.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"items": {
										"type": "array",
										"items": {}
									},
									"sourceUrl": {
										"type": "string"
									}
								},
								"required": [
									"items"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:import"
			}
		},
		"/knowledge-bases/{id}/init-knowledge": {
			"post": {
				"operationId": "initKnowledgeBaseFromWebsite",
				"summary": "Fill from a website",
				"tags": [
					"Knowledge bases"
				],
				"description": "Crawls a URL and turns what it finds into records. Runs in the background — this returning does not mean the crawl has finished.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"url": {
										"type": "string",
										"format": "uri"
									},
									"preview": {
										"type": "boolean"
									}
								},
								"required": [
									"url"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:crawl"
			}
		},
		"/knowledge-bases/{id}/records": {
			"delete": {
				"operationId": "deleteAllKnowledgeBaseRecords",
				"summary": "Delete all records",
				"tags": [
					"Knowledge base records"
				],
				"description": "Empties it without deleting the knowledge base. Not reversible.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:record:delete"
			},
			"get": {
				"operationId": "listKnowledgeBaseRecords",
				"summary": "List records",
				"tags": [
					"Knowledge base records"
				],
				"description": "Returns the records in one knowledge base. To search across every base at once, use `GET /knowledge-base-records`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "data_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "data_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "data_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "data_repo",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "data_title",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "data_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_category",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ds_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ds_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "ds_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "dsi_embedding_model",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "summary",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/KnowledgeBaseRecord"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:record:view"
			},
			"post": {
				"operationId": "createKnowledgeBaseRecord",
				"summary": "Add a record",
				"tags": [
					"Knowledge base records"
				],
				"description": "Its fields are the shape the knowledge base's schema declares.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"data_title": {
										"type": "string"
									},
									"data_repo": {
										"type": "object"
									},
									"data_content": {
										"type": "object"
									},
									"data_form": {
										"type": "object"
									},
									"data_metadata": {
										"type": "object"
									},
									"data_acl": {
										"type": "object"
									},
									"data_chunk": {
										"type": "object"
									},
									"data_embedding_model": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBaseRecord"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:record:create"
			}
		},
		"/knowledge-bases/{id}/records/{record_id}": {
			"delete": {
				"operationId": "deleteKnowledgeBaseRecord",
				"summary": "Delete a record",
				"tags": [
					"Knowledge base records"
				],
				"description": "Deactivates the record. It stops being returned and stops being retrieved by agents.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "record_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:record:delete"
			},
			"get": {
				"operationId": "getKnowledgeBaseRecord",
				"summary": "Get a record",
				"tags": [
					"Knowledge base records"
				],
				"description": "Returns one record, shaped by the form its knowledge base was created with.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "record_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBaseRecord"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:record:view"
			},
			"patch": {
				"operationId": "updateKnowledgeBaseRecord",
				"summary": "Update a record",
				"tags": [
					"Knowledge base records"
				],
				"description": "Applies the `data_`-prefixed fields present in the body. Editing the content re-embeds the record, so retrieval sees the change without a reindex.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "record_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"data_title": {
										"type": "string"
									},
									"data_active": {
										"type": "boolean"
									},
									"data_repo": {
										"type": "object"
									},
									"data_content": {
										"type": "object"
									},
									"data_form": {
										"type": "object"
									},
									"data_metadata": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/KnowledgeBaseRecord"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:record:edit"
			}
		},
		"/knowledge-bases/google-fonts": {
			"get": {
				"operationId": "listGoogleFonts",
				"summary": "List Google Fonts",
				"tags": [
					"Knowledge bases"
				],
				"description": "A static catalog of `{family, category}`, used when picking type in the design tools. Exposes no workspace data.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			}
		},
		"/knowledge-bases/stats": {
			"get": {
				"operationId": "getKnowledgeBaseStats",
				"summary": "Get statistics",
				"tags": [
					"Knowledge bases"
				],
				"description": "Counts of bases and records, for a dashboard rather than a listing.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "knowledge-base:view"
			}
		},
		"/me": {
			"get": {
				"operationId": "getMe",
				"summary": "Get the current user",
				"tags": [
					"Me"
				],
				"description": "Who the caller is, which workspace they are acting in, and what they may do — the permissions and plan features the rest of the API enforces, plus the credit balance it spends against.\n\n`usr_permissions` is already the effective set: the caller's roles intersected with what their plan entitles, narrowed again by `key_permissions` when an API key authenticated the request. A permission absent here will be refused everywhere else.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"usr_id": {
											"type": "string",
											"format": "uuid"
										},
										"usr_email": {
											"type": "string",
											"format": "email"
										},
										"usr_name": {
											"type": "string"
										},
										"usr_name_first": {
											"type": "string"
										},
										"usr_name_last": {
											"type": "string"
										},
										"usr_lang": {
											"type": [
												"string",
												"null"
											]
										},
										"usr_permissions": {
											"type": "array",
											"items": {
												"type": "string"
											}
										},
										"tenant_id": {
											"type": "string",
											"format": "uuid"
										},
										"tenant_name": {
											"type": "string"
										},
										"features": {
											"type": "array",
											"items": {
												"type": "string"
											},
											"description": "The plan features this workspace is entitled to."
										},
										"credits": {
											"type": "object",
											"properties": {
												"available": {
													"type": [
														"number",
														"null"
													],
													"description": "The cycle entitlement, or null when it is unmetered."
												},
												"used": {
													"type": "number"
												},
												"remaining": {
													"type": [
														"number",
														"null"
													]
												},
												"hasCredits": {
													"type": "boolean"
												},
												"low": {
													"type": "boolean"
												}
											},
											"required": [
												"available",
												"used",
												"remaining",
												"hasCredits",
												"low"
											],
											"additionalProperties": false
										},
										"auth_method": {
											"type": "string",
											"enum": [
												"jwt",
												"api_key"
											],
											"description": "How this request authenticated."
										}
									},
									"required": [
										"usr_id",
										"usr_email",
										"usr_name",
										"usr_name_first",
										"usr_name_last",
										"usr_lang",
										"usr_permissions",
										"tenant_id",
										"tenant_name",
										"features",
										"credits",
										"auth_method"
									],
									"additionalProperties": false
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			}
		},
		"/media-analysis-schemas": {
			"get": {
				"operationId": "listMediaAnalysisSchemas",
				"summary": "List schemas",
				"tags": [
					"Media analysis schemas"
				],
				"description": "Returns the workspace's analysis schemas, including the field definitions of each. At most one is in use at a time: the one the `imageAnalysisFormId` workspace setting names.\n\nRequires the `module-custom-analysis` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "form_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "form_config",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "form_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "form_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "form_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "form_managed_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "form_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "form_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/MediaAnalysisSchema"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null,
				"x-required-plan": "module-custom-analysis"
			},
			"post": {
				"operationId": "createMediaAnalysisSchema",
				"summary": "Create a schema",
				"tags": [
					"Media analysis schemas"
				],
				"description": "Creating a schema does not put it in use — point the `imageAnalysisFormId` workspace setting at it to have analysis apply it.\n\nRequires the `module-custom-analysis` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"form_name": {
										"type": "string",
										"minLength": 1
									},
									"form_description": {
										"type": "string"
									},
									"form_config": {
										"type": "object"
									},
									"form_metadata": {
										"type": "object"
									}
								},
								"required": [
									"form_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/MediaAnalysisSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-analysis:edit",
				"x-required-plan": "module-custom-analysis"
			}
		},
		"/media-analysis-schemas/{id}": {
			"delete": {
				"operationId": "deleteMediaAnalysisSchema",
				"summary": "Delete a schema",
				"tags": [
					"Media analysis schemas"
				],
				"description": "Deactivates the schema. Files already analyzed keep the values they were analyzed with.\n\nRequires the `module-custom-analysis` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-analysis:edit",
				"x-required-plan": "module-custom-analysis"
			},
			"get": {
				"operationId": "getMediaAnalysisSchema",
				"summary": "Get a schema",
				"tags": [
					"Media analysis schemas"
				],
				"description": "Returns the schema with its field definitions.\n\nRequires the `module-custom-analysis` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/MediaAnalysisSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null,
				"x-required-plan": "module-custom-analysis"
			},
			"patch": {
				"operationId": "updateMediaAnalysisSchema",
				"summary": "Update a schema",
				"tags": [
					"Media analysis schemas"
				],
				"description": "Applies the `form_`-prefixed fields present in the body. Changes reach future analysis runs; files already analyzed keep the values they were analyzed with.\n\nRequires the `module-custom-analysis` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"form_name": {
										"type": "string"
									},
									"form_description": {
										"type": "string"
									},
									"form_active": {
										"type": "boolean"
									},
									"form_config": {
										"type": "object"
									},
									"form_metadata": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/MediaAnalysisSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "admin:media-analysis:edit",
				"x-required-plan": "module-custom-analysis"
			}
		},
		"/media-files": {
			"get": {
				"operationId": "listMediaFiles",
				"summary": "List media files",
				"tags": [
					"Files"
				],
				"description": "Returns files with the albums each belongs to. An embedding in the request adds a `similarity` score and orders by it; a face embedding does the same through `face_similarity`. `GET /files` is the plainer listing — this one is the library's own, and it is the only place the similarity searches are offered.\n\n`repo_type` is required, as it is on `GET /files`: `media` for the uploaded library, `generated` for what the platform produced on its own. An image generated inside a conversation belongs to that conversation instead — list those with `repo_type=thread`.\n\n`fileType` cuts the list by kind — `Image`, `Video`, `Audio` or `Document` — and `file_format` by the file name's extension, `mov` or `mp4`, with or without the leading dot. Both repeat to widen the selection rather than narrow it, and `GET /media-files/formats` answers which values are worth sending for a given repository. `file_added_by` keeps only files the named users uploaded, by user id, and repeats the same way.\n\n`analyzed=false` keeps the files AI analysis never produced output for — deferred while credits were exhausted, failed, or uploaded before analysis existed — the set worth re-running; `analyzed=true` is its complement.\n\nRequires either `media:view` or `infographic:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "aiGenerated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "analyzed",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "contentType",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"image",
								"infographic"
							],
							"type": "string"
						}
					},
					{
						"name": "embedding_search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "face_embedding",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "face_person",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "face_threshold",
						"in": "query",
						"required": false,
						"schema": {
							"type": "number",
							"minimum": 0,
							"maximum": 1
						}
					},
					{
						"name": "favorite",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_format",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "fileType",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "has_faces",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
						}
					},
					{
						"name": "repo_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "repo_type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"generated",
								"docs",
								"ds",
								"thread",
								"design",
								"prompt",
								"ppt",
								"ppt_template",
								"form"
							],
							"type": "string"
						}
					},
					{
						"name": "search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 200
						}
					},
					{
						"name": "similarityThreshold",
						"in": "query",
						"required": false,
						"schema": {
							"type": "number",
							"minimum": 0,
							"maximum": 1
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/MediaFile"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"infographic:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/media-files/formats": {
			"get": {
				"operationId": "listMediaFileFormats",
				"summary": "List formats",
				"tags": [
					"Files"
				],
				"description": "The kinds and formats of file actually present in the repository the request names, each with how many files carry it. This is the option list behind the media library's type filter — it is what lets that filter offer `mov` and `mp4` as separate choices without offering formats the account holds none of.\n\nA row is a filter: `kind` is what `fileType` takes on `GET /media-files` and `format` is what `file_format` takes, so a caller sends one straight back. The counts describe the repository, the album and the favorite flag and nothing else — the gallery's remaining filters and both similarity searches leave them alone, so a count says what is in here rather than what the current query matches. A file whose name carries no extension has no format and is counted under its kind alone.\n\nCounting is exact, which means reading every file the caller can see. A library too large to do that inside the server's budget answers with all four kinds, a null `count` on each and no formats — the filter still works, it just stops saying how many. Treat a null count as \"not counted\" rather than zero.\n\nRequires either `media:view` or `infographic:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "af_album",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "favorite",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "repo_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "repo_type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"generated",
								"docs",
								"ds",
								"thread",
								"design",
								"prompt",
								"ppt",
								"ppt_template",
								"form"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"kinds": {
											"type": "array",
											"items": {
												"type": "object",
												"properties": {
													"kind": {
														"type": "string",
														"enum": [
															"Image",
															"Video",
															"Audio",
															"Document"
														]
													},
													"count": {
														"anyOf": [
															{
																"type": "integer"
															},
															{
																"type": "null"
															}
														],
														"description": "Null when the library was too large to count in time."
													}
												},
												"required": [
													"kind",
													"count"
												],
												"additionalProperties": false
											}
										},
										"formats": {
											"type": "array",
											"items": {
												"type": "object",
												"properties": {
													"format": {
														"type": "string",
														"description": "The file name extension, lower case and without the dot."
													},
													"kind": {
														"type": "string",
														"enum": [
															"Image",
															"Video",
															"Audio",
															"Document"
														]
													},
													"count": {
														"type": "integer"
													}
												},
												"required": [
													"format",
													"kind",
													"count"
												],
												"additionalProperties": false
											},
											"description": "Ordered by count, most common first."
										}
									},
									"required": [
										"kinds",
										"formats"
									],
									"additionalProperties": false
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"infographic:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/media-tags": {
			"post": {
				"operationId": "createMediaTag",
				"summary": "Add a tag",
				"tags": [
					"Media tags"
				],
				"description": "Adds one tag to an existing group in the named `scope`. To restructure the groups themselves, replace them wholesale.\n\nRequires either `media:tag:create` or `document:tag:create`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"scope": {
										"enum": [
											"media",
											"docs"
										],
										"type": "string"
									},
									"group": {
										"type": "string",
										"minLength": 1,
										"maxLength": 100
									},
									"name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 50
									}
								},
								"required": [
									"group",
									"name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:tag:create",
					"document:tag:create"
				],
				"x-permission-mode": "any"
			}
		},
		"/memories": {
			"delete": {
				"operationId": "deleteAllMemories",
				"summary": "Delete all memories",
				"tags": [
					"Memories"
				],
				"description": "Deletes every memory belonging to the caller and returns how many went. Not reversible.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"get": {
				"operationId": "listMemories",
				"summary": "List memories",
				"tags": [
					"Memories"
				],
				"description": "What the assistant has remembered about the calling user — facts it carries into later conversations. Nobody else's are visible, including to an administrator.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "mem_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "mem_type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"fact",
								"preference",
								"context"
							],
							"type": "string"
						}
					},
					{
						"name": "mem_value",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Memory"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"post": {
				"operationId": "createMemory",
				"summary": "Add a memory",
				"tags": [
					"Memories"
				],
				"description": "Records something to remember about the calling user. Memories are personal — nobody else in the workspace sees them.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"mem_value": {
										"type": "string",
										"minLength": 1,
										"maxLength": 1000
									},
									"mem_type": {
										"enum": [
											"fact",
											"preference",
											"context"
										],
										"type": "string"
									}
								},
								"required": [
									"mem_value"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Memory"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			}
		},
		"/memories/{id}": {
			"delete": {
				"operationId": "deleteMemory",
				"summary": "Delete a memory",
				"tags": [
					"Memories"
				],
				"description": "Forgets one memory. To clear them all at once, delete the collection.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"patch": {
				"operationId": "updateMemory",
				"summary": "Update a memory",
				"tags": [
					"Memories"
				],
				"description": "Rewrites one memory. Only the caller's own memories can be reached.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"mem_value": {
										"type": "string",
										"minLength": 1,
										"maxLength": 1000
									},
									"mem_type": {
										"enum": [
											"fact",
											"preference",
											"context"
										],
										"type": "string"
									},
									"mem_active": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Memory"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			}
		},
		"/object-lifecycle-flows": {
			"get": {
				"operationId": "listObjectLifecycleFlows",
				"summary": "List flows",
				"tags": [
					"Object lifecycle flows"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the workspace's object lifecycle flows, each with its states. At most one is active at a time.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sm_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/ObjectLifecycleFlow"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"post": {
				"operationId": "createObjectLifecycleFlow",
				"summary": "Create a flow",
				"tags": [
					"Object lifecycle flows"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nDefines the states objects move through and who may move them. New objects start in the initial state. Answers 409 while an active flow exists — update or delete that one instead.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"states": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"si_label": {
													"type": "string"
												}
											},
											"required": [
												"si_label"
											]
										}
									},
									"transitions": {
										"type": "array",
										"items": {}
									},
									"sm_name": {
										"type": "string"
									},
									"sm_default": {
										"type": "boolean"
									}
								},
								"required": [
									"states"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectLifecycleFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-lifecycle-flows/{id}": {
			"delete": {
				"operationId": "deleteObjectLifecycleFlow",
				"summary": "Delete a flow",
				"tags": [
					"Object lifecycle flows"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nStops objects being governed. Records keep the state they are in.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			},
			"get": {
				"operationId": "getObjectLifecycleFlow",
				"summary": "Get a flow",
				"tags": [
					"Object lifecycle flows"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the flow with its states, its transitions, and the roles each transition requires.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectLifecycleFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"put": {
				"operationId": "updateObjectLifecycleFlow",
				"summary": "Update a flow",
				"tags": [
					"Object lifecycle flows"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReplaces the flow's states and transitions. Objects already sitting in a state the new definition drops keep that value until something moves them.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"states": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"si_label": {
													"type": "string"
												}
											},
											"required": [
												"si_label"
											]
										}
									},
									"transitions": {
										"type": "array",
										"items": {}
									},
									"sm_name": {
										"type": "string"
									},
									"sm_default": {
										"type": "boolean"
									}
								},
								"required": [
									"states"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectLifecycleFlow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-schemas": {
			"get": {
				"operationId": "listObjectSchemas",
				"summary": "List object schemas",
				"tags": [
					"Object schemas"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the workspace's object schemas, including the field definitions of each.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "form_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "form_config",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "form_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "form_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "form_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "form_managed_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "form_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "form_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ObjectSchema"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null,
				"x-required-plan": "module-objects"
			},
			"post": {
				"operationId": "createObjectSchema",
				"summary": "Create an object schema",
				"tags": [
					"Object schemas"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nDeclares the attributes a kind of object has. Point an object at it with `obj_form` to have its `obj_content` validated against these fields.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"form_name": {
										"type": "string",
										"minLength": 1
									},
									"form_description": {
										"type": "string"
									},
									"form_config": {
										"type": "object"
									},
									"form_metadata": {
										"type": "object"
									}
								},
								"required": [
									"form_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-schemas/{id}": {
			"delete": {
				"operationId": "deleteObjectSchema",
				"summary": "Delete an object schema",
				"tags": [
					"Object schemas"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nDeactivates the schema. Objects pointing at it stop accepting writes to `obj_content` until they are pointed at another one.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			},
			"get": {
				"operationId": "getObjectSchema",
				"summary": "Get an object schema",
				"tags": [
					"Object schemas"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the schema with its field definitions.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null,
				"x-required-plan": "module-objects"
			},
			"patch": {
				"operationId": "updateObjectSchema",
				"summary": "Update an object schema",
				"tags": [
					"Object schemas"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nApplies the `form_`-prefixed fields present in the body. Objects already stored keep the values they were stored with — removing a field hides it rather than erasing what was collected.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"form_name": {
										"type": "string"
									},
									"form_description": {
										"type": "string"
									},
									"form_active": {
										"type": "boolean"
									},
									"form_config": {
										"type": "object"
									},
									"form_metadata": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSchema"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources": {
			"get": {
				"operationId": "listObjectSources",
				"summary": "List object sources",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe upstream systems this workspace pulls records from. Secrets inside `src_config` come back masked.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "src_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "src_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "src_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "src_provider",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ObjectSource"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"post": {
				"operationId": "createObjectSource",
				"summary": "Create an object source",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRegisters a connection to the system that owns the product data. `src_config` carries `baseUrl`, `auth` (basic or OAuth client credentials), `context`, `workspace`, the `roots` to walk, `classifications` to mirror, the `types` mapping onto object types, an optional `eventQueue` and a `schedule`. Enabling the schedule provisions the delta job.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"src_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 200
									},
									"src_provider": {
										"enum": [
											"step"
										],
										"type": "string"
									},
									"src_config": {
										"type": "object"
									},
									"src_metadata": {
										"type": "object"
									}
								},
								"required": [
									"src_name",
									"src_config"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSource"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}": {
			"delete": {
				"operationId": "deleteObjectSource",
				"summary": "Delete an object source",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nDeactivates the source, cancels a run in progress and pauses its schedule. Records already pulled stay where they are.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			},
			"get": {
				"operationId": "getObjectSource",
				"summary": "Get an object source",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns one source with its connection, scope and mapping. Secrets are masked; send the mask back unchanged to keep a stored value.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSource"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"patch": {
				"operationId": "updateObjectSource",
				"summary": "Update an object source",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nApplies the fields present. A `src_config` replaces the stored one whole, with masked secrets restored from what is stored. The schedule follows the new config.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"src_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 200
									},
									"src_config": {
										"type": "object"
									},
									"src_metadata": {
										"type": "object"
									},
									"src_provider": {
										"type": "string"
									}
								},
								"required": [
									"src_provider"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSource"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/discover-schema": {
			"post": {
				"operationId": "discoverObjectSourceSchema",
				"summary": "Draft a schema from source",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReads a sample record of `step_type` (`sample_id` from the connection test, otherwise the first one found under the configured roots), reads the definitions of the attributes it carries, and returns object-schema fields plus the field mapping to review. Nothing is saved.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"step_type": {
										"type": "string",
										"minLength": 1,
										"maxLength": 200
									},
									"sample_id": {
										"type": "string",
										"minLength": 1,
										"maxLength": 200
									},
									"src_config": {
										"type": "object"
									}
								},
								"required": [
									"step_type"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"stepType": {
											"type": "string"
										},
										"sampleId": {
											"type": "string"
										},
										"sampleName": {
											"type": [
												"string",
												"null"
											]
										},
										"attributes": {
											"type": "array",
											"items": {
												"type": "object"
											}
										},
										"fields": {
											"type": "array",
											"items": {
												"type": "object"
											}
										},
										"mapping": {
											"type": "object",
											"additionalProperties": {
												"type": "string"
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/full-load": {
			"post": {
				"operationId": "startObjectSourceFullLoad",
				"summary": "Start a full load",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nWalks every configured root and writes what it finds. Answers 202 with the run; follow it under `/object-sources/{id}/jobs`. `force` rewrites records whose content did not change. Refused while another run is active, and refused outright when no type and no scheme is mapped.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"force": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSyncJob"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:create",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/jobs": {
			"get": {
				"operationId": "listObjectSourceJobs",
				"summary": "List runs",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nEvery recent run against the source, newest first, with counts and the records each could not settle.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "osj_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "osj_kind",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "osj_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "osj_trigger",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ObjectSyncJob"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/jobs/{job_id}": {
			"get": {
				"operationId": "getObjectSourceJob",
				"summary": "Get a run",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nOne run with its progress. `osj_stalled` marks a run whose worker went away; resume it.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "job_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSyncJob"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/jobs/{job_id}/cancel": {
			"post": {
				"operationId": "cancelObjectSourceJob",
				"summary": "Cancel a run",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nStops the run at its next checkpoint. Everything applied so far stays.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "job_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSyncJob"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:create",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/jobs/{job_id}/resume": {
			"post": {
				"operationId": "resumeObjectSourceJob",
				"summary": "Resume a run",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nPuts a stalled or failed run back in the queue from its last checkpoint.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "job_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSyncJob"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:create",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/jobs/{job_id}/retry-failed": {
			"post": {
				"operationId": "retryObjectSourceJobFailures",
				"summary": "Retry failed records",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nStarts a new run over exactly the records this one could not settle.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "job_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSyncJob"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:create",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/sync-now": {
			"post": {
				"operationId": "startObjectSourceDelta",
				"summary": "Pull changes now",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReads the event queue once, outside the schedule. Answers 202 with the run. Refused when the source has no event queue or another run is active.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectSyncJob"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:create",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/{id}/test-connection": {
			"post": {
				"operationId": "testObjectSourceConnection",
				"summary": "Test a source connection",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nSigns in to the source, reads the first root, asks the event queue for its status, and reports the address the source saw the call come from. Runs from the service whose address is allow-listed. Send `src_config` to test settings that are not saved yet.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"src_config": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"ok": {
											"type": "boolean"
										},
										"checks": {
											"type": "array",
											"items": {
												"type": "object",
												"properties": {
													"name": {
														"type": "string"
													},
													"ok": {
														"type": "boolean"
													},
													"detail": {
														"type": [
															"string",
															"null"
														]
													},
													"status": {
														"type": [
															"integer",
															"null"
														]
													}
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-sources/test-connection": {
			"post": {
				"operationId": "testObjectSourceDraft",
				"summary": "Test unsaved settings",
				"tags": [
					"Object sources"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe same checks as the per-source test, for a connection that has not been saved yet. `src_config` is required.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"src_config": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"ok": {
											"type": "boolean"
										},
										"checks": {
											"type": "array",
											"items": {
												"type": "object",
												"properties": {
													"name": {
														"type": "string"
													},
													"ok": {
														"type": "boolean"
													},
													"detail": {
														"type": [
															"string",
															"null"
														]
													},
													"status": {
														"type": [
															"integer",
															"null"
														]
													}
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:schema:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-taxonomies": {
			"get": {
				"operationId": "listObjectTaxonomyNodes",
				"summary": "List taxonomy nodes",
				"tags": [
					"Object taxonomies"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe nodes of a scheme, in display order — filter to one with `tax_type`. Ask for a whole tree with a `limit` that covers it: a page cut through a tree leaves children whose parent is missing. Pass `counts=true` for the number of objects filed under each node, and `root=true` for the top level only.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "counts",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "root",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "tax_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "tax_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "tax_key",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "tax_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "tax_parent",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "tax_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ObjectTaxonomy"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"post": {
				"operationId": "createObjectTaxonomyNode",
				"summary": "Create a taxonomy node",
				"tags": [
					"Object taxonomies"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nA node with no `tax_parent` starts a new tree. A node with one must share its parent's `tax_type` — a tree belongs to a single scheme.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"tax_type": {
										"type": "string",
										"minLength": 1,
										"maxLength": 64
									},
									"tax_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 300
									},
									"tax_key": {
										"type": "string",
										"maxLength": 200
									},
									"tax_parent": {
										"type": "string",
										"format": "uuid"
									},
									"tax_order": {
										"type": "integer"
									},
									"tax_metadata": {
										"type": "object"
									}
								},
								"required": [
									"tax_type",
									"tax_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectTaxonomy"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:taxonomy:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/object-taxonomies/{id}": {
			"delete": {
				"operationId": "deleteObjectTaxonomyNode",
				"summary": "Delete a taxonomy node",
				"tags": [
					"Object taxonomies"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRefused while the node still has children, unless `reparent_children=true` attaches them to its parent. Objects filed under it stop being classified there but are otherwise untouched.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "reparent_children",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:taxonomy:edit",
				"x-required-plan": "module-objects"
			},
			"get": {
				"operationId": "getObjectTaxonomyNode",
				"summary": "Get a taxonomy node",
				"tags": [
					"Object taxonomies"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns one node of a classification scheme.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectTaxonomy"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"patch": {
				"operationId": "updateObjectTaxonomyNode",
				"summary": "Update a taxonomy node",
				"tags": [
					"Object taxonomies"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nSetting `tax_parent` moves the node and everything under it. A move that would put a node inside its own subtree is refused. `tax_type` cannot be changed.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"tax_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 300
									},
									"tax_key": {
										"type": "string",
										"maxLength": 200
									},
									"tax_parent": {
										"type": "string",
										"format": "uuid"
									},
									"tax_order": {
										"type": "integer"
									},
									"tax_metadata": {
										"type": "object"
									},
									"tax_type": {
										"type": "string"
									}
								},
								"required": [
									"tax_type"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectTaxonomy"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:taxonomy:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/objects": {
			"get": {
				"operationId": "listObjects",
				"summary": "List objects",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nFilter by kind with `obj_type`, by business key with `obj_key`, by attribute with `obj_content`, and by classification with `taxonomy` — one node id, or several comma-separated to match only objects filed under every one of them. `q` searches names and business keys.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "obj_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "obj_content",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "obj_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "obj_form",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "obj_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "obj_key",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "obj_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "obj_state_item",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "obj_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "obj_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "q",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "taxonomy",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/BusinessObject"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"post": {
				"operationId": "createObject",
				"summary": "Create an object",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\n`obj_content` is checked against the form `obj_form` names, so an attribute the form does not declare is refused rather than stored. Leave `obj_form` out and the schema declaring this `obj_type` is used — you need not know its id. A kind with no schema behind it is accepted as sent.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"obj_type": {
										"type": "string",
										"minLength": 1,
										"maxLength": 64
									},
									"obj_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 500
									},
									"obj_key": {
										"type": "string",
										"maxLength": 200
									},
									"obj_form": {
										"type": "string",
										"format": "uuid"
									},
									"obj_content": {
										"type": "object"
									},
									"obj_state_item": {
										"type": "string",
										"format": "uuid"
									},
									"obj_repo": {
										"type": "object"
									},
									"obj_metadata": {
										"type": "object"
									},
									"obj_acl": {
										"type": "object"
									}
								},
								"required": [
									"obj_type",
									"obj_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/BusinessObject"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:create",
				"x-required-plan": "module-objects"
			}
		},
		"/objects/{id}": {
			"delete": {
				"operationId": "deleteObject",
				"summary": "Delete an object",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nDeactivates the object and drops every relation it took part in. Its business key becomes free for a new record to use.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:delete",
				"x-required-plan": "module-objects"
			},
			"get": {
				"operationId": "getObject",
				"summary": "Get an object",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the object with its attributes and every relation it takes part in, in both directions.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"allOf": [
										{
											"$ref": "#/components/schemas/BusinessObject"
										},
										{
											"type": "object",
											"properties": {
												"relations": {
													"type": "array",
													"items": {
														"$ref": "#/components/schemas/ObjectRelation"
													}
												}
											}
										}
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"patch": {
				"operationId": "updateObject",
				"summary": "Update an object",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nApplies the `obj_`-prefixed fields present in the body. `obj_content` replaces the stored attributes whole rather than merging into them.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"obj_type": {
										"type": "string",
										"minLength": 1,
										"maxLength": 64
									},
									"obj_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 500
									},
									"obj_key": {
										"type": "string",
										"maxLength": 200
									},
									"obj_form": {
										"type": "string",
										"format": "uuid"
									},
									"obj_content": {
										"type": "object"
									},
									"obj_state_item": {
										"type": "string",
										"format": "uuid"
									},
									"obj_repo": {
										"type": "object"
									},
									"obj_metadata": {
										"type": "object"
									},
									"obj_acl": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/BusinessObject"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/objects/{id}/relations": {
			"get": {
				"operationId": "listObjectRelations",
				"summary": "List relations",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe edges this object takes part in, oldest first. `direction` narrows to the ones leading out of it or into it; by default you get both.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "direction",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"from",
								"to",
								"both"
							],
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "rel_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ObjectRelation"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:view",
				"x-required-plan": "module-objects"
			},
			"post": {
				"operationId": "createObjectRelation",
				"summary": "Create a relation",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nLinks this object to something else — another object, a file, or a taxonomy node with `classified-as`. `rel_type` is your own vocabulary, not a fixed list. Asserting an edge that already exists updates its metadata instead of failing.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"rel_type": {
										"type": "string",
										"minLength": 1,
										"maxLength": 64
									},
									"rel_to": {
										"type": "string",
										"format": "uuid"
									},
									"rel_to_type": {
										"type": "string",
										"minLength": 1,
										"maxLength": 32
									},
									"rel_metadata": {
										"type": "object"
									}
								},
								"required": [
									"rel_type",
									"rel_to",
									"rel_to_type"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ObjectRelation"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/objects/{id}/relations/{relation_id}": {
			"delete": {
				"operationId": "deleteObjectRelation",
				"summary": "Delete a relation",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRemoves the link. Neither end is otherwise affected.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "relation_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/objects/actions/transition": {
			"post": {
				"operationId": "transitionObjects",
				"summary": "Change object states",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nMoves objects to another state in the flow that governs them. A move the flow does not allow is refused rather than forced.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"obj_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"target_state_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"obj_ids",
									"target_state_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:edit",
				"x-required-plan": "module-objects"
			}
		},
		"/objects/actions/upsert": {
			"post": {
				"operationId": "upsertObject",
				"summary": "Upsert by key",
				"tags": [
					"Objects"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nCreates or updates the object with this `obj_type` and `obj_key`, so an upstream system can send the same record repeatedly without producing duplicates. `obj_content` is validated against the schema declaring this `obj_type`, so a caller needs only its own vocabulary and never an id of ours. Answers 201 when it created one and 200 when it updated one.\n\nRequires the `module-objects` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"obj_type": {
										"type": "string",
										"minLength": 1,
										"maxLength": 64
									},
									"obj_key": {
										"type": "string",
										"minLength": 1,
										"maxLength": 200
									},
									"obj_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 500
									},
									"obj_form": {
										"type": "string",
										"format": "uuid"
									},
									"obj_content": {
										"type": "object"
									},
									"obj_state_item": {
										"type": "string",
										"format": "uuid"
									},
									"obj_repo": {
										"type": "object"
									},
									"obj_metadata": {
										"type": "object"
									}
								},
								"required": [
									"obj_type",
									"obj_key"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/BusinessObject"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "object:create",
				"x-required-plan": "module-objects"
			}
		},
		"/people": {
			"get": {
				"operationId": "listPeople",
				"summary": "List people",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the people in the workspace, most-photographed first, each with the number of faces assigned to it and the number of suggestions waiting for review.\n\n`unnamed=true` returns only the clusters nobody has named yet, and `needs_review=true` only those with suggestions pending — the two queues the review UI is built around.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "fp_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "needs_review",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "unnamed",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Person"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:view"
			}
		},
		"/people/{id}": {
			"delete": {
				"operationId": "deletePerson",
				"summary": "Delete a person",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReleases every face assigned to this person and then deactivates it. The faces and the photos survive — they go back to being unassigned detections, available to be grouped again.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			},
			"put": {
				"operationId": "updatePerson",
				"summary": "Rename a person",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"fp_name": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/{id}/photos": {
			"get": {
				"operationId": "listPersonPhotos",
				"summary": "List photos",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nOnly files the caller may read are returned — the file's own access rules still apply, so two people looking at the same person can see different photos.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/PersonPhoto"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:view"
			}
		},
		"/people/{id}/reindex": {
			"post": {
				"operationId": "reindexPerson",
				"summary": "Rebuild the face index",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRecomputes the references this person is matched against, after their assignments have changed enough to be worth it. Runs in the background: a request made while one is already running answers 202 rather than starting a second.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/{id}/set-cover": {
			"post": {
				"operationId": "setPersonCover",
				"summary": "Set the cover face",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe detection must already belong to this person.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"fd_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"fd_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/{id}/suggestions/verify": {
			"post": {
				"operationId": "verifyFaceSuggestions",
				"summary": "Verify suggestions",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRuns one vision comparison of the person's reference faces against each unverified candidate and records a `match`, `no_match` or `unsure` verdict — it catches what the face embeddings cannot.\n\nIt decides nothing on its own: verdicts come back through the suggestion list, and a `no_match` withholds that suggestion. Idempotent, and already-verified candidates are skipped, so calling it twice costs nothing.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/assign": {
			"post": {
				"operationId": "assignFace",
				"summary": "Assign a face",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nAssigns one detected face. Omit `fp_id` and a new person is created for it — optionally named with `fp_name` — which is how a face is named for the first time.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"fd_id": {
										"type": "string",
										"format": "uuid"
									},
									"fp_id": {
										"type": "string",
										"format": "uuid"
									},
									"fp_name": {
										"type": "string"
									}
								},
								"required": [
									"fd_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/merge": {
			"post": {
				"operationId": "mergePeople",
				"summary": "Merge two people",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nMoves every face from `source_id` onto `target_id` and retires the source. This is the fix for one person having been split across two clusters.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"source_id": {
										"type": "string",
										"format": "uuid"
									},
									"target_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"source_id",
									"target_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/suggestions": {
			"get": {
				"operationId": "listFaceSuggestions",
				"summary": "List suggestions",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nFaces the matcher believes belong to someone already named, closest match first, waiting for a yes or no. Filter to one person with `fp_id`.\n\nSuggestions that plainly contradict the person are withheld rather than shown and rejected: a gender estimate against confidently-gendered references, an age far from the person's median, or a `no_match` verdict from the vision check. Anything already verified carries its verdict here.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "fp_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/FaceSuggestion"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:view"
			}
		},
		"/people/suggestions/{id}/confirm": {
			"post": {
				"operationId": "confirmFaceSuggestion",
				"summary": "Confirm a suggestion",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/suggestions/{id}/reject": {
			"post": {
				"operationId": "rejectFaceSuggestion",
				"summary": "Reject a suggestion",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/suggestions/actions/resolve": {
			"post": {
				"operationId": "resolveFaceSuggestions",
				"summary": "Resolve suggestions",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nApplies one `action` — `confirm` or `reject` — to every id in `fd_ids`. A suggestion someone else already resolved is skipped rather than failing the batch, so the counts in the response are the truth about what this call did.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"action": {
										"enum": [
											"confirm",
											"reject"
										],
										"type": "string"
									},
									"fd_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"action",
									"fd_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"confirmed": {
											"type": "integer"
										},
										"rejected": {
											"type": "integer"
										},
										"skipped": {
											"type": "integer",
											"description": "Already assigned or already resolved elsewhere."
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/people/unassign": {
			"post": {
				"operationId": "unassignFace",
				"summary": "Unassign a face",
				"tags": [
					"People"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nDetaches a face from its person and leaves it as an unassigned detection.",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"fd_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"fd_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:face:edit"
			}
		},
		"/presentation-templates": {
			"get": {
				"operationId": "listPresentationTemplates",
				"summary": "List templates",
				"tags": [
					"Presentation templates"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "ppt_tpl_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "ppt_tpl_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ppt_tpl_created_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "ppt_tpl_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "ppt_tpl_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/PresentationTemplate"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:view",
				"x-required-plan": "module-ppt"
			},
			"post": {
				"operationId": "createPresentationTemplate",
				"summary": "Upload a template",
				"tags": [
					"Presentation templates"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nTakes a `.pptx` upload. Its slide layouts and placeholders are read out of the file and become the shapes generated content is fitted into.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"ppt_tpl_name": {
										"type": "string",
										"minLength": 1
									},
									"ppt_tpl_description": {
										"type": "string"
									},
									"ppt_tpl_config": {
										"type": "string"
									}
								},
								"required": [
									"ppt_tpl_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/PresentationTemplate"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:template:edit",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentation-templates/{id}": {
			"get": {
				"operationId": "getPresentationTemplate",
				"summary": "Get a template",
				"tags": [
					"Presentation templates"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/PresentationTemplate"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:view",
				"x-required-plan": "module-ppt"
			},
			"put": {
				"operationId": "updatePresentationTemplate",
				"summary": "Update a template",
				"tags": [
					"Presentation templates"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"ppt_tpl_name": {
										"type": "string"
									},
									"ppt_tpl_description": {
										"type": "string"
									},
									"ppt_tpl_config": {
										"type": "string"
									},
									"ppt_tpl_active": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/PresentationTemplate"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:template:edit",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentation-templates/{id}/file": {
			"post": {
				"operationId": "replacePresentationTemplateFile",
				"summary": "Replace the .pptx",
				"tags": [
					"Presentation templates"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nSwaps the underlying file and re-derives the layout catalog from it, because the placeholders in the old file may not exist in the new one.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:template:edit",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentation-templates/parse": {
			"post": {
				"operationId": "parsePresentationTemplate",
				"summary": "Inspect a .pptx",
				"tags": [
					"Presentation templates"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReads an uploaded file and returns the layouts found in it plus a suggested configuration, without storing anything. This is what lets an upload be reviewed before it becomes a template.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:template:edit",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations": {
			"get": {
				"operationId": "listPresentations",
				"summary": "List presentations",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "ppt_job_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "ppt_job_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "ppt_job_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Presentation"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:view",
				"x-required-plan": "module-ppt"
			},
			"post": {
				"operationId": "createPresentation",
				"summary": "Generate a presentation",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nQueues generation from a brief, a template and an outline, and returns the job. Generation runs in the background — poll the presentation to follow it.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"jobId": {
										"type": "string",
										"format": "uuid"
									},
									"templateId": {
										"type": "string",
										"format": "uuid"
									},
									"brief": {
										"type": "object"
									},
									"plan": {
										"type": "object",
										"properties": {
											"slides": {
												"type": "array",
												"items": {}
											}
										},
										"required": [
											"slides"
										]
									},
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"threadId": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"templateId",
									"brief",
									"plan"
								]
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:create",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations/{id}": {
			"delete": {
				"operationId": "deletePresentation",
				"summary": "Delete a presentation",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nLimited to presentations the caller owns. The generated deck is removed with it.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:delete",
				"x-required-plan": "module-ppt"
			},
			"get": {
				"operationId": "getPresentation",
				"summary": "Get a presentation",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nIncludes its current status and, once generation has finished, the deck to download.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Presentation"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:view",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations/{id}/duplicate": {
			"post": {
				"operationId": "duplicatePresentation",
				"summary": "Duplicate a presentation",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nClones the brief, outline and content into a new presentation and copies the generated deck. The copy is independent — deleting either one never removes the other's file.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:create",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations/{id}/images/regenerate": {
			"post": {
				"operationId": "regeneratePresentationImage",
				"summary": "Regenerate an image",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nFinds the best photo in the library for that slide and generates a fresh image seeded by it. Recorded as an override on the same terms as choosing one by hand.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"slideIndex": {
										"type": "integer",
										"minimum": 0
									},
									"slotName": {
										"type": "string",
										"minLength": 1
									}
								},
								"required": [
									"slideIndex",
									"slotName"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:edit",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations/{id}/images/select": {
			"post": {
				"operationId": "selectPresentationImage",
				"summary": "Choose a slide image",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRecords the choice as an override. A deck still generating picks it up as it assembles; a finished one needs a rebuild before the file reflects it.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"slideIndex": {
										"type": "integer",
										"minimum": 0
									},
									"slotName": {
										"type": "string",
										"minLength": 1
									},
									"fileId": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"slideIndex",
									"slotName",
									"fileId"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:edit",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations/{id}/rebuild": {
			"post": {
				"operationId": "rebuildPresentation",
				"summary": "Rebuild the deck",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRegenerates the file from the presentation's current content, including any image overrides.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:edit",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations/{id}/rename": {
			"patch": {
				"operationId": "renamePresentation",
				"summary": "Rename a presentation",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nChanges only the display name, which is also the download filename. The plan is untouched, so renaming never changes what a rebuild produces.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"title": {
										"type": "string",
										"minLength": 1,
										"maxLength": 200
									}
								},
								"required": [
									"title"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:edit",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations/draft": {
			"post": {
				"operationId": "savePresentationDraft",
				"summary": "Save a draft",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nStores the brief, template and outline as a draft without queueing generation, so the work survives leaving the page and can be picked up again.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"jobId": {
										"type": "string",
										"format": "uuid"
									},
									"templateId": {
										"type": "string",
										"format": "uuid"
									},
									"brief": {
										"type": "object"
									},
									"plan": {
										"type": "object"
									},
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"threadId": {
										"type": "string",
										"format": "uuid"
									},
									"step": {
										"type": "string"
									}
								},
								"required": [
									"templateId",
									"brief"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:create",
				"x-required-plan": "module-ppt"
			}
		},
		"/presentations/plan": {
			"post": {
				"operationId": "planPresentation",
				"summary": "Plan an outline",
				"tags": [
					"Presentations"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nTurns a brief and a template into a proposed outline, and saves it onto the draft so it is not lost. Nothing is generated yet — this is the step where the structure is reviewed and edited.\n\nRequires the `module-ppt` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"jobId": {
										"type": "string",
										"format": "uuid"
									},
									"templateId": {
										"type": "string",
										"format": "uuid"
									},
									"brief": {
										"type": "object",
										"properties": {
											"topic": {
												"type": "string",
												"minLength": 1
											},
											"audience": {
												"type": "string"
											},
											"slideCount": {
												"type": "integer",
												"minimum": 3,
												"maximum": 20
											},
											"audienceProfileIds": {
												"type": "array",
												"items": {
													"type": "string",
													"format": "uuid"
												}
											},
											"toneId": {
												"type": "string",
												"format": "uuid"
											},
											"referenceUrls": {
												"type": "array",
												"items": {}
											},
											"instructions": {
												"type": "string"
											}
										},
										"required": [
											"topic"
										]
									},
									"agentId": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"templateId",
									"brief"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "presentation:create",
				"x-required-plan": "module-ppt"
			}
		},
		"/prompt-categories": {
			"get": {
				"operationId": "listPromptCategories",
				"summary": "List categories",
				"tags": [
					"Prompt categories"
				],
				"description": "The workspace's own prompt categories plus the product-level ones shared with it, in the order they are managed in, each with a count of the prompts filed under it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"categories": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/PromptCategory"
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"put": {
				"operationId": "replacePromptCategories",
				"summary": "Replace categories",
				"tags": [
					"Prompt categories"
				],
				"description": "Send the complete ordered list you want — this is a replacement, not a patch. An entry with an id is renamed in place and takes its position from the array; one without is created; anything you leave out is removed, including from the prompts filed under it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"categories": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"cat_name": {
													"type": "string",
													"minLength": 1,
													"maxLength": 60
												},
												"cat_id": {
													"type": "string",
													"format": "uuid"
												},
												"cat_icon": {
													"type": "string"
												}
											},
											"required": [
												"cat_name"
											]
										}
									}
								},
								"required": [
									"categories"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"categories": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/PromptCategory"
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "prompt:category:edit"
			}
		},
		"/prompts": {
			"get": {
				"operationId": "listPrompts",
				"summary": "List prompts",
				"tags": [
					"Prompts"
				],
				"description": "Returns the prompts available to the workspace, including ones published by the platform. A prompt the workspace does not own is listed without its text or configuration.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "prompt_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "prompt_agent",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "prompt_author",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "prompt_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "prompt_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "prompt_description_short",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "prompt_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "prompt_managed_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "prompt_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "prompt_tenant_categories",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "prompt_text",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "prompt_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Prompt"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"post": {
				"operationId": "createPrompt",
				"summary": "Create a prompt",
				"tags": [
					"Prompts"
				],
				"description": "Creates a reusable prompt. The inputs it asks for are wildcards, which are declared separately and referenced by name.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"prompt_name": {
										"type": "string",
										"minLength": 1
									},
									"prompt_agent": {
										"type": "string",
										"format": "uuid"
									},
									"prompt_text": {
										"type": "string"
									},
									"prompt_description": {
										"type": "string"
									},
									"prompt_description_short": {
										"type": "string"
									},
									"prompt_config": {
										"type": "object",
										"properties": {
											"canvas_output": {
												"type": "boolean"
											}
										}
									},
									"prompt_tenant_time_savings": {
										"type": "string",
										"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
									},
									"prompt_tenant_enabled": {
										"type": "boolean"
									}
								},
								"required": [
									"prompt_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Prompt"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "prompt:create"
			}
		},
		"/prompts/{id}": {
			"delete": {
				"operationId": "deletePrompt",
				"summary": "Delete a prompt",
				"tags": [
					"Prompts"
				],
				"description": "Deactivates the prompt. Threads that already used it keep the messages it produced.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "prompt:delete"
			},
			"get": {
				"operationId": "getPrompt",
				"summary": "Get a prompt",
				"tags": [
					"Prompts"
				],
				"description": "Returns the prompt with the wildcards it asks for. A prompt published by the platform is returned without its text.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Prompt"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "prompt:view"
			},
			"patch": {
				"operationId": "updatePrompt",
				"summary": "Update a prompt",
				"tags": [
					"Prompts"
				],
				"description": "Applies the `prompt_`-prefixed fields present in the body. A prompt the workspace does not own cannot be edited, only used.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"prompt_name": {
										"type": "string"
									},
									"prompt_text": {
										"type": "string"
									},
									"prompt_agent": {
										"type": "string",
										"format": "uuid"
									},
									"prompt_description": {
										"type": "string"
									},
									"prompt_description_short": {
										"type": "string"
									},
									"prompt_config": {
										"type": "object",
										"properties": {
											"canvas_output": {
												"type": "boolean"
											}
										}
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Prompt"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "prompt:edit"
			}
		},
		"/prompts/{id}/categories": {
			"put": {
				"operationId": "setPromptCategories",
				"summary": "Set categories",
				"tags": [
					"Prompts"
				],
				"description": "Replaces how the calling workspace files the prompt — per workspace, so filing a product prompt affects nobody else. Categories are the workspace's own taxonomy, defined under `/prompt-categories`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"categories": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								},
								"required": [
									"categories"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "prompt:edit"
			}
		},
		"/prompts/{id}/form": {
			"get": {
				"operationId": "getPromptForm",
				"summary": "Get the input form",
				"tags": [
					"Prompts"
				],
				"description": "The fields a prompt asks for before it runs, resolved from the wildcards it references — this is what a caller needs in order to supply its inputs.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			}
		},
		"/prompts/{id}/history": {
			"get": {
				"operationId": "listPromptHistory",
				"summary": "List prompt history",
				"tags": [
					"Prompts"
				],
				"description": "Every recorded change, newest first, each as a per-field `{from, to}` changeset.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"type": "object",
										"properties": {
											"history_id": {
												"type": "string",
												"format": "uuid"
											},
											"history_timestamp": {
												"type": "string",
												"format": "date-time"
											},
											"history_user": {
												"type": [
													"string",
													"null"
												],
												"format": "uuid"
											},
											"history_op": {
												"type": "string",
												"description": "The kind of change — insert, update or delete."
											},
											"history_changeset": {
												"type": "object",
												"description": "One entry per field that changed, keyed by column name.",
												"additionalProperties": {
													"type": "object",
													"properties": {
														"from": {},
														"to": {}
													}
												}
											},
											"history_ref": {
												"type": "object",
												"description": "What the writer noted about the change rather than the columns: the action that made it, or the reason it was made."
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "prompt:view"
			}
		},
		"/prompts/{id}/history/{history_id}/revert": {
			"post": {
				"operationId": "revertPrompt",
				"summary": "Revert to a version",
				"tags": [
					"Prompts"
				],
				"description": "Puts the prompt back to the state a history entry recorded, and audits the restore itself so it can be undone in turn. Only the fields the history view shows are written.\n\nRestoring the prompt text re-derives the input form from it, so the fields the prompt asks for match the text that is now stored.\n\nA restore can write less than the version held, and `skipped` says what it left alone and why — a field whose stored value was last written outside the app has no audited value to restore over.\n\nFor a platform-published prompt this restores only the calling workspace's own overrides, the same fields its history returns.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "history_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"restored": {
											"type": "array",
											"description": "Columns written back, by name.",
											"items": {
												"type": "string"
											}
										},
										"skipped": {
											"type": "array",
											"description": "Columns the version carried that were deliberately not written.",
											"items": {
												"type": "object",
												"properties": {
													"field": {
														"type": "string"
													},
													"reason": {
														"type": "string",
														"enum": [
															"unrecorded",
															"not_permitted"
														],
														"description": "unrecorded — the stored value was written outside the app, so there is no audited value to restore over it; not_permitted — restoring it needs a permission or plan the caller no longer has."
													},
													"detail": {
														"type": "string"
													}
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "prompt:edit"
			}
		},
		"/prompts/recent": {
			"get": {
				"operationId": "listRecentPrompts",
				"summary": "List recent prompts",
				"tags": [
					"Prompts"
				],
				"description": "Returns the prompts the calling user has run most recently, newest first. `last_used` is when they last ran it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Prompt"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			}
		},
		"/prompts/stats": {
			"get": {
				"operationId": "getPromptStats",
				"summary": "Get prompt statistics",
				"tags": [
					"Prompts"
				],
				"description": "How many prompts exist and how heavily they are used, for a dashboard rather than a listing.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			}
		},
		"/publications": {
			"get": {
				"operationId": "listPublications",
				"summary": "List publications",
				"tags": [
					"Publications"
				],
				"description": "Everything the workspace has released, across every asset. This is the view that answers \"what is public right now\" as one sortable list.\n\nRequires the `module-publication` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "pub_file",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "pub_state",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"draft",
								"scheduled",
								"published",
								"revoked"
							],
							"type": "string"
						}
					},
					{
						"name": "search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Publication"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:publish",
				"x-required-plan": "module-publication"
			}
		},
		"/scheduled-jobs": {
			"get": {
				"operationId": "listScheduledJobs",
				"summary": "List scheduled jobs",
				"tags": [
					"Scheduled jobs"
				],
				"description": "Platform jobs with this workspace's overrides applied, plus its own jobs.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "job_scope",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "job_title",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "job_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ScheduledJob"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "scheduled-job:view"
			}
		},
		"/scheduled-jobs/{id}": {
			"get": {
				"operationId": "getScheduledJob",
				"summary": "Get a scheduled job",
				"tags": [
					"Scheduled jobs"
				],
				"description": "Returns one job with its schedule and what the workspace has changed about it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ScheduledJob"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "scheduled-job:view"
			}
		},
		"/scheduled-jobs/{id}/override": {
			"delete": {
				"operationId": "deleteScheduledJobOverride",
				"summary": "Delete a job override",
				"tags": [
					"Scheduled jobs"
				],
				"description": "The job goes back to the platform schedule.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "scheduled-job:edit"
			},
			"put": {
				"operationId": "setScheduledJobOverride",
				"summary": "Set a job override",
				"tags": [
					"Scheduled jobs"
				],
				"description": "Changes the schedule for this workspace only. The platform job is untouched.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"job_tenant_enabled": {
										"type": "boolean"
									},
									"job_tenant_cron": {
										"type": "string"
									},
									"job_tenant_timezone": {
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "scheduled-job:edit"
			}
		},
		"/scheduled-jobs/{id}/run": {
			"post": {
				"operationId": "runScheduledJob",
				"summary": "Run a job now",
				"tags": [
					"Scheduled jobs"
				],
				"description": "Runs it for this workspace only, without affecting the schedule or anyone else.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "scheduled-job:execute"
			}
		},
		"/scheduled-jobs/{id}/runs": {
			"get": {
				"operationId": "listScheduledJobRuns",
				"summary": "List job runs",
				"tags": [
					"Scheduled jobs"
				],
				"description": "Returns what every run of this job did, newest first.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "scheduled-job:view"
			}
		},
		"/share-links": {
			"get": {
				"operationId": "listMyShareLinks",
				"summary": "List share links",
				"tags": [
					"Share links"
				],
				"description": "Returns the share links the caller created. Every link in the workspace is listed under `/admin/share-links`, which needs an administrator.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/ShareLink"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "share-link:view"
			},
			"post": {
				"operationId": "createShareLink",
				"summary": "Create a share link",
				"tags": [
					"Share links"
				],
				"description": "Two kinds, chosen with `share_type`. A **download** link — the default — publishes the files in `file_ids` for someone outside the workspace to fetch. An **upload** link runs the other way: it lets someone outside send files in without an account.\n\nBoth can carry an expiry and a password.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"share_type": {
										"enum": [
											"download",
											"upload"
										],
										"type": "string"
									},
									"file_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"name": {
										"type": "string",
										"maxLength": 255
									},
									"expires_at": {
										"type": "string",
										"format": "date-time"
									},
									"password": {
										"type": "string",
										"minLength": 1
									},
									"album_id": {
										"type": "string",
										"format": "uuid"
									},
									"album_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"pre_tags": {
										"type": "object"
									},
									"max_files": {
										"type": "integer",
										"minimum": 1,
										"maximum": 10000
									},
									"max_size": {
										"type": "integer",
										"minimum": 1
									},
									"allow_change_tags": {
										"type": "boolean"
									},
									"allow_change_albums": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ShareLink"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "share-link:create"
			}
		},
		"/share-links/{id}": {
			"delete": {
				"operationId": "deleteShareLink",
				"summary": "Delete a share link",
				"tags": [
					"Share links"
				],
				"description": "The link stops working immediately. The files it pointed at are untouched.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "share-link:delete"
			},
			"get": {
				"operationId": "getShareLink",
				"summary": "Get a share link",
				"tags": [
					"Share links"
				],
				"description": "Pass `include=uploaded_files` on an upload link to get what has been sent through it so far.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "include",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ShareLink"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "share-link:view"
			},
			"patch": {
				"operationId": "updateShareLink",
				"summary": "Update a share link",
				"tags": [
					"Share links"
				],
				"description": "Deactivating with `share_active: false` is how a link is switched off without losing the record of what was shared.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"share_name": {
										"type": "string",
										"maxLength": 255
									},
									"share_active": {
										"type": "boolean"
									},
									"share_expires_at": {
										"type": "string",
										"format": "date-time"
									},
									"share_password": {
										"type": "string"
									},
									"share_max_files": {
										"type": "integer",
										"minimum": 1,
										"maximum": 10000
									},
									"share_max_size": {
										"type": "integer",
										"minimum": 1
									},
									"share_allow_change_tags": {
										"type": "boolean"
									},
									"share_allow_change_albums": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/ShareLink"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "share-link:edit"
			}
		},
		"/sites": {
			"get": {
				"operationId": "listSites",
				"summary": "List sites",
				"tags": [
					"Website content"
				],
				"description": "Returns the workspace's sites, each with page, folder and per-status counts, newest first. `sitemap_last_edited` is the later of the site's own `sitemap_updated` and the last change to any of its pages; `sort=-sitemap_last_edited` puts the site most recently worked on first. A \"site\" is a sitemap: the page tree plus the instructions that content is generated from.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "sitemap_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Site"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"post": {
				"operationId": "createSite",
				"summary": "Create a site",
				"tags": [
					"Website content"
				],
				"description": "Creates an empty site. Pages are added afterwards — by hand, by importing an existing sitemap, or by having a structure proposed from a description of the business.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"sitemap_name": {
										"type": "string",
										"minLength": 1
									},
									"sitemap_domain": {
										"type": "string"
									},
									"sitemap_description": {
										"type": "string"
									},
									"sitemap_config": {
										"type": "object"
									},
									"sitemap_tpl_group": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"sitemap_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Site"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/sites/{id}": {
			"delete": {
				"operationId": "deleteSite",
				"summary": "Delete a site",
				"tags": [
					"Website content"
				],
				"description": "Soft delete. The site and its pages stop being listed; nothing is removed from a connected CMS.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:delete"
			},
			"get": {
				"operationId": "getSite",
				"summary": "Get a site",
				"tags": [
					"Website content"
				],
				"description": "Returns the site and every page under it in one response. Pages carry `node_parent` and `node_order`, so the tree is rebuilt from a flat list rather than requested level by level. The pages come without `node_content`: a body is the largest thing a page carries and a site has no bounded number of pages, so a tree that carried every body would grow past what one response can hold. Read the body of one page from `GET /sites/{id}/pages/{page_id}`, or pass `include=content` to fetch the site with every body inline — for an export, where the whole thing is the point.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "include",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Site"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"patch": {
				"operationId": "updateSite",
				"summary": "Update a site",
				"tags": [
					"Website content"
				],
				"description": "Applies the `sitemap_`-prefixed fields present in the body. This is the site itself; its pages are edited through the page endpoints.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"sitemap_name": {
										"type": "string"
									},
									"sitemap_domain": {
										"type": "string"
									},
									"sitemap_description": {
										"type": "string"
									},
									"sitemap_config": {
										"type": "object"
									},
									"sitemap_tpl_group": {
										"type": "string",
										"format": "uuid"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Site"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/approval-flow": {
			"put": {
				"operationId": "setSiteApprovalFlow",
				"summary": "Set the review flow",
				"tags": [
					"Website content"
				],
				"description": "Chooses how the site's pages are reviewed: `default` follows the workspace's default approval flow, `flow` names one in `flow_id`, and `none` turns review off for this site. Requires `content:workflow:edit` rather than `content:edit`, because deciding what review a site gets is the same decision as defining the flows. Pages already approved or published land on the new flow's final step; pages mid-review re-enter at its start. The answer names the flow now governing the site in `governing_flow` — with `default` that is whichever flow holds the role, and with `none` it is null.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"mode": {
										"enum": [
											"default",
											"flow",
											"none"
										],
										"type": "string"
									},
									"flow_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"mode"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:workflow:edit"
			}
		},
		"/sites/{id}/approve-all": {
			"post": {
				"operationId": "approveAllPages",
				"summary": "Approve all pages",
				"tags": [
					"Website content"
				],
				"description": "Marks every generated page on the site as approved in one step, for a site reviewed in bulk rather than page by page.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/cms": {
			"delete": {
				"operationId": "disconnectCms",
				"summary": "Disconnect the CMS",
				"tags": [
					"CMS sync"
				],
				"description": "Forgets the connection and the per-page links to it. Content is kept on both sides — this stops syncing, it does not delete anything.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			},
			"get": {
				"operationId": "getCmsConnection",
				"summary": "Get the CMS connection",
				"tags": [
					"CMS sync"
				],
				"description": "Returns `{connected: false}` when the site has no connection, so this is safe to call before one is set up.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/cms/automation": {
			"get": {
				"operationId": "getCmsAutomation",
				"summary": "Get sync automation",
				"tags": [
					"CMS sync"
				],
				"description": "What this site does about its CMS unattended: whether the nightly comparison covers it, what it may pull without being asked, and the URL the CMS calls when its content changes.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"put": {
				"operationId": "updateCmsAutomation",
				"summary": "Set sync automation",
				"tags": [
					"CMS sync"
				],
				"description": "Sets the standing rules. `autoPull` is `off`, `unedited` (pages the CMS changed that nobody has touched here since we last sent them) or `all`; a page that changed on both sides is never pulled automatically under any of them. Nothing here ever pushes — copy reaching a live website stays a person's decision.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"scan": {
										"type": "boolean"
									},
									"autoPull": {
										"enum": [
											"off",
											"unedited",
											"all"
										],
										"type": "string"
									},
									"notify": {
										"enum": [
											"off",
											"changes"
										],
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/cms/connect": {
			"post": {
				"operationId": "connectCms",
				"summary": "Connect a CMS",
				"tags": [
					"CMS sync"
				],
				"description": "Stores the credentials for a CMS and verifies them against it. Nothing is synced yet — pull or push afterward.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"provider": {
										"enum": [
											"storyblok",
											"aem"
										],
										"type": "string"
									},
									"settings": {
										"type": "object"
									},
									"dryRun": {
										"type": "boolean"
									}
								},
								"required": [
									"provider",
									"settings"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/cms/plan": {
			"get": {
				"operationId": "planCmsSync",
				"summary": "Preview a sync",
				"tags": [
					"CMS sync"
				],
				"description": "Compares both sides and returns the plan — what would be created, updated, and what conflicts. Read-only: nothing moves until you pull or push.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "direction",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"pull",
								"push",
								"both"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/cms/pull": {
			"post": {
				"operationId": "pullFromCms",
				"summary": "Pull content",
				"tags": [
					"CMS sync"
				],
				"description": "Brings the CMS's content into the site. Preview it first with `GET /sites/{id}/cms/plan`, which reports what a pull would change without changing it.\n\nA pull touching more than a handful of pages answers **202** with a `job` instead of the result: hundreds of rate-limited calls to a CMS take minutes, which is longer than any request should be held open. Follow the run at `GET /sites/{id}/cms/sync-jobs/{job_id}`. Send `background: true` to be given a job whatever the size.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"resolution": {
										"enum": [
											"manual",
											"local",
											"remote"
										],
										"type": "string"
									},
									"nodeIds": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"externalIds": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"statuses": {
										"type": "array",
										"items": {}
									},
									"publish": {
										"type": "boolean"
									},
									"force": {
										"type": "boolean"
									},
									"background": {
										"type": "boolean"
									},
									"dryRun": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/sites/{id}/cms/push": {
			"post": {
				"operationId": "pushToCms",
				"summary": "Push content",
				"tags": [
					"CMS sync"
				],
				"description": "Sends the site's content to the CMS. Local edits win over anything changed in the CMS since the last sync; the plan endpoint reports those conflicts before you commit to them.\n\nAnswers **202** with a `job` once the push is larger than a handful of pages — see `pullFromCms`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"resolution": {
										"enum": [
											"manual",
											"local",
											"remote"
										],
										"type": "string"
									},
									"nodeIds": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"externalIds": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"statuses": {
										"type": "array",
										"items": {}
									},
									"publish": {
										"type": "boolean"
									},
									"force": {
										"type": "boolean"
									},
									"background": {
										"type": "boolean"
									},
									"dryRun": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/cms/scan": {
			"post": {
				"operationId": "scanCmsSync",
				"summary": "Scan for changes",
				"tags": [
					"CMS sync"
				],
				"description": "Same comparison as the plan, and it remembers the verdict on the site so the page tree can show where the two sides disagree without comparing again. Use the plan endpoint for a read that leaves nothing behind.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "direction",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"pull",
								"push",
								"both"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/cms/schemas/pull": {
			"post": {
				"operationId": "pullCmsSchemas",
				"summary": "Pull content schemas",
				"tags": [
					"CMS sync"
				],
				"description": "Mirrors the CMS's component definitions into a content-schema library, so generated content is shaped the way the CMS expects it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/sites/{id}/cms/schemas/push": {
			"post": {
				"operationId": "pushCmsSchemas",
				"summary": "Push content schemas",
				"tags": [
					"CMS sync"
				],
				"description": "Sends the workspace's content schemas to the CMS as component definitions, so pages pushed afterward have somewhere to land.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"templateIds": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/cms/sync-jobs": {
			"get": {
				"operationId": "listCmsSyncJobs",
				"summary": "List sync runs",
				"tags": [
					"CMS sync"
				],
				"description": "Every recent pull and push for this site, newest first: who ran it, what it moved, how long it took and which pages it could not settle.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 100
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/cms/sync-jobs/{job_id}": {
			"get": {
				"operationId": "getCmsSyncJob",
				"summary": "Get a sync run",
				"tags": [
					"CMS sync"
				],
				"description": "Progress and outcome of one run. `done` and `failed` advance against `total` while it works; `stalled` reports a run whose worker was lost, which can be resumed without losing what it applied.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "job_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/cms/sync-jobs/{job_id}/cancel": {
			"post": {
				"operationId": "cancelCmsSyncJob",
				"summary": "Cancel a sync run",
				"tags": [
					"CMS sync"
				],
				"description": "Stops the run at its next checkpoint. Pages already synced stay synced — this is a stop, not a rollback.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "job_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/cms/sync-jobs/{job_id}/resume": {
			"post": {
				"operationId": "resumeCmsSyncJob",
				"summary": "Resume a sync run",
				"tags": [
					"CMS sync"
				],
				"description": "Continues a run that stalled or failed, from its last checkpoint. Pages it already settled are not touched again.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "job_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/cms/sync-jobs/{job_id}/retry-failed": {
			"post": {
				"operationId": "retryCmsSyncJobFailures",
				"summary": "Retry failed pages",
				"tags": [
					"CMS sync"
				],
				"description": "Starts a new run over exactly the pages the named run could not settle. The original run keeps its record.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "job_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/cms/webhook": {
			"delete": {
				"operationId": "deleteCmsWebhook",
				"summary": "Delete a change webhook",
				"tags": [
					"CMS sync"
				],
				"description": "Withdraws the URL. Deliveries to it stop being accepted immediately; the site falls back to the scheduled comparison.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			},
			"post": {
				"operationId": "createCmsWebhook",
				"summary": "Create a change webhook",
				"tags": [
					"CMS sync"
				],
				"description": "Issues the URL to register in the CMS, so a change there is noticed in seconds rather than at the next scheduled comparison. Called again it replaces the URL, which is how one is rotated. Send `secret` to have deliveries checked against the provider's signature. Refused where the connected CMS cannot call a URL.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"secret": {
										"type": "string",
										"maxLength": 200
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/comments": {
			"get": {
				"operationId": "listSiteComments",
				"summary": "List site comments",
				"tags": [
					"Website content"
				],
				"description": "Every comment thread on the site, one row each, newest activity first — the review status of a whole site without fetching a page at a time. Threads only: replies are counted in `cmt_reply_count` and their authors listed in `cmt_participants`, and the full conversation is read from the page it is on. Each row names its page in `cmt_page` and its anchor in `cmt_anchor_label`, resolved against the page as it stands; `cmt_anchor_unattached` marks a thread whose field has since been moved or removed. Filter with `status=open` (the default) or `status=resolved`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "status",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"open",
								"resolved",
								"all"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/PageCommentThread"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:comment:view"
			}
		},
		"/sites/{id}/content-generation-agent": {
			"patch": {
				"operationId": "setSiteContentAgent",
				"summary": "Set the writing agent",
				"tags": [
					"Website content"
				],
				"description": "Sets the agent used when generating this site's content. Requires `content:generate` rather than `content:edit` — choosing who writes is part of generating, not part of editing the site.\n\nA single page overrides this by naming an agent in its own `node_instructions_params.contentAgentId`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agentId": {
										"type": "string",
										"format": "uuid"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/generate-all": {
			"post": {
				"operationId": "generateAllPages",
				"summary": "Generate all pages",
				"tags": [
					"Website content"
				],
				"description": "Queues content generation for each empty page that has instructions of its own or inherited from a parent. Returns once the work is queued; generation runs in the background and pages move to `draft` as they complete.\n\nA page that names its own agent in `node_instructions_params.contentAgentId` is written by that one, so a single run can span pages written by different agents. `agentId` covers the rest.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"proofread": {
										"type": "boolean"
									},
									"review": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/generate-briefs": {
			"post": {
				"operationId": "generatePageBriefs",
				"summary": "Generate all briefs",
				"tags": [
					"Website content"
				],
				"description": "Starts background brief generation, one job per page. Returns as soon as the jobs are queued, not when they finish — poll the site's `briefsJob` for progress.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"nodeIds": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"options": {
										"type": "object"
									},
									"siteBrief": {
										"type": "string",
										"maxLength": 20000
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/generate-site-brief": {
			"post": {
				"operationId": "generateSiteBrief",
				"summary": "Generate the site brief",
				"tags": [
					"Website content"
				],
				"description": "Drafts the site-level instructions every page inherits, reading the live site where one exists.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"domain": {
										"type": "string",
										"maxLength": 2048
									},
									"paths": {
										"type": "array",
										"items": {
											"type": "string"
										}
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/generate-structure": {
			"post": {
				"operationId": "generateSiteStructure",
				"summary": "Generate the structure",
				"tags": [
					"Website content"
				],
				"description": "Proposes a page tree from a description of the business, for a site that does not exist yet. Returns the proposal for review — it is not saved until you import it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"description": {
										"type": "string",
										"minLength": 10,
										"maxLength": 10000
									},
									"size": {
										"enum": [
											"starter",
											"standard",
											"full"
										],
										"type": "string"
									}
								},
								"required": [
									"description"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/generation-defaults": {
			"get": {
				"operationId": "getSiteGenerationDefaults",
				"summary": "Get generation defaults",
				"tags": [
					"Website content"
				],
				"description": "The site's instructions for the two passes that follow the copywriter, beside the platform defaults they replace when set: `review` (what the review agent writes about each page) and `editor` (what the editor agent is told to enforce and report). Set through the site's `sitemap_config`: `reviewInstructions` and `editorInstructions`, beside the agents themselves in `reviewAgentId` and `editorAgentId`. A page appends its own notes in `node_instructions_params.reviewInstructions` / `editorInstructions`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"review": {
											"type": "object",
											"properties": {
												"instructions": {
													"type": "string"
												},
												"default": {
													"type": "string"
												}
											}
										},
										"editor": {
											"type": "object",
											"properties": {
												"instructions": {
													"type": "string"
												},
												"default": {
													"type": "string"
												},
												"agentPrompt": {
													"type": "string",
													"description": "A system prompt to start an editor agent from, for a workspace that has none yet."
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/import": {
			"post": {
				"operationId": "importSitePages",
				"summary": "Import pages",
				"tags": [
					"Website content"
				],
				"description": "Builds the page tree from URLs or page titles. Accepts a `urls` array, sitemap XML, a `url` to fetch the XML from, or a plain one-per-line list — the parser is deliberately tolerant, because this input is usually pasted by a person. A list with nothing URL-shaped in it is read as page titles: each line becomes a page whose slug is made from the title, and a line indented under the one before it becomes that page's child.\n\nEvery listed path becomes a page, whether or not other listed paths sit beneath it: a section landing page is still a page. A segment that appears only as an ancestor becomes a folder, since nothing was said about it. A `type` of `page` or `folder`, from a column or the sidecar, decides either way, and on a path that already exists it changes the node in place, except that a page holding content is never turned into a folder.\n\nA comma, tab or semicolon separated file is read as a table when its first row names the columns: `url` (or `path`, `slug`) locates the page, `name` (or `title`) names it, and `instructions` and `type` are applied the same way the `instructions` sidecar is. A heading is matched on any word it carries, so `V1 URL (slug)` is a URL column; a table with a name column and no URL column gets its slugs from the names. Without a recognized header row the first URL-looking cell of each line is taken and the rest of the line is discarded. A page that arrives without a name is named after its slug, dashes to spaces and words capitalized. On a dry run the response reports which `format` was read and which columns went unused.\n\nIt also accepts a site export: post the exported document as the body, or its `nodes` array on its own. A URL path cannot carry capitalization, sibling order, or two pages under the same folder sharing a slug, so an export is the input that survives a round trip — the tree, page names, order and type are read from the file. Pages are matched on the ids in the file, then on their slug path, and updated where they match; nothing is deleted, so a page the file no longer mentions stays. Content in the file is written as a draft, which withdraws any sign-off it had, exactly as editing the page would.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"xml": {
										"type": "string"
									},
									"url": {
										"type": "string"
									},
									"urls": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"nodes": {
										"type": "array",
										"items": {
											"type": "object"
										}
									},
									"keys": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"dryRun": {
										"type": "boolean"
									},
									"instructions": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/sites/{id}/pages": {
			"post": {
				"operationId": "createPage",
				"summary": "Add a page",
				"tags": [
					"Website content"
				],
				"description": "Adds a page or folder to the tree. Omit `node_order` and it is appended to the bottom of its sibling group, which is almost always what you want — passing 0 collides with every existing sibling.\n\n`node_slug` is the page's own URL segment and is derived from `node_name` when omitted. Two pages under one parent cannot share it, so a slug already in use is numbered off it (`about`, `about-2`) and the response carries the one the page was given.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"node_parent": {
										"type": "string",
										"format": "uuid"
									},
									"node_name": {
										"type": "string",
										"minLength": 1
									},
									"node_type": {
										"enum": [
											"page",
											"folder"
										],
										"type": "string"
									},
									"node_slug": {
										"type": "string"
									},
									"node_instructions": {
										"type": "string"
									},
									"node_instructions_params": {
										"type": "object"
									},
									"node_children_instructions": {
										"type": "string"
									},
									"node_component": {
										"type": "string"
									},
									"node_order": {
										"type": "integer"
									}
								},
								"required": [
									"node_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Page"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/sites/{id}/pages/{page_id}": {
			"delete": {
				"operationId": "deletePage",
				"summary": "Delete a page",
				"tags": [
					"Website content"
				],
				"description": "Removes the page and everything filed under it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:delete"
			},
			"get": {
				"operationId": "getPage",
				"summary": "Get a page",
				"tags": [
					"Website content"
				],
				"description": "One page: what it is for, what has been written into it, and how far through review it is.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Page"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			},
			"patch": {
				"operationId": "updatePage",
				"summary": "Update a page",
				"tags": [
					"Website content"
				],
				"description": "Applies the `node_`-prefixed fields present in the body. Writing content directly is allowed — generation is one way to fill a page, not the only one. Writing `node_content` into a page that had been approved withdraws that sign-off: the page returns to draft and re-enters the site's review at the first step, since nobody has read the text it now holds. The approved copy is kept — `POST /sites/{id}/pages/{page_id}/restore-approved` puts it back.\n\nA `node_slug` that another page under the same parent already answers to is refused with 409: the address was named rather than derived, so numbering it off would publish the page somewhere other than where it was asked for.\n\n`node_type` moves a node between `page` and `folder`; pages under it stay either way. A page that holds content is refused as a folder with 409. Discard the content first.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"node_name": {
										"type": "string"
									},
									"node_slug": {
										"type": "string"
									},
									"node_type": {
										"enum": [
											"page",
											"folder"
										],
										"type": "string"
									},
									"node_instructions": {
										"type": "string"
									},
									"node_instructions_params": {
										"type": "object"
									},
									"node_children_instructions": {
										"type": "string"
									},
									"node_component": {
										"type": "string"
									},
									"node_order": {
										"type": "integer"
									},
									"node_content": {
										"type": "object"
									},
									"node_content_summary": {
										"type": "string"
									},
									"node_metadata": {
										"type": "object"
									},
									"node_meta": {
										"type": "object",
										"properties": {
											"title": {
												"type": "string",
												"maxLength": 60
											},
											"description": {
												"type": "string",
												"maxLength": 150
											}
										}
									},
									"node_review": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Page"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/{page_id}/alt-text": {
			"post": {
				"operationId": "generatePageAltText",
				"summary": "Write image alt text",
				"tags": [
					"Website content"
				],
				"description": "Looks at one image and writes alt text for it in the context of this page: the site, the page, the field it sits in (`fieldPath`) and the copy beside it. The image is either a file of the workspace (`file_id`, which the caller must be able to read) or a public web address (`url`, fetched once and never stored). Returns the text for review; nothing is saved until the page is. `currentContent` lets an editor pass unsaved copy and `instruction` steers this one run.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"file_id": {
										"type": "string",
										"format": "uuid"
									},
									"url": {
										"type": "string",
										"format": "uri"
									},
									"fieldPath": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"currentContent": {
										"type": "object"
									},
									"instruction": {
										"type": "string",
										"maxLength": 2000
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/{page_id}/approved-content": {
			"get": {
				"operationId": "getApprovedContent",
				"summary": "Get the approved copy",
				"tags": [
					"Website content"
				],
				"description": "The content as it stood when the page was last signed off, which is not what `node_content` holds once anyone has edited it. Editing an approved page returns it to draft and keeps this, so it answers both \"what changed since approval\" and \"what does the live website still show\". 404 while nothing about the page has ever been approved — `node_approved_at` on the page says which it is.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/pages/{page_id}/assignee": {
			"put": {
				"operationId": "updatePageAssignee",
				"summary": "Assign a page",
				"tags": [
					"Website content"
				],
				"description": "Hands the page to a member of the workspace, or takes it from them with `assignee_id: null`. Assignment says who the page waits on and nothing more — it does not move the page, and workflow moves do not change it. The new assignee is notified.\n\nRequires either `content:edit` or `content:review`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"assignee_id": {
										"type": "string"
									}
								},
								"required": [
									"assignee_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Page"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"content:edit",
					"content:review"
				],
				"x-permission-mode": "any"
			}
		},
		"/sites/{id}/pages/{page_id}/cms/compare": {
			"get": {
				"operationId": "compareCmsPage",
				"summary": "Compare a page",
				"tags": [
					"CMS sync"
				],
				"description": "Both versions of one page, field by field, with the differing fields first — what a conflict needs in order to be decidable.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/pages/{page_id}/cms/merge": {
			"post": {
				"operationId": "mergeCmsPage",
				"summary": "Merge a page",
				"tags": [
					"CMS sync"
				],
				"description": "Settles a page that changed on both sides by keeping each field from the side named in `choices` — `{\"title\": \"local\", \"body\": \"remote\"}`. Fields nobody names keep the local value; `_name`, `_slug` and `_text` name the three that are not content fields. The merged copy is written here and then sent to the CMS under the same approval gate as any push, so on a site under review it waits for a reviewer and the response reports `awaitingApproval`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"choices": {
										"type": "object"
									},
									"publish": {
										"type": "boolean"
									}
								},
								"required": [
									"choices"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/{page_id}/cms/pull": {
			"post": {
				"operationId": "pullPageFromCms",
				"summary": "Pull one page",
				"tags": [
					"CMS sync"
				],
				"description": "Replaces the local copy of this page with the CMS's. The local version is discarded.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/sites/{id}/pages/{page_id}/cms/push": {
			"post": {
				"operationId": "pushPageToCms",
				"summary": "Push one page",
				"tags": [
					"CMS sync"
				],
				"description": "Pushes a single page named explicitly. `force` bypasses the approval gate and the nothing-changed check, since the caller asked for this page by name; a genuine conflict is still reported unless `resolution` says how to settle it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/{page_id}/comments": {
			"get": {
				"operationId": "listPageComments",
				"summary": "List page comments",
				"tags": [
					"Website content"
				],
				"description": "Returns every comment on the page in one response, threads and replies together, oldest first — group them by `cmt_parent` rather than requesting a thread at a time. A thread names what it is about through `cmt_field_path`, an array of field keys and array indices addressing one part of the record (`[\"body\", 0, \"headline\"]`); a thread with no field path is about the page as a whole. Filter with `status=open` or `status=resolved`; resolution belongs to the thread, so replies are filtered with the thread they are in.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cmt_parent",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "status",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"open",
								"resolved",
								"all"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Comment"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:comment:view"
			},
			"post": {
				"operationId": "createPageComment",
				"summary": "Post a comment",
				"tags": [
					"Website content"
				],
				"description": "Starts a thread, or replies to one when `cmt_parent` is given. A reply inherits the anchor and the resolved state of the thread it joins, so it takes no `cmt_field_path` of its own. A path is stored as sent except that array indices are normalized to numbers, so `[\"body\", \"0\"]` and `[\"body\", 0]` are one anchor rather than two. Anyone named in `cmt_mentions` is notified, as is everyone already in the thread.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"cmt_body": {
										"type": "string",
										"minLength": 1,
										"maxLength": 10000
									},
									"cmt_mentions": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"id": {
													"type": "string",
													"format": "uuid"
												}
											}
										}
									},
									"cmt_field_path": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"cmt_parent": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"cmt_body"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Comment"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:comment:create"
			}
		},
		"/sites/{id}/pages/{page_id}/comments/{comment_id}": {
			"delete": {
				"operationId": "deletePageComment",
				"summary": "Delete a comment",
				"tags": [
					"Website content"
				],
				"description": "Soft delete, by the author or by anyone holding `content:comment:delete`. Deleting the first comment of a thread removes its replies with it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "comment_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:comment:create"
			},
			"patch": {
				"operationId": "updatePageComment",
				"summary": "Edit a comment",
				"tags": [
					"Website content"
				],
				"description": "Rewrites the text of your own comment. Moderating someone else's means deleting it, not rewriting what they said.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "comment_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"cmt_body": {
										"type": "string",
										"minLength": 1,
										"maxLength": 10000
									},
									"cmt_mentions": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"id": {
													"type": "string",
													"format": "uuid"
												}
											}
										}
									}
								},
								"required": [
									"cmt_body"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Comment"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:comment:create"
			}
		},
		"/sites/{id}/pages/{page_id}/comments/{comment_id}/reopen": {
			"post": {
				"operationId": "reopenPageComment",
				"summary": "Reopen a thread",
				"tags": [
					"Website content"
				],
				"description": "Puts a resolved thread back on the open list.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "comment_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Comment"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:comment:create"
			}
		},
		"/sites/{id}/pages/{page_id}/comments/{comment_id}/resolve": {
			"post": {
				"operationId": "resolvePageComment",
				"summary": "Resolve a thread",
				"tags": [
					"Website content"
				],
				"description": "Marks the thread settled and drops it out of the open list. Nothing is deleted — a resolved thread is the record of the review, and reopening restores it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "comment_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Comment"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:comment:create"
			}
		},
		"/sites/{id}/pages/{page_id}/generate": {
			"post": {
				"operationId": "generatePageContent",
				"summary": "Generate one page",
				"tags": [
					"Website content"
				],
				"description": "Queues this page to be written from its brief and the site's knowledge, into the shape its content schema declares. Returns once the work is queued, not when the copy is ready: the page sits in `generating` and moves to `draft` when it lands.\n\nThe writer is the agent this page names in `node_instructions_params.contentAgentId`, falling back to `agentId` and then to the site's agent.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"proofread": {
										"type": "boolean"
									},
									"review": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/{page_id}/generate-field": {
			"post": {
				"operationId": "generatePageField",
				"summary": "Generate one field",
				"tags": [
					"Website content"
				],
				"description": "Rewrites one field of a page's structured content, optionally against an instruction, leaving the rest untouched. The page must already have structured content to regenerate a field from.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"proofread": {
										"type": "boolean"
									},
									"review": {
										"type": "boolean"
									},
									"fieldPath": {
										"type": "array",
										"items": {
											"type": "string"
										}
									},
									"currentContent": {
										"type": "object"
									},
									"instruction": {
										"type": "string",
										"maxLength": 2000
									}
								},
								"required": [
									"fieldPath"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/{page_id}/generate-folder": {
			"post": {
				"operationId": "generateFolderContent",
				"summary": "Generate a branch",
				"tags": [
					"Website content"
				],
				"description": "The same as generating the whole site, scoped to one branch — every empty page beneath this node, however deeply nested. The node may be a folder or a page that has pages under it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"proofread": {
										"type": "boolean"
									},
									"review": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/{page_id}/generate-meta": {
			"post": {
				"operationId": "generatePageMeta",
				"summary": "Generate page meta data",
				"tags": [
					"Website content"
				],
				"description": "Writes an SEO meta title (at most 60 characters) and meta description (at most 150) from the page's draft copy. The content template's `metaTitleInstructions` and `metaDescriptionInstructions` replace the platform defaults (see `GET /content-schemas/meta-defaults`); the page-level notes are appended. Returns the pair for review; nothing is saved until the page is. The page must hold draft content to write from. `currentContent` lets an editor pass unsaved copy; `instructions` overrides the saved page-level meta instructions for this one run.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"currentContent": {
										"type": "object"
									},
									"instructions": {
										"type": "string",
										"maxLength": 2000
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/{page_id}/generate/cancel": {
			"post": {
				"operationId": "cancelPageGeneration",
				"summary": "Cancel page generation",
				"tags": [
					"Website content"
				],
				"description": "Frees a page stuck in `generating`, back to `draft` where it still holds copy and `empty` where it never had any, so it can be edited again. The queued job is not recalled: copy that lands later is still saved. Answers 409 when the page is not generating.\n\nRequires either `content:edit` or `content:generate`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Page"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"content:edit",
					"content:generate"
				],
				"x-permission-mode": "any"
			}
		},
		"/sites/{id}/pages/{page_id}/history": {
			"get": {
				"operationId": "listPageHistory",
				"summary": "List page history",
				"tags": [
					"Website content"
				],
				"description": "What has happened to a page, newest first: every workflow move, who made it, and the note they left, and every write into its copy with what made it in `history_ref.source`. Page content itself is omitted — this answers how a page got where it is, not what it said at each point, which `GET /sites/{id}/pages/{page_id}/versions` does.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/pages/{page_id}/proofread": {
			"post": {
				"operationId": "proofreadPage",
				"summary": "Proofread a page",
				"tags": [
					"Website content"
				],
				"description": "Runs the site's editor agent over the page's saved copy, in the background, without regenerating it. The editor reads the brief the page was written to and its own guideline knowledge, corrects wording that breaks them, and lists each change in `editor.changes` with the rule it serves. The structure is never touched: fields, blocks, images and links come back exactly as saved, only words change. Answers 202 with the page marked `node_metadata.proofreading`; the copy is not touched, so the page keeps its status and stays editable. The record lands under `node_review.editor` when the editor is done, or the failure under `node_metadata.lastProofreadError`, and either clears the mark; the corrected copy waits on the record as `proposed` and reaches `node_content` only when a caller applies it, marking each change `applied`. A page already being proofread is answered as it stands; one that is generating is refused with 409. The editor is the agent this page names in `node_instructions_params.editorAgentId`, then `agentId`, then the site's; a page that opted out of the automatic pass is still proofread here, since the request is the opt-in. 400 when no editor is set. `instructions` stands in for the page's editor notes for this one run.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"instructions": {
										"type": "string",
										"maxLength": 4000
									}
								}
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Page"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/{page_id}/reference-docs": {
			"post": {
				"operationId": "uploadPageReferenceDoc",
				"summary": "Upload a reference doc",
				"tags": [
					"Website content"
				],
				"description": "Takes one document as a multipart upload (`files` field) and stores it as reference material for the page. Put the returned `file_id` into an entry of the page's `node_instructions_params.referenceUrls` (`{fileId, name, note?}`) and generation reads the document the way it reads a reference link. PDF, Word, PowerPoint, Excel, CSV, plain text and Markdown are accepted.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"file_id": {
											"type": "string",
											"format": "uuid"
										},
										"file_name": {
											"type": "string"
										},
										"file_type": {
											"type": "string"
										},
										"file_size": {
											"type": "integer"
										}
									},
									"required": [
										"file_id",
										"file_name",
										"file_type"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/{page_id}/reference-docs/{file_id}": {
			"delete": {
				"operationId": "deletePageReferenceDoc",
				"summary": "Delete a reference doc",
				"tags": [
					"Website content"
				],
				"description": "Removes a reference document that was uploaded for this page, bytes included. Only files stored as this page's reference material can be addressed here; the matching `node_instructions_params.referenceUrls` entry is the caller's to clean up.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "file_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/{page_id}/reorder": {
			"post": {
				"operationId": "reorderPage",
				"summary": "Reorder a page",
				"tags": [
					"Website content"
				],
				"description": "Moves a page to a position under a parent, carrying everything nested under it. `node_parent` must name a page of the same site outside the moved page's own subtree; anything else is refused. Both affected sibling groups are renumbered contiguously from 0, so a tree that arrived with gapped or duplicated ordering comes back consistent.\n\nA move already rewrites the page's address, so a slug the destination has spoken for is numbered off rather than refused. Read `node_slug` off the response for what the page ended up at.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"node_parent": {
										"type": "string",
										"format": "uuid"
									},
									"node_order": {
										"type": "integer"
									}
								},
								"required": [
									"node_order"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/{page_id}/restore-approved": {
			"post": {
				"operationId": "restoreApprovedContent",
				"summary": "Restore approved copy",
				"tags": [
					"Website content"
				],
				"description": "Discards the edits made since the last sign-off and puts that copy back, returning the page to approved. Nothing unreviewed reaches a website this way — the content written is exactly what was approved — which is why it takes `content:edit` rather than a review permission. Where the site is under review this ends a review in progress: the page leaves whichever step it had reached and lands back on the final one.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Page"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/{page_id}/review": {
			"post": {
				"operationId": "generatePageReview",
				"summary": "Write a page review",
				"tags": [
					"Website content"
				],
				"description": "Writes the page's review from its saved copy, in the background: where each fact, figure and claim came from, the search terms and questions the page covers, and the trademarks and acronyms it uses, following the site's review instructions (see `GET /sites/{id}/generation-defaults`) with the page's notes appended. The writer is the review agent this page names in `node_instructions_params.reviewAgentId`, then `agentId`, then the site's; any of those may be the word `copywriter`, meaning the agent that writes the page reviews it too, which is the one that can trace a fact to its source. Generation writes the review on its own when the site names a review agent; this is for a page written before that, or edited since. Answers 202 with the page marked `node_metadata.reviewing`; the copy is not touched, so the page keeps its status and stays editable. The review lands under `node_review.review` when the agent is done, or the failure under `node_metadata.lastReviewError`, and either clears the mark. A page already being reviewed is answered as it stands. 400 when no review agent is set. `instructions` stands in for the page's saved review notes for this one run.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"instructions": {
										"type": "string",
										"maxLength": 4000
									}
								}
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Page"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/{page_id}/status": {
			"patch": {
				"operationId": "updatePageStatus",
				"summary": "Set the page status",
				"tags": [
					"Website content"
				],
				"description": "Sets the status by hand: `empty`, `draft`, `approved` or `pushed`, from any status but `generating`, which belongs to the worker until the copy lands or the run is cancelled. A page needs no copy to be approved; marking one approved as it stands is how a page that wants no new text is signed off. `empty` discards whatever content the page holds. Approval is what marks content ready to leave the platform, so it is the gate a CMS push checks. Where the site has an approval workflow, both ends of the sign-off are that workflow's moves to make and this endpoint answers 409 for either: approving (or publishing) a page, and withdrawing an approval by sending it back to draft or empty.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"status": {
										"enum": [
											"empty",
											"draft",
											"approved",
											"pushed"
										],
										"type": "string"
									}
								},
								"required": [
									"status"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/{page_id}/versions": {
			"get": {
				"operationId": "listPageVersions",
				"summary": "List page versions",
				"tags": [
					"Website content"
				],
				"description": "Every version of the page's copy on record, newest first, each reduced to what changed against the one before it: the name, the slug, the content and the metadata, with the status and review step where the write moved them. `history_ref.source` says what wrote it: a save, a generation, a proofread, a CMS pull or merge, an import, a restore, a discard. The state a page held before its first recorded write is kept once, unattributed, as the oldest entry, so the earliest diff is against what the page really held. At most 100 entries come back.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"type": "object",
										"properties": {
											"history_id": {
												"type": "string",
												"format": "uuid"
											},
											"history_timestamp": {
												"type": "string",
												"format": "date-time"
											},
											"history_user": {
												"type": [
													"string",
													"null"
												],
												"format": "uuid"
											},
											"history_op": {
												"type": "string",
												"description": "The kind of change — insert, update or delete."
											},
											"history_changeset": {
												"type": "object",
												"description": "One entry per field that changed, keyed by column name.",
												"additionalProperties": {
													"type": "object",
													"properties": {
														"from": {},
														"to": {}
													}
												}
											},
											"history_ref": {
												"type": "object",
												"description": "What the writer noted about the change rather than the columns: the action that made it, or the reason it was made."
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/{id}/pages/{page_id}/versions/{history_id}/revert": {
			"post": {
				"operationId": "revertPageToVersion",
				"summary": "Revert page to version",
				"tags": [
					"Website content"
				],
				"description": "Puts the content and metadata of a version back on the page, and records the restore as a version of its own so it can be undone in turn. The name and slug a version carried are shown but not written back. Restoring is an edit: the page returns to draft, an approval it held is withdrawn and, under review, it re-enters at the flow's first step. The approved copy is untouched. 409 while the page is being generated.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "history_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "page_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"restored": {
											"type": "array",
											"description": "Columns written back, by name.",
											"items": {
												"type": "string"
											}
										},
										"skipped": {
											"type": "array",
											"description": "Columns the version carried that were deliberately not written.",
											"items": {
												"type": "object",
												"properties": {
													"field": {
														"type": "string"
													},
													"reason": {
														"type": "string",
														"enum": [
															"unrecorded",
															"not_permitted"
														],
														"description": "unrecorded — the stored value was written outside the app, so there is no audited value to restore over it; not_permitted — restoring it needs a permission or plan the caller no longer has."
													},
													"detail": {
														"type": "string"
													}
												}
											}
										}
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/actions/generate": {
			"post": {
				"operationId": "generatePages",
				"summary": "Generate pages",
				"tags": [
					"Website content"
				],
				"description": "The same as generating the whole site, scoped to the pages named in `page_ids` — a hand-picked set rather than a branch. Pages already holding content, and pages with no instructions of their own or inherited, sit the run out rather than failing it; `queued` reports how many were taken.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"agentId": {
										"type": "string",
										"format": "uuid"
									},
									"proofread": {
										"type": "boolean"
									},
									"review": {
										"type": "boolean"
									}
								},
								"required": [
									"page_ids"
								]
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/actions/move": {
			"post": {
				"operationId": "movePages",
				"summary": "Move pages",
				"tags": [
					"Website content"
				],
				"description": "Puts every page named in `page_ids` under `node_parent` (top level when null), after whatever is already there and in the order they hold in the tree. A page whose ancestor is also named travels with it and keeps its place, so a selected branch arrives intact. `node_parent` must be a page of the same site outside every moved subtree; anything else is refused.\n\nA move already rewrites a page's address, so a slug the destination has spoken for is numbered off rather than refused; `renamedCount` says how many were. Pages the site does not hold are reported back rather than failing the rest.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"node_parent": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"page_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/actions/proofread": {
			"post": {
				"operationId": "proofreadPages",
				"summary": "Proofread pages",
				"tags": [
					"Website content"
				],
				"description": "Runs the editor agent over the pages named in `page_ids`, in the background, the way generation runs: each page sits in `generating` while the editor works and returns to `draft` with its copy corrected and the editor's record on its review. Corrections are applied outright rather than proposed, so only draft pages holding copy are taken; empty, generating, approved and published pages sit the run out, as do folders. `queued` reports how many were taken. The editor is each page's own, then `agentId`, then the site's; a page that opted out of the automatic pass is still proofread, since the request is the opt-in. 400 when none of the pages has an editor.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"agentId": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"page_ids"
								]
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/actions/review": {
			"post": {
				"operationId": "reviewPages",
				"summary": "Review pages",
				"tags": [
					"Website content"
				],
				"description": "Writes the review of each page named in `page_ids`, in the background, one task per page. Unlike generation or proofreading the copy is not touched, so a page keeps its status and stays editable; `node_metadata.reviewing` marks it until the review lands under `node_review.review`. Pages with copy (draft, approved or published) are taken; empty and generating pages, folders and pages already being reviewed sit the run out. The reviewer is each page's own, then `agentId`, then the site's, with `copywriter` meaning whoever writes that page. `queued` reports how many were taken; 400 when none of the pages has a review agent. Each review costs a full writer-sized call.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"agentId": {
										"type": "string"
									}
								},
								"required": [
									"page_ids"
								]
							}
						}
					}
				},
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/{id}/pages/actions/status": {
			"post": {
				"operationId": "updatePagesStatus",
				"summary": "Set page statuses",
				"tags": [
					"Website content"
				],
				"description": "Sets the status of every page named in `page_ids` under the rules of setting one page's status. A page already holding it counts as done. One that is generating, or whose move the site's approval workflow reserves, is reported back with the reason rather than failing the rest, as is a page the site does not hold.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"status": {
										"enum": [
											"empty",
											"draft",
											"approved",
											"pushed"
										],
										"type": "string"
									}
								},
								"required": [
									"page_ids",
									"status"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/pages/actions/transition": {
			"post": {
				"operationId": "transitionPages",
				"summary": "Move pages",
				"tags": [
					"Website content"
				],
				"description": "Puts pages on a step of the site's approval workflow — any step, in either direction, from wherever they stand. The step's own gate decides who may set it (403 when it does not name the caller); pages the caller cannot write are reported per page rather than refusing the rest. Reaching the final step is what marks a page approved; leaving it withdraws that. The note is kept on each page's history and sent to whoever the page waits on — its assignee, or whoever can act on it next while unassigned. Passing `assignee_id` hands the pages over in the same move (`null` clears); leaving it out keeps every page with whoever holds it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"target_state_id": {
										"type": "string",
										"format": "uuid"
									},
									"note": {
										"type": "string",
										"maxLength": 2000
									},
									"assignee_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"page_ids",
									"target_state_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:review"
			}
		},
		"/sites/{id}/pages/actions/update-settings": {
			"post": {
				"operationId": "updatePagesSettings",
				"summary": "Update page settings",
				"tags": [
					"Website content"
				],
				"description": "Writes generation settings onto every page named in `page_ids` at once: content instructions, content template, audience profiles, tone and copywriter agent. Only the fields present in the body are touched, and `null` (or an empty list) clears a field, returning the page to what it inherits from its folder or the site. Everything else a page carries, its content and review state included, is left alone. Pages the site does not hold are reported back rather than failing the rest.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"page_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"format": "uuid"
										}
									},
									"node_instructions": {
										"type": "string",
										"maxLength": 20000
									},
									"template_id": {
										"type": "string",
										"format": "uuid"
									},
									"audience_profile_ids": {
										"type": "array",
										"items": {
											"type": "string",
											"minLength": 1,
											"maxLength": 200
										}
									},
									"tone_id": {
										"type": "string",
										"maxLength": 200
									},
									"content_agent_id": {
										"type": "string",
										"format": "uuid"
									},
									"editor_agent_id": {
										"type": "string",
										"format": "uuid"
									},
									"editor_skipped": {
										"type": "boolean"
									},
									"review_agent_id": {
										"type": "string"
									}
								},
								"required": [
									"page_ids"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:edit"
			}
		},
		"/sites/{id}/reset-generating": {
			"post": {
				"operationId": "resetStuckGeneration",
				"summary": "Reset stuck pages",
				"tags": [
					"Website content"
				],
				"description": "Frees any page left in `generating` for more than 15 minutes, back to `draft` where it still holds copy and `empty` where it never had any. A safety valve for the case where the background job exhausted its retries and the page would otherwise never come back.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:generate"
			}
		},
		"/sites/cms/providers": {
			"get": {
				"operationId": "listCmsProviders",
				"summary": "List CMS providers",
				"tags": [
					"CMS sync"
				],
				"description": "The providers a site can connect to, and the fields each one needs to connect. Static catalog — it reflects no workspace data.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:view"
			}
		},
		"/sites/import/discover": {
			"post": {
				"operationId": "discoverSitePages",
				"summary": "Discover pages",
				"tags": [
					"Website content"
				],
				"description": "Given a URL, finds its pages: `robots.txt`, then the well-known sitemap paths (expanding sitemap indexes), then a homepage navigation crawl as a fallback. Runs server-side because a browser cannot fetch another origin. Returns the URLs it found without writing anything.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"url": {
										"type": "string",
										"minLength": 3,
										"maxLength": 2048
									}
								},
								"required": [
									"url"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "content:create"
			}
		},
		"/social/connections": {
			"get": {
				"operationId": "listSocialConnections",
				"summary": "List social accounts",
				"tags": [
					"Social"
				],
				"description": "Which platforms this workspace is connected to and whether each connection is still usable — the thing to check first when a post fails.\n\nRequires the `module-social-post` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "social:view",
				"x-required-plan": "module-social-post"
			}
		},
		"/social/posts": {
			"get": {
				"operationId": "listSocialPosts",
				"summary": "List posts",
				"tags": [
					"Social"
				],
				"description": "Returns posts sent or scheduled to a social platform, newest first, with the source file's name and type alongside each.\n\nRequires the `module-social-post` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "file_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "platform",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"instagram"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "sp_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "sp_scheduled_at",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "status",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"scheduled",
								"publishing",
								"published",
								"failed",
								"cancelled"
							],
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/SocialPost"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "social:view",
				"x-required-plan": "module-social-post"
			},
			"post": {
				"operationId": "publishSocialPost",
				"summary": "Send a post",
				"tags": [
					"Social"
				],
				"description": "Sends a file the workspace already holds to a connected account. Give `scheduled_at` to queue it for later instead of posting immediately — a scheduled post can still be cancelled, a sent one cannot.\n\nRequires `social:publish`, `media:download`, `document:download`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` and `presentation:view` together.\n\nRequires the `module-social-post` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_id": {
										"type": "string",
										"format": "uuid"
									},
									"platform": {
										"enum": [
											"instagram"
										],
										"type": "string"
									},
									"caption": {
										"type": "string"
									},
									"media_type": {
										"enum": [
											"IMAGE",
											"VIDEO",
											"REELS",
											"STORIES",
											"CAROUSEL"
										],
										"type": "string"
									},
									"scheduled_at": {
										"type": "string",
										"format": "date-time"
									}
								},
								"required": [
									"file_id",
									"platform"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"social:publish",
					"media:download",
					"document:download",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "all",
				"x-required-plan": "module-social-post"
			}
		},
		"/social/posts/{id}": {
			"delete": {
				"operationId": "cancelSocialPost",
				"summary": "Cancel a post",
				"tags": [
					"Social"
				],
				"description": "Only while it is still scheduled. Once it has gone out, it has to be removed on the platform itself.\n\nRequires the `module-social-post` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "social:publish",
				"x-required-plan": "module-social-post"
			},
			"get": {
				"operationId": "getSocialPost",
				"summary": "Get a post",
				"tags": [
					"Social"
				],
				"description": "The record with the file it sent, including the outcome reported by the platform.\n\nRequires the `module-social-post` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/SocialPost"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "social:view",
				"x-required-plan": "module-social-post"
			}
		},
		"/spaces": {
			"get": {
				"operationId": "listSpaces",
				"summary": "List spaces",
				"tags": [
					"Spaces"
				],
				"description": "Spaces nest. Pass `space_parent` with a space id for that space's children, or the literal `root` for the top level.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "full_text_search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "space_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "space_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "space_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "space_parent",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Space"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:view"
			},
			"post": {
				"operationId": "createSpace",
				"summary": "Create a space",
				"tags": [
					"Spaces"
				],
				"description": "Creates a space. Spaces can nest, and a thread lives in at most one of them.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"space_name": {
										"type": "string",
										"minLength": 1
									},
									"space_description": {
										"type": "string"
									},
									"space_icon": {
										"type": "string"
									},
									"space_color": {
										"type": "string"
									},
									"space_parent": {
										"type": "string",
										"format": "uuid"
									},
									"space_default_agent": {
										"type": "string",
										"format": "uuid"
									},
									"space_system_prompt": {
										"type": "string"
									},
									"space_knowledge": {
										"type": "array",
										"items": {}
									},
									"space_metadata": {
										"type": "object"
									},
									"space_acl": {
										"type": "object"
									}
								},
								"required": [
									"space_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Space"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:create"
			}
		},
		"/spaces/{id}": {
			"delete": {
				"operationId": "deleteSpace",
				"summary": "Delete a space",
				"tags": [
					"Spaces"
				],
				"description": "Deletes the space itself. Threads inside it are not deleted — they revert to being personal threads belonging to whoever started them.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:delete"
			},
			"get": {
				"operationId": "getSpace",
				"summary": "Get a space",
				"tags": [
					"Spaces"
				],
				"description": "Returns the space with its membership and where it sits in the tree.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Space"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:view"
			},
			"patch": {
				"operationId": "updateSpace",
				"summary": "Update a space",
				"tags": [
					"Spaces"
				],
				"description": "Applies the `space_`-prefixed fields present in the body. Only an owner may change who has access or move the space.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"space_name": {
										"type": "string",
										"minLength": 1
									},
									"space_description": {
										"type": "string"
									},
									"space_icon": {
										"type": "string"
									},
									"space_color": {
										"type": "string"
									},
									"space_parent": {
										"type": "string",
										"format": "uuid"
									},
									"space_default_agent": {
										"type": "string",
										"format": "uuid"
									},
									"space_system_prompt": {
										"type": "string"
									},
									"space_knowledge": {
										"type": "array",
										"items": {}
									},
									"space_metadata": {
										"type": "object"
									},
									"space_acl": {
										"type": "object"
									},
									"space_active": {
										"type": "boolean"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Space"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:edit"
			}
		},
		"/spaces/{id}/members": {
			"get": {
				"operationId": "listSpaceMembers",
				"summary": "List members",
				"tags": [
					"Spaces"
				],
				"description": "Each member with the operations they hold on the space.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:view"
			},
			"post": {
				"operationId": "setSpaceMember",
				"summary": "Add or update a member",
				"tags": [
					"Spaces"
				],
				"description": "One call for both: the member's entry is written to whatever `role` says, whether or not they were already a member. Only a space owner may call it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"usr_id": {
										"type": "string",
										"format": "uuid"
									},
									"role": {
										"enum": [
											"viewer",
											"member",
											"owner"
										],
										"type": "string"
									}
								},
								"required": [
									"usr_id",
									"role"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:edit"
			}
		},
		"/spaces/{id}/members/{user_id}": {
			"delete": {
				"operationId": "removeSpaceMember",
				"summary": "Remove a member",
				"tags": [
					"Spaces"
				],
				"description": "Removes one member. Threads they started stay in the space.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "user_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:edit"
			}
		},
		"/spaces/{id}/threads/{thread_id}": {
			"delete": {
				"operationId": "removeThreadFromSpace",
				"summary": "Remove a thread",
				"tags": [
					"Spaces"
				],
				"description": "Takes the thread out of the space without deleting it — it goes back to being the author's own.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "thread_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:edit"
			},
			"post": {
				"operationId": "moveThreadIntoSpace",
				"summary": "Add a thread",
				"tags": [
					"Spaces"
				],
				"description": "Two permissions meet here, and both are required: write access to the space, and either ownership of the thread or write access to it. A private thread becomes visible to the space when it moves in; a thread already shared more widely keeps its sharing.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "thread_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "space:edit"
			}
		},
		"/stock-photos": {
			"get": {
				"operationId": "searchStockPhotos",
				"summary": "Search stock photos",
				"tags": [
					"Stock photos"
				],
				"description": "Searches a third-party stock photography library. Nothing is stored by this request — the results are the provider's, and each carries the attribution that must be shown wherever the photo is displayed. With no `query`, the provider's editorial selection is returned. Answers 503 when the workspace has no stock provider configured, and 403 when an administrator has turned stock photos off for the workspace.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "color",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 32
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "orientation",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"landscape",
								"portrait",
								"squarish"
							],
							"type": "string"
						}
					},
					{
						"name": "page",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 100
						}
					},
					{
						"name": "per_page",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 30
						}
					},
					{
						"name": "query",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 200
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "stock-photo:view"
			}
		},
		"/stock-photos/{id}/import": {
			"post": {
				"operationId": "importStockPhoto",
				"summary": "Import a stock photo",
				"tags": [
					"Stock photos"
				],
				"description": "Copies one searched photo into the workspace as a file and returns it. Without `file_repo` the photo lands in the media library, which additionally requires `media:upload`; with one, it is filed against that object and follows its access rules. Answers 403 when stock photos are turned off for the workspace.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"file_repo": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "stock-photo:import"
			}
		},
		"/studio/generate-image": {
			"post": {
				"operationId": "generateStudioImage",
				"summary": "Generate an image",
				"tags": [
					"Studio"
				],
				"description": "The image is stored in the library like any other file, with the prompt kept alongside it, so it is findable later rather than only being downloadable now.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"prompt": {
										"type": "string",
										"minLength": 3,
										"maxLength": 2000
									},
									"aspect_ratio": {
										"enum": [
											"1:1",
											"2:3",
											"3:2",
											"3:4",
											"4:3",
											"4:5",
											"5:4",
											"9:16",
											"16:9",
											"21:9"
										],
										"type": "string"
									}
								},
								"required": [
									"prompt"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "studio:image:generate"
			}
		},
		"/studio/generate-infographic": {
			"post": {
				"operationId": "generateInfographic",
				"summary": "Generate an infographic",
				"tags": [
					"Studio"
				],
				"description": "Produces an HTML source and a PNG of it, linked as one file. Both are treated the same as an infographic made anywhere else in the platform.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"brief": {
										"type": "string",
										"minLength": 3,
										"maxLength": 4000
									},
									"size": {
										"enum": [
											"square",
											"portrait",
											"story",
											"wide",
											"linkedin",
											"poster"
										],
										"type": "string"
									},
									"style": {
										"enum": [
											"clean",
											"bold",
											"editorial",
											"diagram"
										],
										"type": "string"
									},
									"data": {
										"type": "object",
										"properties": {
											"kind": {
												"enum": [
													"none",
													"text",
													"file",
													"ds"
												],
												"type": "string"
											}
										}
									}
								},
								"required": [
									"brief"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:generate"
			}
		},
		"/studio/generate-infographic-native": {
			"post": {
				"operationId": "generateEditableInfographic",
				"summary": "Generate an editable infographic",
				"tags": [
					"Studio"
				],
				"description": "Produces a design rather than a picture: real text layers and real chart objects, opened in the design editor. Its charts stay bound to the data they were built from, so refreshing one re-reads the source instead of redrawing an image.\n\nRequires the `module-design` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"brief": {
										"type": "string",
										"minLength": 3,
										"maxLength": 4000
									},
									"size": {
										"enum": [
											"square",
											"portrait",
											"story",
											"wide",
											"linkedin",
											"poster"
										],
										"type": "string"
									},
									"data": {
										"type": "object",
										"properties": {
											"kind": {
												"enum": [
													"none",
													"text",
													"file",
													"ds"
												],
												"type": "string"
											}
										}
									}
								},
								"required": [
									"brief"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "design:create",
				"x-required-plan": "module-design"
			}
		},
		"/studio/infographic-options": {
			"get": {
				"operationId": "listInfographicOptions",
				"summary": "List infographic options",
				"tags": [
					"Studio"
				],
				"description": "What the composer accepts. Read it rather than hard-coding the list.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "infographic:view"
			}
		},
		"/studio/media-ideas": {
			"get": {
				"operationId": "listMediaIdeas",
				"summary": "List media ideas",
				"tags": [
					"Studio"
				],
				"description": "Images and videos produced on a schedule by an automated workflow, offered as starting points. Nothing is generated by this request.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
						}
					},
					{
						"name": "wf_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "media:view"
			}
		},
		"/tasks": {
			"get": {
				"operationId": "listTasks",
				"summary": "List tasks",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the workspace's tasks. Templates are hidden unless `task_is_template` asks for them.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "task_assigned_to",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "task_autopilot_only",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "task_created_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "task_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "task_is_template",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "task_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "task_priority",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "task_routines_only",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "task_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "task_workflow_only",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Task"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:view",
				"x-required-plan": "module-tasks"
			},
			"post": {
				"operationId": "createTask",
				"summary": "Create a task",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nCreates a task. To create one from a saved template, use `POST /tasks/{id}/copy`.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"task_name": {
										"type": "string",
										"minLength": 1
									}
								},
								"required": [
									"task_name"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Task"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:create",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/{id}": {
			"delete": {
				"operationId": "deleteTask",
				"summary": "Delete a task",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nDeactivates the task. It stops being listed; its history and its thread are kept.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:delete",
				"x-required-plan": "module-tasks"
			},
			"get": {
				"operationId": "getTask",
				"summary": "Get a task",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns the task with its status, its owner and where it has got to in review.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Task"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:view",
				"x-required-plan": "module-tasks"
			},
			"patch": {
				"operationId": "updateTask",
				"summary": "Update a task",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nApplies the `task_`-prefixed fields present in the body. Moving a task through review goes through the review endpoints, which record who decided what.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Task"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:edit",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/{id}/approve": {
			"post": {
				"operationId": "reviewTask",
				"summary": "Approve or reject a task",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe creator's half of review. `approved: true` completes it; `false` sends it back in progress with your comments attached.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:edit",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/{id}/copy": {
			"post": {
				"operationId": "copyTask",
				"summary": "Create from a template",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nClones a template into a real task. The body may override who it is assigned to, its name, due date and priority.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:create",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/{id}/routine": {
			"patch": {
				"operationId": "updateRoutine",
				"summary": "Change the schedule",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nEnable, disable or reschedule it. Accepts a cron expression and timezone, and optionally an end date or a maximum number of runs.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:edit",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/{id}/run-autopilot": {
			"post": {
				"operationId": "runTaskAutopilot",
				"summary": "Run autopilot",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRuns a model — it consumes credits and counts against the expensive rate-limit tier.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:edit",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/{id}/send-email": {
			"post": {
				"operationId": "sendTaskEmail",
				"summary": "Email the response",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nEmails the task's response to a recipient, for the tasks whose output is meant to leave the platform.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:email:send",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/{id}/submit-review": {
			"post": {
				"operationId": "submitTaskForReview",
				"summary": "Submit for review",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe assignee's half of review. The task moves to awaiting review rather than to done.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:edit",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/autopilot/activity": {
			"get": {
				"operationId": "listAutopilotActivity",
				"summary": "List autopilot runs",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nReturns what autopilot has done recently and to which tasks — the record behind the work nobody asked for by hand.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:view",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/briefing/run": {
			"post": {
				"operationId": "runBriefing",
				"summary": "Generate the briefing",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nBuilds it on demand instead of waiting for the scheduled run.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:create",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/briefing/today": {
			"get": {
				"operationId": "getTodayBriefing",
				"summary": "Get today's briefing",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe morning summary of what is waiting, as shown on the dashboard.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:view",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/enrich": {
			"post": {
				"operationId": "enrichTaskBrief",
				"summary": "Enrich a brief",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRuns a model — it consumes credits and counts against the expensive rate-limit tier.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"raw": {
										"type": "string",
										"minLength": 1
									}
								},
								"required": [
									"raw"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:create",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/events": {
			"get": {
				"operationId": "streamTaskEvents",
				"summary": "Stream task events",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nA server-sent event stream of changes across the workspace. Responds with `text/event-stream`.\n\nPair it with slow polling rather than relying on it alone: the event bus is per-instance and in memory, so a reconnection can land somewhere that missed an event.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:view",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/routines": {
			"get": {
				"operationId": "listRoutines",
				"summary": "List routines",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nThe task templates set to run on a schedule.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "array",
									"items": {
										"$ref": "#/components/schemas/Task"
									}
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:view",
				"x-required-plan": "module-tasks"
			},
			"post": {
				"operationId": "createRoutine",
				"summary": "Create a routine",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nTakes what was worked out in a thread and makes it a task template that can run on a schedule.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"thread_id": {
										"type": "string",
										"format": "uuid"
									},
									"instruction": {
										"type": "string"
									},
									"schedule_hint": {
										"type": "string"
									},
									"message_id": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"thread_id"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:create",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/routines/{id}/run": {
			"post": {
				"operationId": "runRoutineNow",
				"summary": "Run a routine now",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nRuns it immediately without affecting its schedule.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:create",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/stats": {
			"get": {
				"operationId": "getTaskStats",
				"summary": "Get task statistics",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nCounts by status and by owner, for a dashboard rather than a listing.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:view",
				"x-required-plan": "module-tasks"
			}
		},
		"/tasks/suggestions": {
			"get": {
				"operationId": "listRoutineSuggestions",
				"summary": "List suggested routines",
				"tags": [
					"Tasks"
				],
				"description": "> **Beta** — this operation may change on 30 days notice. See [versioning](/versioning).\n\nWork the caller repeats often enough that it could run on a schedule instead.\n\nRequires the `module-tasks` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"x-stability": "beta",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:view",
				"x-required-plan": "module-tasks"
			}
		},
		"/threads": {
			"get": {
				"operationId": "listThreads",
				"summary": "List threads",
				"tags": [
					"Threads"
				],
				"description": "Returns the conversations the caller can see — their own, plus any shared with them or with a space they belong to. Context-agent threads are excluded unless `thread_type` asks for them.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "full_text_search",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "thread_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "thread_agent",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "thread_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "thread_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "thread_ids",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "thread_ids.*",
						"in": "query",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "thread_ref",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "thread_space",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "thread_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "thread_title",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "thread_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "thread_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "thread_user",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Thread"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:view"
			},
			"post": {
				"operationId": "createThread",
				"summary": "Create a thread",
				"tags": [
					"Threads"
				],
				"description": "Pass `thread_space` to create it inside a space, which requires write access to that space. Without one it is personal to the caller.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"thread_id": {
										"type": "string"
									},
									"thread_ref": {
										"type": "object"
									},
									"thread_agent": {
										"type": "string",
										"format": "uuid"
									},
									"thread_title": {
										"type": "string"
									},
									"thread_active": {
										"type": "boolean"
									},
									"thread_user": {
										"type": "string",
										"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
									},
									"thread_acl": {
										"type": "object"
									},
									"thread_type": {
										"type": "string"
									},
									"thread_space": {
										"type": "string",
										"format": "uuid"
									},
									"thread_share_mode": {
										"enum": [
											"private",
											"space",
											"collab"
										],
										"type": "string"
									}
								},
								"required": [
									"thread_id"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Thread"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:create"
			}
		},
		"/threads/{id}": {
			"delete": {
				"operationId": "deleteThread",
				"summary": "Delete a thread",
				"tags": [
					"Threads"
				],
				"description": "Deactivates the thread and the messages in it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:delete"
			},
			"get": {
				"operationId": "getThread",
				"summary": "Get a thread",
				"tags": [
					"Threads"
				],
				"description": "Returns the conversation with its agent, its subject and who it is shared with. The messages in it are read separately.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Thread"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:view"
			},
			"patch": {
				"operationId": "updateThread",
				"summary": "Update a thread",
				"tags": [
					"Threads"
				],
				"description": "Applies the `thread_`-prefixed fields present in the body. Only an owner may change who the thread is shared with.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"thread_status": {
										"type": "string"
									},
									"thread_active": {
										"type": "boolean"
									},
									"thread_agent": {
										"type": "string",
										"format": "uuid"
									},
									"thread_user": {
										"type": "string",
										"format": "uuid"
									},
									"thread_acl": {
										"type": "object"
									},
									"thread_space": {
										"type": "string",
										"format": "uuid"
									},
									"thread_share_mode": {
										"enum": [
											"private",
											"space",
											"collab"
										],
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Thread"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:edit"
			}
		},
		"/threads/{id}/events": {
			"get": {
				"operationId": "streamThreadEvents",
				"summary": "Stream thread events",
				"tags": [
					"Threads"
				],
				"description": "A server-sent event stream: `user_message`, `assistant_message`, `lock` and `presence`. This is how a client follows a reply as it is generated rather than polling for it.\n\nResponds with `text/event-stream`, not JSON — use an SSE client.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:view"
			}
		},
		"/threads/{id}/files": {
			"get": {
				"operationId": "listThreadFiles",
				"summary": "List thread files",
				"tags": [
					"Threads"
				],
				"description": "Files belonging to this conversation — what was attached to it, and what was generated in it.\n\nRequires any one of `media:view`, `document:view`, `knowledge-base:view`, `thread:view`, `design:view`, `prompt:view` or `presentation:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "file_added_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "file_hash",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "file_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_provider_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_size",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "file_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "file_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "repo_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "repo_type",
						"in": "query",
						"required": false,
						"schema": {
							"enum": [
								"media",
								"generated",
								"docs",
								"ds",
								"thread",
								"design",
								"prompt",
								"ppt",
								"ppt_template",
								"form"
							],
							"type": "string"
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/File"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"media:view",
					"document:view",
					"knowledge-base:view",
					"thread:view",
					"design:view",
					"prompt:view",
					"presentation:view"
				],
				"x-permission-mode": "any"
			}
		},
		"/threads/{id}/members": {
			"get": {
				"operationId": "listThreadMembers",
				"summary": "List members",
				"tags": [
					"Threads"
				],
				"description": "Returns who the thread is shared with, and what each of them may do with it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:view"
			},
			"post": {
				"operationId": "setThreadMember",
				"summary": "Add a member",
				"tags": [
					"Threads"
				],
				"description": "Only the owner of a personal thread may share it. A thread that lives in a space takes its access from the space instead, so this does not apply to one.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"usr_id": {
										"type": "string",
										"format": "uuid"
									},
									"role": {
										"enum": [
											"viewer",
											"member",
											"owner"
										],
										"type": "string"
									}
								},
								"required": [
									"usr_id",
									"role"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:edit"
			}
		},
		"/threads/{id}/members/{user_id}": {
			"delete": {
				"operationId": "removeThreadMember",
				"summary": "Remove a member",
				"tags": [
					"Threads"
				],
				"description": "The owner cannot be removed from their own thread.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "user_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:edit"
			}
		},
		"/threads/{id}/messages": {
			"get": {
				"operationId": "listMessages",
				"summary": "List messages",
				"tags": [
					"Messages"
				],
				"description": "Returns the messages in one thread, oldest first. The thread is the collection — it comes from the path, so a message can never be read through a thread it does not belong to.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "msg_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "msg_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "msg_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "msg_model",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "msg_sender",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Message"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "message:view"
			},
			"post": {
				"operationId": "createMessage",
				"summary": "Send a message",
				"tags": [
					"Messages"
				],
				"description": "Posts to the thread and starts the assistant's reply. **This is the endpoint that runs a model**, so it consumes credits and is counted against the expensive rate-limit tier.\n\nThe reply is produced asynchronously — follow the thread's event stream rather than waiting on this response for it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"msg_content": {
										"type": "array",
										"items": {}
									},
									"thread_agent": {
										"type": "string",
										"format": "uuid"
									},
									"thread_ref": {
										"type": "object"
									},
									"msg_model": {
										"type": "string"
									},
									"msg_active": {
										"type": "boolean"
									},
									"responseMessageId": {
										"type": "string",
										"format": "uuid"
									},
									"attach_logo": {
										"type": "boolean"
									},
									"retry": {
										"type": "boolean"
									},
									"imageQuality": {
										"enum": [
											"1K",
											"2K",
											"4K"
										],
										"type": "string"
									},
									"aspectRatio": {
										"enum": [
											"1:1",
											"2:3",
											"3:2",
											"3:4",
											"4:3",
											"4:5",
											"5:4",
											"9:16",
											"16:9",
											"21:9"
										],
										"type": "string"
									},
									"design_template": {
										"type": "string",
										"format": "uuid"
									}
								},
								"required": [
									"msg_content"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Message"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "message:create"
			}
		},
		"/threads/{id}/messages/{message_id}": {
			"get": {
				"operationId": "getMessage",
				"summary": "Get a message",
				"tags": [
					"Messages"
				],
				"description": "Returns one message with its content, its sender and what the model spent on it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "message_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Message"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "message:view"
			}
		},
		"/threads/{id}/messages/{message_id}/content": {
			"patch": {
				"operationId": "updateMessageContent",
				"summary": "Edit a message",
				"tags": [
					"Messages"
				],
				"description": "Rewrites the text of a message already sent. It does not re-run the model — discard the exchange for that.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "message_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"msg_content": {
										"type": "array",
										"items": {}
									}
								},
								"required": [
									"msg_content"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "message:create"
			}
		},
		"/threads/{id}/messages/{message_id}/discard": {
			"delete": {
				"operationId": "discardMessageExchange",
				"summary": "Undo an exchange",
				"tags": [
					"Messages"
				],
				"description": "Removes this message, the user message that prompted it, and everything after it in the thread — rewinding the conversation to before the exchange. Used to back out an edit that went wrong.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "message_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "message:create"
			}
		},
		"/threads/{id}/messages/{message_id}/feedback": {
			"patch": {
				"operationId": "rateMessage",
				"summary": "Rate a message",
				"tags": [
					"Messages"
				],
				"description": "Records a thumbs up or down against an assistant reply.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "message_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"feedback_type": {
										"enum": [
											"up",
											"down",
											"clear"
										],
										"type": "string"
									}
								},
								"required": [
									"feedback_type"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "message:create"
			}
		},
		"/threads/{id}/presence": {
			"post": {
				"operationId": "sendThreadPresence",
				"summary": "Report presence",
				"tags": [
					"Threads"
				],
				"description": "Heartbeat behind the presence events. Send it periodically while the thread is open.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"state": {
										"enum": [
											"viewing",
											"typing"
										],
										"type": "string"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:view"
			}
		},
		"/threads/actions/find-or-create": {
			"post": {
				"operationId": "findOrCreateThread",
				"summary": "Find or create a thread",
				"tags": [
					"Threads"
				],
				"description": "For conversations attached to something else — a file, a task. Returns the existing thread or starts one.\n\nIt is a POST because it writes. If you only want to look, `GET /threads?thread_ref=…` reads and never creates.\n\nRequires both `thread:create` and `thread:view`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"thread_ref": {
										"type": "object"
									},
									"thread_agent": {
										"type": "string",
										"format": "uuid"
									},
									"thread_status": {
										"type": "string"
									},
									"thread_title": {
										"type": "string"
									}
								},
								"required": [
									"thread_ref"
								]
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Thread"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": [
					"thread:create",
					"thread:view"
				],
				"x-permission-mode": "all"
			}
		},
		"/threads/search": {
			"get": {
				"operationId": "searchThreads",
				"summary": "Search threads",
				"tags": [
					"Threads"
				],
				"description": "Searches titles and message text, returning matching threads with a highlighted snippet and the message that produced it.\n\nUnless you narrow it yourself, the search covers roughly the last 60 days. Messages are stored in time-partitioned tables, and an unbounded search would read every partition — the window is what keeps it fast.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "deep",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 50
						}
					},
					{
						"name": "q",
						"in": "query",
						"required": true,
						"schema": {
							"type": "string",
							"minLength": 2
						}
					},
					{
						"name": "thread_space",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "thread:view"
			}
		},
		"/usage/summary": {
			"get": {
				"operationId": "getUsageSummary",
				"summary": "Get a usage summary",
				"tags": [
					"Usage"
				],
				"description": "What has been consumed this cycle and what the plan allows.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "usage:view"
			}
		},
		"/voice-agents": {
			"get": {
				"operationId": "listVoiceAgents",
				"summary": "List voice agents",
				"tags": [
					"Voice agents"
				],
				"description": "Returns the workspace's voice agents and the numbers they answer on.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/VoiceAgent"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:view",
				"x-required-plan": "module-voice-agent"
			},
			"post": {
				"operationId": "createVoiceAgent",
				"summary": "Create a voice agent",
				"tags": [
					"Voice agents"
				],
				"description": "Creates the agent and its configuration. It has no phone number until you request one.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"vag_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 255
									},
									"vag_agent": {
										"type": "string",
										"format": "uuid"
									},
									"vag_config": {
										"type": "object"
									},
									"vag_limits": {
										"type": "object"
									}
								},
								"required": [
									"vag_name",
									"vag_agent"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/VoiceAgent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:create",
				"x-required-plan": "module-voice-agent"
			}
		},
		"/voice-agents/{id}": {
			"delete": {
				"operationId": "deleteVoiceAgent",
				"summary": "Delete a voice agent",
				"tags": [
					"Voice agents"
				],
				"description": "Soft delete: the agent stops answering and stops being listed. Its call history is kept, and a phone number it still holds is not released — release it first if you are done paying for it.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:delete",
				"x-required-plan": "module-voice-agent"
			},
			"get": {
				"operationId": "getVoiceAgent",
				"summary": "Get a voice agent",
				"tags": [
					"Voice agents"
				],
				"description": "Returns the voice agent with the AI agent behind it and, if one is provisioned, its phone number.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/VoiceAgent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:view",
				"x-required-plan": "module-voice-agent"
			},
			"patch": {
				"operationId": "updateVoiceAgent",
				"summary": "Update a voice agent",
				"tags": [
					"Voice agents"
				],
				"description": "Applies the `vag_`-prefixed fields present in the body. Changes reach the telephony provider on the next call, not retroactively.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"vag_name": {
										"type": "string",
										"minLength": 1,
										"maxLength": 255
									},
									"vag_active": {
										"type": "boolean"
									},
									"vag_agent": {
										"type": "string",
										"format": "uuid"
									},
									"vag_config": {
										"type": "object"
									},
									"vag_limits": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/VoiceAgent"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:edit",
				"x-required-plan": "module-voice-agent"
			}
		},
		"/voice-agents/{id}/analytics": {
			"get": {
				"operationId": "getVoiceAgentAnalytics",
				"summary": "Get call statistics",
				"tags": [
					"Voice agents"
				],
				"description": "Call count, total duration and credits consumed over the last `days` (30 by default).\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "days",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 1,
							"maximum": 90
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:view",
				"x-required-plan": "module-voice-agent"
			}
		},
		"/voice-agents/{id}/calls": {
			"get": {
				"operationId": "listVoiceCalls",
				"summary": "List calls",
				"tags": [
					"Voice agents"
				],
				"description": "Returns the calls this agent took, newest first, with how each one ended.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "vcall_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "vcall_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/VoiceCall"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:call:view",
				"x-required-plan": "module-voice-agent"
			}
		},
		"/voice-agents/{id}/calls/{call_id}": {
			"get": {
				"operationId": "getVoiceCall",
				"summary": "Get one call",
				"tags": [
					"Voice agents"
				],
				"description": "Returns the call with its transcript, summary and analysis. Details are refreshed from the telephony provider as they are read, so a call that just ended fills in rather than staying empty.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "call_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/VoiceCall"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:call:view",
				"x-required-plan": "module-voice-agent"
			}
		},
		"/voice-agents/{id}/calls/{call_id}/recording": {
			"get": {
				"operationId": "getVoiceCallRecording",
				"summary": "Stream a call recording",
				"tags": [
					"Voice agents"
				],
				"description": "Streams the audio rather than handing back a provider URL. The provider's own links are raw bucket endpoints or expiring presigned URLs and are not reliably playable in a browser, so this resolves a working source per request. Responds with audio, not JSON.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "call_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:call:view",
				"x-required-plan": "module-voice-agent"
			}
		},
		"/voice-agents/{id}/phone-number": {
			"delete": {
				"operationId": "releasePhoneNumber",
				"summary": "Release the phone number",
				"tags": [
					"Voice agents"
				],
				"description": "Gives the number back to the provider and stops the charge. The number is gone — you will not get the same one back, so anything advertising it needs updating first.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:number:edit",
				"x-required-plan": "module-voice-agent"
			},
			"post": {
				"operationId": "provisionPhoneNumber",
				"summary": "Assign a phone number",
				"tags": [
					"Voice agents"
				],
				"description": "Rents a number and points it at this agent. **This starts a recurring third-party charge.**\n\nPick the country with `country` (US by default) and optionally an `areaCode` where the country supports one. An agent may hold one number at a time: asking again while it has one returns 400, so release the current number before requesting a different one.\n\nRequires the `module-voice-agent` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"country": {
										"type": "string",
										"enum": [
											"US",
											"CA",
											"GB",
											"AU"
										]
									},
									"areaCode": {
										"type": "string",
										"pattern": "^\\d{3}$"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "voice-agent:number:edit",
				"x-required-plan": "module-voice-agent"
			}
		},
		"/widget-sessions/{id}": {
			"get": {
				"operationId": "getWidgetSession",
				"summary": "Get a conversation",
				"tags": [
					"Chat widgets"
				],
				"description": "The captured contact details together with the conversation they came from.\n\nRequires the `module-chat-widget` license feature. Without it the request is refused with 403 `license_required` — see [plans and modules](/plans-and-modules).",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "chat-widget:view",
				"x-required-plan": "module-chat-widget"
			}
		},
		"/wildcards": {
			"get": {
				"operationId": "listWildcards",
				"summary": "List wildcards",
				"tags": [
					"Wildcards"
				],
				"description": "Returns the named inputs prompts can ask for, and how each one is collected.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "wildcard_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "wildcard_control_props",
						"in": "query",
						"required": false,
						"schema": {
							"type": "object"
						},
						"style": "deepObject",
						"explode": true
					},
					{
						"name": "wildcard_control_type",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "wildcard_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "wildcard_description",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "wildcard_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "wildcard_managed_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "wildcard_name",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "wildcard_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Wildcard"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"post": {
				"operationId": "createWildcard",
				"summary": "Create a wildcard",
				"tags": [
					"Wildcards"
				],
				"description": "Declares an input a prompt can ask for. The control type decides how it is collected when the prompt runs.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"wildcard_name": {
										"type": "string",
										"minLength": 1
									},
									"wildcard_description": {
										"type": "string"
									},
									"wildcard_control_type": {
										"type": "string",
										"minLength": 1
									},
									"wildcard_control_props": {
										"type": "object"
									}
								},
								"required": [
									"wildcard_name",
									"wildcard_control_type"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Wildcard"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "wildcard:create"
			}
		},
		"/wildcards/{id}": {
			"delete": {
				"operationId": "deleteWildcard",
				"summary": "Delete a wildcard",
				"tags": [
					"Wildcards"
				],
				"description": "Prompts already referencing it keep the reference, so check before removing one in use.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "wildcard:delete"
			},
			"get": {
				"operationId": "getWildcard",
				"summary": "Get a wildcard",
				"tags": [
					"Wildcards"
				],
				"description": "Returns one wildcard with its control type and that control's settings.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Wildcard"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": null
			},
			"patch": {
				"operationId": "updateWildcard",
				"summary": "Update a wildcard",
				"tags": [
					"Wildcards"
				],
				"description": "Applies the `wildcard_`-prefixed fields present in the body. Prompts referencing it by name pick the change up on their next run.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"requestBody": {
					"required": false,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"wildcard_name": {
										"type": "string"
									},
									"wildcard_active": {
										"type": "boolean"
									},
									"wildcard_control_type": {
										"type": "string"
									},
									"wildcard_control_props": {
										"type": "object"
									}
								}
							}
						}
					}
				},
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Wildcard"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "wildcard:edit"
			}
		},
		"/workflow-instances": {
			"get": {
				"operationId": "listWorkflowInstances",
				"summary": "List instances",
				"tags": [
					"Workflow instances"
				],
				"description": "Every run of every workflow in the workspace, newest first. Filter to one workflow with `wi_workflow`, or to a period with `wi_created`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "wi_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "wi_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "wi_initiated_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "wi_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "wi_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "wi_workflow",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/WorkflowInstance"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:instance:view"
			}
		},
		"/workflow-instances/{id}": {
			"get": {
				"operationId": "getWorkflowInstance",
				"summary": "Get an instance",
				"tags": [
					"Workflow instances"
				],
				"description": "Where the run has reached, step by step. Every step the workflow defines is listed — the ones that have not run yet carry a `pending` status — along with any task it is waiting on.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/WorkflowInstance"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:instance:view"
			}
		},
		"/workflow-instances/{id}/refresh": {
			"post": {
				"operationId": "refreshWorkflowInstance",
				"summary": "Refresh an instance",
				"tags": [
					"Workflow instances"
				],
				"description": "Asks the execution engine what this run is doing and stores the answer. Status normally arrives on its own when the run finishes; this is for a run that looks stuck.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:instance:view"
			}
		},
		"/workflows": {
			"get": {
				"operationId": "listWorkflows",
				"summary": "List workflows",
				"tags": [
					"Workflows"
				],
				"description": "Returns the workspace's workflows. The compiled definition is not included — read one workflow to get it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "wf_active",
						"in": "query",
						"required": false,
						"schema": {
							"type": "boolean"
						}
					},
					{
						"name": "wf_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "wf_title",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"type": "object",
									"properties": {
										"data": {
											"type": "array",
											"items": {
												"$ref": "#/components/schemas/Workflow"
											}
										},
										"has_more": {
											"type": "boolean",
											"description": "Whether more rows exist past this page."
										},
										"next_cursor": {
											"type": [
												"string",
												"null"
											],
											"description": "Pass back as `cursor` for the next page. Null on the last page."
										}
									},
									"required": [
										"data",
										"has_more",
										"next_cursor"
									]
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:view"
			},
			"post": {
				"operationId": "createWorkflow",
				"summary": "Create a workflow",
				"tags": [
					"Workflows"
				],
				"description": "Creates a workflow. It is authored here, then compiled and deployed before anything can run it.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"requestBody": {
					"required": true,
					"content": {
						"application/json": {
							"schema": {
								"type": "object",
								"properties": {
									"wf_title": {
										"type": "string"
									},
									"wf_description": {
										"type": "string"
									}
								},
								"required": [
									"wf_title"
								]
							}
						}
					}
				},
				"responses": {
					"201": {
						"description": "Created",
						"headers": {
							"Location": {
								"description": "URL of the created resource.",
								"schema": {
									"type": "string",
									"format": "uri-reference"
								}
							}
						},
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Workflow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:create"
			}
		},
		"/workflows/{id}": {
			"delete": {
				"operationId": "deleteWorkflow",
				"summary": "Delete a workflow",
				"tags": [
					"Workflows"
				],
				"description": "Deactivates the workflow. Instances that already ran keep their record.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:delete"
			},
			"get": {
				"operationId": "getWorkflow",
				"summary": "Get a workflow",
				"tags": [
					"Workflows"
				],
				"description": "Returns the workflow with its steps, its trigger and whether it is deployed.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Workflow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:view"
			},
			"patch": {
				"operationId": "updateWorkflow",
				"summary": "Update a workflow",
				"tags": [
					"Workflows"
				],
				"description": "Applies the `wf_`-prefixed fields present in the body. Editing a deployed workflow does not redeploy it — compile and deploy again for the change to take effect.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success",
						"content": {
							"application/json": {
								"schema": {
									"$ref": "#/components/schemas/Workflow"
								}
							}
						}
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:edit"
			}
		},
		"/workflows/{id}/compile": {
			"post": {
				"operationId": "compileWorkflow",
				"summary": "Compile a workflow",
				"tags": [
					"Workflows"
				],
				"description": "Turns the authored steps into the definition the engine runs, and reports what does not compile. Nothing is deployed — this is the check before deploying.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:edit"
			}
		},
		"/workflows/{id}/deploy": {
			"post": {
				"operationId": "deployWorkflow",
				"summary": "Deploy a workflow",
				"tags": [
					"Workflows"
				],
				"description": "Publishes the compiled definition to the execution engine. Until this runs, edits are invisible to anything executing.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:deploy"
			}
		},
		"/workflows/{id}/instances": {
			"get": {
				"operationId": "listInstancesForWorkflow",
				"summary": "List instances",
				"tags": [
					"Workflows"
				],
				"description": "The same collection as `GET /workflow-instances`, narrowed to this workflow.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "cursor",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"maxLength": 512,
							"pattern": "^[A-Za-z0-9_-]+$"
						}
					},
					{
						"name": "limit",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"exclusiveMaximum": 10001
						}
					},
					{
						"name": "offset",
						"in": "query",
						"required": false,
						"schema": {
							"type": "integer",
							"minimum": 0,
							"exclusiveMaximum": 1000001
						}
					},
					{
						"name": "sort",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"minLength": 1,
							"maxLength": 64,
							"pattern": "^-?[a-z0-9_]+$"
						}
					},
					{
						"name": "wi_created",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "wi_id",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "wi_initiated_by",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "wi_status",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string"
						}
					},
					{
						"name": "wi_updated",
						"in": "query",
						"required": false,
						"schema": {
							"type": "array",
							"items": {}
						}
					},
					{
						"name": "wi_workflow",
						"in": "query",
						"required": false,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:instance:view"
			},
			"post": {
				"operationId": "startWorkflowInstance",
				"summary": "Start an instance",
				"tags": [
					"Workflows"
				],
				"description": "Starts an instance of the deployed definition. Answers 202 with the instance to follow the progress by — `Location` points at it under `/workflow-instances`.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"202": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:execute"
			}
		},
		"/workflows/{id}/steps/{step_id}": {
			"delete": {
				"operationId": "deleteWorkflowStep",
				"summary": "Delete a step",
				"tags": [
					"Workflows"
				],
				"description": "Removes one step. Steps that pointed at it need repointing before the workflow will compile.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "step_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"204": {
						"description": "Success. No content."
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:edit"
			},
			"patch": {
				"operationId": "updateWorkflowStep",
				"summary": "Update a step",
				"tags": [
					"Workflows"
				],
				"description": "Changes one step of a workflow. The workflow has to be compiled again before the change reaches anything running.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					},
					{
						"name": "step_id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:edit"
			}
		},
		"/workflows/functions": {
			"get": {
				"operationId": "listWorkflowFunctions",
				"summary": "List functions",
				"tags": [
					"Workflows"
				],
				"description": "The registry a step is built against. Static — it describes the platform, not the workspace.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:view"
			}
		},
		"/workflows/next-states": {
			"get": {
				"operationId": "listNextStates",
				"summary": "List next states",
				"tags": [
					"Workflows"
				],
				"description": "Where the caller may move something next, given its current state and their permissions.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "state",
						"in": "query",
						"required": true,
						"schema": {
							"type": "string",
							"minLength": 1
						}
					},
					{
						"name": "workflow",
						"in": "query",
						"required": true,
						"schema": {
							"type": "string",
							"minLength": 1
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "workflow:view"
			}
		},
		"/workflows/tasks/{id}/complete": {
			"post": {
				"operationId": "completeWorkflowTask",
				"summary": "Complete a manual step",
				"tags": [
					"Workflows"
				],
				"description": "A workflow can pause for a human decision. This supplies it and lets the instance continue.",
				"parameters": [
					{
						"$ref": "#/components/parameters/TenantId"
					},
					{
						"name": "id",
						"in": "path",
						"required": true,
						"schema": {
							"type": "string",
							"format": "uuid"
						}
					}
				],
				"responses": {
					"200": {
						"description": "Success"
					},
					"400": {
						"$ref": "#/components/responses/400"
					},
					"401": {
						"$ref": "#/components/responses/401"
					},
					"403": {
						"$ref": "#/components/responses/403"
					},
					"404": {
						"$ref": "#/components/responses/404"
					},
					"422": {
						"$ref": "#/components/responses/422"
					},
					"429": {
						"$ref": "#/components/responses/429"
					},
					"500": {
						"$ref": "#/components/responses/500"
					}
				},
				"x-required-permission": "task:edit"
			}
		}
	},
	"components": {
		"securitySchemes": {
			"ApiKeyAuth": {
				"type": "apiKey",
				"in": "header",
				"name": "X-Api-Key",
				"description": "A `gai_`-prefixed API key. Send `X-Tenant-Id` alongside it to name the workspace the key acts in. Keys carry their own permission scope, an optional IP allowlist and an optional expiry."
			},
			"BearerAuth": {
				"type": "http",
				"scheme": "bearer",
				"bearerFormat": "JWT",
				"description": "A user session token. Used by first-party clients; integrations use `X-Api-Key`."
			}
		},
		"parameters": {
			"TenantId": {
				"name": "X-Tenant-Id",
				"in": "header",
				"required": true,
				"description": "The workspace this request acts in. Every row the API returns is isolated to it at the database layer by row-level security.",
				"schema": {
					"type": "string",
					"format": "uuid"
				}
			}
		},
		"schemas": {
			"AccessLogEntry": {
				"description": "One request the workspace made, as the access log recorded it.",
				"type": "object",
				"properties": {
					"log_id": {
						"type": "string",
						"format": "uuid"
					},
					"log_timestamp": {
						"type": "string",
						"format": "date-time"
					},
					"log_user": {
						"type": "string"
					},
					"log_api_key": {
						"type": "string"
					},
					"log_level": {
						"type": "string"
					},
					"log_method": {
						"type": "string"
					},
					"log_url": {
						"type": "string"
					},
					"log_params": {
						"type": "string"
					},
					"log_query": {
						"type": "string"
					},
					"log_body": {
						"type": "string"
					},
					"log_user_name": {
						"type": "string"
					}
				}
			},
			"Agent": {
				"description": "An AI agent: the prompt it answers from, the model it runs on, and the tools and knowledge it may reach for.",
				"type": "object",
				"properties": {
					"agent_id": {
						"type": "string",
						"format": "uuid"
					},
					"agent_name": {
						"type": "string"
					},
					"agent_description": {
						"type": "string"
					},
					"agent_icon": {
						"type": "string"
					},
					"agent_model": {
						"type": "string"
					},
					"agent_temperature": {
						"type": "number"
					},
					"agent_top_p": {
						"type": "string"
					},
					"agent_audience": {
						"type": "string"
					},
					"agent_ds": {
						"type": "string"
					},
					"agent_system_prompt": {
						"type": "string"
					},
					"agent_config": {
						"type": "object"
					},
					"agent_tools": {
						"type": "string"
					},
					"agent_conns": {
						"type": "string"
					},
					"agent_metadata": {
						"type": "object"
					},
					"agent_managed_by": {
						"type": "string"
					},
					"agent_active": {
						"type": "boolean"
					},
					"agent_created": {
						"type": "string",
						"format": "date-time"
					},
					"agent_updated": {
						"type": "string",
						"format": "date-time"
					},
					"agent_tenant_id": {
						"type": "string",
						"format": "uuid"
					},
					"agent_tenant_enabled": {
						"type": "boolean"
					},
					"agent_tenant_ds": {
						"type": "string"
					},
					"agent_tenant_instructions": {
						"type": "string"
					},
					"agent_tenant_metadata": {
						"type": "object"
					}
				}
			},
			"AuditEvent": {
				"description": "One change to one record: who made it, when, and what changed.",
				"type": "object",
				"properties": {
					"history_id": {
						"type": "string",
						"format": "uuid"
					},
					"history_timestamp": {
						"type": "string",
						"format": "date-time"
					},
					"history_user": {
						"type": "string"
					},
					"history_record": {
						"type": "string"
					},
					"history_table": {
						"type": "string"
					},
					"history_op": {
						"type": "string"
					},
					"history_ref": {
						"type": "string"
					},
					"history_changeset": {
						"type": "string"
					},
					"history_user_name": {
						"type": "string"
					}
				}
			},
			"BusinessObject": {
				"description": "A record the workspace keeps about a thing — a product, a venue, a course. Its attributes are defined by the form `obj_form` names, not by fixed columns.",
				"type": "object",
				"properties": {
					"obj_id": {
						"type": "string",
						"format": "uuid"
					},
					"obj_active": {
						"type": "boolean"
					},
					"obj_created": {
						"type": "string",
						"format": "date-time"
					},
					"obj_updated": {
						"type": "string",
						"format": "date-time"
					},
					"obj_created_by": {
						"type": "string"
					},
					"obj_type": {
						"type": "string"
					},
					"obj_key": {
						"type": "string"
					},
					"obj_name": {
						"type": "string"
					},
					"obj_form": {
						"type": "string"
					},
					"obj_content": {
						"type": "object"
					},
					"obj_state_item": {
						"type": "string"
					},
					"obj_repo": {
						"type": "string"
					},
					"obj_metadata": {
						"type": "object"
					}
				}
			},
			"CalendarEvent": {
				"description": "A dated event on the workspace's social calendar, with what the workspace decided about it.",
				"type": "object",
				"properties": {
					"ce_id": {
						"type": "string",
						"format": "uuid"
					},
					"ce_summary": {
						"type": "string"
					},
					"ce_description": {
						"type": "string"
					},
					"ce_location": {
						"type": "string"
					},
					"ce_start": {
						"type": "string",
						"format": "date"
					},
					"ce_end": {
						"type": "string",
						"format": "date"
					},
					"ce_source": {
						"type": "string",
						"enum": [
							"system",
							"feed",
							"custom"
						]
					},
					"ce_hidden": {
						"type": "boolean"
					},
					"ce_template": {
						"type": "string",
						"format": "uuid"
					},
					"ce_template_name": {
						"type": "string"
					}
				}
			},
			"ChatWidget": {
				"description": "An embeddable chat widget: the agent behind it, where it may be embedded, and how it looks.",
				"type": "object",
				"properties": {
					"widget_id": {
						"type": "string",
						"format": "uuid"
					},
					"widget_active": {
						"type": "boolean"
					},
					"widget_created": {
						"type": "string",
						"format": "date-time"
					},
					"widget_updated": {
						"type": "string",
						"format": "date-time"
					},
					"widget_created_by": {
						"type": "string"
					},
					"widget_key": {
						"type": "string"
					},
					"widget_name": {
						"type": "string"
					},
					"widget_agent": {
						"type": "string"
					},
					"widget_origins": {
						"type": "string"
					},
					"widget_welcome": {
						"type": "string"
					},
					"widget_theme": {
						"type": "string"
					},
					"widget_config": {
						"type": "object"
					},
					"widget_limits": {
						"type": "string"
					}
				}
			},
			"ChatWidgetSession": {
				"description": "One visitor's conversation with an embedded chat widget, and whatever it captured about them.",
				"type": "object",
				"properties": {
					"wses_id": {
						"type": "string",
						"format": "uuid"
					},
					"wses_active": {
						"type": "boolean"
					},
					"wses_created": {
						"type": "string",
						"format": "date-time"
					},
					"wses_updated": {
						"type": "string",
						"format": "date-time"
					},
					"wses_widget": {
						"type": "string"
					},
					"wses_thread": {
						"type": "string"
					},
					"wses_user_agent": {
						"type": "string"
					},
					"wses_origin": {
						"type": "string"
					},
					"wses_page_url": {
						"type": "string"
					},
					"wses_country": {
						"type": "string"
					},
					"wses_message_count": {
						"type": "integer"
					},
					"wses_credits": {
						"type": "number"
					},
					"wses_lead": {
						"type": "string"
					},
					"wses_metadata": {
						"type": "object"
					},
					"wses_first_message": {
						"type": [
							"string",
							"null"
						],
						"description": "The visitor's opening message, cut to 300 characters. Null when the visitor never wrote."
					},
					"wses_feedback_down": {
						"type": "integer",
						"description": "How many answers in the conversation the visitor rated not helpful."
					}
				}
			},
			"Comment": {
				"description": "A comment on a record, optionally anchored to one part of it, and its replies.",
				"type": "object",
				"properties": {
					"cmt_id": {
						"type": "string",
						"format": "uuid"
					},
					"cmt_created": {
						"type": "string",
						"format": "date-time"
					},
					"cmt_updated": {
						"type": "string",
						"format": "date-time"
					},
					"cmt_entity_type": {
						"type": "string"
					},
					"cmt_entity": {
						"type": "string",
						"format": "uuid"
					},
					"cmt_field_path": {
						"type": [
							"array",
							"null"
						],
						"items": {
							"oneOf": [
								{
									"type": "string"
								},
								{
									"type": "integer",
									"minimum": 0
								}
							]
						},
						"description": "Field keys and array indices addressing one part of the record, from its root. Null means the record as a whole."
					},
					"cmt_parent": {
						"type": "string"
					},
					"cmt_user": {
						"type": "string"
					},
					"cmt_body": {
						"type": "string"
					},
					"cmt_mentions": {
						"type": "array",
						"items": {
							"type": "object",
							"properties": {
								"id": {
									"type": "string",
									"format": "uuid"
								},
								"name": {
									"type": "string"
								}
							}
						},
						"description": "Users named in the body, as the directory spells them."
					},
					"cmt_resolved_at": {
						"type": "string",
						"format": "date-time"
					},
					"cmt_resolved_by": {
						"type": "string"
					},
					"cmt_author": {
						"type": "object",
						"description": "Who wrote it — enough to attribute and draw an avatar without a second request."
					},
					"cmt_resolved_by_name": {
						"type": [
							"string",
							"null"
						],
						"description": "Display name of whoever resolved the thread. Null while it is open."
					}
				}
			},
			"ContentApprovalFlow": {
				"description": "The review steps a website page moves through before it can be published — what each step is called, and who may move a page into it.",
				"type": "object",
				"properties": {
					"sm_id": {
						"type": "string",
						"format": "uuid"
					},
					"sm_active": {
						"type": "boolean"
					},
					"sm_created": {
						"type": "string",
						"format": "date-time"
					},
					"sm_updated": {
						"type": "string",
						"format": "date-time"
					},
					"sm_name": {
						"type": "string"
					},
					"sm_default": {
						"type": "boolean",
						"description": "The flow governing every site that has not chosen one of its own. At most one flow is the default."
					},
					"sm_transitions": {
						"type": "array",
						"description": "Retired for content flows: pages move by selecting a step directly, gated by the step's own `si_roles.enter`. Old definitions may still carry authored moves here; nothing reads them.",
						"items": {
							"type": "object",
							"properties": {
								"from": {
									"type": [
										"string",
										"null"
									],
									"format": "uuid",
									"description": "Source state id; null is the ungoverned starting point."
								},
								"to": {
									"type": "string",
									"format": "uuid"
								},
								"roles": {
									"type": "array",
									"items": {
										"type": "string",
										"format": "uuid"
									}
								},
								"users": {
									"type": "array",
									"items": {
										"type": "string",
										"format": "uuid"
									},
									"description": "Individuals who may make the move, whatever roles they hold."
								},
								"label": {
									"type": [
										"string",
										"null"
									],
									"description": "What to call the move where a client offers it; the target state's name is used when this is empty."
								},
								"back": {
									"type": "boolean",
									"description": "The move sends work back to be revised — clients render it as a return and ask the mover for a note. When absent, a move to an earlier state counts as a return."
								},
								"notify": {
									"type": "boolean",
									"description": "Tell the people who can act next that the record reached them. Defaults to true."
								},
								"actions": {
									"type": "array",
									"items": {
										"type": "string"
									},
									"description": "Side effects the move triggers, from the governed module's own vocabulary."
								}
							}
						}
					},
					"sm_metadata": {
						"type": "object"
					},
					"states": {
						"type": "array",
						"items": {
							"type": "object",
							"description": "One state of the machine, in display order.",
							"properties": {
								"si_id": {
									"type": "string",
									"format": "uuid"
								},
								"si_label": {
									"type": "string"
								},
								"si_color": {
									"type": [
										"string",
										"null"
									]
								},
								"si_order": {
									"type": "integer"
								},
								"si_initial": {
									"type": "boolean",
									"description": "The state new records enter the machine in."
								},
								"si_final": {
									"type": "boolean",
									"description": "A resting state; final states are visible to every role."
								},
								"si_note": {
									"type": "boolean",
									"description": "Moving a record into this state asks the mover for a note."
								},
								"si_roles": {
									"type": "object",
									"description": "Gates per concern: `view` is roles that may see records here, `enter` is `{roles, users}` who may move a record here — empty or absent leaves the concern open."
								},
								"si_active": {
									"type": "boolean"
								}
							}
						},
						"description": "The flow's steps, in the order pages move through them."
					}
				}
			},
			"ContentSchema": {
				"description": "The field shape a page type is generated into: a component name and the fields it holds.",
				"type": "object",
				"properties": {
					"tpl_id": {
						"type": "string",
						"format": "uuid"
					},
					"tpl_active": {
						"type": "boolean"
					},
					"tpl_created": {
						"type": "string",
						"format": "date-time"
					},
					"tpl_updated": {
						"type": "string",
						"format": "date-time"
					},
					"tpl_group": {
						"type": "string"
					},
					"tpl_name": {
						"type": "string"
					},
					"tpl_component": {
						"type": "string"
					},
					"tpl_nestable": {
						"type": "string"
					},
					"tpl_fields": {
						"type": "string"
					},
					"tpl_metadata": {
						"type": "object"
					}
				}
			},
			"Design": {
				"description": "Editable multi-layer artwork: the canvas its layers sit on, and the preview rendered from them.",
				"type": "object",
				"properties": {
					"de_id": {
						"type": "string",
						"format": "uuid"
					},
					"de_created": {
						"type": "string",
						"format": "date-time"
					},
					"de_updated": {
						"type": "string",
						"format": "date-time"
					},
					"de_user": {
						"type": "string"
					},
					"de_name": {
						"type": "string"
					},
					"de_description": {
						"type": "string"
					},
					"de_type": {
						"type": "string"
					},
					"de_template": {
						"type": "string"
					},
					"de_categories": {
						"type": "string"
					},
					"de_canvas_width": {
						"type": "string"
					},
					"de_canvas_height": {
						"type": "string"
					},
					"de_canvas_unit": {
						"type": "string"
					},
					"de_canvas_dpi": {
						"type": "string"
					},
					"de_canvas_background": {
						"type": "string"
					},
					"de_preview_file": {
						"type": "string"
					},
					"de_export_settings": {
						"type": "object"
					},
					"de_metadata": {
						"type": "object"
					},
					"de_version": {
						"type": "string"
					},
					"preview_file": {
						"type": "object"
					}
				}
			},
			"DesignCategory": {
				"description": "One term in the workspace's design taxonomy. A product-shipped term (`cat_managed_by` set) is shared and cannot be renamed by the workspace.",
				"type": "object",
				"properties": {
					"cat_id": {
						"type": "string",
						"format": "uuid"
					},
					"cat_created": {
						"type": "string",
						"format": "date-time"
					},
					"cat_updated": {
						"type": "string",
						"format": "date-time"
					},
					"cat_managed_by": {
						"type": "string"
					},
					"cat_name": {
						"type": "string"
					},
					"cat_order": {
						"type": "integer"
					},
					"cat_icon": {
						"type": "string"
					},
					"cat_metadata": {
						"type": "object"
					},
					"usage_count": {
						"type": "integer",
						"description": "How many designs are filed under it."
					}
				}
			},
			"DesignLayer": {
				"description": "One element on a design's canvas — text, an image, a shape or a group — with where it sits and how it looks.",
				"type": "object",
				"properties": {
					"dl_id": {
						"type": "string",
						"format": "uuid"
					},
					"dl_created": {
						"type": "string",
						"format": "date-time"
					},
					"dl_updated": {
						"type": "string",
						"format": "date-time"
					},
					"dl_parent": {
						"type": "string"
					},
					"dl_name": {
						"type": "string"
					},
					"dl_type": {
						"type": "string"
					},
					"dl_order": {
						"type": "integer"
					},
					"dl_locked": {
						"type": "boolean"
					},
					"dl_visible": {
						"type": "boolean"
					},
					"dl_opacity": {
						"type": "string"
					},
					"dl_position": {
						"type": "string"
					},
					"dl_size": {
						"type": "integer"
					},
					"dl_rotation": {
						"type": "string"
					},
					"dl_scale": {
						"type": "string"
					},
					"dl_flip": {
						"type": "string"
					},
					"dl_content": {
						"type": "object"
					},
					"dl_style": {
						"type": "string"
					},
					"dl_constraints": {
						"type": "string"
					},
					"dl_metadata": {
						"type": "object"
					}
				}
			},
			"DesignVersion": {
				"description": "One saved snapshot of a design, as the version timeline lists it.",
				"type": "object",
				"properties": {
					"de_id": {
						"type": "string",
						"format": "uuid"
					},
					"de_name": {
						"type": "string"
					},
					"de_created": {
						"type": "string",
						"format": "date-time"
					},
					"de_version": {
						"type": "string"
					},
					"de_metadata": {
						"type": "object"
					},
					"de_canvas_width": {
						"type": "string"
					},
					"de_canvas_height": {
						"type": "string"
					},
					"de_canvas_unit": {
						"type": "string"
					},
					"de_canvas_dpi": {
						"type": "string"
					},
					"de_preview_file": {
						"type": "string"
					},
					"preview_file": {
						"type": "object"
					},
					"layer_count": {
						"type": "integer"
					}
				}
			},
			"Document": {
				"description": "A document in the library: the file itself, the folders it sits in, and the summary written for it when it was uploaded.",
				"type": "object",
				"properties": {
					"file_repo": {
						"$ref": "#/components/schemas/FileRepo"
					},
					"file_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_name": {
						"type": "string"
					},
					"file_type": {
						"type": "string"
					},
					"file_size": {
						"type": "integer"
					},
					"file_created": {
						"type": "string",
						"format": "date-time"
					},
					"file_updated": {
						"type": "string",
						"format": "date-time"
					},
					"file_added_by": {
						"type": "string"
					},
					"file_hash": {
						"type": "string"
					},
					"file_metadata": {
						"type": "object"
					},
					"file_replicas": {
						"type": "string"
					},
					"file_status": {
						"type": "string"
					},
					"file_bucket": {
						"type": "string"
					},
					"file_folder": {
						"type": "string"
					},
					"file_provider_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_summary": {
						"type": "string"
					},
					"file_pref": {
						"type": "object"
					},
					"file_folders": {
						"type": "array",
						"items": {
							"type": "object"
						}
					},
					"file_deprecated": {
						"type": "object"
					},
					"file_relation_count": {
						"type": "integer",
						"description": "How many other documents this one is linked to."
					},
					"markdown_ready": {
						"type": "boolean"
					},
					"similarity": {
						"type": "number"
					}
				}
			},
			"DocumentRelation": {
				"description": "A typed link between two documents, read from one document's side: the type, which way it runs, and the document on the other end.",
				"type": "object",
				"properties": {
					"rel_id": {
						"type": "string",
						"format": "uuid"
					},
					"rel_type": {
						"type": "string"
					},
					"rel_created": {
						"type": "string",
						"format": "date-time"
					},
					"rel_created_by": {
						"type": "string"
					},
					"rel_metadata": {
						"type": "object"
					},
					"direction": {
						"type": "string",
						"enum": [
							"from",
							"to"
						],
						"description": "`from` when this document is the one the type's label describes, `to` when it is the one pointed at."
					},
					"label": {
						"type": "string",
						"description": "The type's label as it reads from this document."
					},
					"relation_type": {
						"type": "object",
						"description": "The relationship type: `rt_id`, `rt_name`, `rt_inverse_name`, `rt_symmetric`."
					},
					"document": {
						"type": "object",
						"description": "The document on the other end: `file_id`, `file_name`, `file_type`, `file_size`, `file_updated`, `file_deprecated`."
					}
				}
			},
			"ErrorCode": {
				"type": "string",
				"description": "The closed vocabulary of error codes. Branch on this rather than on `title` or `detail`.",
				"enum": [
					"bad_request",
					"malformed_json",
					"malformed_body",
					"unsupported_encoding",
					"unsupported_charset",
					"request_aborted",
					"payload_too_large",
					"validation_failed",
					"unsupported_media_type",
					"unauthorized",
					"session_expired",
					"session_limit_reached",
					"forbidden",
					"origin_not_allowed",
					"turnstile_failed",
					"agent_not_public",
					"license_required",
					"payment_required",
					"insufficient_credits",
					"daily_cap_reached",
					"resource_not_found",
					"conflict",
					"resource_gone",
					"geo_restricted",
					"business_rule",
					"design_locked",
					"design_is_template",
					"export_too_large",
					"file_not_recoverable",
					"template_gone",
					"template_missing",
					"fields_missing",
					"text_fields_missing",
					"rate_limited",
					"server_busy",
					"assistant_busy",
					"db_pool_timeout",
					"internal_error",
					"not_implemented",
					"upstream_error",
					"ai_generation_failed",
					"service_unavailable",
					"gateway_timeout",
					"maintenance"
				]
			},
			"ExtensionInstall": {
				"description": "An extension as this workspace has it: whether it is offered, enabled or disabled, and the scopes an administrator granted it.",
				"type": "object",
				"properties": {
					"inst_id": {
						"type": "string",
						"format": "uuid"
					},
					"inst_status": {
						"type": "string"
					},
					"inst_version": {
						"type": "string"
					},
					"inst_scopes": {
						"type": "string"
					},
					"inst_created": {
						"type": "string",
						"format": "date-time"
					},
					"inst_updated": {
						"type": "string",
						"format": "date-time"
					},
					"ext_slug": {
						"type": "string",
						"description": "The extension the install is of."
					},
					"ext_name": {
						"type": "string"
					},
					"ext_description": {
						"type": [
							"string",
							"null"
						]
					}
				}
			},
			"ExtensionStateDocument": {
				"description": "One JSON document an extension keeps in the workspace, under a key it chooses.",
				"type": "object",
				"properties": {
					"exs_id": {
						"type": "string",
						"format": "uuid"
					},
					"exs_key": {
						"type": "string"
					},
					"exs_value": {
						"type": "string"
					},
					"exs_version": {
						"type": "string"
					},
					"exs_created": {
						"type": "string",
						"format": "date-time"
					},
					"exs_updated": {
						"type": "string",
						"format": "date-time"
					},
					"exs_updated_by": {
						"type": "string"
					}
				}
			},
			"Face": {
				"description": "A face detected in a photo, and the person it was matched to if it has been.",
				"type": "object",
				"properties": {
					"fd_id": {
						"type": "string",
						"format": "uuid"
					},
					"fd_file": {
						"type": "string"
					},
					"fd_person": {
						"type": "string"
					},
					"fd_confidence": {
						"type": "number"
					},
					"fd_match_distance": {
						"type": "string"
					},
					"fd_assigned_at": {
						"type": "string",
						"format": "date-time"
					},
					"fd_thumbnail": {
						"type": "string"
					},
					"fd_box": {
						"type": "string"
					},
					"fd_metadata": {
						"type": "object"
					},
					"fd_age": {
						"type": "string"
					},
					"fd_gender": {
						"type": "string"
					},
					"fd_gender_confidence": {
						"type": "number"
					},
					"fd_expression": {
						"type": "string"
					},
					"fd_expression_confidence": {
						"type": "number"
					},
					"fd_sharpness": {
						"type": "string"
					},
					"fd_created": {
						"type": "string",
						"format": "date-time"
					},
					"fd_low_quality": {
						"type": "boolean"
					},
					"fp_id": {
						"type": "string",
						"format": "uuid"
					},
					"fp_name": {
						"type": "string"
					}
				}
			},
			"FaceSuggestion": {
				"description": "An unassigned face the matcher believes belongs to a person already known.",
				"type": "object",
				"properties": {
					"fd_id": {
						"type": "string",
						"format": "uuid"
					},
					"fd_file": {
						"type": "string"
					},
					"fd_thumbnail": {
						"type": "string"
					},
					"fd_confidence": {
						"type": "number"
					},
					"fd_created": {
						"type": "string",
						"format": "date-time"
					},
					"fd_gender": {
						"type": "string"
					},
					"fd_gender_confidence": {
						"type": "number"
					},
					"fd_age": {
						"type": "string"
					},
					"suggest_verify": {
						"type": "object"
					},
					"suggested_distance": {
						"type": "number"
					},
					"fp_id": {
						"type": "string",
						"format": "uuid"
					},
					"fp_name": {
						"type": "string"
					},
					"person_thumbnail": {
						"type": "string"
					},
					"person_gender": {
						"type": "string"
					},
					"person_age": {
						"type": "number"
					},
					"file_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_name": {
						"type": "string"
					},
					"file_type": {
						"type": "string"
					},
					"file_replicas": {
						"type": "object"
					},
					"file_bucket": {
						"type": "string"
					},
					"file_folder": {
						"type": "string"
					},
					"file_provider_id": {
						"type": "string"
					},
					"file_created": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"File": {
				"description": "Anything stored in the workspace: what it is, where its bytes sit, and what is known about it.",
				"type": "object",
				"properties": {
					"file_repo": {
						"$ref": "#/components/schemas/FileRepo"
					},
					"file_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_name": {
						"type": "string"
					},
					"file_type": {
						"type": "string"
					},
					"file_size": {
						"type": "integer"
					},
					"file_created": {
						"type": "string",
						"format": "date-time"
					},
					"file_updated": {
						"type": "string",
						"format": "date-time"
					},
					"file_metadata": {
						"type": "object"
					},
					"file_provider_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_bucket": {
						"type": "string"
					},
					"file_folder": {
						"type": "string"
					},
					"file_hash": {
						"type": "string"
					},
					"file_status": {
						"type": "string"
					},
					"file_added_by": {
						"type": "string"
					},
					"file_replicas": {
						"type": "string"
					},
					"file_summary": {
						"type": "string"
					},
					"file_pref": {
						"type": "object"
					}
				}
			},
			"FileRepo": {
				"type": "object",
				"description": "What the file belongs to. One key naming the owning object, or `library` for a library it sits in rather than an object it belongs to. Keys the platform stamps (presentation jobs, form submissions, workflow runs) are returned but cannot be sent.",
				"properties": {
					"library": {
						"type": "array",
						"items": {
							"type": "string",
							"enum": [
								"media",
								"generated",
								"docs"
							]
						},
						"description": "A library rather than an object: `media` is the shared media library, `docs` is the document library, and `generated` is what the platform produced without filing it anywhere else."
					},
					"ds": {
						"type": "string",
						"format": "uuid",
						"description": "A knowledge base. Its files are the documents it indexes."
					},
					"thread": {
						"type": "string",
						"format": "uuid",
						"description": "A conversation. Its files are the attachments sent to it and the images generated in it."
					},
					"design": {
						"type": "string",
						"format": "uuid",
						"description": "A design. Its files are the assets placed on it and the previews rendered from it."
					},
					"prompt": {
						"type": "string",
						"format": "uuid",
						"description": "A saved prompt. Its files are the references attached to it."
					},
					"ppt": {
						"type": "string",
						"format": "uuid",
						"description": "The presentation job that generated this file.",
						"readOnly": true
					},
					"ppt_template": {
						"type": "string",
						"format": "uuid",
						"description": "The presentation template this file belongs to — the uploaded master deck or a layout background extracted from it.",
						"readOnly": true
					},
					"form": {
						"type": "string",
						"format": "uuid",
						"description": "The form whose submission carried this file.",
						"readOnly": true
					},
					"submission": {
						"type": "string",
						"format": "uuid",
						"description": "The form submission this file was uploaded with.",
						"readOnly": true
					},
					"field": {
						"type": "string",
						"description": "The form field this file was uploaded into.",
						"readOnly": true
					},
					"infographic": {
						"type": "string",
						"format": "uuid",
						"description": "The rendered infographic this file was derived from.",
						"readOnly": true
					},
					"sitemap": {
						"type": "string",
						"format": "uuid",
						"description": "The site whose page content this reference file was written for.",
						"readOnly": true
					},
					"node": {
						"type": "string",
						"format": "uuid",
						"description": "The site page this reference file was written for.",
						"readOnly": true
					},
					"wf_instance": {
						"type": "string",
						"format": "uuid",
						"description": "The workflow run that generated this file.",
						"readOnly": true
					},
					"wf_name": {
						"type": "string",
						"description": "The name of the workflow that generated this file.",
						"readOnly": true
					}
				}
			},
			"FileVersion": {
				"description": "A copy of a file that a later save replaced.",
				"type": "object",
				"properties": {
					"fv_id": {
						"type": "string",
						"format": "uuid"
					},
					"fv_created": {
						"type": "string",
						"format": "date-time"
					},
					"fv_master": {
						"type": "string"
					},
					"fv_reason": {
						"type": "string"
					},
					"fv_size": {
						"type": "integer"
					},
					"fv_type": {
						"type": "string"
					},
					"fv_hash": {
						"type": "string"
					},
					"fv_replicas": {
						"type": "string"
					},
					"fv_metadata": {
						"type": "object"
					},
					"fv_added_by": {
						"type": "string"
					},
					"fv_name": {
						"type": "string"
					},
					"fv_added_by_name": {
						"type": "string"
					}
				}
			},
			"GeoRestriction": {
				"description": "A named set of countries that published assets are blocked from reaching.",
				"type": "object",
				"properties": {
					"geo_id": {
						"type": "string",
						"format": "uuid"
					},
					"geo_name": {
						"type": "string"
					},
					"geo_workspace_wide": {
						"type": "string"
					},
					"geo_source": {
						"type": "string"
					},
					"geo_active": {
						"type": "boolean"
					},
					"geo_created": {
						"type": "string",
						"format": "date-time"
					},
					"geo_updated": {
						"type": "string",
						"format": "date-time"
					},
					"geo_countries": {
						"type": "array",
						"items": {
							"type": "string"
						}
					},
					"geo_usage": {
						"type": "integer"
					}
				}
			},
			"Infographic": {
				"description": "A generated data graphic: the image, and the HTML it was rendered from.",
				"type": "object",
				"properties": {
					"file_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_name": {
						"type": "string"
					},
					"file_type": {
						"type": "string"
					},
					"file_size": {
						"type": "integer"
					},
					"file_created": {
						"type": "string",
						"format": "date-time"
					},
					"file_updated": {
						"type": "string",
						"format": "date-time"
					},
					"file_added_by": {
						"type": "string"
					},
					"file_repo": {
						"type": "string"
					},
					"file_hash": {
						"type": "string"
					},
					"file_metadata": {
						"type": "object"
					},
					"file_replicas": {
						"type": "string"
					},
					"file_provider_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_bucket": {
						"type": "string"
					},
					"file_folder": {
						"type": "string"
					},
					"file_pref": {
						"type": "object"
					},
					"version_count": {
						"type": "integer"
					}
				}
			},
			"Integration": {
				"description": "A connection to a third-party product, and the state of that connection.",
				"type": "object",
				"properties": {
					"conn_id": {
						"type": "string",
						"format": "uuid"
					},
					"conn_active": {
						"type": "boolean"
					},
					"conn_created": {
						"type": "string",
						"format": "date-time"
					},
					"conn_updated": {
						"type": "string",
						"format": "date-time"
					},
					"conn_name": {
						"type": "string"
					},
					"conn_provider": {
						"type": "string"
					},
					"conn_status": {
						"type": "string"
					},
					"conn_config": {
						"type": "object"
					},
					"conn_provider_params": {
						"type": "string"
					},
					"conn_metadata": {
						"type": "object"
					}
				}
			},
			"KnowledgeBase": {
				"description": "A set of records agents retrieve from.",
				"type": "object",
				"properties": {
					"ds_id": {
						"type": "string",
						"format": "uuid"
					},
					"ds_name": {
						"type": "string"
					},
					"ds_description": {
						"type": "string"
					},
					"ds_type": {
						"type": "string"
					},
					"ds_category": {
						"type": "string"
					},
					"ds_subcategory": {
						"type": "string"
					},
					"ds_config": {
						"type": "object"
					},
					"ds_metadata": {
						"type": "object"
					},
					"ds_active": {
						"type": "boolean"
					},
					"ds_created": {
						"type": "string",
						"format": "date-time"
					},
					"ds_updated": {
						"type": "string",
						"format": "date-time"
					},
					"form_id": {
						"type": "string",
						"format": "uuid",
						"description": "The knowledge base's record schema — see `GET /knowledge-base-schemas/{id}`. Null unless the base is form-backed."
					},
					"form_name": {
						"type": "string"
					},
					"form_managed_by": {
						"type": "string",
						"format": "uuid"
					}
				}
			},
			"KnowledgeBaseRecord": {
				"description": "One record in a knowledge base, shaped by the form its base was created with.",
				"type": "object",
				"properties": {
					"data_id": {
						"type": "string",
						"format": "uuid"
					},
					"data_title": {
						"type": "string"
					},
					"data_repo": {
						"type": "string"
					},
					"data_content": {
						"type": "object"
					},
					"data_form": {
						"type": "string"
					},
					"data_metadata": {
						"type": "object"
					},
					"data_active": {
						"type": "boolean"
					},
					"data_created": {
						"type": "string",
						"format": "date-time"
					},
					"data_updated": {
						"type": "string",
						"format": "date-time"
					},
					"data_excerpt": {
						"type": "string"
					}
				}
			},
			"KnowledgeBaseSchema": {
				"description": "The record shape of a form-backed knowledge base. Product-shipped schemas are the standard templates a new base starts from; a fork copies one into the workspace.",
				"type": "object",
				"properties": {
					"form_id": {
						"type": "string",
						"format": "uuid"
					},
					"form_name": {
						"type": "string"
					},
					"form_description": {
						"type": "string"
					},
					"form_config": {
						"type": "object"
					},
					"form_metadata": {
						"type": "object"
					},
					"form_managed_by": {
						"type": "string"
					},
					"form_active": {
						"type": "boolean"
					},
					"form_created": {
						"type": "string",
						"format": "date-time"
					},
					"form_updated": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"MediaAnalysisSchema": {
				"description": "Fields the workspace adds to media analysis — what the vision model extracts from every analyzed image, over and above the built-in analysis.",
				"type": "object",
				"properties": {
					"form_id": {
						"type": "string",
						"format": "uuid"
					},
					"form_name": {
						"type": "string"
					},
					"form_description": {
						"type": "string"
					},
					"form_config": {
						"type": "object"
					},
					"form_metadata": {
						"type": "object"
					},
					"form_managed_by": {
						"type": "string"
					},
					"form_active": {
						"type": "boolean"
					},
					"form_created": {
						"type": "string",
						"format": "date-time"
					},
					"form_updated": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"MediaFile": {
				"description": "A file as the media library lists it: the file itself, the albums it sits in, and — when the request searched by image or by face — how close the match was.",
				"type": "object",
				"properties": {
					"file_repo": {
						"$ref": "#/components/schemas/FileRepo"
					},
					"file_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_name": {
						"type": "string"
					},
					"file_type": {
						"type": "string"
					},
					"file_size": {
						"type": "integer"
					},
					"file_created": {
						"type": "string",
						"format": "date-time"
					},
					"file_updated": {
						"type": "string",
						"format": "date-time"
					},
					"file_added_by": {
						"type": "string"
					},
					"file_hash": {
						"type": "string"
					},
					"file_metadata": {
						"type": "object"
					},
					"file_replicas": {
						"type": "string"
					},
					"file_status": {
						"type": "string"
					},
					"file_bucket": {
						"type": "string"
					},
					"file_folder": {
						"type": "string"
					},
					"file_provider_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_state_item": {
						"type": "string"
					},
					"file_pref": {
						"type": "object"
					},
					"file_albums": {
						"type": "array",
						"items": {
							"type": "object"
						}
					},
					"similarity": {
						"type": "number"
					},
					"face_similarity": {
						"type": "number"
					}
				}
			},
			"MediaStatusFlow": {
				"description": "The statuses media moves through before the whole workspace sees it — who sees an item in each status, and who may move it on.",
				"type": "object",
				"properties": {
					"sm_id": {
						"type": "string",
						"format": "uuid"
					},
					"sm_active": {
						"type": "boolean"
					},
					"sm_created": {
						"type": "string",
						"format": "date-time"
					},
					"sm_updated": {
						"type": "string",
						"format": "date-time"
					},
					"sm_object_criteria": {
						"type": "object"
					},
					"sm_transitions": {
						"type": "array",
						"description": "The moves the machine allows. `roles` and `users` are alternatives — holding one of the roles or being one of the users is enough — and naming neither leaves the move open to anyone who can write the record.",
						"items": {
							"type": "object",
							"properties": {
								"from": {
									"type": [
										"string",
										"null"
									],
									"format": "uuid",
									"description": "Source state id; null is the ungoverned starting point."
								},
								"to": {
									"type": "string",
									"format": "uuid"
								},
								"roles": {
									"type": "array",
									"items": {
										"type": "string",
										"format": "uuid"
									}
								},
								"users": {
									"type": "array",
									"items": {
										"type": "string",
										"format": "uuid"
									},
									"description": "Individuals who may make the move, whatever roles they hold."
								},
								"label": {
									"type": [
										"string",
										"null"
									],
									"description": "What to call the move where a client offers it; the target state's name is used when this is empty."
								},
								"back": {
									"type": "boolean",
									"description": "The move sends work back to be revised — clients render it as a return and ask the mover for a note. When absent, a move to an earlier state counts as a return."
								},
								"notify": {
									"type": "boolean",
									"description": "Tell the people who can act next that the record reached them. Defaults to true."
								},
								"actions": {
									"type": "array",
									"items": {
										"type": "string"
									},
									"description": "Side effects the move triggers, from the governed module's own vocabulary."
								}
							}
						}
					},
					"sm_metadata": {
						"type": "object"
					},
					"states": {
						"type": "array",
						"items": {
							"type": "object",
							"description": "One state of the machine, in display order.",
							"properties": {
								"si_id": {
									"type": "string",
									"format": "uuid"
								},
								"si_label": {
									"type": "string"
								},
								"si_color": {
									"type": [
										"string",
										"null"
									]
								},
								"si_order": {
									"type": "integer"
								},
								"si_initial": {
									"type": "boolean",
									"description": "The state new records enter the machine in."
								},
								"si_final": {
									"type": "boolean",
									"description": "A resting state; final states are visible to every role."
								},
								"si_note": {
									"type": "boolean",
									"description": "Moving a record into this state asks the mover for a note."
								},
								"si_roles": {
									"type": "object",
									"description": "Gates per concern: `view` is roles that may see records here, `enter` is `{roles, users}` who may move a record here — empty or absent leaves the concern open."
								},
								"si_active": {
									"type": "boolean"
								}
							}
						},
						"description": "The flow's statuses, in display order."
					}
				}
			},
			"Memory": {
				"description": "Something the assistant remembers about the calling user.",
				"type": "object",
				"properties": {
					"mem_id": {
						"type": "string",
						"format": "uuid"
					},
					"mem_value": {
						"type": "string"
					},
					"mem_type": {
						"type": "string"
					},
					"mem_source": {
						"type": "string"
					},
					"mem_thread": {
						"type": "string"
					},
					"mem_active": {
						"type": "boolean"
					},
					"mem_metadata": {
						"type": "object"
					},
					"mem_created": {
						"type": "string",
						"format": "date-time"
					},
					"mem_updated": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"Message": {
				"description": "One message in a thread — what was said, by whom, and what it cost.",
				"type": "object",
				"properties": {
					"msg_id": {
						"type": "string",
						"format": "uuid"
					},
					"msg_thread": {
						"type": "string"
					},
					"msg_parent": {
						"type": "string"
					},
					"msg_sequence": {
						"type": "string"
					},
					"msg_role": {
						"type": "string"
					},
					"msg_content": {
						"type": "object"
					},
					"msg_sender": {
						"type": "string"
					},
					"msg_model": {
						"type": "string"
					},
					"msg_metadata": {
						"type": "object"
					},
					"msg_error": {
						"type": "string"
					},
					"msg_feedback": {
						"type": "string"
					},
					"msg_form": {
						"type": "string"
					},
					"msg_version": {
						"type": "string"
					},
					"msg_edited_at": {
						"type": "string",
						"format": "date-time"
					},
					"msg_tool_calls": {
						"type": "string"
					},
					"msg_tool_call_id": {
						"type": "string",
						"format": "uuid"
					},
					"msg_created": {
						"type": "string",
						"format": "date-time"
					},
					"msg_active": {
						"type": "boolean"
					}
				}
			},
			"ObjectLifecycleFlow": {
				"description": "The states the workspace's records move through — who sees a record in each state, and who may move it on.",
				"type": "object",
				"properties": {
					"sm_id": {
						"type": "string",
						"format": "uuid"
					},
					"sm_active": {
						"type": "boolean"
					},
					"sm_created": {
						"type": "string",
						"format": "date-time"
					},
					"sm_updated": {
						"type": "string",
						"format": "date-time"
					},
					"sm_object_criteria": {
						"type": "object"
					},
					"sm_transitions": {
						"type": "array",
						"description": "The moves the machine allows. `roles` and `users` are alternatives — holding one of the roles or being one of the users is enough — and naming neither leaves the move open to anyone who can write the record.",
						"items": {
							"type": "object",
							"properties": {
								"from": {
									"type": [
										"string",
										"null"
									],
									"format": "uuid",
									"description": "Source state id; null is the ungoverned starting point."
								},
								"to": {
									"type": "string",
									"format": "uuid"
								},
								"roles": {
									"type": "array",
									"items": {
										"type": "string",
										"format": "uuid"
									}
								},
								"users": {
									"type": "array",
									"items": {
										"type": "string",
										"format": "uuid"
									},
									"description": "Individuals who may make the move, whatever roles they hold."
								},
								"label": {
									"type": [
										"string",
										"null"
									],
									"description": "What to call the move where a client offers it; the target state's name is used when this is empty."
								},
								"back": {
									"type": "boolean",
									"description": "The move sends work back to be revised — clients render it as a return and ask the mover for a note. When absent, a move to an earlier state counts as a return."
								},
								"notify": {
									"type": "boolean",
									"description": "Tell the people who can act next that the record reached them. Defaults to true."
								},
								"actions": {
									"type": "array",
									"items": {
										"type": "string"
									},
									"description": "Side effects the move triggers, from the governed module's own vocabulary."
								}
							}
						}
					},
					"sm_metadata": {
						"type": "object"
					},
					"states": {
						"type": "array",
						"items": {
							"type": "object",
							"description": "One state of the machine, in display order.",
							"properties": {
								"si_id": {
									"type": "string",
									"format": "uuid"
								},
								"si_label": {
									"type": "string"
								},
								"si_color": {
									"type": [
										"string",
										"null"
									]
								},
								"si_order": {
									"type": "integer"
								},
								"si_initial": {
									"type": "boolean",
									"description": "The state new records enter the machine in."
								},
								"si_final": {
									"type": "boolean",
									"description": "A resting state; final states are visible to every role."
								},
								"si_note": {
									"type": "boolean",
									"description": "Moving a record into this state asks the mover for a note."
								},
								"si_roles": {
									"type": "object",
									"description": "Gates per concern: `view` is roles that may see records here, `enter` is `{roles, users}` who may move a record here — empty or absent leaves the concern open."
								},
								"si_active": {
									"type": "boolean"
								}
							}
						},
						"description": "The flow's states, in display order."
					}
				}
			},
			"ObjectRelation": {
				"description": "A typed, directional link between two things — one object and another, a file and an object, or an object and a classification node.",
				"type": "object",
				"properties": {
					"rel_id": {
						"type": "string",
						"format": "uuid"
					},
					"rel_active": {
						"type": "boolean"
					},
					"rel_created": {
						"type": "string",
						"format": "date-time"
					},
					"rel_created_by": {
						"type": "string"
					},
					"rel_type": {
						"type": "string"
					},
					"rel_from": {
						"type": "string"
					},
					"rel_from_type": {
						"type": "string"
					},
					"rel_to": {
						"type": "string"
					},
					"rel_to_type": {
						"type": "string"
					},
					"rel_metadata": {
						"type": "object"
					}
				}
			},
			"ObjectSchema": {
				"description": "The attributes one kind of object has. Objects naming it in `obj_form` store their values against these fields.",
				"type": "object",
				"properties": {
					"form_id": {
						"type": "string",
						"format": "uuid"
					},
					"form_name": {
						"type": "string"
					},
					"form_description": {
						"type": "string"
					},
					"form_config": {
						"type": "object"
					},
					"form_metadata": {
						"type": "object"
					},
					"form_managed_by": {
						"type": "string"
					},
					"form_active": {
						"type": "boolean"
					},
					"form_created": {
						"type": "string",
						"format": "date-time"
					},
					"form_updated": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"ObjectSource": {
				"description": "A connection to an upstream system records are pulled from, with the mapping that turns its data into objects. Secrets in `src_config` read back masked.",
				"type": "object",
				"properties": {
					"src_id": {
						"type": "string",
						"format": "uuid"
					},
					"src_active": {
						"type": "boolean"
					},
					"src_created": {
						"type": "string",
						"format": "date-time"
					},
					"src_updated": {
						"type": "string",
						"format": "date-time"
					},
					"src_created_by": {
						"type": "string"
					},
					"src_name": {
						"type": "string"
					},
					"src_provider": {
						"type": "string"
					},
					"src_config": {
						"type": "object"
					},
					"src_state": {
						"type": "string"
					},
					"src_metadata": {
						"type": "object"
					}
				}
			},
			"ObjectSyncJob": {
				"description": "One run against a source: a full load, a scheduled delta or a retry of an earlier run's failures, with its counts and the records it could not settle.",
				"type": "object",
				"properties": {
					"osj_id": {
						"type": "string",
						"format": "uuid"
					},
					"osj_source": {
						"type": "string"
					},
					"osj_kind": {
						"type": "string"
					},
					"osj_trigger": {
						"type": "string"
					},
					"osj_status": {
						"type": "string"
					},
					"osj_created": {
						"type": "string",
						"format": "date-time"
					},
					"osj_updated": {
						"type": "string",
						"format": "date-time"
					},
					"osj_started": {
						"type": "string"
					},
					"osj_finished": {
						"type": "string"
					},
					"osj_created_by": {
						"type": "string"
					},
					"osj_options": {
						"type": "string"
					},
					"osj_total": {
						"type": "string"
					},
					"osj_done": {
						"type": "string"
					},
					"osj_failed": {
						"type": "string"
					},
					"osj_result": {
						"type": "string"
					},
					"osj_failures": {
						"type": "string"
					},
					"osj_error": {
						"type": "string"
					},
					"osj_cancel": {
						"type": "string"
					},
					"osj_stalled": {
						"type": "boolean",
						"description": "Running, but its worker has stopped reporting in. Resume it."
					}
				}
			},
			"ObjectTaxonomy": {
				"description": "One node of a classification scheme. Nodes sharing a `tax_type` form one tree; `tax_parent` is the node above, and a node with none is a root.",
				"type": "object",
				"properties": {
					"tax_id": {
						"type": "string",
						"format": "uuid"
					},
					"tax_active": {
						"type": "boolean"
					},
					"tax_created": {
						"type": "string",
						"format": "date-time"
					},
					"tax_updated": {
						"type": "string",
						"format": "date-time"
					},
					"tax_type": {
						"type": "string"
					},
					"tax_name": {
						"type": "string"
					},
					"tax_key": {
						"type": "string"
					},
					"tax_parent": {
						"type": "string"
					},
					"tax_order": {
						"type": "integer"
					},
					"tax_metadata": {
						"type": "object"
					},
					"object_count": {
						"type": "integer",
						"description": "How many objects are filed directly under this node."
					}
				}
			},
			"Page": {
				"description": "One page or folder in a site's tree: what it is for, what has been written into it, and how far along that is.",
				"type": "object",
				"properties": {
					"node_id": {
						"type": "string",
						"format": "uuid"
					},
					"node_created": {
						"type": "string",
						"format": "date-time"
					},
					"node_updated": {
						"type": "string",
						"format": "date-time"
					},
					"node_sitemap": {
						"type": "string"
					},
					"node_parent": {
						"type": "string"
					},
					"node_order": {
						"type": "integer"
					},
					"node_type": {
						"type": "string",
						"enum": [
							"page",
							"folder"
						],
						"description": "A `page` holds content and may have pages under it; a `folder` only holds pages. A page with content cannot become a folder."
					},
					"node_name": {
						"type": "string"
					},
					"node_slug": {
						"type": "string"
					},
					"node_instructions": {
						"type": "string"
					},
					"node_instructions_params": {
						"type": "string"
					},
					"node_children_instructions": {
						"type": "string"
					},
					"node_component": {
						"type": "string"
					},
					"node_content": {
						"type": "object"
					},
					"node_content_summary": {
						"type": "string"
					},
					"node_content_status": {
						"type": "string"
					},
					"node_state_item": {
						"type": "string"
					},
					"node_threads": {
						"type": "string"
					},
					"node_metadata": {
						"type": "object"
					},
					"node_meta": {
						"type": "object",
						"properties": {
							"title": {
								"type": "string",
								"maxLength": 60
							},
							"description": {
								"type": "string",
								"maxLength": 150
							}
						},
						"description": "The page's SEO meta data. Filled by generation from the draft copy and editable; kept out of `node_content` so it is never pushed to a connected CMS."
					},
					"node_review": {
						"type": "object",
						"properties": {
							"review": {
								"type": "object",
								"properties": {
									"text": {
										"type": "string",
										"description": "The review as Markdown: where each fact came from, the search terms covered, the trademarks and acronyms used."
									},
									"generated_at": {
										"type": "string",
										"format": "date-time"
									},
									"agent_id": {
										"type": [
											"string",
											"null"
										],
										"format": "uuid"
									},
									"agent_name": {
										"type": [
											"string",
											"null"
										]
									}
								}
							},
							"editor": {
								"type": "object",
								"properties": {
									"agent_id": {
										"type": [
											"string",
											"null"
										],
										"format": "uuid"
									},
									"agent_name": {
										"type": [
											"string",
											"null"
										]
									},
									"summary": {
										"type": "string",
										"description": "One sentence on the state of the draft."
									},
									"changes": {
										"type": "array",
										"items": {
											"type": "object",
											"properties": {
												"field": {
													"type": "string",
													"description": "The field key, or a path into a block list."
												},
												"what": {
													"type": "string"
												},
												"why": {
													"type": "string",
													"description": "The rule or guideline the change serves."
												},
												"applied": {
													"type": "boolean",
													"description": "Whether the change has been taken into the page."
												}
											}
										}
									},
									"proposed": {
										"type": "object",
										"description": "The corrected copy as the editor proposed it, kept until every change is applied or the page is proofread again."
									},
									"notes": {
										"type": "string",
										"description": "The summary and changes as one Markdown document."
									},
									"changed": {
										"type": "boolean",
										"description": "Whether the editor changed the copy."
									},
									"reviewed_at": {
										"type": "string",
										"format": "date-time"
									},
									"error": {
										"type": "string",
										"description": "Set when the editor pass failed and the draft stood as written."
									}
								}
							}
						},
						"description": "Reviewer material written alongside the copy: the review agent's account of the page when the site names one (`review`), and the editor agent's pass when the site names an editor (`editor`). Kept out of `node_content` so it never reaches a CMS. Left out of the site tree; read it from one page, or `include=review`."
					},
					"node_assignee": {
						"type": [
							"string",
							"null"
						],
						"format": "uuid",
						"description": "Who the page currently waits on. Set freely via `PUT /sites/{id}/pages/{page_id}/assignee` and carried unchanged through workflow moves unless the move says otherwise."
					},
					"node_approved_at": {
						"type": [
							"string",
							"null"
						],
						"format": "date-time",
						"description": "When the page was last signed off. A page carrying this and standing at `draft` has been edited since — the copy that was approved is still kept, and `GET /sites/{id}/pages/{page_id}/approved-content` answers with it."
					},
					"node_approved_by": {
						"type": [
							"string",
							"null"
						],
						"format": "uuid",
						"description": "Who signed it off. Null on pages approved before this was recorded."
					},
					"node_open_comments": {
						"type": "integer",
						"description": "Unresolved comment threads on this page. Only sent when a site is fetched whole."
					}
				}
			},
			"PageCommentThread": {
				"description": "One comment thread on a page, summarized: where it sits, how the conversation stands, and who is in it.",
				"type": "object",
				"properties": {
					"cmt_id": {
						"type": "string",
						"format": "uuid"
					},
					"cmt_created": {
						"type": "string",
						"format": "date-time"
					},
					"cmt_updated": {
						"type": "string",
						"format": "date-time"
					},
					"cmt_entity": {
						"type": "string",
						"format": "uuid",
						"description": "The page the thread is on."
					},
					"cmt_field_path": {
						"type": [
							"array",
							"null"
						],
						"items": {
							"oneOf": [
								{
									"type": "string"
								},
								{
									"type": "integer",
									"minimum": 0
								}
							]
						},
						"description": "Field keys and array indices addressing one part of the page, from its root. Null means the page as a whole."
					},
					"cmt_user": {
						"type": "string"
					},
					"cmt_body": {
						"type": "string"
					},
					"cmt_mentions": {
						"type": "array",
						"items": {
							"type": "object",
							"properties": {
								"id": {
									"type": "string",
									"format": "uuid"
								},
								"name": {
									"type": "string"
								}
							}
						},
						"description": "Users named in the body, as the directory spells them."
					},
					"cmt_resolved_at": {
						"type": "string",
						"format": "date-time"
					},
					"cmt_resolved_by": {
						"type": "string"
					},
					"cmt_author": {
						"type": "object",
						"description": "Who opened the thread — enough to attribute and draw an avatar."
					},
					"cmt_resolved_by_name": {
						"type": [
							"string",
							"null"
						],
						"description": "Display name of whoever resolved the thread. Null while it is open."
					},
					"cmt_participants": {
						"type": "array",
						"description": "Everyone who has spoken in the thread, the opener included."
					},
					"cmt_reply_count": {
						"type": "integer",
						"description": "Replies under the thread, not counting the comment that opened it."
					},
					"cmt_last_activity": {
						"type": "string",
						"description": "When the thread was last added to. A reply is its own row and never touches the first comment, so this is not `cmt_updated`."
					},
					"cmt_page": {
						"type": "object",
						"description": "The page the thread is on: its id, name, slug, content status, and its place in the tree."
					},
					"cmt_anchor_label": {
						"type": [
							"string",
							"null"
						],
						"description": "What the anchored field is called, read against the page as it stands (`Body › Plan with confidence › Text`). Null for a thread about the page as a whole."
					},
					"cmt_anchor_unattached": {
						"type": "boolean",
						"description": "True when the anchor no longer resolves — the block it named was moved or removed, and the conversation outlived its subject."
					}
				}
			},
			"Person": {
				"description": "A named identity that faces are grouped into.",
				"type": "object",
				"properties": {
					"fp_id": {
						"type": "string",
						"format": "uuid"
					},
					"fp_name": {
						"type": "string"
					},
					"fp_cover": {
						"type": "string"
					},
					"fp_metadata": {
						"type": "object"
					},
					"fp_active": {
						"type": "boolean"
					},
					"fp_created": {
						"type": "string",
						"format": "date-time"
					},
					"fp_updated": {
						"type": "string",
						"format": "date-time"
					},
					"cover_thumbnail": {
						"type": "string"
					},
					"face_count": {
						"type": "integer"
					},
					"manual_count": {
						"type": "integer"
					},
					"suggestion_count": {
						"type": "integer"
					},
					"total_count": {
						"type": "integer"
					}
				}
			},
			"PersonPhoto": {
				"description": "A photo a person appears in: the file, plus the detection that matched them.",
				"type": "object",
				"properties": {
					"file_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_name": {
						"type": "string"
					},
					"file_type": {
						"type": "string"
					},
					"file_size": {
						"type": "integer"
					},
					"file_created": {
						"type": "string",
						"format": "date-time"
					},
					"file_updated": {
						"type": "string",
						"format": "date-time"
					},
					"file_replicas": {
						"type": "string"
					},
					"file_metadata": {
						"type": "object"
					},
					"file_status": {
						"type": "string"
					},
					"file_bucket": {
						"type": "string"
					},
					"file_folder": {
						"type": "string"
					},
					"file_provider_id": {
						"type": "string",
						"format": "uuid"
					},
					"fd_id": {
						"type": "string",
						"format": "uuid"
					},
					"fd_thumbnail": {
						"type": "string"
					},
					"fd_confidence": {
						"type": "number"
					},
					"fd_match_distance": {
						"type": "number"
					},
					"fd_box": {
						"type": "object"
					}
				}
			},
			"Presentation": {
				"description": "A generated deck: its plan, its progress, and the file it produced.",
				"type": "object",
				"properties": {
					"ppt_job_id": {
						"type": "string",
						"format": "uuid"
					},
					"ppt_job_created": {
						"type": "string",
						"format": "date-time"
					},
					"ppt_job_updated": {
						"type": "string",
						"format": "date-time"
					},
					"ppt_job_created_by": {
						"type": "string"
					},
					"ppt_job_status": {
						"type": "string"
					},
					"ppt_job_progress": {
						"type": "string"
					},
					"ppt_job_title": {
						"type": "string"
					},
					"ppt_job_params": {
						"type": "string"
					},
					"ppt_job_plan": {
						"type": "string"
					},
					"ppt_job_output_file_id": {
						"type": "string",
						"format": "uuid"
					},
					"ppt_job_error": {
						"type": "string"
					},
					"ppt_job_metadata": {
						"type": "object"
					}
				}
			},
			"PresentationTemplate": {
				"description": "A .pptx file decks are generated into, and the layouts read out of it.",
				"type": "object",
				"properties": {
					"ppt_tpl_id": {
						"type": "string",
						"format": "uuid"
					},
					"ppt_tpl_name": {
						"type": "string"
					},
					"ppt_tpl_description": {
						"type": "string"
					},
					"ppt_tpl_file_id": {
						"type": "string",
						"format": "uuid"
					},
					"ppt_tpl_config": {
						"type": "object"
					},
					"ppt_tpl_metadata": {
						"type": "object"
					},
					"ppt_tpl_active": {
						"type": "boolean"
					},
					"ppt_tpl_created": {
						"type": "string",
						"format": "date-time"
					},
					"ppt_tpl_updated": {
						"type": "string",
						"format": "date-time"
					},
					"file_name": {
						"type": "string"
					},
					"file_replicas": {
						"type": "array",
						"items": {
							"type": "string"
						}
					}
				}
			},
			"Problem": {
				"type": "object",
				"description": "Every non-2xx response, in the RFC 9457 problem+json shape.",
				"required": [
					"type",
					"title",
					"status",
					"code"
				],
				"properties": {
					"type": {
						"type": "string",
						"format": "uri",
						"description": "A URI identifying the error kind.",
						"examples": [
							"https://docs.genuineai.app/errors/validation-failed"
						]
					},
					"title": {
						"type": "string",
						"description": "A short, human-readable summary of the error kind."
					},
					"status": {
						"type": "integer",
						"description": "The HTTP status code, repeated in the body."
					},
					"detail": {
						"type": "string",
						"description": "What went wrong with this specific request."
					},
					"instance": {
						"type": "string",
						"description": "The path that produced the error."
					},
					"code": {
						"$ref": "#/components/schemas/ErrorCode"
					},
					"errorId": {
						"type": "string",
						"description": "Correlates the response with our logs. Quote it in support requests."
					},
					"upstreamCode": {
						"type": "string",
						"description": "A code minted by a provider we call (Stripe, Vapi). Never one of ours."
					},
					"invalidFields": {
						"type": "array",
						"description": "Present on 422. One entry per field that failed validation.",
						"items": {
							"type": "object",
							"properties": {
								"path": {
									"type": "string"
								},
								"location": {
									"type": "string"
								},
								"msg": {
									"type": "string"
								}
							}
						}
					},
					"feature": {
						"type": "string",
						"description": "Present on `license_required`. The module the workspace is missing, as named on the operation and in `features` on `GET /me`.",
						"examples": [
							"module-design"
						]
					}
				}
			},
			"Prompt": {
				"description": "A reusable prompt and the inputs it asks for.",
				"type": "object",
				"properties": {
					"prompt_id": {
						"type": "string",
						"format": "uuid"
					},
					"prompt_name": {
						"type": "string"
					},
					"prompt_description": {
						"type": "string"
					},
					"prompt_description_short": {
						"type": "string"
					},
					"prompt_icon": {
						"type": "string"
					},
					"prompt_agent": {
						"type": "string"
					},
					"prompt_author": {
						"type": "string"
					},
					"prompt_config": {
						"type": "object"
					},
					"prompt_metadata": {
						"type": "object"
					},
					"prompt_supported_models": {
						"type": "string"
					},
					"prompt_text": {
						"type": "string"
					},
					"prompt_wildcards": {
						"type": "string"
					},
					"prompt_managed_by": {
						"type": "string"
					},
					"prompt_active": {
						"type": "boolean"
					},
					"prompt_created": {
						"type": "string",
						"format": "date-time"
					},
					"prompt_updated": {
						"type": "string",
						"format": "date-time"
					},
					"agent_id": {
						"type": "string",
						"format": "uuid"
					},
					"agent_name": {
						"type": "string"
					},
					"agent_icon": {
						"type": "string"
					},
					"prompt_tenant_id": {
						"type": "string",
						"format": "uuid"
					},
					"prompt_tenant_categories": {
						"type": "array",
						"items": {
							"type": "string",
							"format": "uuid"
						},
						"description": "How this workspace filed the prompt — ids from `/prompt-categories`. Per workspace, so filing a product prompt affects nobody else."
					},
					"prompt_tenant_time_savings": {
						"type": "integer"
					},
					"last_used": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"PromptCategory": {
				"description": "One term in the workspace's prompt taxonomy. A product-shipped term (`cat_managed_by` set) is shared and cannot be renamed by the workspace.",
				"type": "object",
				"properties": {
					"cat_id": {
						"type": "string",
						"format": "uuid"
					},
					"cat_created": {
						"type": "string",
						"format": "date-time"
					},
					"cat_updated": {
						"type": "string",
						"format": "date-time"
					},
					"cat_managed_by": {
						"type": "string"
					},
					"cat_name": {
						"type": "string"
					},
					"cat_order": {
						"type": "integer"
					},
					"cat_icon": {
						"type": "string"
					},
					"cat_metadata": {
						"type": "object"
					},
					"usage_count": {
						"type": "integer",
						"description": "How many prompts are filed under it."
					}
				}
			},
			"Publication": {
				"description": "An asset released to a permanent public URL, with the distribution rules that govern it.",
				"type": "object",
				"properties": {
					"pub_id": {
						"type": "string",
						"format": "uuid"
					},
					"pub_file": {
						"type": "string"
					},
					"pub_state": {
						"type": "string"
					},
					"pub_version": {
						"type": "string"
					},
					"pub_hostname": {
						"type": "string"
					},
					"pub_name": {
						"type": "string"
					},
					"pub_size": {
						"type": "integer"
					},
					"pub_content_type": {
						"type": "string"
					},
					"pub_hash": {
						"type": "string"
					},
					"pub_start": {
						"type": "string",
						"format": "date-time"
					},
					"pub_end": {
						"type": "string",
						"format": "date-time"
					},
					"pub_copy_state": {
						"type": "string"
					},
					"pub_error": {
						"type": "string"
					},
					"pub_deny": {
						"type": "array",
						"items": {
							"type": "string"
						}
					},
					"pub_restrictions": {
						"type": "array",
						"items": {
							"type": "string",
							"format": "uuid"
						}
					},
					"pub_created": {
						"type": "string",
						"format": "date-time"
					},
					"pub_updated": {
						"type": "string",
						"format": "date-time"
					},
					"pub_published": {
						"type": "string"
					},
					"pub_revoked": {
						"type": "string"
					},
					"pub_url": {
						"type": "string",
						"format": "uri"
					},
					"pub_stale": {
						"type": "boolean"
					},
					"pub_file_name": {
						"type": "string"
					},
					"pub_published_name": {
						"type": "string"
					}
				}
			},
			"RelationType": {
				"description": "A relationship type items of a library can be linked with: how it reads from each end and whether it has a direction.",
				"type": "object",
				"properties": {
					"rt_id": {
						"type": "string",
						"format": "uuid"
					},
					"rt_active": {
						"type": "boolean"
					},
					"rt_created": {
						"type": "string",
						"format": "date-time"
					},
					"rt_updated": {
						"type": "string",
						"format": "date-time"
					},
					"rt_name": {
						"type": "string"
					},
					"rt_inverse_name": {
						"type": "string"
					},
					"rt_symmetric": {
						"type": "boolean"
					},
					"rt_description": {
						"type": "string"
					}
				}
			},
			"Role": {
				"description": "A named set of permissions users can hold.",
				"type": "object",
				"properties": {
					"role_id": {
						"type": "string",
						"format": "uuid"
					},
					"role_name": {
						"type": "string"
					},
					"role_description": {
						"type": "string"
					},
					"role_icon": {
						"type": "string"
					},
					"role_permissions": {
						"type": "string"
					},
					"role_managed_by": {
						"type": "string"
					},
					"role_active": {
						"type": "boolean"
					},
					"role_created": {
						"type": "string",
						"format": "date-time"
					},
					"role_users_count": {
						"type": "integer"
					}
				}
			},
			"ScheduledJob": {
				"description": "Recurring work the platform runs for the workspace, and when it next runs.",
				"type": "object",
				"properties": {
					"job_id": {
						"type": "string",
						"format": "uuid"
					},
					"job_managed_by": {
						"type": "string"
					},
					"job_active": {
						"type": "boolean"
					},
					"job_created": {
						"type": "string",
						"format": "date-time"
					},
					"job_updated": {
						"type": "string",
						"format": "date-time"
					},
					"job_name": {
						"type": "string"
					},
					"job_title": {
						"type": "string"
					},
					"job_description": {
						"type": "string"
					},
					"job_cron": {
						"type": "string"
					},
					"job_timezone": {
						"type": "string"
					},
					"job_type": {
						"type": "string"
					},
					"job_workflow": {
						"type": "string"
					},
					"job_config": {
						"type": "object"
					},
					"job_scope": {
						"type": "string"
					},
					"job_max_retries": {
						"type": "string"
					},
					"job_timeout_seconds": {
						"type": "string"
					},
					"job_metadata": {
						"type": "object"
					},
					"override_id": {
						"type": "string",
						"format": "uuid"
					},
					"override_enabled": {
						"type": "boolean"
					},
					"override_cron": {
						"type": "string"
					},
					"override_timezone": {
						"type": "string"
					},
					"override_config": {
						"type": "object"
					},
					"last_run_status": {
						"type": "string"
					},
					"last_run_at": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"SecurityEvent": {
				"description": "One authentication event on an account — a sign-in attempt, a credential change, or a second-factor action.",
				"type": "object",
				"properties": {
					"ae_id": {
						"type": "string",
						"format": "uuid"
					},
					"ae_timestamp": {
						"type": "string",
						"format": "date-time"
					},
					"ae_user": {
						"type": "string",
						"format": "uuid"
					},
					"ae_type": {
						"type": "string"
					},
					"ae_success": {
						"type": "boolean"
					},
					"ae_ip": {
						"type": "string"
					},
					"ae_user_agent": {
						"type": "string"
					},
					"ae_city": {
						"type": "string"
					},
					"ae_country": {
						"type": "string"
					},
					"ae_connection": {
						"type": "string"
					},
					"ae_client_name": {
						"type": "string"
					},
					"ae_user_name": {
						"type": "string"
					}
				}
			},
			"ShareLink": {
				"description": "A link that publishes files outward, or accepts them inward, without an account.",
				"type": "object",
				"properties": {
					"share_id": {
						"type": "string",
						"format": "uuid"
					},
					"share_name": {
						"type": "string"
					},
					"share_type": {
						"type": "string"
					},
					"share_active": {
						"type": "boolean"
					},
					"share_created": {
						"type": "string",
						"format": "date-time"
					},
					"share_updated": {
						"type": "string",
						"format": "date-time"
					},
					"share_created_by": {
						"type": "string"
					},
					"share_expires_at": {
						"type": "string",
						"format": "date-time"
					},
					"share_file_ids": {
						"type": "string"
					},
					"share_album_id": {
						"type": "string",
						"format": "uuid"
					},
					"share_options": {
						"type": "string"
					},
					"share_view_count": {
						"type": "integer"
					},
					"share_download_count": {
						"type": "integer"
					},
					"share_max_files": {
						"type": "string"
					},
					"share_max_size": {
						"type": "integer"
					},
					"share_created_by_name": {
						"type": "string"
					},
					"share_file_count": {
						"type": "integer"
					},
					"share_upload_count": {
						"type": "integer"
					},
					"share_last_upload_at": {
						"type": "string",
						"format": "date-time"
					},
					"share_password_set": {
						"type": "boolean"
					},
					"share_pre_tags": {
						"type": "array",
						"items": {
							"type": "string"
						}
					},
					"share_album_ids": {
						"type": "array",
						"items": {
							"type": "string",
							"format": "uuid"
						}
					},
					"share_allow_change_tags": {
						"type": "boolean"
					},
					"share_allow_change_albums": {
						"type": "boolean"
					},
					"kiosk_url": {
						"type": "string",
						"format": "uri"
					}
				}
			},
			"Site": {
				"description": "A website whose page tree and content the platform drafts, fills and keeps in step with a CMS.",
				"type": "object",
				"properties": {
					"sitemap_id": {
						"type": "string",
						"format": "uuid"
					},
					"sitemap_created": {
						"type": "string",
						"format": "date-time"
					},
					"sitemap_updated": {
						"type": "string",
						"format": "date-time"
					},
					"sitemap_user": {
						"type": "string"
					},
					"sitemap_name": {
						"type": "string"
					},
					"sitemap_domain": {
						"type": "string"
					},
					"sitemap_description": {
						"type": "string"
					},
					"sitemap_config": {
						"type": "object"
					},
					"sitemap_metadata": {
						"type": "object"
					},
					"sitemap_tpl_group": {
						"type": "string"
					},
					"sitemap_approval_mode": {
						"type": "string",
						"enum": [
							"default",
							"flow",
							"none"
						],
						"description": "How the site is reviewed: the workspace's default approval flow, the one `sitemap_approval_flow` names, or not at all. Set through `PUT /sites/{id}/approval-flow`."
					},
					"sitemap_approval_flow": {
						"type": [
							"string",
							"null"
						],
						"format": "uuid",
						"description": "The approval flow the site chose; only read when `sitemap_approval_mode` is `flow`."
					},
					"sitemap_last_edited": {
						"type": "string",
						"format": "date-time",
						"description": "The later of `sitemap_updated` and the last change to any of the site's pages. Only sent by the list."
					}
				}
			},
			"SocialPost": {
				"description": "A post sent to a connected social account, or scheduled to be.",
				"type": "object",
				"properties": {
					"sp_id": {
						"type": "string",
						"format": "uuid"
					},
					"sp_file": {
						"type": "string"
					},
					"sp_user": {
						"type": "string"
					},
					"sp_platform": {
						"type": "string"
					},
					"sp_status": {
						"type": "string"
					},
					"sp_caption": {
						"type": "string"
					},
					"sp_media_type": {
						"type": "string"
					},
					"sp_platform_data": {
						"type": "string"
					},
					"sp_metadata": {
						"type": "object"
					},
					"sp_error": {
						"type": "string"
					},
					"sp_scheduled_at": {
						"type": "string",
						"format": "date-time"
					},
					"sp_published_at": {
						"type": "string",
						"format": "date-time"
					},
					"sp_created": {
						"type": "string",
						"format": "date-time"
					},
					"sp_updated": {
						"type": "string",
						"format": "date-time"
					},
					"file_name": {
						"type": "string"
					},
					"file_type": {
						"type": "string"
					},
					"file_replicas": {
						"type": "object"
					}
				}
			},
			"Space": {
				"description": "A shared home for conversations: who may see it, and what it collects.",
				"type": "object",
				"properties": {
					"space_id": {
						"type": "string",
						"format": "uuid"
					},
					"space_active": {
						"type": "boolean"
					},
					"space_created": {
						"type": "string",
						"format": "date-time"
					},
					"space_updated": {
						"type": "string",
						"format": "date-time"
					},
					"space_created_by": {
						"type": "string"
					},
					"space_name": {
						"type": "string"
					},
					"space_description": {
						"type": "string"
					},
					"space_icon": {
						"type": "string"
					},
					"space_color": {
						"type": "string"
					},
					"space_parent": {
						"type": "string"
					},
					"space_default_agent": {
						"type": "string"
					},
					"space_system_prompt": {
						"type": "string"
					},
					"space_knowledge": {
						"type": "string"
					},
					"space_metadata": {
						"type": "object"
					},
					"thread_count": {
						"type": "integer"
					},
					"child_count": {
						"type": "integer"
					}
				}
			},
			"Task": {
				"description": "A work item: what is being asked, who owns it, and where it has got to in review.",
				"type": "object",
				"properties": {
					"task_id": {
						"type": "string",
						"format": "uuid"
					},
					"task_number": {
						"type": "integer"
					},
					"task_name": {
						"type": "string"
					},
					"task_description": {
						"type": "string"
					},
					"task_status": {
						"type": "string"
					},
					"task_priority": {
						"type": "string"
					},
					"task_assigned_to": {
						"type": "string"
					},
					"task_assigned_at": {
						"type": "string",
						"format": "date-time"
					},
					"task_created_by": {
						"type": "string"
					},
					"task_due_at": {
						"type": "string",
						"format": "date-time"
					},
					"task_form": {
						"type": "string"
					},
					"task_data": {
						"type": "string"
					},
					"task_copilot": {
						"type": "string"
					},
					"task_wf": {
						"type": "string"
					},
					"task_wf_instance": {
						"type": "string"
					},
					"task_wf_step": {
						"type": "string"
					},
					"task_callback_url": {
						"type": "string"
					},
					"task_is_template": {
						"type": "string"
					},
					"task_active": {
						"type": "boolean"
					},
					"task_created": {
						"type": "string",
						"format": "date-time"
					},
					"task_updated": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"Thread": {
				"description": "One conversation — the agent answering it, what it is about, and where it is filed.",
				"type": "object",
				"properties": {
					"thread_id": {
						"type": "string",
						"format": "uuid"
					},
					"thread_title": {
						"type": "string"
					},
					"thread_type": {
						"type": "string"
					},
					"thread_status": {
						"type": "string"
					},
					"thread_summary": {
						"type": "string"
					},
					"thread_context": {
						"type": "string"
					},
					"thread_ref": {
						"type": "string"
					},
					"thread_agent": {
						"type": "string"
					},
					"thread_user": {
						"type": "string"
					},
					"thread_space": {
						"type": "string"
					},
					"thread_share_mode": {
						"type": "string"
					},
					"thread_generating_for": {
						"type": "string"
					},
					"thread_metadata": {
						"type": "object"
					},
					"thread_active": {
						"type": "boolean"
					},
					"thread_created": {
						"type": "string",
						"format": "date-time"
					},
					"thread_updated": {
						"type": "string",
						"format": "date-time"
					},
					"agent_id": {
						"type": "string",
						"format": "uuid"
					},
					"agent_name": {
						"type": "string"
					},
					"agent_icon": {
						"type": "string"
					},
					"agent_active": {
						"type": "boolean"
					},
					"prompt_id": {
						"type": "string",
						"format": "uuid"
					},
					"prompt_name": {
						"type": "string"
					}
				}
			},
			"UploadTarget": {
				"description": "A file record awaiting its bytes, with the signed URL to PUT them to — or, when the file was refused, why.",
				"type": "object",
				"properties": {
					"file_id": {
						"type": "string",
						"format": "uuid"
					},
					"file_name": {
						"type": "string"
					},
					"file_type": {
						"type": "string"
					},
					"file_size": {
						"type": "integer"
					},
					"file_created": {
						"type": "string",
						"format": "date-time"
					},
					"file_status": {
						"type": "string"
					},
					"file_repo": {
						"type": "string"
					},
					"file_metadata": {
						"type": "object"
					},
					"file_bucket": {
						"type": "string"
					},
					"file_folder": {
						"type": "string"
					},
					"file_provider_id": {
						"type": "string",
						"format": "uuid"
					},
					"uploadUrl": {
						"type": "string",
						"format": "uri",
						"description": "PUT the bytes here, then finalize the file. Absent on a rejected file."
					},
					"rejection_reason": {
						"type": "string",
						"description": "Why this file was not accepted. Absent on an accepted one."
					}
				}
			},
			"UsageEntry": {
				"description": "One metered action and what it consumed.",
				"type": "object",
				"properties": {
					"usage_id": {
						"type": "string",
						"format": "uuid"
					},
					"usage_timestamp": {
						"type": "string",
						"format": "date-time"
					},
					"usage_user": {
						"type": "string"
					},
					"usage_param": {
						"type": "string"
					},
					"usage_details": {
						"type": "string"
					},
					"usage_consumed_units": {
						"type": "string"
					},
					"usage_consumed_credits": {
						"type": "number"
					},
					"usage_cost_id": {
						"type": "string",
						"format": "uuid"
					}
				}
			},
			"User": {
				"description": "A person in the workspace.",
				"type": "object",
				"properties": {
					"usr_id": {
						"type": "string",
						"format": "uuid"
					},
					"usr_email": {
						"type": "string"
					},
					"usr_created": {
						"type": "string",
						"format": "date-time"
					},
					"usr_active": {
						"type": "boolean"
					},
					"usr_name_first": {
						"type": "string"
					},
					"usr_name_last": {
						"type": "string"
					},
					"usr_lang": {
						"type": "string"
					},
					"usr_theme": {
						"type": "string"
					},
					"usr_name": {
						"type": "string"
					},
					"external_user": {
						"type": "boolean"
					},
					"memb_picture": {
						"type": "string"
					},
					"memb_active": {
						"type": "boolean"
					},
					"memb_roles": {
						"type": "array",
						"items": {
							"type": "string",
							"format": "uuid"
						}
					},
					"memb_permissions": {
						"type": "array",
						"items": {
							"type": "string"
						}
					},
					"memb_settings": {
						"type": "object"
					},
					"memb_last_login": {
						"type": "string",
						"format": "date-time"
					},
					"memb_attr": {
						"type": "object"
					}
				}
			},
			"VoiceAgent": {
				"description": "An AI agent that answers a phone number, and the number it answers on.",
				"type": "object",
				"properties": {
					"vag_id": {
						"type": "string",
						"format": "uuid"
					},
					"vag_active": {
						"type": "boolean"
					},
					"vag_created": {
						"type": "string",
						"format": "date-time"
					},
					"vag_updated": {
						"type": "string",
						"format": "date-time"
					},
					"vag_created_by": {
						"type": "string"
					},
					"vag_key": {
						"type": "string"
					},
					"vag_name": {
						"type": "string"
					},
					"vag_agent": {
						"type": "string"
					},
					"vag_config": {
						"type": "object"
					},
					"vag_limits": {
						"type": "string"
					},
					"vag_provider_ref": {
						"type": "string"
					}
				}
			},
			"VoiceCall": {
				"description": "One call a voice agent took: who called, how it ended, and what was said.",
				"type": "object",
				"properties": {
					"vcall_id": {
						"type": "string",
						"format": "uuid"
					},
					"vcall_created": {
						"type": "string",
						"format": "date-time"
					},
					"vcall_type": {
						"type": "string"
					},
					"vcall_from": {
						"type": "string"
					},
					"vcall_to": {
						"type": "string"
					},
					"vcall_status": {
						"type": "string"
					},
					"vcall_ended_reason": {
						"type": "string"
					},
					"vcall_started": {
						"type": "string"
					},
					"vcall_ended": {
						"type": "string"
					},
					"vcall_duration_seconds": {
						"type": "string"
					},
					"vcall_credits": {
						"type": "number"
					},
					"vcall_summary": {
						"type": "string"
					},
					"vcall_analysis": {
						"type": "string"
					},
					"vcall_has_recording": {
						"type": "boolean"
					},
					"vcall_has_transcript": {
						"type": "boolean"
					}
				}
			},
			"Wildcard": {
				"description": "A named input a prompt asks for, and how it is collected.",
				"type": "object",
				"properties": {
					"wildcard_id": {
						"type": "string",
						"format": "uuid"
					},
					"wildcard_name": {
						"type": "string"
					},
					"wildcard_description": {
						"type": "string"
					},
					"wildcard_control_type": {
						"type": "string"
					},
					"wildcard_control_props": {
						"type": "string"
					},
					"wildcard_metadata": {
						"type": "object"
					},
					"wildcard_managed_by": {
						"type": "string"
					},
					"wildcard_active": {
						"type": "boolean"
					},
					"wildcard_created": {
						"type": "string",
						"format": "date-time"
					},
					"wildcard_updated": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"Workflow": {
				"description": "A multi-step process: what it does, what starts it, and whether it is deployed.",
				"type": "object",
				"properties": {
					"wf_id": {
						"type": "string",
						"format": "uuid"
					},
					"wf_name": {
						"type": "string"
					},
					"wf_title": {
						"type": "string"
					},
					"wf_description": {
						"type": "string"
					},
					"wf_version": {
						"type": "string"
					},
					"wf_trigger": {
						"type": "string"
					},
					"wf_status": {
						"type": "string"
					},
					"wf_provider": {
						"type": "string"
					},
					"wf_managed_by": {
						"type": "string"
					},
					"wf_active": {
						"type": "boolean"
					},
					"wf_created": {
						"type": "string",
						"format": "date-time"
					},
					"wf_updated": {
						"type": "string",
						"format": "date-time"
					}
				}
			},
			"WorkflowInstance": {
				"description": "One run of a workflow: where it got to, and what it is waiting on.",
				"type": "object",
				"properties": {
					"wi_id": {
						"type": "string",
						"format": "uuid"
					},
					"wi_workflow": {
						"type": "string"
					},
					"wi_status": {
						"type": "string"
					},
					"wi_provider": {
						"type": "string"
					},
					"wi_provider_id": {
						"type": "string",
						"format": "uuid"
					},
					"wi_state": {
						"type": "string"
					},
					"wi_error": {
						"type": "string"
					},
					"wi_initiated_by": {
						"type": "string"
					},
					"wi_created": {
						"type": "string",
						"format": "date-time"
					},
					"wi_updated": {
						"type": "string",
						"format": "date-time"
					},
					"wf_name": {
						"type": "string",
						"description": "Name of the workflow this instance runs."
					}
				}
			}
		},
		"responses": {
			"400": {
				"description": "Bad request",
				"content": {
					"application/problem+json": {
						"schema": {
							"$ref": "#/components/schemas/Problem"
						}
					}
				}
			},
			"401": {
				"description": "Authentication required",
				"content": {
					"application/problem+json": {
						"schema": {
							"$ref": "#/components/schemas/Problem"
						}
					}
				}
			},
			"403": {
				"description": "Not permitted",
				"content": {
					"application/problem+json": {
						"schema": {
							"$ref": "#/components/schemas/Problem"
						}
					}
				}
			},
			"404": {
				"description": "Resource not found",
				"content": {
					"application/problem+json": {
						"schema": {
							"$ref": "#/components/schemas/Problem"
						}
					}
				}
			},
			"422": {
				"description": "Validation failed",
				"content": {
					"application/problem+json": {
						"schema": {
							"$ref": "#/components/schemas/Problem"
						}
					}
				}
			},
			"429": {
				"description": "Rate limit exceeded",
				"content": {
					"application/problem+json": {
						"schema": {
							"$ref": "#/components/schemas/Problem"
						}
					}
				}
			},
			"500": {
				"description": "Internal server error",
				"content": {
					"application/problem+json": {
						"schema": {
							"$ref": "#/components/schemas/Problem"
						}
					}
				}
			}
		}
	}
}
