{"data":{"how_to_use":"Per-entity CRUD via GET/POST/PATCH/DELETE on /api/v3/{resource}; the dedicated endpoints listed below are preferred where they exist. Paths here are relative to /api/v3 and every write applies immediately — the preview-then-confirm handshake is an assistant-surface convention with no REST equivalent. This matrix describes the assistant-facing plane; see GET /api/v3/docs (OpenAPI) for the full route set, which is wider in places.","company_timezone":"Naive (offset-less) datetime input to POST/PATCH /time-entries start/end is interpreted in the company's own timezone, not UTC — call GET /auth/me for its value. Every timestamp OUTPUT is UTC (`Z`): convert to that timezone before naming a day or bucketing by month — 00:00 on the 1st is 22:00Z the day before. A recurring occurrence's day is its `recurrence_date`, never its `date`.","entities":{"attachments":{"read":true,"create":false,"update":false,"delete":true,"create_unavailable_because":"file upload needs a multipart request the assistant can't compose yet — upload files in Uku, or via POST /tasks/{id}/attachments on the REST API directly.","update_unavailable_because":"attachments have no editable fields via the API."},"budgets":{"read":true,"create":true,"update":true,"delete":true,"gated_by_app":"budgets"},"calendar":{"read":true,"create":true,"update":true,"delete":true},"client-groups":{"read":true,"create":true,"update":true,"delete":true},"client-members":{"read":true,"create":true,"update":true,"delete":true},"clients":{"read":true,"create":true,"update":true,"delete":true},"contacts":{"read":true,"create":true,"update":true,"delete":true},"content-templates":{"read":true,"create":true,"update":true,"delete":true},"custom-fields":{"read":true,"create":true,"update":true,"delete":true},"delegations":{"read":true,"create":true,"update":true,"delete":true},"digitizations":{"read":true,"create":true,"update":false,"delete":false,"gated_by_app":"documents"},"documents":{"read":true,"create":true,"update":true,"delete":true,"gated_by_app":"documents"},"folder-templates":{"read":true,"create":true,"update":true,"delete":true,"gated_by_app":"documents"},"folders":{"read":true,"create":true,"update":true,"delete":true,"gated_by_app":"documents"},"members":{"read":true,"create":true,"update":true,"delete":false,"delete_unavailable_because":"removing or deactivating a member is backoffice-only — the API deliberately has no member-delete endpoint."},"notes":{"read":true,"create":true,"update":true,"delete":true},"product-fields":{"read":true,"create":true,"update":true,"delete":true,"gated_by_app":"billing"},"projects":{"read":true,"create":true,"update":true,"delete":true},"roles":{"read":true,"create":true,"update":true,"delete":true},"suppliers":{"read":true,"create":true,"update":true,"delete":true},"task-automations":{"read":true,"create":true,"update":true,"delete":true},"task-relations":{"read":true,"create":true,"update":false,"delete":true,"update_unavailable_because":"the API has no task-relation PATCH — delete and re-create instead."},"tasks":{"read":true,"create":true,"update":true,"delete":true},"taxes":{"read":true,"create":true,"update":true,"delete":false,"delete_unavailable_because":"taxes have no delete anywhere on API v3 — deactivate one in the Uku backoffice.","gated_by_app":"billing"},"time-entries":{"read":true,"create":true,"update":true,"delete":true},"topics":{"read":true,"create":true,"update":true,"delete":true},"workflow-roles":{"read":true,"create":true,"update":true,"delete":true},"agreements":{"read":true,"create":true,"update":true,"delete":true,"generic_pair_excluded_because":"set a member's cost / sales (billing) rates, office/remote share, works-weekends/holidays flags and per-weekday working time for a period with the dedicated POST /members/{id}/agreements (PATCH .../agreements/{agreement_id} to edit) endpoint instead — and READ them with the same endpoint, called with person_id alone. All of it needs the `financials` scope."},"auth-keys":{"read":false,"create":false,"update":false,"delete":false,"unavailable_because":"API key management is not an assistant job — manage keys in Settings -> API Keys."},"contract-rows":{"read":false,"create":false,"update":false,"delete":false,"unavailable_because":"change a contract's lines with the dedicated PATCH /contracts/{id} endpoint — it edits, adds and removes lines AND each line's own price periods in one previewed call, which is the only place the resulting agreement is visible before it decides what the client is billed. Needs the `financials` scope."},"contracts":{"read":true,"create":true,"update":true,"delete":true,"generic_pair_excluded_because":"use the dedicated endpoints instead: POST /contracts to add one, PATCH /contracts/{id} to change it — its dates and invoicing, its lines, and each line's own price periods, all in one previewed call. DELETING a contract stays off the assistant: it is the record of what a client agreed to and what every invoice raised from it was based on. End it instead by setting `date_until`, or delete it in the Uku backoffice. Both endpoints need the `financials` scope.","gated_by_app":"billing"},"flextime":{"read":true,"create":true,"update":true,"delete":true,"generic_pair_excluded_because":"flextime writes are not on the assistant. Confirm or decline a member's period in Uku's backoffice (Reports → Flextime); raw flextime row writes (editing duration or the credit ledger directly) mutate an employee's running balance and need the `financials` scope — do those in the backoffice or the REST API with a financials-scoped key."},"invoice-rows":{"read":false,"create":false,"update":false,"delete":false,"unavailable_because":"the generic record endpoints deliberately never write money data (prices, budgets, credits, monitors, seller profiles) — these change what a client is charged, so they are only reachable where a dedicated endpoint covers them, and no endpoint covers this one yet. A `financials`-scoped key is refused here too, so this is NOT a permissions problem and a different key will not help. Do it in the Uku backoffice, or call the REST API directly."},"invoice-sellers":{"read":true,"create":true,"update":true,"delete":false,"generic_pair_excluded_because":"the generic record endpoints deliberately never write money data (prices, budgets, credits, monitors, seller profiles) — these change what a client is charged, so they are only reachable where a dedicated endpoint covers them, and no endpoint covers this one yet. A `financials`-scoped key is refused here too, so this is NOT a permissions problem and a different key will not help. Do it in the Uku backoffice, or call the REST API directly.","gated_by_app":"billing"},"invoices":{"read":true,"create":true,"update":true,"delete":false,"generic_pair_excluded_because":"use the dedicated invoice endpoints instead: POST /clients/{id}/invoices (the billing engine's own run, for anything a contract covers), POST /invoices (a one-off, with its lines and a real total in the preview), POST /invoices/{id}/rows, PATCH /invoices/{id} (and PATCH/DELETE on /invoices/{id}/rows/{row_id}) (correct the dates, the reference, the comment or a line — and remove lines), PATCH /invoices/{id} with status=created, POST /invoices/{id}/send, POST /invoices/{id}/mark-paid (paid=true) or /mark-unpaid (paid=false) — all of which need the `financials` scope. The client, the currency and the invoice number are not editable on any surface, and the sums are derived from the rows — change a line, not a total.","gated_by_app":"billing"},"monitors":{"read":true,"create":true,"update":true,"delete":true,"generic_pair_excluded_because":"the generic record endpoints deliberately never write money data (prices, budgets, credits, monitors, seller profiles) — these change what a client is charged, so they are only reachable where a dedicated endpoint covers them, and no endpoint covers this one yet. A `financials`-scoped key is refused here too, so this is NOT a permissions problem and a different key will not help. Do it in the Uku backoffice, or call the REST API directly."},"product-prices":{"read":false,"create":false,"update":false,"delete":false,"unavailable_because":"change a price with the dedicated PATCH /products/{id} endpoint — it edits, adds and removes a product's price rows in one previewed call, which is the only place the resulting price list (and whether its tiers add up) is visible before it goes live. Needs the `financials` scope."},"products":{"read":true,"create":true,"update":true,"delete":true,"generic_pair_excluded_because":"use the dedicated endpoints instead: POST /products to add one, PATCH /products/{id} to change its settings, its tax, or its prices. DELETING a product stays off the assistant — every contract row pointing at it would lose the only thing it gets money from; retire it with PATCH /products/{id}(status=\"inactive\") or delete it in the Uku backoffice. Both endpoints need the `financials` scope.","gated_by_app":"billing"},"reclaims":{"read":true,"create":false,"update":true,"delete":false,"generic_pair_excluded_because":"the generic record endpoints deliberately never write money data (prices, budgets, credits, monitors, seller profiles) — these change what a client is charged, so they are only reachable where a dedicated endpoint covers them, and no endpoint covers this one yet. A `financials`-scoped key is refused here too, so this is NOT a permissions problem and a different key will not help. Do it in the Uku backoffice, or call the REST API directly."},"teams":{"read":true,"create":true,"update":true,"delete":true,"generic_pair_excluded_because":"use the dedicated team endpoints instead: POST /teams, PATCH /teams/{id} (roster and/or lead), DELETE /teams/{id} (they wrap the backoffice rights-propagation the generic PATCH can't). Read teams with GET /teams / GET /teams/{id}."},"webhooks":{"read":true,"create":true,"update":true,"delete":true,"generic_pair_excluded_because":"webhook subscription management is not an assistant job."},"workflow-templates":{"read":true,"create":true,"update":true,"delete":false,"generic_pair_excluded_because":"use the dedicated template endpoints instead: POST /workflow-templates, POST /workflow-templates/{id}/tasks (PATCH .../tasks/{task_id} to edit), DELETE /workflow-templates/{id}/tasks/{task_id}, POST /workflow-templates/{id}/apply, POST /workflow-templates/{id}/push."}},"curated_tools":{"identity":["GET /auth/me","GET /tasks?assignee_id=<your person id from GET /auth/me>"],"company_setup":["GET /company/apps","POST /company/apps/{id}/activate","PATCH /company/billing-settings"],"search":["GET /search","GET /tasks","GET /clients","GET /clients/{id}","GET /tasks/{id}","GET /time-entries","GET /clients/{id}/folder-tree"],"reports":["GET /reports/time-summary","the BI metrics reference in GET /api/v3/docs","GET /reports/kpi-summary","GET /reports/bi/{shape} (series or breakdown)","the /insight deep-link format documented in GET /api/v3/docs","POST /reports/bi/refresh"],"audit":["GET /activities","GET /activities/{id}"],"help":["the Uku Help Center at help.getuku.com"],"task_writes":["POST /tasks","POST /tasks/{id}/complete","POST /tasks/{id}/reopen","POST /time-entries","PUT /tasks/{id}/checklist","POST /tasks/{id}/comments","PATCH /tasks/{id}","POST /tasks/bulk-action"],"client_writes":["POST /clients/{id}/documents-folder","PUT /clients/{id}/folder-template","POST /documents","POST /digitizations","POST /clients/{id}/emails"],"billing_setup":["GET /products","GET /products/{id}","POST /products","PATCH /products/{id}","POST /taxes","GET /contracts","GET /contracts/{id}","POST /contracts","PATCH /contracts/{id}","POST /contracts/{id}/apply"],"invoicing":["GET /invoices","GET /invoices/{id}","GET /missed-billing","POST /clients/{id}/invoices","POST /invoices","POST /invoices/{id}/rows","PATCH /invoices/{id} (and PATCH/DELETE on /invoices/{id}/rows/{row_id})","PATCH /invoices/{id} with status=created","POST /invoices/{id}/send","POST /invoices/{id}/mark-paid (paid=true) or /mark-unpaid (paid=false)"],"accounting_software":["GET /integrations/invoices","POST /invoices/{id}/export","POST /invoices/{id}/refresh-payment-status"],"budgets_flextime":["GET /budgets/{id}","GET /flextime/balance","POST /members/{id}/agreements (PATCH .../agreements/{agreement_id} to edit)"],"teams":["GET /teams","GET /teams/{id}","POST /teams","PATCH /teams/{id}","DELETE /teams/{id}"],"workflow_templates":["GET /workflow-templates","GET /workflow-templates/{id}","POST /workflow-templates","POST /workflow-templates/{id}/tasks (PATCH .../tasks/{task_id} to edit)","DELETE /workflow-templates/{id}/tasks/{task_id}","GET /clients/{id} plus /clients/{id}/member-roles and /clients/{id}/workflow-tasks","PUT /clients/{id}/manager","PUT /clients/{id}/member-roles","POST /workflow-templates/{id}/apply","POST /workflow-templates/{id}/push"],"project_workflows":["GET /project-workflows","GET /project-workflows/{id}","POST /project-workflows/{id}/apply","POST /project-workflows/{id}/push"],"bulk_and_jobs":["GET /jobs/{id}"]},"not_available":[{"what":"bulk member actions (add/replace/remove members, teams, or roles across many clients at once)","why":"available to INTEGRATION keys only — a personal (per-person) key can't run tenant-wide bulk mutations","instead":"use an integration key, or change members one client at a time with PUT /clients/{id}/member-roles"},{"what":"delete a client or project","why":"blast radius too large for a chat confirmation","instead":"archive via PATCH /{resource}/{id}(status), or delete in the Uku backoffice"},{"what":"invite a member, or remove one","why":"sending an invitation grants access and takes a paid seat — account management, deliberately backoffice-only. Adding a LIMITED member (a placeholder with no login, no invite and no seat) IS available via POST /{resource}(resource=\"members\")","instead":"POST /{resource}(resource=\"members\") for a placeholder; Uku backoffice → Members to invite or remove"},{"what":"change a member's role or status (promote/demote, activate/deactivate)","why":"management, not daily work — the API/assistant is for daily work, not owner-level administration (CTO decision 2026-07-23); a PATCH touching role/status is refused (MANAGEMENT_UI_ONLY)","instead":"Uku backoffice → Settings → Members"},{"what":"change the Uku subscription (create / upgrade / downgrade a plan)","why":"subscription management is owner-level administration, deliberately UI-only — the API is for daily work","instead":"Uku backoffice → Settings → Billing / Subscription"},{"what":"create a company, or delete a company or account","why":"company/account lifecycle is owner-level administration, deliberately UI-only (and not a daily-work action)","instead":"Uku backoffice (create a company at signup; delete via Settings / Uku support)"},{"what":"invoice actions (list, view, create, generate from contracts, send, mark paid/unpaid)","why":"available via the dedicated invoicing endpoints, but they need a financials-scoped key — a personal (per-person) key doesn't carry financials unless its OAuth connection was granted financial-data access at consent time","instead":"use GET /invoices / GET /invoices/{id} / POST /invoices / POST /invoices/{id}/rows / POST /clients/{id}/invoices / POST /invoices/{id}/send / POST /invoices/{id}/mark-paid (paid=true) or /mark-unpaid (paid=false) with a key that has the financials scope (an integration key, or a financials-granted personal OAuth connection)"},{"what":"contract / product reference, budget usage, flextime balance","why":"available via the dedicated money-plane endpoints (waves 2-3, 2026-07-23), but they need a financials-scoped key — a personal key doesn't carry financials unless its OAuth connection was granted financial-data access at consent time","instead":"read with GET /contracts / GET /contracts/{id} / GET /products / GET /products/{id} / GET /budgets/{id} / GET /flextime/balance, using a key that has the financials scope. Flextime period sign-off (confirm/decline) is not on the assistant at all — Uku backoffice, Reports → Flextime"},{"what":"a member's cost / sales (billing) rate for a period","why":"available via the dedicated POST /members/{id}/agreements (PATCH .../agreements/{agreement_id} to edit) endpoint (2026-07-23) — the daily-work rate slice of the member agreement — but it needs a financials-scoped key; a personal key doesn't carry financials unless its OAuth connection was granted financial-data access at consent time","instead":"use POST /members/{id}/agreements (PATCH .../agreements/{agreement_id} to edit)(person_id, date_from, ...) with a key that has the financials scope"},{"what":"other money data writes (contract/product EDITS, standalone price edits, taxes, budgets, reclaims, monitors) and raw flextime-row edits","why":"needs the financials scope and has billing / credit-ledger side effects; the dedicated money writes are the document CREATES (POST /contracts / POST /products / POST /invoices, wave 4) and the FULL member agreement slice (cost/sales rates, office_rate, works-weekends/holidays, per-weekday working time) — editing those documents and everything else listed stays backoffice","instead":"Uku backoffice, or the REST API with a financials-scoped key"},{"what":"find a CLIENT through GET /search","why":"GET /search has no client category — the app searches clients in the browser from its own cached client list, so there was never a server-side client search to expose. An empty result from GET /search therefore means 'clients were not searched', NOT 'no such client'","instead":"GET /{resource}(resource=\"clients\", q=\"Acme\") — matches the client name or its client code, the same two fields the app matches"},{"what":"convert a checklist item into its own standalone task","why":"net-new backend behavior, descoped to UKU-820","instead":"compose it today: POST /tasks with the item's text, then PUT /tasks/{id}/checklist(action=\"toggle\") to tick the original"},{"what":"start/stop a timer","why":"no API timer surface","instead":"log the finished duration with POST /time-entries"},{"what":"file upload or file delete","why":"upload needs multipart; delete is too risky from chat (a file can be an e-signed document's source)","instead":"manage files in Uku; attachments can still be listed/read here"},{"what":"API key / webhook management","why":"not an assistant job","instead":"Uku Settings → API Keys"},{"what":"undo a change (restore a deleted record, roll back a bulk action, put a task back exactly as it was)","why":"no undo or restore verb exists on API v3 or MCP — every DELETE /{resource}/{id} is a soft delete with no way back through the API, and bulk archive/restore rebuilds a task's status rather than restoring it","instead":"pairwise inverses where one exists (POST /invoices/{id}/mark-paid (paid=true) or /mark-unpaid (paid=false)(paid=false), POST /tasks/{id}/reopen, PUT /tasks/{id}/checklist(action=\"toggle\") back, DELETE /{resource}/{id} on a task or time entry just created — refused for a time entry in a locked billing period); Uku backoffice → Audit trail for field undo, deleted-task restore, and rollback of a bulk workflow apply or client import within 7 days; POST /reclaims/{id}/undo for a billing reclaim"}],"idempotency":{"header":"Idempotency-Key","methods":["POST"],"max_key_length":200,"stored_response_ttl_hours":24,"replay_header":"Idempotency-Replayed","conflict_error_code":"IDEMPOTENCY_CONFLICT","paths":["/agreements","/budgets","/calendar","/client-groups","/client-members","/clients","/clients/bulk-member-action","/contacts","/content-templates","/contracts","/custom-fields","/delegations","/digitizations","/documents","/flextime","/folder-templates","/folders","/integrations/reference-data/sync","/invoice-sellers","/invoices","/members","/monitors","/notes","/product-fields","/products","/project-workflows","/projects","/roles","/suppliers","/task-automations","/task-relations","/tasks","/taxes","/teams","/time-entries","/time-entries/bulk","/topics","/workflow-roles","/workflow-templates"],"path_shapes":["/clients/{id}/documents-folder","/clients/{id}/emails","/clients/{id}/invoices","/clients/{id}/monitors","/company/apps/{id}/activate","/content-templates/{id}/rows","/contracts/{id}/apply","/contracts/{id}/rows","/contracts/{id}/rows/{id}/prices","/invoices/{id}/export","/invoices/{id}/mark-paid","/invoices/{id}/mark-unpaid","/invoices/{id}/refresh-payment-status","/invoices/{id}/rows","/invoices/{id}/send","/members/{id}/agreements","/notes/{id}/attachments","/products/{id}/prices","/project-workflows/{id}/apply","/project-workflows/{id}/push","/project-workflows/{id}/tasks","/tasks/bulk-action","/tasks/{id}/attachments","/tasks/{id}/comments","/tasks/{id}/complete","/tasks/{id}/reopen","/webhooks/{id}/deliveries/{event_id}/replay","/workflow-templates/{id}/apply","/workflow-templates/{id}/push","/workflow-templates/{id}/tasks"],"not_covered":[{"path":"/auth/keys","why":"the response carries the API key itself, shown once and never stored; a replayable copy would sit in Redis for 24h"},{"path":"/auth/keys/{id}/rotate","why":"same — the rotated key is in the response"},{"path":"/reports/bi/refresh","why":"a refresh already running returns already_running, so a duplicate is a no-op"},{"path":"/reclaims/{id}/undo","why":"one-way transition; a second call correctly returns 409 RECLAIM_NOT_UNDOABLE"},{"path":"/webhooks","why":"the response carries the subscription's HMAC signing secret, shown once and never stored — same secret-at-rest rule as /auth/keys"},{"path":"/webhooks/{id}/rotate-secret","why":"same — the new secret is in the response"}],"id_placeholder":"{id}","note":"Send the header on any listed POST to make a retry safe: a repeat with the same key replays the original response instead of acting twice. Anything not listed is not covered — sending the header there changes nothing. `paths` are exact; `path_shapes` and `not_covered[].path` use `{id}` for ANY numeric id segment (`{event_id}` is the one string-id segment, a delivery's event id), so they will not string-match the OpenAPI spec, which names each parameter individually (`{task_id}`, `{key_id}`) — substitute, don't compare. Read this list at runtime rather than copying it."}}}