{"openapi":"3.1.0","info":{"title":"Dora REST API","version":"1","description":"Dora is the AI account manager for teams that do client work. An agentic client portal: Dora briefs every request and gets it signed off, and your team or your own AI agents do the work. The REST API does what you can do in the app, as you, with an API key from Dora's Connect your AI page. Docs: https://dora.work/docs/api.","contact":{"name":"Dora support","email":"support@dora.work"}},"externalDocs":{"url":"https://dora.work/docs/api"},"servers":[{"url":"https://dora.work/api/v1"}],"security":[{"apiKey":[]}],"tags":[{"name":"Read","description":"Reads. Work with read-only keys."},{"name":"Write","description":"Changes. Need a read-and-write key."}],"paths":{"/me":{"get":{"operationId":"get_me","summary":"Get my account","description":"Who you are, and what this connection can do.","tags":["Read"],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update_me","summary":"Update my account","description":"Change your display name, profile photo, or whether you get the weekly and monthly summary emails.","tags":["Write"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Display name."},"avatarFileId":{"type":"string","description":"Image file ID from upload_file, under 5 MB. null removes the photo."},"summaryEmails":{"type":"boolean","description":"Summary emails: weekly (and Dora's monthly recap) for client teams, weekly across all clients for company staff."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/notifications":{"get":{"operationId":"list_notifications","summary":"List notifications","description":"Your 50 most recent notifications, newest first.","tags":["Read"],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/notifications/read":{"post":{"operationId":"mark_notifications_read","summary":"Mark notifications read","description":"Mark notifications read. Leave out IDs to mark all read.","tags":["Write"],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"notificationIds":{"type":"array","items":{"type":"string"},"description":"Notification IDs."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces":{"get":{"operationId":"list_workspaces","summary":"List workspaces","description":"List the client workspaces you can access.","tags":["Read"],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_workspace","summary":"Create workspace","description":"Create a client workspace. The website pre-fills the brand profile, and emails get invites. Staff only.","tags":["Write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orgId":{"type":"string","description":"Company (from get_me) the client belongs to. Optional if you admin one."},"name":{"type":"string","description":"Client name."},"website":{"type":"string","description":"Client website, e.g. acme.com."},"services":{"type":"array","items":{"type":"string"},"description":"Service keys from get_config: what the contract covers."},"emails":{"type":"array","items":{"type":"string"},"description":"Client teammates to invite."}},"required":["name","services"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/config":{"get":{"operationId":"get_config","summary":"Get config","description":"A company's setup: services, request types, library categories, client profile fields, and timing (autoApproveDays, followUpDays), with the keys other tools take. Pass a workspace for its company, or a company ID from get_me.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"query","required":false,"description":"Workspace ID.","schema":{"type":"string"}},{"name":"orgId","in":"query","required":false,"description":"Company ID from get_me.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs":{"post":{"operationId":"create_company","summary":"Create company","description":"Create a company portal from its website: Dora reads the site and drafts the setup (request types, library, client profile) and logo. You become its owner. If the site can't be read, it asks for an answer: call again with what clients usually ask for. If you already have a company for that site, returns it with existing: true instead of making another.","tags":["Write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"website":{"type":"string","description":"The company's website, e.g. acme.com."},"answer":{"type":"string","description":"What clients usually ask the company for, when asked."}},"required":["website"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/config/proposals":{"post":{"operationId":"propose_config_change","summary":"Propose config change","description":"Describe a change to your company's setup in plain words and get the full setup after it, plus a summary. Nothing is saved: apply it with update_config. Admins only. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID from get_me.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"instruction":{"type":"string","description":"The change, e.g. \"Add an onboarding request type\"."}},"required":["instruction"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/clients":{"post":{"operationId":"add_clients","summary":"Add clients","description":"Add clients from a list, one per line: websites, emails, or company names. Each company gets a workspace; people at the same company share it and get an invite. Admins only. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID from get_me.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"The list, one client per line."}},"required":["text"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/webhooks":{"get":{"operationId":"list_webhooks","summary":"List webhooks","description":"A company's webhooks and how their last delivery went. Staff only.","tags":["Read"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_webhook","summary":"Create webhook","description":"Add a webhook: Dora POSTs every request event to the URL (request.created, request.status_changed, request.approved, request.changes_requested, comment.created, work.submitted, estimate.proposed, estimate.answered). Returns the signing secret once. Each POST has a Dora-Event header and Dora-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<body>\">. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"An https:// URL."}},"required":["url"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/webhooks/{webhookId}":{"delete":{"operationId":"delete_webhook","summary":"Delete webhook","description":"Remove a webhook. Staff only.","tags":["Write"],"parameters":[{"name":"webhookId","in":"path","required":true,"description":"Webhook ID from list_webhooks.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}":{"patch":{"operationId":"update_company","summary":"Update company","description":"Change your company's name, the name its emails come from, or its logo. Admins only. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID from get_me.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"Company name."},"emailFromName":{"type":"string","description":"Name emails come from. Empty uses the company name."},"logoFileId":{"type":"string","description":"Image file ID from upload_file. null removes the logo."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/config":{"patch":{"operationId":"update_config","summary":"Update config","description":"Replace sections of your company's setup (services, requestTypes, libraryName, libraryCategories, profileFields, assetChecklist, autoApproveDays: days until a request in review approves itself, 0 for never, default 7; followUpDays: days a client can leave a question, review or estimate before Dora nudges them by email, twice at most, 0 for never, default 2). Send whole sections; omitted ones stay. Read the current setup with get_config first. Admins only. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID from get_me.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"config":{"type":"object","description":"Sections to replace, same shape as get_config returns plus each item's key. requestTypes items need key, label, description, placeholder, include, icon, services. To pause a request type (clients can't open new ones), add paused: { until?: \"2026-11-04\" (the day it reopens; omit to pause until resumed), note?: \"shown to clients\" }; remove paused to resume."}},"required":["config"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/people":{"get":{"operationId":"list_company_people","summary":"List company people","description":"Your company's staff with their roles, plus pending invites. Staff only.","tags":["Read"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID from get_me.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"invite_company_member","summary":"Invite company member","description":"Invite someone to your company's team. Roles: owner, admin, member. Admins only; only owners invite owners. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID from get_me.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"Their email."},"role":{"type":"string","enum":["owner","admin","member"],"description":"Role."}},"required":["email","role"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/people/{userId}":{"patch":{"operationId":"set_company_member_role","summary":"Set company member role","description":"Change a teammate's role. Admins only; only owners touch owners. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID from get_me.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"User ID from list_company_people.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"role":{"type":"string","enum":["owner","admin","member"],"description":"Role."}},"required":["role"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"remove_company_member","summary":"Remove company member","description":"Remove someone from your company's team. Admins only. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID from get_me.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"User ID from list_company_people.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/org-invites/{inviteId}":{"delete":{"operationId":"revoke_company_invite","summary":"Revoke company invite","description":"Cancel a pending invite to your company's team. Staff only.","tags":["Write"],"parameters":[{"name":"inviteId","in":"path","required":true,"description":"Invite ID from list_company_people.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}":{"patch":{"operationId":"update_workspace","summary":"Update workspace","description":"Rename a workspace, change its services, or archive it. Staff only.","tags":["Write"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"New name."},"services":{"type":"array","items":{"type":"string"},"description":"Service keys from get_config: what the contract covers."},"archived":{"type":"boolean","description":"Archive or restore."},"allowance":{"type":"object","description":"Monthly allowance: { requestsPerMonth: number, overLimit: \"warn\" | \"queue\" }. Over it, a client's new request is marked over allowance; with queue, it waits for next month. null removes the allowance."},"agreement":{"type":"object","description":"What the client's agreement covers, shown to them as \"What's included\": notes (plain text), startsOn and endsOn (YYYY-MM-DD). Empty strings clear a field."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/people":{"get":{"operationId":"list_people","summary":"List people","description":"Everyone on a workspace: the client team and the company's staff. Use staff IDs for assignees.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/members":{"get":{"operationId":"list_members","summary":"List members","description":"The client team on a workspace, plus pending invites.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"invite_member","summary":"Invite member","description":"Invite someone to a workspace by email.","tags":["Write"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"Their email."}},"required":["email"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/members/{userId}":{"delete":{"operationId":"remove_member","summary":"Remove member","description":"Remove someone from a workspace. Staff only.","tags":["Write"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}},{"name":"userId","in":"path","required":true,"description":"User ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/invites/{inviteId}":{"delete":{"operationId":"revoke_invite","summary":"Revoke invite","description":"Cancel a pending invite. Staff only.","tags":["Write"],"parameters":[{"name":"inviteId","in":"path","required":true,"description":"Invite ID from list_members.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/requests":{"get":{"operationId":"list_requests","summary":"List requests","description":"List requests in a workspace, newest activity first. Optionally filter by status.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Only this status.","schema":{"type":"string","enum":["backlog","todo","in_progress","needs_input","in_review","done","cancelled"]}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_request","summary":"Create request","description":"Open a new request in a workspace.","tags":["Write"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"Short title."},"body":{"type":"string","description":"Details, plain text."},"type":{"type":"string","description":"Request type key from get_config."},"neededBy":{"type":"string","description":"When the client needs it. Date like 2026-10-30. null clears it."},"files":{"type":"array","description":"Files from upload_file, as { fileId, name }.","items":{"type":"object","properties":{"fileId":{"type":"string"},"name":{"type":"string"}},"required":["fileId","name"]}}},"required":["title"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/suggested-assignee":{"get":{"operationId":"suggest_assignee","summary":"Suggest assignee","description":"Who should take a request, and why: weighs the client's account team, who's done this kind of work before, what each person says they do, who's away, and how much each has open. When the work also needs a skill the first person doesn't have, \"also\" names a second person. Use it to assign or to explain a choice. Staff only.","tags":["Read"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/team-load":{"get":{"operationId":"team_load","summary":"Get team workload","description":"Everyone on a company's team with how many open requests they have, what they do, and when they're back if away. Use it to spot who's overloaded and to rebalance. Staff only.","tags":["Read"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/auto-assign":{"post":{"operationId":"set_auto_assign","summary":"Set auto assign","description":"Turn Dora's auto-assign on or off for a company. When it's on and a client's request has no account lead (or the lead is away), she assigns it to whoever fits best and leaves a note saying why. Admins only. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"on":{"type":"boolean","description":"On or off."}},"required":["on"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/me/work":{"get":{"operationId":"get_my_work","summary":"Get my work","description":"Your work profile at each company you're on the team of: what you focus on (Dora uses it to suggest who should take a request) and the day you're away until, if any. Staff only.","tags":["Read"],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update_my_work","summary":"Update my work","description":"Change your work profile at a company: what you focus on (a short phrase, like 'web builds and SEO'), or the day you're away until (Dora won't assign you work until then; null means you're back). Staff only.","tags":["Write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"orgId":{"type":"string","description":"Company ID."},"focus":{"type":"string","description":"What you focus on. Empty clears it."},"awayUntil":{"type":"string","description":"Away until this day. null means you're back. Date like 2026-10-30. null clears it."}},"required":["orgId"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/files":{"post":{"operationId":"attach_request_files","summary":"Attach request files","description":"Attach files to a request's details (not a comment). Upload them with upload_file first.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","description":"Files from upload_file, as { fileId, name }.","items":{"type":"object","properties":{"fileId":{"type":"string"},"name":{"type":"string"}},"required":["fileId","name"]}}},"required":["files"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/request-files/{attachmentId}":{"delete":{"operationId":"remove_request_file","summary":"Remove request file","description":"Remove a file from a request's details. The file IDs are in get_request's attachments.","tags":["Write"],"parameters":[{"name":"attachmentId","in":"path","required":true,"description":"File ID from get_request.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/briefing":{"get":{"operationId":"get_briefing","summary":"Get my briefing","description":"Where things stand for the person you're helping, in Dora's words. For the team: their next requests in the order to do them, what's past due, what's waiting on clients, and what's up for grabs. For a client: what needs them. Call it first when someone starts a conversation about their work.","tags":["Read"],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/inbox":{"get":{"operationId":"inbox","summary":"Get team inbox","description":"Requests across every client of your company, for staff. Staff only.","tags":["Read"],"parameters":[{"name":"view","in":"query","required":true,"description":"Which requests to show.","schema":{"type":"string","enum":["mine","unassigned","waiting","open"]}},{"name":"clients","in":"query","required":false,"description":"mine: clients whose account team you're on, plus anything assigned to you. Default all. Doesn't apply to view mine.","schema":{"type":"string","enum":["mine","all"]}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}":{"get":{"operationId":"get_request","summary":"Get request","description":"One request with its full timeline of comments and changes, files, and Brand Library references.","tags":["Read"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update_request","summary":"Update request","description":"Edit a request. Anyone who can see it can change title, body, type, and neededBy. Status, who's assigned, priority, due date, and waitingOnClient are staff only. A request can have several assignees.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"New title."},"body":{"type":"string","description":"New body, plain text."},"type":{"type":"string","description":"Request type key from get_config."},"neededBy":{"type":"string","description":"When the client needs it. Date like 2026-10-30. null clears it."},"status":{"type":"string","enum":["backlog","todo","in_progress","needs_input","in_review","done","cancelled"],"description":"Workflow status."},"assigneeIds":{"type":"array","description":"Everyone who should be on it: staff user IDs from list_people. Replaces who's on it; [] unassigns everyone. To add someone, send the current assignees plus them.","items":{"type":"string"}},"assigneeId":{"type":"string","description":"One staff user ID, the same as assigneeIds with just them. null unassigns everyone."},"priority":{"type":"string","enum":["none","low","medium","high","urgent"],"description":"Priority."},"dueDate":{"type":"string","description":"The team's due date. Date like 2026-10-30. null clears it."},"waitingOnClient":{"type":"boolean","description":"false: the team isn't waiting on the client for this request (it stops showing as waiting until someone asks them something new). true undoes that."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete_request","summary":"Delete request","description":"Delete a request and its comments and files. Staff can delete any request; clients only their own, before it's picked up.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/context":{"get":{"operationId":"get_request_context","summary":"Get request context","description":"Everything needed to do a request, in one call: the request and its thread, files, the kind of request and what it needs, the client's rules and decisions (follow them), the client's agreement and brand profile, related Brand Library items, and similar requests already delivered with what was handed over. Start here before working on a request.","tags":["Read"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/work":{"post":{"operationId":"submit_work","summary":"Submit work","description":"Hand over finished work for the client to review: a note of what changed, a preview link, and files. It's posted on the request as the work, the request moves to In review, and the client team is emailed to approve it or ask for changes. Staff only.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"note":{"type":"string","description":"What was done and anything the client should check, plain text."},"previewUrl":{"type":"string","description":"Where to see the work, an https:// link."},"files":{"type":"array","description":"Files from upload_file, as { fileId, name }.","items":{"type":"object","properties":{"fileId":{"type":"string"},"name":{"type":"string"}},"required":["fileId","name"]}}},"required":["note"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/comments/{commentId}/reactions":{"post":{"operationId":"react_to_comment","summary":"React to comment","description":"React to a comment with an emoji, or take your reaction back if it's already there (it toggles). Reactions show under the comment with who left them; get_request's timeline lists them. Use it to acknowledge something without a reply. Nobody is notified.","tags":["Write"],"parameters":[{"name":"commentId","in":"path","required":true,"description":"Comment ID, from get_request's timeline.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"emoji":{"type":"string","enum":["👍","❤️","🎉","😄","👀","🙏"],"description":"The reaction."}},"required":["emoji"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/brief":{"post":{"operationId":"fix_brief","summary":"Fix brief","description":"Correct Dora's brief on a request (get_request's \"brief\") when it got something wrong or missed something. Give the correction in one plain sentence, like \"The deadline is Friday, not Thursday\" or \"It's the pricing page, not the homepage\". Dora rewrites the brief with it in a few seconds, replacing the current one (the earlier version isn't kept; the request, its details and comments aren't changed), and later rewrites keep the correction. The brief is visible to the client.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"correction":{"type":"string","description":"What the brief should say instead."}},"required":["correction"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/brief/rewrite":{"post":{"operationId":"rewrite_brief","summary":"Rewrite brief","description":"Have Dora rewrite a request's brief now, from the request and its client-visible thread: after editing the details, or to brief a request the team opened (requests from clients get one on their own). It replaces the current brief; the earlier version isn't kept, and the request, its details and comments aren't changed. Team only. Staff only.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/follow-ups":{"post":{"operationId":"set_follow_ups","summary":"Set follow ups","description":"Pause or resume Dora's follow-ups on one request. While a request waits on the client (a question, a review, an estimate), Dora nudges them by email after the company's followUpDays, twice at most, then tells the team. get_request's \"followUp\" says when she nudges next. Team only. Staff only.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"paused":{"type":"boolean","description":"true to pause her nudges on this request, false to resume."}},"required":["paused"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/answer":{"post":{"operationId":"answer_request","summary":"Answer request","description":"For a request that's Needs input (Waiting on the client): say the client has answered, which hands it back to the team (to the status it had before, usually In progress). Use it when the client has given what was asked, or says there's nothing more they can add.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/sign-off":{"post":{"operationId":"sign_off_request","summary":"Sign off request","description":"Answer a request that's In review: approve it (it becomes Done) or ask for changes (back to In progress, with a comment saying what). Clients normally do this; staff can record an approval they got elsewhere.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"decision":{"type":"string","enum":["approve","changes"],"description":"Approve, or ask for changes."},"comment":{"type":"string","description":"What should change. Required when asking for changes."}},"required":["decision"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/change-order":{"post":{"operationId":"propose_change_order","summary":"Propose change order","description":"Mark a request as outside the client's agreement and send them an estimate to approve or decline. It doesn't count toward their monthly allowance. Pass estimate null to withdraw an unanswered estimate. Staff only.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"estimate":{"type":"string","description":"The price or effort, as the client should read it, like \"$450\" or \"6 hours\". null withdraws it."},"note":{"type":"string","description":"Why it's extra, or what the estimate covers."}},"required":["estimate"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/change-order/answer":{"post":{"operationId":"answer_change_order","summary":"Answer change order","description":"Approve or decline the estimate on a request that's outside the agreement. Clients do this.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"approve":{"type":"boolean","description":"True to approve, false to decline."}},"required":["approve"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/recurring":{"get":{"operationId":"list_recurring_requests","summary":"List recurring requests","description":"A client's recurring requests: what each opens, its schedule, the next day it opens, and whether it's paused. Staff only.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"create_recurring_request","summary":"Create recurring request","description":"Set up a request that opens itself on a schedule, like a monthly report. Give fromRequestId to copy an existing request (it counts as the first one), or a title and body. The repeat is { unit: \"week\" | \"month\", every: 1-12, day } where day is 1 (Monday) to 7 (Sunday) for weeks, or 1-31 for months (31 means the last day). Team only. Staff only.","tags":["Write"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fromRequestId":{"type":"string","description":"Copy this request's title, text, type, assignees, and priority."},"title":{"type":"string","description":"Title for each request it opens."},"body":{"type":"string","description":"Text for each request, in Markdown."},"type":{"type":"string","description":"Request type key from get_config."},"assigneeIds":{"type":"array","description":"Who each request is assigned to (team user IDs).","items":{"type":"string"}},"assigneeId":{"type":"string","description":"One assignee, the same as assigneeIds with just them."},"priority":{"type":"string","enum":["none","low","medium","high","urgent"],"description":"Priority for each request."},"repeat":{"type":"object","description":"{ unit: \"week\" | \"month\", every: number, day: number }, for example { unit: \"month\", every: 1, day: 1 } for the 1st of every month."},"startOn":{"type":"string","description":"The first day it can open; it opens on the first scheduled day from then. Date like 2026-10-30. null clears it."},"dueAfterDays":{"type":"number","description":"Each request is due this many days after it opens."}},"required":["repeat"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/recurring/{recurringId}":{"patch":{"operationId":"update_recurring_request","summary":"Update recurring request","description":"Change a recurring request: what it opens (fields, or fromRequestId to copy a request), its schedule, or pause it (active false) and resume it (active true). Team only. Staff only.","tags":["Write"],"parameters":[{"name":"recurringId","in":"path","required":true,"description":"Recurring request ID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"fromRequestId":{"type":"string","description":"Future ones copy this request's title, text, type, assignees, and priority."},"title":{"type":"string","description":"New title."},"body":{"type":"string","description":"New text, in Markdown."},"type":{"type":"string","description":"Request type key. null clears it."},"assigneeIds":{"type":"array","description":"Who each request is assigned to. [] clears it.","items":{"type":"string"}},"assigneeId":{"type":"string","description":"One assignee, the same as assigneeIds with just them. null clears it."},"priority":{"type":"string","enum":["none","low","medium","high","urgent"],"description":"Priority."},"repeat":{"type":"object","description":"New schedule: { unit: \"week\" | \"month\", every, day }."},"startOn":{"type":"string","description":"Restart the schedule from this day. Date like 2026-10-30. null clears it."},"dueAfterDays":{"type":"number","description":"Days after opening that each is due. null clears it."},"active":{"type":"boolean","description":"false pauses, true resumes."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete_recurring_request","summary":"Delete recurring request","description":"Stop a recurring request for good. Requests it already opened stay. Team only. Staff only.","tags":["Write"],"parameters":[{"name":"recurringId","in":"path","required":true,"description":"Recurring request ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/recurring/{recurringId}/run":{"post":{"operationId":"run_recurring_request","summary":"Run recurring request","description":"Open one of a recurring request now, outside its schedule (the schedule carries on). Team only. Staff only.","tags":["Write"],"parameters":[{"name":"recurringId","in":"path","required":true,"description":"Recurring request ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/requests/{requestId}/comments":{"post":{"operationId":"add_comment","summary":"Add comment","description":"Comment on a request, or reply in a comment's thread with parentId (threads are one level: a reply to a reply joins the same thread, and is as private as it). Internal comments are only visible to staff.","tags":["Write"],"parameters":[{"name":"requestId","in":"path","required":true,"description":"Request ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","description":"Comment, plain text."},"internal":{"type":"boolean","description":"Staff only."},"parentId":{"type":"string","description":"Comment ID to reply to, from get_request."},"files":{"type":"array","description":"Files from upload_file, as { fileId, name }.","items":{"type":"object","properties":{"fileId":{"type":"string"},"name":{"type":"string"}},"required":["fileId","name"]}}},"required":["body"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/comments/{commentId}":{"patch":{"operationId":"edit_comment","summary":"Edit comment","description":"Edit one of your comments.","tags":["Write"],"parameters":[{"name":"commentId","in":"path","required":true,"description":"Comment ID from get_request.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"body":{"type":"string","description":"New text."}},"required":["body"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete_comment","summary":"Delete comment","description":"Delete one of your comments.","tags":["Write"],"parameters":[{"name":"commentId","in":"path","required":true,"description":"Comment ID from get_request.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/files":{"post":{"operationId":"upload_file","summary":"Upload file","description":"Upload a file (up to 10 MB), then attach it with create_request, add_comment, or add_library_files.","tags":["Write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"File name, e.g. logo.svg."},"contentType":{"type":"string","description":"MIME type, e.g. image/svg+xml."},"data":{"type":"string","description":"File contents, base64-encoded."}},"required":["name","contentType","data"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/library":{"get":{"operationId":"search_library","summary":"Search library","description":"List or search a client's library: files, links, notes, docs, and work delivered on finished requests. Searching includes each item's text. Old versions are left out unless includeOld is true. Each item has a link to cite it with.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"description":"Search text.","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Only this category key, from get_config.","schema":{"type":"string"}},{"name":"includeOld","in":"query","required":false,"description":"Include versions a newer one has replaced.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"add_to_library","summary":"Add to library","description":"Add a link or a note to a client's library. It's read and sorted automatically.","tags":["Write"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"A link to add."},"text":{"type":"string","description":"Or a note to add."},"title":{"type":"string","description":"Title for a note."},"teamOnly":{"type":"boolean","description":"Only the company's team sees it. Team only."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/library":{"get":{"operationId":"search_company_library","summary":"Search company library","description":"List or search the company library: the team's own docs, templates, and files for every client. Team only. Staff only.","tags":["Read"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID.","schema":{"type":"string"}},{"name":"query","in":"query","required":false,"description":"Search text.","schema":{"type":"string"}},{"name":"category","in":"query","required":false,"description":"Only this category key, from get_config.","schema":{"type":"string"}},{"name":"includeOld","in":"query","required":false,"description":"Include versions a newer one has replaced.","schema":{"type":"boolean"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"add_to_company_library","summary":"Add to company library","description":"Add a link or a note to the company library. Team only. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"A link to add."},"text":{"type":"string","description":"Or a note to add."},"title":{"type":"string","description":"Title for a note."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/library/{itemId}":{"get":{"operationId":"get_library_item","summary":"Get library item","description":"One library item with its text (a doc's full text, a file's extracted text), its link, and its versions.","tags":["Read"],"parameters":[{"name":"itemId","in":"path","required":true,"description":"Library item ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update_library_item","summary":"Update library item","description":"Rename, recategorize, or retag a library item, change who sees it, or mark it as the newer version of another item (replaces; null undoes it and turns down Dora's suggestion).","tags":["Write"],"parameters":[{"name":"itemId","in":"path","required":true,"description":"Library item ID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"New title."},"category":{"type":"string","description":"Category key from get_config."},"tags":{"type":"array","items":{"type":"string"},"description":"Tags."},"teamOnly":{"type":"boolean","description":"Only the company's team sees it. Team only."},"replaces":{"type":"string","description":"Library item ID this is the newer version of. null undoes it."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete_library_item","summary":"Delete library item","description":"Remove an item from a library.","tags":["Write"],"parameters":[{"name":"itemId","in":"path","required":true,"description":"Library item ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/library/files":{"post":{"operationId":"add_library_files","summary":"Add library files","description":"Add uploaded files to a client's library. With replaces (one file), it's a new version of that item and the old one is kept as an earlier version.","tags":["Write"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","description":"Files from upload_file, as { fileId, name }.","items":{"type":"object","properties":{"fileId":{"type":"string"},"name":{"type":"string"}},"required":["fileId","name"]}},"replaces":{"type":"string","description":"Library item ID this file is a new version of."},"teamOnly":{"type":"boolean","description":"Only the company's team sees them. Team only."}},"required":["files"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orgs/{orgId}/library/files":{"post":{"operationId":"add_company_library_files","summary":"Add company library files","description":"Add uploaded files to the company library. Team only. Staff only.","tags":["Write"],"parameters":[{"name":"orgId","in":"path","required":true,"description":"Company ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"files":{"type":"array","description":"Files from upload_file, as { fileId, name }.","items":{"type":"object","properties":{"fileId":{"type":"string"},"name":{"type":"string"}},"required":["fileId","name"]}}},"required":["files"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/library-docs":{"post":{"operationId":"create_library_doc","summary":"Create library doc","description":"Write a doc in a client's library (workspaceId) or the company library (orgId): a brand voice, kickoff notes, how you work together. The body is Markdown (headings, lists, bold, links); don't repeat the title as a heading.","tags":["Write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"workspaceId":{"type":"string","description":"Workspace ID, for a client's library."},"orgId":{"type":"string","description":"Or the company ID, for the company library."},"title":{"type":"string","description":"Doc title."},"body":{"type":"string","description":"The doc, in Markdown."},"teamOnly":{"type":"boolean","description":"In a client's library, only the company's team sees it. Team only."}},"required":["title"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/library-docs/{itemId}":{"patch":{"operationId":"update_library_doc","summary":"Update library doc","description":"Rename a library doc or replace its text (Markdown). Read it first with get_library_item and send the whole doc back. Don't repeat the title as a heading.","tags":["Write"],"parameters":[{"name":"itemId","in":"path","required":true,"description":"Library item ID of the doc.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"title":{"type":"string","description":"New title."},"body":{"type":"string","description":"The whole doc, in Markdown."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/library/{itemId}/retry":{"post":{"operationId":"retry_library_item","summary":"Reprocess library item","description":"Have Dora read a library item again: after it failed to process, or after the file or linked page changed. For a link, Dora fetches the page again. Replaces what Dora wrote about it, and hands its category back to Dora even if someone set it by hand.","tags":["Write"],"parameters":[{"name":"itemId","in":"path","required":true,"description":"Library item ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/library-rules":{"get":{"operationId":"list_library_rules","summary":"List library rules","description":"A client's rules (standing preferences, like \"Never use orange\") and decisions (choices made on past requests), or the company's own rules (orgId). Follow them in any work for the client. The team also gets Dora's suggestions waiting for review.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"query","required":false,"description":"Workspace ID, for a client's rules.","schema":{"type":"string"}},{"name":"orgId","in":"query","required":false,"description":"Or the company ID, for the company's own rules.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"operationId":"add_library_rule","summary":"Add library rule","description":"Keep a rule or decision for a client (workspaceId) or the company (orgId). One short sentence. Link the request it came from if there is one.","tags":["Write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"workspaceId":{"type":"string","description":"Workspace ID, for a client's rule."},"orgId":{"type":"string","description":"Or the company ID, for a company rule."},"kind":{"type":"string","enum":["rule","decision"],"description":"Rule (default) or decision."},"text":{"type":"string","description":"The rule, in one short sentence."},"teamOnly":{"type":"boolean","description":"Only the company's team sees it. Team only."},"requestId":{"type":"string","description":"The request it came from."}},"required":["text"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/library-rules/{ruleId}":{"patch":{"operationId":"update_library_rule","summary":"Update library rule","description":"Reword a rule, switch rule and decision, or change who sees it.","tags":["Write"],"parameters":[{"name":"ruleId","in":"path","required":true,"description":"Rule ID.","schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","description":"New wording."},"kind":{"type":"string","enum":["rule","decision"],"description":"Rule or decision."},"teamOnly":{"type":"boolean","description":"Only the company's team sees it. Team only."}}}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"operationId":"delete_library_rule","summary":"Delete library rule","description":"Delete a rule or decision.","tags":["Write"],"parameters":[{"name":"ruleId","in":"path","required":true,"description":"Rule ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/library-rules/{ruleId}/resolve":{"post":{"operationId":"resolve_library_rule","summary":"Resolve library rule","description":"Keep (optionally reworded) or skip one of Dora's suggested rules. Team only. Staff only.","tags":["Write"],"parameters":[{"name":"ruleId","in":"path","required":true,"description":"Rule ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accept":{"type":"boolean","description":"Keep it."},"text":{"type":"string","description":"Reworded, if keeping it."}},"required":["accept"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/brand-profile":{"get":{"operationId":"get_brand_profile","summary":"Get brand profile","description":"A workspace's brand profile, its rules and decisions, what's still missing, and details found in uploads waiting for review.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"operationId":"update_brand_profile","summary":"Update brand profile","description":"Set brand profile fields. An empty value clears a field.","tags":["Write"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"fields":{"type":"array","description":"Fields to set, as { field, value }.","items":{"type":"object","properties":{"field":{"type":"string","description":"Profile field key from get_config, or website."},"value":{"type":"string"}},"required":["field","value"]}}},"required":["fields"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/workspaces/{workspaceId}/delivery":{"get":{"operationId":"get_delivery_record","summary":"Get delivery record","description":"What a client got in a month: requests delivered and how they were approved, average turnaround, use of the monthly allowance, approved estimates, and Dora's recap once the month is over.","tags":["Read"],"parameters":[{"name":"workspaceId","in":"path","required":true,"description":"Workspace ID.","schema":{"type":"string"}},{"name":"month","in":"query","required":false,"description":"Month like 2026-10. Defaults to this month.","schema":{"type":"string"}}],"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/brand-profile/suggestions/{suggestionId}":{"post":{"operationId":"resolve_suggestion","summary":"Resolve suggestion","description":"Accept or skip a brand profile detail found in an upload (from get_brand_profile).","tags":["Write"],"parameters":[{"name":"suggestionId","in":"path","required":true,"description":"Suggestion ID.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"accept":{"type":"boolean","description":"true to use it, false to skip it."}},"required":["accept"]}}}},"responses":{"200":{"description":"The result, as JSON.","content":{"application/json":{"schema":{}}}},"400":{"description":"Invalid input.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Not allowed for this key: read-only, another client, or staff only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key from Connect your AI in Dora's settings, sent as `Authorization: Bearer <key>`."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"}},"required":["error"]}}}}