{"openapi":"3.1.0","info":{"title":"Simpler API","version":"4fb66a9588e02a57","description":"Execution substrate for SEA SMB operations. Every operation here is generated from the metadata catalog (D1 meta_* rows) — the same registry that generates the MCP tools and validates execution, so this spec structurally cannot drift from runtime behavior. REST and MCP are dual projections of one executor.","contact":{"name":"Simpler","url":"https://simpler.asia","email":"support@simpler.asia"}},"servers":[{"url":"https://simpler.asia","description":"This deployment."}],"paths":{"/api/agent-notes/send_cross_tenant":{"post":{"operationId":"agent_note_send_cross_tenant","summary":"send_cross_tenant agent_note","description":"Send a cross-tenant AI-to-AI message into another tenant's agent_note inbox — the door that turns a cross_tenant_comm consent grant into an actual reach. Both tenants must be KYB-approved and the recipient must hold an active grant (claims can narrow it further); every recipient-side failure refuses identically so the network can't be probed for who exists — only your OWN unapproved KYB answers distinctly, since that discloses nothing about the target. Your sender identity is injected server-side into from_tenant_id and cannot be spoofed. NEXT: agent_note_list on the recipient side confirms delivery. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from_tenant_id":{"type":"string","maxLength":40},"consent_grant_id":{"type":"string","maxLength":40},"subject":{"type":"string","maxLength":200},"body":{"type":"string","maxLength":4000},"related_entity_type":{"type":"string","maxLength":60},"related_entity_id":{"type":"string","maxLength":40},"status":{"type":"string","enum":["unread","read"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/agent_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/agent-notes/mark_read":{"post":{"operationId":"agent_note_mark_read","summary":"mark_read agent_note","description":"Confirm receipt of a note in your cross-tenant agent_note inbox — the ONLY edit a recipient holds, moving status unread to read under the registry's transition guard. Idempotent: re-confirming an already-read note is a no-op, and the subject/body stay fixed forever so a recipient can never rewrite what the sender said. NEXT: agent_note_list to see the rest of the inbox. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"from_tenant_id":{"type":"string","maxLength":40},"consent_grant_id":{"type":"string","maxLength":40},"subject":{"type":"string","maxLength":200},"body":{"type":"string","maxLength":4000},"related_entity_type":{"type":"string","maxLength":60},"related_entity_id":{"type":"string","maxLength":40},"status":{"type":"string","enum":["unread","read"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/agent_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/agent-notes":{"get":{"operationId":"agent_note_list","summary":"list agent_note","description":"Executes the catalog action agent_note.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/agent_note_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/agent_note_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/agent-notes/{id}":{"get":{"operationId":"agent_note_read","summary":"read agent_note","description":"Executes the catalog action agent_note.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The agent_note id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/agent_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/brand-assets/save":{"post":{"operationId":"brand_assets_save","summary":"save brand_assets","description":"Create or update the tenant's brand kit (colors, fonts, tone, logo, tagline) in one call. There is only ever one row per scope, so this is the single write lane for both the first save and every edit after. logo_key must come from the dedicated logo upload route, and colors_json, fonts_json, and tone_json must each parse as a JSON object or array; two saves racing on the same scope resolve as CONFLICT for the loser to re-read and retry. NEXT: brand_assets_read to fetch what was stored. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","maxLength":32},"logo_key":{"type":"string","maxLength":512},"colors_json":{"type":"string","maxLength":2000},"fonts_json":{"type":"string","maxLength":1000},"tone_json":{"type":"string","maxLength":2000},"industry":{"type":"string","maxLength":120},"tagline":{"type":"string","maxLength":300},"source_url":{"type":"string","maxLength":2048},"extracted_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/brand_assets_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/brand-assets/{id}":{"get":{"operationId":"brand_assets_read","summary":"read brand_assets","description":"Executes the catalog action brand_assets.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The brand_assets id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/brand_assets_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/brand-assets":{"get":{"operationId":"brand_assets_list","summary":"list brand_assets","description":"Executes the catalog action brand_assets.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/brand_assets_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/brand_assets_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/consent-grants":{"put":{"operationId":"consent_grant_upsert","summary":"upsert consent_grant","description":"Executes the catalog action consent_grant.upsert (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","enum":["sbin_participation","green_extraction","cross_tenant_comm","cross_tenant_settlement"]},"status":{"type":"string","enum":["granted","revoked"]},"claims_json":{"type":"string","maxLength":2000}},"required":["scope"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/consent_grant_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"consent_grant_list","summary":"list consent_grant","description":"Executes the catalog action consent_grant.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/consent_grant_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/consent_grant_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/consent-grants/{id}":{"get":{"operationId":"consent_grant_read","summary":"read consent_grant","description":"Executes the catalog action consent_grant.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The consent_grant id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/consent_grant_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/contacts/create":{"post":{"operationId":"contact_create","summary":"create contact","description":"Create a contact and, in the same call, log its first note and/or first interaction — the composite first-touch door. Children validate before the contact write; if the contact commits but a child then fails, the error names the contact's id plus the exact call to finish it, never a silent orphan. A contact with the same email or phone already in this tenant refuses with CONFLICT. NEXT: contact_upsert merges into an existing contact instead of creating a duplicate. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"status":{"type":"string","enum":["lead","contacted","qualified","customer","vip","inactive"]},"source":{"type":"string","enum":["manual","import","invoice","sync"]},"tags":{"type":"string","maxLength":2000},"last_contact_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/contact_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/contacts/upsert":{"post":{"operationId":"contact_upsert","summary":"upsert contact","description":"Create-or-merge a contact keyed on email-then-phone identity — the sync door the future desktop harness and ingest lanes write through. Matching probes email first, then phone; a hit MERGES only the fields you send (omitted fields keep their stored values, so a partial sync payload can never wipe a curated field), a miss creates. Status moves still obey the transition machine — an upsert cannot jump straight to vip. Accepts the same first-note/first-interaction composite children as contact_create. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"status":{"type":"string","enum":["lead","contacted","qualified","customer","vip","inactive"]},"source":{"type":"string","enum":["manual","import","invoice","sync"]},"tags":{"type":"string","maxLength":2000},"last_contact_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/contact_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/contacts/{id}":{"patch":{"operationId":"contact_update","summary":"update contact","description":"Executes the catalog action contact.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The contact id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"status":{"type":"string","enum":["lead","contacted","qualified","customer","vip","inactive"]},"source":{"type":"string","enum":["manual","import","invoice","sync"]},"tags":{"type":"string","maxLength":2000},"last_contact_at":{"type":"integer","description":"Unix epoch milliseconds."},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/contact_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"contact_delete","summary":"delete contact","description":"Executes the catalog action contact.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The contact id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/contact_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"contact_read","summary":"read contact","description":"Executes the catalog action contact.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The contact id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/contact_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/contacts":{"get":{"operationId":"contact_list","summary":"list contact","description":"Executes the catalog action contact.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/contact_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/contact_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/contacts/search":{"get":{"operationId":"contact_search","summary":"search contact","description":"Executes the catalog action contact.search (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/contact_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/contact_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/contact-notes/create":{"post":{"operationId":"contact_note_create","summary":"create contact_note","description":"Add a note to a contact — the same door as the granular tool, extended only to accept contact_name, contact_email or contact_phone in place of contact_id. A name match must be unique: more than one hit refuses, listing the candidate ids; zero matches on every alias refuses with the runnable two-step call to create the contact first, then retry. NEXT: contact_upsert when no contact exists yet. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":"string","maxLength":40},"content":{"type":"string","maxLength":5000}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/contact_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/contact-notes":{"get":{"operationId":"contact_note_list","summary":"list contact_note","description":"Executes the catalog action contact_note.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/contact_note_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/contact_note_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/contact-notes/{id}":{"get":{"operationId":"contact_note_read","summary":"read contact_note","description":"Executes the catalog action contact_note.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The contact_note id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/contact_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"contact_note_delete","summary":"delete contact_note","description":"Executes the catalog action contact_note.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The contact_note id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/contact_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/desk-surfaces/create":{"post":{"operationId":"desk_surface_create","summary":"create desk_surface","description":"Pins one widget or a saved artifact onto the operator's home canvas. kind='widget' requires widget_key from the shipped enum; kind='artifact' requires content_ref (an assistant artifact id) — the door enforces whichever pair the kind demands, since the schema alone cannot express it. Rows are private to the creating user, even though teammates share the same tenant. NEXT: desk_surface_list reads the current layout. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["widget","artifact"]},"widget_key":{"type":"string","enum":["calendar-money-month","fx-converter","from-ai-inbox","assignments","market-discovery","sticky-notes","quick-start","coin-flip","interests"]},"content_ref":{"type":"string","maxLength":64},"x":{"type":"integer"},"y":{"type":"integer"},"w":{"type":"integer"},"h":{"type":"integer"},"z_index":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/desk_surface_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/desk-surfaces/update":{"post":{"operationId":"desk_surface_update","summary":"update desk_surface","description":"Moves, resizes, or restacks a surface already on the desk canvas — x/y/w/h/z_index are real column writes, not a layout cache. The surface's identity is frozen here: kind, widget_key, and content_ref never change through this door, only via delete then re-create. NEXT: desk_surface_list to find the id to move. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"kind":{"type":"string","enum":["widget","artifact"]},"widget_key":{"type":"string","enum":["calendar-money-month","fx-converter","from-ai-inbox","assignments","market-discovery","sticky-notes","quick-start","coin-flip","interests"]},"content_ref":{"type":"string","maxLength":64},"x":{"type":"integer"},"y":{"type":"integer"},"w":{"type":"integer"},"h":{"type":"integer"},"z_index":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/desk_surface_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/desk-surfaces/{id}":{"get":{"operationId":"desk_surface_read","summary":"read desk_surface","description":"Executes the catalog action desk_surface.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The desk_surface id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/desk_surface_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"desk_surface_delete","summary":"delete desk_surface","description":"Executes the catalog action desk_surface.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The desk_surface id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/desk_surface_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/desk-surfaces":{"get":{"operationId":"desk_surface_list","summary":"list desk_surface","description":"Executes the catalog action desk_surface.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/desk_surface_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/desk_surface_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/edit-projects/create":{"post":{"operationId":"edit_project_create","summary":"create edit_project","description":"Create a canvas project from a Fabric.js toJSON serialization (canvas_json, required): every embedded data:image src is pulled out, hashed, and written to a tenant-scoped, content-addressed R2 key before the row is saved, so canvas_json never carries image bytes and identical images dedupe across projects. SVG, an unrecognized image type, an oversized embedded image, or a canvas still too large after externalization refuse the whole create — nothing is silently dropped. An optional thumbnail_data_url is externalized the same way into thumbnail_key; thumbnail_key and version are server-set and refuse if you pass them. NEXT: edit_project_update to autosave the same project as it changes. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"canvas_json":{"type":"string","maxLength":150000},"thumbnail_key":{"type":"string","maxLength":300},"width":{"type":"integer"},"height":{"type":"integer"},"version":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/edit_project_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/edit-projects/update":{"post":{"operationId":"edit_project_update","summary":"update edit_project","description":"Save changes to an existing canvas project by id — the autosave door: send only the fields that changed (name, canvas_json, width, height, thumbnail_data_url), everything else on the row is left alone. A canvas_json you send goes through the same image-externalization and hygiene refusal as edit_project_create (embedded images become R2 keys; SVG, unrecognized types, oversized images, or a still-too-large canvas refuse the whole save). version is bumped by the door itself on every save and thumbnail_key is server-minted from thumbnail_data_url — both refuse if you pass them directly. NEXT: edit_project_read to confirm the saved version. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"canvas_json":{"type":"string","maxLength":150000},"thumbnail_key":{"type":"string","maxLength":300},"width":{"type":"integer"},"height":{"type":"integer"},"version":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/edit_project_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/edit-projects/{id}":{"get":{"operationId":"edit_project_read","summary":"read edit_project","description":"Executes the catalog action edit_project.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The edit_project id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/edit_project_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"edit_project_delete","summary":"delete edit_project","description":"Executes the catalog action edit_project.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The edit_project id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/edit_project_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/edit-projects":{"get":{"operationId":"edit_project_list","summary":"list edit_project","description":"Executes the catalog action edit_project.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/edit_project_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/edit_project_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/create":{"post":{"operationId":"expense_create","summary":"create expense","description":"Logs a new expense — amount_cents must be integer CENTS (a decimal string via `amount` also works, and `category` resolves to a category_id by name). A same-amount, same-UTC-day duplicate for the same user is refused as CONFLICT unless you resend identically with force: true. Status is honor-or-refuse: admin/owner creators land 'approved' by default (or may request it explicitly), everyone else always starts 'draft'. NEXT: expense_submit sends a draft into the approval queue. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"expense_date":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_key":{"type":"string","maxLength":200},"ocr_json":{"type":"string","maxLength":8000},"notes":{"type":"string","maxLength":2000},"tags_json":{"type":"string","maxLength":2000},"subtotal_cents":{"type":"integer"},"tax_amount_cents":{"type":"integer"},"tax_rate_bps":{"type":"integer"},"tax_type":{"type":"string","enum":["GST","SST","VAT","PPN"]},"status":{"type":"string","enum":["draft","pending","approved","rejected","reimbursed"]},"submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"approved_by":{"type":"string","maxLength":40},"approved_at":{"type":"integer","description":"Unix epoch milliseconds."},"rejection_reason":{"type":"string","maxLength":500},"rejected_at":{"type":"integer","description":"Unix epoch milliseconds."},"reimbursed_at":{"type":"integer","description":"Unix epoch milliseconds."},"recurrence_id":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/update":{"post":{"operationId":"expense_update","summary":"update expense","description":"Edits an expense's own fields only — status and approval stamps refuse with VALIDATION_ERROR here since those are transitions (expense_submit, expense_approve, expense_reject, expense_reimburse). amount_cents, if changed, must stay integer CENTS. Only the expense's own creator may edit it, and content freezes once the row is 'pending', reimbursed, or approved by someone else — draft, rejected, and your own self-approved rows stay editable. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"expense_date":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_key":{"type":"string","maxLength":200},"ocr_json":{"type":"string","maxLength":8000},"notes":{"type":"string","maxLength":2000},"tags_json":{"type":"string","maxLength":2000},"subtotal_cents":{"type":"integer"},"tax_amount_cents":{"type":"integer"},"tax_rate_bps":{"type":"integer"},"tax_type":{"type":"string","enum":["GST","SST","VAT","PPN"]},"status":{"type":"string","enum":["draft","pending","approved","rejected","reimbursed"]},"submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"approved_by":{"type":"string","maxLength":40},"approved_at":{"type":"integer","description":"Unix epoch milliseconds."},"rejection_reason":{"type":"string","maxLength":500},"rejected_at":{"type":"integer","description":"Unix epoch milliseconds."},"reimbursed_at":{"type":"integer","description":"Unix epoch milliseconds."},"recurrence_id":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/delete":{"post":{"operationId":"expense_delete","summary":"delete expense","description":"Deletes an expense you created — draft and rejected rows only. Pending, approved, and reimbursed rows are approval-trail records and refuse with CONFLICT (approval_locked: true), and the lock is pinned into the delete itself so a status change racing your read still refuses instead of silently deleting. NEXT: expense_reject it first (admin+) if it must leave the books. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"expense_date":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_key":{"type":"string","maxLength":200},"ocr_json":{"type":"string","maxLength":8000},"notes":{"type":"string","maxLength":2000},"tags_json":{"type":"string","maxLength":2000},"subtotal_cents":{"type":"integer"},"tax_amount_cents":{"type":"integer"},"tax_rate_bps":{"type":"integer"},"tax_type":{"type":"string","enum":["GST","SST","VAT","PPN"]},"status":{"type":"string","enum":["draft","pending","approved","rejected","reimbursed"]},"submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"approved_by":{"type":"string","maxLength":40},"approved_at":{"type":"integer","description":"Unix epoch milliseconds."},"rejection_reason":{"type":"string","maxLength":500},"rejected_at":{"type":"integer","description":"Unix epoch milliseconds."},"reimbursed_at":{"type":"integer","description":"Unix epoch milliseconds."},"recurrence_id":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/submit":{"post":{"operationId":"expense_submit","summary":"submit expense","description":"Sends your own draft expense into the approval queue — draft only; an already-submitted or resolved expense refuses CONFLICT, and only the expense's own creator may submit it. Nobody is notified automatically — approvers see it appear in the Team Claims view. NEXT: expense_approve or expense_reject (admin/owner). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"expense_date":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_key":{"type":"string","maxLength":200},"ocr_json":{"type":"string","maxLength":8000},"notes":{"type":"string","maxLength":2000},"tags_json":{"type":"string","maxLength":2000},"subtotal_cents":{"type":"integer"},"tax_amount_cents":{"type":"integer"},"tax_rate_bps":{"type":"integer"},"tax_type":{"type":"string","enum":["GST","SST","VAT","PPN"]},"status":{"type":"string","enum":["draft","pending","approved","rejected","reimbursed"]},"submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"approved_by":{"type":"string","maxLength":40},"approved_at":{"type":"integer","description":"Unix epoch milliseconds."},"rejection_reason":{"type":"string","maxLength":500},"rejected_at":{"type":"integer","description":"Unix epoch milliseconds."},"reimbursed_at":{"type":"integer","description":"Unix epoch milliseconds."},"recurrence_id":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/approve":{"post":{"operationId":"expense_approve","summary":"approve expense","description":"Approves a submitted expense claim — requires the admin or owner role, and only a 'pending' expense qualifies (CONFLICT otherwise). Stamps approved_by and approved_at with the caller and the current time; once approved, the row's content freezes for everyone except the approver themselves. NEXT: expense_reimburse (owner only) to pay it out. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"expense_date":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_key":{"type":"string","maxLength":200},"ocr_json":{"type":"string","maxLength":8000},"notes":{"type":"string","maxLength":2000},"tags_json":{"type":"string","maxLength":2000},"subtotal_cents":{"type":"integer"},"tax_amount_cents":{"type":"integer"},"tax_rate_bps":{"type":"integer"},"tax_type":{"type":"string","enum":["GST","SST","VAT","PPN"]},"status":{"type":"string","enum":["draft","pending","approved","rejected","reimbursed"]},"submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"approved_by":{"type":"string","maxLength":40},"approved_at":{"type":"integer","description":"Unix epoch milliseconds."},"rejection_reason":{"type":"string","maxLength":500},"rejected_at":{"type":"integer","description":"Unix epoch milliseconds."},"reimbursed_at":{"type":"integer","description":"Unix epoch milliseconds."},"recurrence_id":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/reject":{"post":{"operationId":"expense_reject","summary":"reject expense","description":"Rejects a submitted expense claim — requires the admin or owner role, and only a 'pending' expense qualifies (CONFLICT otherwise). rejection_reason (up to 500 chars) is optional but records why; rejected is terminal and never counts as spend, so a corrected claim is a fresh expense_create, never a resubmit. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"expense_date":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_key":{"type":"string","maxLength":200},"ocr_json":{"type":"string","maxLength":8000},"notes":{"type":"string","maxLength":2000},"tags_json":{"type":"string","maxLength":2000},"subtotal_cents":{"type":"integer"},"tax_amount_cents":{"type":"integer"},"tax_rate_bps":{"type":"integer"},"tax_type":{"type":"string","enum":["GST","SST","VAT","PPN"]},"status":{"type":"string","enum":["draft","pending","approved","rejected","reimbursed"]},"submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"approved_by":{"type":"string","maxLength":40},"approved_at":{"type":"integer","description":"Unix epoch milliseconds."},"rejection_reason":{"type":"string","maxLength":500},"rejected_at":{"type":"integer","description":"Unix epoch milliseconds."},"reimbursed_at":{"type":"integer","description":"Unix epoch milliseconds."},"recurrence_id":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/reimburse":{"post":{"operationId":"expense_reimburse","summary":"reimburse expense","description":"Marks an approved expense as paid out — restricted to the tenant owner because it moves real money, and only an 'approved' expense qualifies (CONFLICT otherwise). Stamps reimbursed_at, after which the row's content freezes unconditionally since the amount approved is the amount recorded as paid. Records the payout only — no funds move automatically. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"expense_date":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_key":{"type":"string","maxLength":200},"ocr_json":{"type":"string","maxLength":8000},"notes":{"type":"string","maxLength":2000},"tags_json":{"type":"string","maxLength":2000},"subtotal_cents":{"type":"integer"},"tax_amount_cents":{"type":"integer"},"tax_rate_bps":{"type":"integer"},"tax_type":{"type":"string","enum":["GST","SST","VAT","PPN"]},"status":{"type":"string","enum":["draft","pending","approved","rejected","reimbursed"]},"submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"approved_by":{"type":"string","maxLength":40},"approved_at":{"type":"integer","description":"Unix epoch milliseconds."},"rejection_reason":{"type":"string","maxLength":500},"rejected_at":{"type":"integer","description":"Unix epoch milliseconds."},"reimbursed_at":{"type":"integer","description":"Unix epoch milliseconds."},"recurrence_id":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/{id}":{"get":{"operationId":"expense_read","summary":"read expense","description":"Executes the catalog action expense.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The expense id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses":{"get":{"operationId":"expense_list","summary":"list expense","description":"Executes the catalog action expense.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/expense_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/expense_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/search":{"get":{"operationId":"expense_search","summary":"search expense","description":"Executes the catalog action expense.search (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/expense_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/expense_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expenses/aggregate":{"get":{"operationId":"expense_aggregate","summary":"aggregate expense","description":"Executes the catalog action expense.aggregate (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"function","in":"query","required":true,"schema":{"type":"string","enum":["count","sum"]}},{"name":"property","in":"query","required":false,"schema":{"type":"string"},"description":"Required for sum: a declared numeric property."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"type":"object","properties":{"function":{"type":"string"},"value":{"type":"number"}}}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-budgets":{"post":{"operationId":"expense_budget_create","summary":"create expense_budget","description":"Executes the catalog action expense_budget.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"category_id":{"type":"string","maxLength":40},"monthly_limit_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"alert_at_pct":{"type":"integer"},"is_active":{"type":"integer"}},"required":["monthly_limit_cents"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_budget_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"expense_budget_list","summary":"list expense_budget","description":"Executes the catalog action expense_budget.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/expense_budget_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/expense_budget_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-budgets/{id}":{"patch":{"operationId":"expense_budget_update","summary":"update expense_budget","description":"Executes the catalog action expense_budget.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The expense_budget id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"category_id":{"type":"string","maxLength":40},"monthly_limit_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"alert_at_pct":{"type":"integer"},"is_active":{"type":"integer"},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_budget_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"expense_budget_delete","summary":"delete expense_budget","description":"Executes the catalog action expense_budget.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The expense_budget id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_budget_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"expense_budget_read","summary":"read expense_budget","description":"Executes the catalog action expense_budget.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The expense_budget id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_budget_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-categories/create":{"post":{"operationId":"expense_category_create","summary":"create expense_category","description":"Adds a custom category to your tenant's category table — slug must be 1-50 chars of lowercase a-z, 0-9, '-' or '_' and unique per tenant (CONFLICT if taken). is_default is server-owned: supplying it at all refuses with VALIDATION_ERROR, and this door always creates with is_default 0 — the 9 seeded defaults exist only via expense_category_ensure_defaults. sort_order defaults to the next open slot when omitted. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","maxLength":50},"name":{"type":"string","maxLength":100},"icon":{"type":"string","maxLength":10},"color":{"type":"string","maxLength":7},"sort_order":{"type":"integer"},"is_default":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_category_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-categories/update":{"post":{"operationId":"expense_category_update","summary":"update expense_category","description":"Edits a category's name, icon, color, or sort_order — slug and is_default are the category's fixed identity, and any attempt to change either refuses with VALIDATION_ERROR. color, when given, must be a #rrggbb hex value. Create a new category instead of trying to rename an existing slug. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","maxLength":50},"name":{"type":"string","maxLength":100},"icon":{"type":"string","maxLength":10},"color":{"type":"string","maxLength":7},"sort_order":{"type":"integer"},"is_default":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_category_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-categories/delete":{"post":{"operationId":"expense_category_delete","summary":"delete expense_category","description":"Deletes a custom category — categories are tenant-shared, so any tenant member can remove one regardless of who created it; the 9 seeded defaults are undeletable and refuse with CONFLICT (default_category: true). Expenses already carrying the deleted category keep their category_id untouched and simply render as Uncategorized; nothing is reassigned or blocked. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","maxLength":50},"name":{"type":"string","maxLength":100},"icon":{"type":"string","maxLength":10},"color":{"type":"string","maxLength":7},"sort_order":{"type":"integer"},"is_default":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_category_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-categories/ensure_defaults":{"post":{"operationId":"expense_category_ensure_defaults","summary":"ensure_defaults expense_category","description":"Seeds the 9 canonical default categories (Food & Dining, Transport, Utilities, Shopping, Entertainment, Healthcare, Travel, Office & Supplies, Other) into your tenant, skipping any slug that already exists. Takes no arguments and is safe to call repeatedly or concurrently — it converges rather than duplicating. NEXT: expense_category_list to see the result. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string","maxLength":50},"name":{"type":"string","maxLength":100},"icon":{"type":"string","maxLength":10},"color":{"type":"string","maxLength":7},"sort_order":{"type":"integer"},"is_default":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_category_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-categories/{id}":{"get":{"operationId":"expense_category_read","summary":"read expense_category","description":"Executes the catalog action expense_category.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The expense_category id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_category_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-categories":{"get":{"operationId":"expense_category_list","summary":"list expense_category","description":"Executes the catalog action expense_category.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/expense_category_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/expense_category_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-recurrence":{"post":{"operationId":"expense_recurrence_create","summary":"create expense_recurrence","description":"Executes the catalog action expense_recurrence.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"notes":{"type":"string","maxLength":2000},"frequency":{"type":"string","enum":["daily","weekly","monthly","yearly"]},"day_of_month":{"type":"integer"},"day_of_week":{"type":"integer"},"next_due":{"type":"integer","description":"Unix epoch milliseconds."},"is_active":{"type":"integer"},"last_generated_at":{"type":"integer","description":"Unix epoch milliseconds."},"total_generated":{"type":"integer"}},"required":["vendor","amount_cents","frequency","next_due"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_recurrence_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"expense_recurrence_list","summary":"list expense_recurrence","description":"Executes the catalog action expense_recurrence.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/expense_recurrence_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/expense_recurrence_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/expense-recurrence/{id}":{"patch":{"operationId":"expense_recurrence_update","summary":"update expense_recurrence","description":"Executes the catalog action expense_recurrence.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The expense_recurrence id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"notes":{"type":"string","maxLength":2000},"frequency":{"type":"string","enum":["daily","weekly","monthly","yearly"]},"day_of_month":{"type":"integer"},"day_of_week":{"type":"integer"},"next_due":{"type":"integer","description":"Unix epoch milliseconds."},"is_active":{"type":"integer"},"last_generated_at":{"type":"integer","description":"Unix epoch milliseconds."},"total_generated":{"type":"integer"},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_recurrence_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"expense_recurrence_delete","summary":"delete expense_recurrence","description":"Executes the catalog action expense_recurrence.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The expense_recurrence id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_recurrence_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"expense_recurrence_read","summary":"read expense_recurrence","description":"Executes the catalog action expense_recurrence.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["expenses"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The expense_recurrence id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/expense_recurrence_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-folders":{"post":{"operationId":"image_folder_create","summary":"create image_folder","description":"Executes the catalog action image_folder.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"color":{"type":"string","maxLength":32}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_folder_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"image_folder_list","summary":"list image_folder","description":"Executes the catalog action image_folder.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/image_folder_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/image_folder_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-folders/{id}":{"patch":{"operationId":"image_folder_update","summary":"update image_folder","description":"Executes the catalog action image_folder.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The image_folder id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"color":{"type":"string","maxLength":32},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_folder_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"image_folder_delete","summary":"delete image_folder","description":"Executes the catalog action image_folder.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The image_folder id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_folder_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"image_folder_read","summary":"read image_folder","description":"Executes the catalog action image_folder.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The image_folder id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_folder_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-library/generate":{"post":{"operationId":"image_library_generate","summary":"generate image_library","description":"Generate up to 4 images in one call (on-network FLUX first, fal as fallback) and store each delivered image as a library row. Billing gates on the estimated cost upfront, but each provider call settles and refunds itself, so only images actually delivered are billed or saved and a partial or failed batch never charges for images you didn't get. NEXT: image_library_list to see the library. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048},"r2_key":{"type":"string","maxLength":512},"width":{"type":"integer"},"height":{"type":"integer"},"format":{"type":"string","maxLength":8},"prompt":{"type":"string","maxLength":2000},"provider":{"type":"string","maxLength":64},"source":{"type":"string","enum":["generated","upload","edit"]},"folder_id":{"type":"string","maxLength":64},"title":{"type":"string","maxLength":200},"tags":{"type":"string","maxLength":4000},"is_favorite":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_library_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"expensive","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-library/save":{"post":{"operationId":"image_library_save","summary":"save image_library","description":"Save an image into the permanent library from a public https URL, a data:image URL, or an R2 key this tenant already owns (the edit-studio hand-off), in one call. Only a key minted by this tenant's own image routes is accepted, and a plain https URL must pass the SSRF guard, so you cannot file someone else's storage or an unsafe fetch target into the library. NEXT: image_library_update to tag, favorite, or file it into a folder. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048},"r2_key":{"type":"string","maxLength":512},"width":{"type":"integer"},"height":{"type":"integer"},"format":{"type":"string","maxLength":8},"prompt":{"type":"string","maxLength":2000},"provider":{"type":"string","maxLength":64},"source":{"type":"string","enum":["generated","upload","edit"]},"folder_id":{"type":"string","maxLength":64},"title":{"type":"string","maxLength":200},"tags":{"type":"string","maxLength":4000},"is_favorite":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_library_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-library/update":{"post":{"operationId":"image_library_update","summary":"update image_library","description":"Edit a library image's metadata: title, tags, folder_id, and is_favorite only. The image's provenance columns (url, r2_key, prompt, provider, source) are immutable after creation, so passing any other field is refused outright rather than silently ignored. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048},"r2_key":{"type":"string","maxLength":512},"width":{"type":"integer"},"height":{"type":"integer"},"format":{"type":"string","maxLength":8},"prompt":{"type":"string","maxLength":2000},"provider":{"type":"string","maxLength":64},"source":{"type":"string","enum":["generated","upload","edit"]},"folder_id":{"type":"string","maxLength":64},"title":{"type":"string","maxLength":200},"tags":{"type":"string","maxLength":4000},"is_favorite":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_library_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-library/delete":{"post":{"operationId":"image_library_delete","summary":"delete image_library","description":"Delete a library image row and best-effort clean up its R2 object. The object delete is fail-open by design: if it errors the row is still gone and the leftover object is treated as storage cost, not a custody risk, so this call never fails on that step. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048},"r2_key":{"type":"string","maxLength":512},"width":{"type":"integer"},"height":{"type":"integer"},"format":{"type":"string","maxLength":8},"prompt":{"type":"string","maxLength":2000},"provider":{"type":"string","maxLength":64},"source":{"type":"string","enum":["generated","upload","edit"]},"folder_id":{"type":"string","maxLength":64},"title":{"type":"string","maxLength":200},"tags":{"type":"string","maxLength":4000},"is_favorite":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_library_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-library/{id}":{"get":{"operationId":"image_library_read","summary":"read image_library","description":"Executes the catalog action image_library.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The image_library id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/image_library_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-library":{"get":{"operationId":"image_library_list","summary":"list image_library","description":"Executes the catalog action image_library.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/image_library_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/image_library_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/image-library/search":{"get":{"operationId":"image_library_search","summary":"search image_library","description":"Executes the catalog action image_library.search (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["images"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/image_library_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/image_library_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/interactions/create":{"post":{"operationId":"interaction_create","summary":"create interaction","description":"Log an interaction — call, meeting, email, message, visit, payment, or other — against a contact. The ONE activity-logging door every lane funnels through, so the contact's last_contact_at freshness bumps no matter which surface logged the touch; the bump never moves backward, so importing older history can never regress a fresher touch. Accepts contact_name, contact_email or contact_phone in place of contact_id. NEXT: contact_read to see the bumped last_contact_at. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":"string","maxLength":40},"interaction_type":{"type":"string","enum":["meeting","call","email","message","visit","payment","other"]},"summary":{"type":"string","maxLength":2000},"occurred_at":{"type":"integer","description":"Unix epoch milliseconds."},"source_ref":{"type":"string","maxLength":80}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/interaction_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/interactions":{"put":{"operationId":"interaction_upsert","summary":"upsert interaction","description":"Executes the catalog action interaction.upsert (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"contact_id":{"type":"string","maxLength":40},"interaction_type":{"type":"string","enum":["meeting","call","email","message","visit","payment","other"]},"summary":{"type":"string","maxLength":2000},"occurred_at":{"type":"integer","description":"Unix epoch milliseconds."},"source_ref":{"type":"string","maxLength":80}},"required":["contact_id","interaction_type","summary","source_ref"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/interaction_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"interaction_list","summary":"list interaction","description":"Executes the catalog action interaction.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/interaction_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/interaction_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/interactions/{id}":{"get":{"operationId":"interaction_read","summary":"read interaction","description":"Executes the catalog action interaction.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["crm"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The interaction id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/interaction_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/create":{"post":{"operationId":"invoice_create","summary":"create invoice","description":"ONE call creates the whole document: claims the next invoice number, then writes the header plus every line in `items` ([{description, quantity, unit_price_cents}], integer CENTS). client_name finds a client by name or creates one. Birth status 'paid' needs items in the same call. tax_scheme sg_gst or my_sst taxes each line by its tax_code (refusals: see tax_scheme). When present, the second content block is the invoice as copy-ready text, shown with a Copy button where the host draws MCP Apps; if the user says they cannot see the invoice, give them that block word for word; share:true adds a client link, only when the user asks for one. NEXT: invoice_payment_record to record money-in. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","paid","cancelled"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"due_date":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"payment_terms":{"type":"string","maxLength":500},"source_type":{"type":"string","enum":["quote","recurring","quick_sale"]},"source_id":{"type":"string","maxLength":40},"cash_sale":{"type":"integer"},"payment_method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"sent_at":{"type":"integer","description":"Unix epoch milliseconds."},"paid_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1},"fx_rate_to_sgd_ppm":{"type":"integer","minimum":1,"maximum":1000000000},"fx_rate_date":{"type":"string","maxLength":10}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/update":{"post":{"operationId":"invoice_update","summary":"update invoice","description":"Edits an invoice's header fields and status. status 'paid' cannot be set here — it derives from the payment ledger, so call invoice_payment_record instead. Status moves are machine-checked (draft to sent/cancelled, sent to cancelled); cancelled is terminal and a paid invoice never reopens by hand. A move to 'sent' stamps sent_at automatically when omitted, and currency is ledger-locked once any live payment exists. An agent's change to notes or payment_terms on an issued invoice waits for the owner's approval; on a draft it does not. tax_scheme and prices_include_tax are fixed at creation, as is the tax rate. NEXT: invoice_payment_record to settle money, invoice_read to verify. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","paid","cancelled"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"due_date":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"payment_terms":{"type":"string","maxLength":500},"source_type":{"type":"string","enum":["quote","recurring","quick_sale"]},"source_id":{"type":"string","maxLength":40},"cash_sale":{"type":"integer"},"payment_method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"sent_at":{"type":"integer","description":"Unix epoch milliseconds."},"paid_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1},"fx_rate_to_sgd_ppm":{"type":"integer","minimum":1,"maximum":1000000000},"fx_rate_date":{"type":"string","maxLength":10}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/share":{"post":{"operationId":"invoice_share","summary":"share invoice","description":"Returns share_url, the client's view link for this invoice, and the full document (parties, lines, totals in integer CENTS) in one call. action: 'get' (default) returns the live link; 'rotate' replaces it and the old link stops working; 'revoke' turns it off. A link the owner turned off stays off for agents: 'get' never re-issues it, and an agent's 'rotate' waits for the owner's approval. Anyone with the link can open the page until the invoice is cancelled or 90 days after payment (see link_serving). There is no PDF file yet; the link opens a print-ready page the client can print or save as PDF. Nothing is sent: give the link to the owner, who decides whether it goes to the client. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","paid","cancelled"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"due_date":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"payment_terms":{"type":"string","maxLength":500},"source_type":{"type":"string","enum":["quote","recurring","quick_sale"]},"source_id":{"type":"string","maxLength":40},"cash_sale":{"type":"integer"},"payment_method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"sent_at":{"type":"integer","description":"Unix epoch milliseconds."},"paid_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1},"fx_rate_to_sgd_ppm":{"type":"integer","minimum":1,"maximum":1000000000},"fx_rate_date":{"type":"string","maxLength":10}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/payer_confirmation":{"post":{"operationId":"invoice_payer_confirmation","summary":"payer_confirmation invoice","description":"Acts on a payer's report, sent from the invoice's client page, that they have paid. action 'accept' records the payment with the same writer as invoice_payment_record, graded counterparty_confirmed: the amount is amount_cents (or amount) when given, else the balance still owed; occurred_at defaults to when the payer reported. An agent's accept waits for the owner's approval. action 'dismiss' closes a report whose money did not arrive. Find reports in invoice_read's payer_confirmations. Refuses a report already accepted or dismissed with CONFLICT (invoice_read shows it), and an invoice with nothing owed unless amount_cents comes with allow_overpayment. Nothing is sent to the payer. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","paid","cancelled"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"due_date":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"payment_terms":{"type":"string","maxLength":500},"source_type":{"type":"string","enum":["quote","recurring","quick_sale"]},"source_id":{"type":"string","maxLength":40},"cash_sale":{"type":"integer"},"payment_method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"sent_at":{"type":"integer","description":"Unix epoch milliseconds."},"paid_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1},"fx_rate_to_sgd_ppm":{"type":"integer","minimum":1,"maximum":1000000000},"fx_rate_date":{"type":"string","maxLength":10}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/debit_note":{"post":{"operationId":"invoice_debit_note","summary":"debit_note invoice","description":"Issues a numbered debit note that raises what an issued ('sent' or 'paid') invoice is owed: an extra charge, or a price or tax correction. It is numbered from the debit note series and adds amount_cents (or a decimal STRING amount), tax at the invoice's rate inside, in its currency; a 'paid' invoice goes back to 'sent' until the rest is paid. Refuses a draft (change its lines instead), a cancelled invoice, an invoice with no lines, another currency, and a paid invoice with no payment recorded (record it first with invoice_payment_record); every refusal names the call to send. Never deleted: undo one with a credit_note. An agent's call parks for approval. Nothing is sent. NEXT: invoice_read. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","paid","cancelled"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"due_date":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"payment_terms":{"type":"string","maxLength":500},"source_type":{"type":"string","enum":["quote","recurring","quick_sale"]},"source_id":{"type":"string","maxLength":40},"cash_sale":{"type":"integer"},"payment_method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"sent_at":{"type":"integer","description":"Unix epoch milliseconds."},"paid_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1},"fx_rate_to_sgd_ppm":{"type":"integer","minimum":1,"maximum":1000000000},"fx_rate_date":{"type":"string","maxLength":10}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":true,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/reissue":{"post":{"operationId":"invoice_reissue","summary":"reissue invoice","description":"Voids a 'sent' invoice with no money on it and reissues it under the next number: 'sent', dated today, same client, currency, notes, terms and lines, tax on today's rules, the old days to pay unless due_date is sent. A foreign-currency sg_gst invoice issued before today needs fx_rate_to_sgd and fx_rate_date for today unless its rate is dated today. The old one is cancelled, its client link stops working, both trails link them. Paid, part-paid, credited or written-off invoices refuse: correct them with a credit note (invoice_adjustment_record). When present, the second content block is the new invoice as copy-ready text. Nothing is sent. NEXT: invoice_share only if the user asks for a link. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","paid","cancelled"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"due_date":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"payment_terms":{"type":"string","maxLength":500},"source_type":{"type":"string","enum":["quote","recurring","quick_sale"]},"source_id":{"type":"string","maxLength":40},"cash_sale":{"type":"integer"},"payment_method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"sent_at":{"type":"integer","description":"Unix epoch milliseconds."},"paid_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1},"fx_rate_to_sgd_ppm":{"type":"integer","minimum":1,"maximum":1000000000},"fx_rate_date":{"type":"string","maxLength":10}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/promise_set":{"post":{"operationId":"invoice_promise_set","summary":"promise_set invoice","description":"Records the date a client promised to pay an issued invoice that still has money owed: promised_payment_date 'YYYY-MM-DD', the business's own date, today or later. clear true removes it. invoice_read then shows promise_status: pending until that business day ends, kept when paid in full by then, broken after it. A broken promise makes promise_follow_up the default purpose of invoice_message_prepare. Each change is kept in the invoice's activity as promise_set. Refuses a draft, a cancelled invoice and one with nothing owed (CONFLICT), and a past or malformed date (VALIDATION_ERROR). Nothing is sent. NEXT: invoice_read. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","paid","cancelled"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"due_date":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"payment_terms":{"type":"string","maxLength":500},"source_type":{"type":"string","enum":["quote","recurring","quick_sale"]},"source_id":{"type":"string","maxLength":40},"cash_sale":{"type":"integer"},"payment_method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"sent_at":{"type":"integer","description":"Unix epoch milliseconds."},"paid_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1},"fx_rate_to_sgd_ppm":{"type":"integer","minimum":1,"maximum":1000000000},"fx_rate_date":{"type":"string","maxLength":10}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/{id}":{"get":{"operationId":"invoice_read","summary":"read invoice","description":"Returns one invoice with its money and state worked out on read, in integer CENTS: subtotal_cents, tax_cents, total_cents, paid_cents, credited_cents, adjusted_cents, remaining_cents (copy remaining_cents, never compute it). state: draft, sent, partially_paid, overdue, written_off, paid or cancelled. Overdue means issued, still owed and due before today in the business time zone (sales_settings.timezone, unset = Asia/Singapore); days_overdue counts days there. activity lists the newest 50 events; viewed_count and last_viewed_at count every view. payer_confirmations lists the payer's \"I've paid\" reports. An unknown id refuses with NOT_FOUND: find it with invoice_list or invoice_search. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The invoice id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices":{"get":{"operationId":"invoice_list","summary":"list invoice","description":"Lists your invoices, newest first (200 at most; pass limit and cursor to page). Every row carries the same worked-out money and state as invoice_read: total_cents, remaining_cents, state, is_overdue, days_overdue (integer CENTS, business days). To find what to chase, pass state 'overdue': only invoices issued, still owed and due before today in the business time zone come back. payer_confirmations_pending counts the payer's \"I've paid\" reports waiting on each row. Refuses an unlisted state, a limit outside 1-200 or a malformed cursor with VALIDATION_ERROR: resend with a listed state, without limit, or with next_cursor exactly as returned. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/invoice_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/invoice_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoices/search":{"get":{"operationId":"invoice_search","summary":"search invoice","description":"Finds invoices whose text fields (invoice number, notes, payment terms) contain every word of q. Rows carry the same worked-out money and state as invoice_read: total_cents, remaining_cents, state, is_overdue (integer CENTS), and payer_confirmations_pending. Refuses an empty q with VALIDATION_ERROR: send the invoice number, such as INV-2026-0001, or a word from its notes. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/invoice_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/invoice_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-clients":{"post":{"operationId":"invoice_client_create","summary":"create invoice_client","description":"Executes the catalog action invoice_client.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"notes":{"type":"string","maxLength":1000},"contact_id":{"type":"string","maxLength":40},"reminder_cadence":{"type":"string","maxLength":16,"enum":["standard","from_due","overdue_only","off"]},"message_language":{"type":"string","maxLength":8,"enum":["en","ms","zh"]}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_client_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"put":{"operationId":"invoice_client_upsert","summary":"upsert invoice_client","description":"Executes the catalog action invoice_client.upsert (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"notes":{"type":"string","maxLength":1000},"contact_id":{"type":"string","maxLength":40},"reminder_cadence":{"type":"string","maxLength":16,"enum":["standard","from_due","overdue_only","off"]},"message_language":{"type":"string","maxLength":8,"enum":["en","ms","zh"]}},"required":["name","email"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_client_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"invoice_client_list","summary":"list invoice_client","description":"Executes the catalog action invoice_client.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/invoice_client_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/invoice_client_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-clients/{id}":{"patch":{"operationId":"invoice_client_update","summary":"update invoice_client","description":"Executes the catalog action invoice_client.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The invoice_client id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"notes":{"type":"string","maxLength":1000},"contact_id":{"type":"string","maxLength":40},"reminder_cadence":{"type":"string","maxLength":16,"enum":["standard","from_due","overdue_only","off"]},"message_language":{"type":"string","maxLength":8,"enum":["en","ms","zh"]},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_client_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"invoice_client_delete","summary":"delete invoice_client","description":"Executes the catalog action invoice_client.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The invoice_client id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_client_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"invoice_client_read","summary":"read invoice_client","description":"Executes the catalog action invoice_client.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The invoice_client id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_client_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-clients/search":{"get":{"operationId":"invoice_client_search","summary":"search invoice_client","description":"Executes the catalog action invoice_client.search (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/invoice_client_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/invoice_client_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-clients/link_tenant":{"post":{"operationId":"invoice_client_link_tenant","summary":"link_tenant invoice_client","description":"Asserts that a billing client IS an on-platform tenant (or pass counterparty_tenant_id null to unlink) and retro-stamps that client's existing invoices with the link in the same call — invoices_stamped in the result is the count. Linking requires the counterparty's 'cross_tenant_settlement' consent AND a live network relationship (an active match or a deal thread); unlinking passes neither gate, since it withdraws your own assertion rather than making a new one. NEXT: invoice_client_read to read back what linked. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"notes":{"type":"string","maxLength":1000},"contact_id":{"type":"string","maxLength":40},"reminder_cadence":{"type":"string","maxLength":16,"enum":["standard","from_due","overdue_only","off"]},"message_language":{"type":"string","maxLength":8,"enum":["en","ms","zh"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_client_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":true,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-items/create":{"post":{"operationId":"invoice_item_create","summary":"create invoice_item","description":"Adds one line item to an invoice. unit_price_cents is integer CENTS, 0 or more ($15.00 → 1500); quantity is 0.001 to 1,000,000 with up to 3 decimals (1.5 hours → 1.5); unit is an optional label (hr, kg); discount_bps is an optional line discount (10% → 1000). quantity × unit_price_cents is at most 10,000,000,000. Refuses a negative price (send discount_bps instead), a 'paid' parent (retire the payment first) and a 'cancelled' parent (issue a new invoice). Re-derives the invoice's paid/sent status. tax_code is the line's code under the document's tax_scheme, refused on a document without a scheme. NEXT: invoice_read to see the updated total. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invoice_id":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":500},"quantity":{"type":"integer","minimum":1,"maximum":1000000},"unit_price_cents":{"type":"integer","minimum":0,"maximum":10000000000},"position":{"type":"integer"},"unit":{"type":"string","maxLength":50},"discount_bps":{"type":"integer","minimum":0,"maximum":10000},"tax_code":{"type":"string","maxLength":20,"enum":["standard","zero_rated","exempt","out_of_scope","sales_10","sales_5","service_8","service_6"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-items/update":{"post":{"operationId":"invoice_item_update","summary":"update invoice_item","description":"Edits a line item's description, quantity, unit, price or discount, or re-parents it to another invoice. expected_updated_at is required: the line's updated_at from your read; without it nothing is written and the refusal names the current value; a line changed since then answers CONFLICT. Bounds: unit_price_cents is integer CENTS, 0 or more; quantity 0.001 to 1,000,000 (3 decimals); discount_bps 0 to 10000; quantity × unit_price_cents at most 10,000,000,000. unit \"\" clears the unit. Refuses when the current or target invoice is paid or cancelled. tax_code is the line's code under the document's tax_scheme, refused on a document without a scheme. NEXT: invoice_read to see the updated total. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invoice_id":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":500},"quantity":{"type":"integer","minimum":1,"maximum":1000000},"unit_price_cents":{"type":"integer","minimum":0,"maximum":10000000000},"position":{"type":"integer"},"unit":{"type":"string","maxLength":50},"discount_bps":{"type":"integer","minimum":0,"maximum":10000},"tax_code":{"type":"string","maxLength":20,"enum":["standard","zero_rated","exempt","out_of_scope","sales_10","sales_5","service_8","service_6"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-items/delete":{"post":{"operationId":"invoice_item_delete","summary":"delete invoice_item","description":"Soft-deletes a line item — it leaves the invoice and its derived total immediately, but the row is retired for audit history, never removed. expected_updated_at is required: the line's updated_at from your read (invoice_item_read); without it the removal is refused and the refusal names the current value. Refuses when the parent invoice is 'paid' (ledger-locked: retire the payment first) or 'cancelled' (terminal: its lines stay as issued), and with CONFLICT when the line changed since that read (read it again). If retiring the line settles the remaining balance on a partially-paid invoice, the parent re-derives to 'paid' by itself. NEXT: invoice_read to see the updated total. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"invoice_id":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":500},"quantity":{"type":"integer","minimum":1,"maximum":1000000},"unit_price_cents":{"type":"integer","minimum":0,"maximum":10000000000},"position":{"type":"integer"},"unit":{"type":"string","maxLength":50},"discount_bps":{"type":"integer","minimum":0,"maximum":10000},"tax_code":{"type":"string","maxLength":20,"enum":["standard","zero_rated","exempt","out_of_scope","sales_10","sales_5","service_8","service_6"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-items/{id}":{"get":{"operationId":"invoice_item_read","summary":"read invoice_item","description":"Executes the catalog action invoice_item.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The invoice_item id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-items":{"get":{"operationId":"invoice_item_list","summary":"list invoice_item","description":"Executes the catalog action invoice_item.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/invoice_item_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/invoice_item_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-recurring":{"post":{"operationId":"invoice_recurring_create","summary":"create invoice_recurring","description":"Executes the catalog action invoice_recurring.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"title":{"type":"string","maxLength":200},"items_json":{"type":"string","maxLength":8000},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"frequency":{"type":"string","enum":["weekly","monthly","yearly"]},"day_of_month":{"type":"integer"},"day_of_week":{"type":"integer"},"next_due":{"type":"integer","description":"Unix epoch milliseconds."},"is_active":{"type":"integer"},"notes":{"type":"string","maxLength":2000},"last_generated_at":{"type":"integer","description":"Unix epoch milliseconds."},"total_generated":{"type":"integer"},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst","none"]},"ends_on":{"type":"integer","description":"Unix epoch milliseconds."},"max_invoices":{"type":"integer","minimum":1,"maximum":1000}},"required":["title","items_json","frequency","next_due"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_recurring_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"invoice_recurring_list","summary":"list invoice_recurring","description":"Executes the catalog action invoice_recurring.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/invoice_recurring_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/invoice_recurring_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-recurring/{id}":{"patch":{"operationId":"invoice_recurring_update","summary":"update invoice_recurring","description":"Executes the catalog action invoice_recurring.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The invoice_recurring id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"title":{"type":"string","maxLength":200},"items_json":{"type":"string","maxLength":8000},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"frequency":{"type":"string","enum":["weekly","monthly","yearly"]},"day_of_month":{"type":"integer"},"day_of_week":{"type":"integer"},"next_due":{"type":"integer","description":"Unix epoch milliseconds."},"is_active":{"type":"integer"},"notes":{"type":"string","maxLength":2000},"last_generated_at":{"type":"integer","description":"Unix epoch milliseconds."},"total_generated":{"type":"integer"},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst","none"]},"ends_on":{"type":"integer","description":"Unix epoch milliseconds."},"max_invoices":{"type":"integer","minimum":1,"maximum":1000},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_recurring_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"invoice_recurring_delete","summary":"delete invoice_recurring","description":"Executes the catalog action invoice_recurring.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The invoice_recurring id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_recurring_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"invoice_recurring_read","summary":"read invoice_recurring","description":"Executes the catalog action invoice_recurring.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The invoice_recurring id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_recurring_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/invoice-recurring/skip":{"post":{"operationId":"invoice_recurring_skip","summary":"skip invoice_recurring","description":"Skips a recurring template's next invoice: next_due moves one period on (the template's own weekly, monthly or yearly day) and no invoice is made. A skip does not count toward max_invoices. Refuses NOT_FOUND for an id outside your tenant (call invoice_recurring_list) and CONFLICT when the template has ended (raise ends_on or max_invoices with invoice_recurring_update) or changed since expected_updated_at (read it again). Each call skips one run: to skip the run after, send expected_updated_at from this answer. Nothing is sent. NEXT: invoice_recurring_read. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"title":{"type":"string","maxLength":200},"items_json":{"type":"string","maxLength":8000},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"frequency":{"type":"string","enum":["weekly","monthly","yearly"]},"day_of_month":{"type":"integer"},"day_of_week":{"type":"integer"},"next_due":{"type":"integer","description":"Unix epoch milliseconds."},"is_active":{"type":"integer"},"notes":{"type":"string","maxLength":2000},"last_generated_at":{"type":"integer","description":"Unix epoch milliseconds."},"total_generated":{"type":"integer"},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst","none"]},"ends_on":{"type":"integer","description":"Unix epoch milliseconds."},"max_invoices":{"type":"integer","minimum":1,"maximum":1000}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/invoice_recurring_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/market-signals/create":{"post":{"operationId":"market_signal_create","summary":"create market_signal","description":"Post to one of the tenant's 8 market-signal wish-bar slots — a buy, sell, swap, capacity-offer or capacity-request visible ONLY to platform-matched partners, never the wider network. The door counts your OPEN signals server-side before writing: the 9th is refused with slots_used/slots_max in the error rather than silently queued. NEXT: market_signal_update to close or fulfil a signal and free a slot. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"signal_type":{"type":"string","enum":["buy","sell","swap","capacity_offer","capacity_request"]},"product":{"type":"string","maxLength":200},"quantity":{"type":"string","maxLength":100},"price_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"deadline":{"type":"integer","description":"Unix epoch milliseconds."},"location":{"type":"string","maxLength":120},"notes":{"type":"string","maxLength":1000},"status":{"type":"string","enum":["open","fulfilled","closed"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market_signal_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/market-signals/{id}":{"patch":{"operationId":"market_signal_update","summary":"update market_signal","description":"Executes the catalog action market_signal.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The market_signal id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"signal_type":{"type":"string","enum":["buy","sell","swap","capacity_offer","capacity_request"]},"product":{"type":"string","maxLength":200},"quantity":{"type":"string","maxLength":100},"price_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"deadline":{"type":"integer","description":"Unix epoch milliseconds."},"location":{"type":"string","maxLength":120},"notes":{"type":"string","maxLength":1000},"status":{"type":"string","enum":["open","fulfilled","closed"]},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market_signal_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"market_signal_read","summary":"read market_signal","description":"Executes the catalog action market_signal.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The market_signal id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/market_signal_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/market-signals":{"get":{"operationId":"market_signal_list","summary":"list market_signal","description":"Executes the catalog action market_signal.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/market_signal_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/market_signal_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-customers/create":{"post":{"operationId":"myinvois_customer_create","summary":"create myinvois_customer","description":"Register a buyer in the LHDN buyer registry so it attaches to future e-invoices with one pick (customer_id) instead of typing the party every time. Validates the TIN format, and validates state_code against the LHDN state table when you send one — a buyer with no real TIN uses the LHDN generic TIN (EI00000000010 Malaysian public, EI00000000020 foreign) instead. NEXT: myinvois_invoice_generate with customer_id. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"tin":{"type":"string","maxLength":30},"brn":{"type":"string","maxLength":50},"sst_number":{"type":"string","maxLength":50},"contact_number":{"type":"string","maxLength":50},"email":{"type":"string","maxLength":320},"address":{"type":"string","maxLength":500},"city":{"type":"string","maxLength":100},"state_code":{"type":"string","maxLength":10},"postal_code":{"type":"string","maxLength":20},"country_code":{"type":"string","maxLength":3},"notes":{"type":"string","maxLength":2000}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_customer_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-customers/update":{"post":{"operationId":"myinvois_customer_update","summary":"update myinvois_customer","description":"Edit a registered buyer's LHDN details — send only the fields you are changing. When tin is included it is re-checked against the same format gate create runs, and when state_code is included it is re-checked against the LHDN state table, so an edited buyer stays valid to generate against. Never touches e-invoices already generated for this buyer; each one sealed its own copy of the buyer party. NEXT: myinvois_customer_list to find the id. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"tin":{"type":"string","maxLength":30},"brn":{"type":"string","maxLength":50},"sst_number":{"type":"string","maxLength":50},"contact_number":{"type":"string","maxLength":50},"email":{"type":"string","maxLength":320},"address":{"type":"string","maxLength":500},"city":{"type":"string","maxLength":100},"state_code":{"type":"string","maxLength":10},"postal_code":{"type":"string","maxLength":20},"country_code":{"type":"string","maxLength":3},"notes":{"type":"string","maxLength":2000}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_customer_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-customers/{id}":{"delete":{"operationId":"myinvois_customer_delete","summary":"delete myinvois_customer","description":"Delete a registered buyer. E-invoices already generated for this buyer keep their sealed copy of the buyer party and are never touched. Refuses an id outside your tenant with NOT_FOUND: call myinvois_customer_list for valid ids. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The myinvois_customer id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_customer_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"myinvois_customer_read","summary":"read myinvois_customer","description":"Read one registered buyer by id: name, TIN, BRN, SST number, address and contact. myinvois_invoice_generate seals the name, TIN, BRN, address and contact; the buyer's SST number stays on this record and is not sealed on the e-invoice. Refuses an id outside your tenant with NOT_FOUND: call myinvois_customer_list or myinvois_customer_search for valid ids. NEXT: myinvois_invoice_generate with this id as customer_id. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The myinvois_customer id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_customer_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-customers":{"get":{"operationId":"myinvois_customer_list","summary":"list myinvois_customer","description":"List registered buyers, newest first, to pick a customer_id for myinvois_invoice_generate. An empty list means none are registered yet: call myinvois_customer_create, or send an inline buyer {name, tin} to myinvois_invoice_generate instead. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/myinvois_customer_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/myinvois_customer_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-customers/search":{"get":{"operationId":"myinvois_customer_search","summary":"search myinvois_customer","description":"Find registered buyers by text: every word must match one of the buyer's text fields, such as name, TIN, BRN, email or address. Refuses an empty q with VALIDATION_ERROR. No match returns an empty list: call myinvois_customer_create to register the buyer. NEXT: myinvois_invoice_generate with the id as customer_id. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/myinvois_customer_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/myinvois_customer_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-invoices/generate":{"post":{"operationId":"myinvois_invoice_generate","summary":"generate myinvois_invoice","description":"Mint a sealed LHDN e-invoice in ONE call: invoice_type, line_items (unit_price_cents in integer CENTS, tax_rate_bps in basis points), and a buyer as customer_id or an inline buyer object. Refuses until myinvois_settings_save is done; invoice_type 02/03/04 also needs original_invoice_id naming a type-01 invoice with a recorded LHDN UUID, checked BEFORE the number is claimed, so a rejected note never burns a number. The result is immutable and carries portal_field_sheet; Simpler never submits it to LHDN. NEXT: the owner keys the field sheet into the MyInvois portal form, then myinvois_invoice_record_submission with the UUID the portal assigns. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"customer_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"invoice_type":{"type":"string","enum":["01","02","03","04"]},"status":{"type":"string","enum":["generated","submitted"]},"issue_date":{"type":"string","maxLength":10},"currency":{"type":"string","maxLength":3},"subtotal_cents":{"type":"integer"},"tax_cents":{"type":"integer"},"total_cents":{"type":"integer"},"buyer_name":{"type":"string","maxLength":255},"buyer_tin":{"type":"string","maxLength":30},"invoice_data":{"type":"string","maxLength":200000},"reference_invoice_id":{"type":"string","maxLength":40},"lhdn_uuid":{"type":"string","maxLength":100},"lhdn_long_id":{"type":"string","maxLength":200},"lhdn_submitted_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-invoices/record_submission":{"post":{"operationId":"myinvois_invoice_record_submission","summary":"record_submission myinvois_invoice","description":"Record the UUID the LHDN MyInvois portal assigned after the owner keyed this e-invoice into the portal (its form or LHDN's Excel batch template). Simpler never submits to LHDN and never calls the MyInvois API; this only stores the UUID the owner copies back. Only a type-01 original accepts a UUID: credit, debit and refund notes are refused (they link through BillingReference), so record the UUID on the original instead. Moves status generated to submitted; calling it again on a submitted invoice corrects a mistyped UUID. NEXT: myinvois_invoice_read to see the UUID attached. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"customer_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"invoice_type":{"type":"string","enum":["01","02","03","04"]},"status":{"type":"string","enum":["generated","submitted"]},"issue_date":{"type":"string","maxLength":10},"currency":{"type":"string","maxLength":3},"subtotal_cents":{"type":"integer"},"tax_cents":{"type":"integer"},"total_cents":{"type":"integer"},"buyer_name":{"type":"string","maxLength":255},"buyer_tin":{"type":"string","maxLength":30},"invoice_data":{"type":"string","maxLength":200000},"reference_invoice_id":{"type":"string","maxLength":40},"lhdn_uuid":{"type":"string","maxLength":100},"lhdn_long_id":{"type":"string","maxLength":200},"lhdn_submitted_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-invoices/{id}":{"get":{"operationId":"myinvois_invoice_read","summary":"read myinvois_invoice","description":"Read one sealed e-invoice by id, with its portal_field_sheet: the document's values laid out to key into the LHDN MyInvois portal form (e-invoice details, supplier, buyer, each line, totals), coded values with their meaning. Simpler never submits to LHDN; portal_field_sheet.portal_routes names the two portal routes (the online form and LHDN's Excel batch template). Refuses an id outside your tenant with NOT_FOUND: call myinvois_invoice_list for valid ids. NEXT: after the portal accepts it, myinvois_invoice_record_submission with the UUID it assigns. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The myinvois_invoice id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_invoice_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-invoices":{"get":{"operationId":"myinvois_invoice_list","summary":"list myinvois_invoice","description":"Executes the catalog action myinvois_invoice.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/myinvois_invoice_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/myinvois_invoice_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-invoices/search":{"get":{"operationId":"myinvois_invoice_search","summary":"search myinvois_invoice","description":"Find generated e-invoices by text: every word must match one of the document's text fields, such as invoice number, buyer name or buyer TIN. Refuses an empty q with VALIDATION_ERROR. Rows carry no field sheet: call myinvois_invoice_read with the id for portal_field_sheet. No match returns an empty list: call myinvois_invoice_list to browse the newest. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/myinvois_invoice_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/myinvois_invoice_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-settings/save":{"post":{"operationId":"myinvois_settings_save","summary":"save myinvois_settings","description":"Save the one-time LHDN supplier profile — the door checks for an existing row on your tenant and creates or updates in place, so this is the only write you ever call. Validates the TIN format, checks msic_code is a 5-digit MSIC code, and checks state_code against the LHDN state table before the row moves. NEXT: myinvois_invoice_generate reads this profile as the supplier party of every e-invoice. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","enum":["default"]},"company_name":{"type":"string","maxLength":255},"tin":{"type":"string","maxLength":30},"brn":{"type":"string","maxLength":50},"sst_number":{"type":"string","maxLength":50},"tourism_tax_number":{"type":"string","maxLength":50},"contact_number":{"type":"string","maxLength":50},"email":{"type":"string","maxLength":320},"msic_code":{"type":"string","maxLength":10},"business_activity":{"type":"string","maxLength":500},"address_line1":{"type":"string","maxLength":500},"address_line2":{"type":"string","maxLength":500},"city":{"type":"string","maxLength":100},"postal_code":{"type":"string","maxLength":20},"state_code":{"type":"string","maxLength":10},"country_code":{"type":"string","maxLength":3},"invoice_prefix":{"type":"string","maxLength":10},"default_currency":{"type":"string","maxLength":3},"default_payment_terms":{"type":"string","maxLength":500}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_settings_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":true,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-settings/{id}":{"get":{"operationId":"myinvois_settings_read","summary":"read myinvois_settings","description":"Read the supplier profile by id: the party printed on every e-invoice (company, TIN, BRN, SST and tourism tax numbers, MSIC code, address). Refuses an id outside your tenant with NOT_FOUND: call myinvois_settings_list, which returns the one profile row. NEXT: myinvois_settings_save to change it. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The myinvois_settings id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_settings_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-settings":{"get":{"operationId":"myinvois_settings_list","summary":"list myinvois_settings","description":"List the supplier profile: at most one row per tenant. An empty list means setup is not done, and myinvois_invoice_generate refuses until it is: call myinvois_settings_save with the company, TIN, BRN, MSIC code and address. NEXT: myinvois_invoice_generate. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/myinvois_settings_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/myinvois_settings_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-templates/create":{"post":{"operationId":"myinvois_template_create","summary":"create myinvois_template","description":"Save a reusable line-item preset so a repeat invoice's items do not get re-typed. line_items_json is parsed and each item validated by the SAME checker myinvois_invoice_generate uses (description, quantity, unit_price_cents in integer CENTS, tax_rate_bps in basis points, tax_type/classification_code/unit_code against the LHDN code tables) and re-serialized canonically, so a saved template's items are always generate-ready. NEXT: myinvois_template_list to pull the items back out for a generate call. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":500},"line_items_json":{"type":"string","maxLength":8000},"payment_terms":{"type":"string","maxLength":500},"notes":{"type":"string","maxLength":2000}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_template_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-templates/update":{"post":{"operationId":"myinvois_template_update","summary":"update myinvois_template","description":"Edit a saved line-item preset. When line_items_json is included it is re-parsed and every item re-validated exactly as create does, so an edited template cannot drift into a shape myinvois_invoice_generate would reject. NEXT: myinvois_template_list to find the id. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":500},"line_items_json":{"type":"string","maxLength":8000},"payment_terms":{"type":"string","maxLength":500},"notes":{"type":"string","maxLength":2000}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_template_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-templates/{id}":{"delete":{"operationId":"myinvois_template_delete","summary":"delete myinvois_template","description":"Delete a saved line-item preset. E-invoices generated from it are never touched: each one sealed its own lines. Refuses an id outside your tenant with NOT_FOUND: call myinvois_template_list for valid ids. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The myinvois_template id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_template_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"myinvois_template_read","summary":"read myinvois_template","description":"Read one line-item preset by id. Its line_items_json holds generate-ready items: pass them as line_items to myinvois_invoice_generate. Refuses an id outside your tenant with NOT_FOUND: call myinvois_template_list for valid ids. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The myinvois_template id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/myinvois_template_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/myinvois-templates":{"get":{"operationId":"myinvois_template_list","summary":"list myinvois_template","description":"List saved line-item presets, newest first. Each line_items_json is generate-ready: pass its items as line_items to myinvois_invoice_generate. An empty list means none are saved yet: call myinvois_template_create. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["myinvois"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/myinvois_template_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/myinvois_template_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quotes/create":{"post":{"operationId":"quote_create","summary":"create quote","description":"ONE call creates the whole document: claims the next atomic quote number, then writes the header plus every line in `items` ([{description, quantity, unit_price_cents}], integer CENTS) together. client_name resolves an existing client by name or creates one. tax_scheme sg_gst or my_sst taxes each line by its tax_code (refusals: see tax_scheme). When present, the second content block is the quote as copy-ready text, shown with a Copy button where the host draws MCP Apps; if the user says they cannot see the quote, give them that block word for word; make a client link with quote_share only when the user asks for one. NEXT: quote_convert to turn the quote into its invoice. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"quote_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","accepted","declined","converted"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"valid_until":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"converted_invoice_id":{"type":"string","maxLength":40},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quotes/update":{"post":{"operationId":"quote_update","summary":"update quote","description":"Edits a quote's header fields and bookkeeping status (draft, sent, accepted, declined move freely). status 'converted' and converted_invoice_id are convert-flow-owned — hand-setting either refuses, and a converted quote is frozen: no status move and no header edit (it could convert again and double-bill; its invoice is the live document, so edit that). tax_scheme and prices_include_tax are fixed at creation, as is the tax rate. NEXT: quote_convert to create the invoice and record the link atomically. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"quote_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","accepted","declined","converted"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"valid_until":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"converted_invoice_id":{"type":"string","maxLength":40},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quotes/convert":{"post":{"operationId":"quote_convert","summary":"convert quote","description":"Converts a quote into its invoice in ONE call: claims the quote's 'converted' status first (so a lost race never creates an orphan invoice), copies every live line item across, and records converted_invoice_id — nothing else to do afterward. Refuses if the quote is already converted (the error carries converted_invoice_id) or declined (revive it with quote_update first), and refuses with nothing converted when the quote or its lines changed while it was converting (for example a quote_item call running at the same time): read the quote again with quote_read, then convert. NEXT: invoice_read on the new invoice. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"quote_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","accepted","declined","converted"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"valid_until":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"converted_invoice_id":{"type":"string","maxLength":40},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quotes/share":{"post":{"operationId":"quote_share","summary":"share quote","description":"Returns share_url, the client's view link for this quote, and the full document (parties, lines, totals in integer CENTS) in one call. action: 'get' (default) returns the live link; 'rotate' replaces it and the old link stops working; 'revoke' turns it off. A link the owner turned off stays off for agents: 'get' never re-issues it, and an agent's 'rotate' waits for the owner's approval. Anyone with the link can open the page until the quote expires, is declined or converted (see link_serving). There is no PDF file yet; the link opens a print-ready page the client can print or save as PDF. Nothing is sent: give the link to the owner, who decides whether it goes to the client. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"client_id":{"type":"string","maxLength":40},"quote_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","accepted","declined","converted"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"valid_until":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"converted_invoice_id":{"type":"string","maxLength":40},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quotes/{id}":{"get":{"operationId":"quote_read","summary":"read quote","description":"Returns one quote with subtotal_cents, tax_cents and total_cents worked out from its live lines (integer CENTS) and effective_status, which reads 'expired' once a sent quote's valid_until has passed (the stored status never says so). A quote with a tax_scheme also returns tax_summary (each line's tax code, net, tax and gross, and the per-code totals). Refuses an unknown id with NOT_FOUND: find the id with quote_list or quote_search. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The quote id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quotes":{"get":{"operationId":"quote_list","summary":"list quote","description":"Lists your quotes, newest first (200 at most; pass limit and cursor to page). Every row carries total_cents (integer CENTS) and effective_status, so an expired quote reads 'expired'. Refuses a limit outside 1-200 or a malformed cursor with VALIDATION_ERROR: resend without them, or with next_cursor exactly as returned. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/quote_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/quote_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quotes/search":{"get":{"operationId":"quote_search","summary":"search quote","description":"Finds quotes whose text fields (quote number, notes) contain every word of q; rows carry total_cents (integer CENTS) and effective_status. Refuses an empty q with VALIDATION_ERROR: send the quote number, such as QUO-2026-0001, or a word from its notes. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/quote_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/quote_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quote-items/create":{"post":{"operationId":"quote_item_create","summary":"create quote_item","description":"Adds one line item to a quote. unit_price_cents is integer CENTS, 0 or more ($15.00 → 1500); quantity is 0.001 to 1,000,000 with up to 3 decimals (1.5 hours → 1.5); unit is an optional label (hr, kg); discount_bps is an optional line discount (10% → 1000). quantity × unit_price_cents is at most 10,000,000,000. Refuses a negative price (send discount_bps instead), a line above the ceiling (split it) and any line on a converted quote (CONFLICT: change its invoice instead). tax_code is the line's code under the document's tax_scheme, refused on a document without a scheme. NEXT: quote_read to see the quote. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"quote_id":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":500},"quantity":{"type":"integer","minimum":1,"maximum":1000000},"unit_price_cents":{"type":"integer","minimum":0,"maximum":10000000000},"position":{"type":"integer"},"unit":{"type":"string","maxLength":50},"discount_bps":{"type":"integer","minimum":0,"maximum":10000},"tax_code":{"type":"string","maxLength":20,"enum":["standard","zero_rated","exempt","out_of_scope","sales_10","sales_5","service_8","service_6"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quote-items/update":{"post":{"operationId":"quote_item_update","summary":"update quote_item","description":"Edits a quote line's description, quantity, unit, price or discount, or moves it to another quote. expected_updated_at is required: the line's updated_at from your read; without it nothing is written and the refusal names the current value; a line changed since then answers CONFLICT. Refuses a line of a converted quote or a move onto one (CONFLICT: change its invoice instead). Bounds: unit_price_cents is integer CENTS, 0 or more; quantity 0.001 to 1,000,000 (3 decimals); discount_bps 0 to 10000; quantity × unit_price_cents at most 10,000,000,000. unit \"\" clears the unit. tax_code is the line's code under the document's tax_scheme, refused on a document without a scheme. NEXT: quote_read. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"quote_id":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":500},"quantity":{"type":"integer","minimum":1,"maximum":1000000},"unit_price_cents":{"type":"integer","minimum":0,"maximum":10000000000},"position":{"type":"integer"},"unit":{"type":"string","maxLength":50},"discount_bps":{"type":"integer","minimum":0,"maximum":10000},"tax_code":{"type":"string","maxLength":20,"enum":["standard","zero_rated","exempt","out_of_scope","sales_10","sales_5","service_8","service_6"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quote-items/delete":{"post":{"operationId":"quote_item_delete","summary":"delete quote_item","description":"Soft-deletes a quote line — it leaves the quote and its totals immediately, but the row is retired for audit history, never removed. expected_updated_at is required: the line's updated_at from your read (quote_item_read); without it the removal is refused and the refusal names the current value. Refuses with CONFLICT when the line changed since that read (read it again and decide on the current line) and on a converted quote (its lines are frozen: change its invoice instead). NEXT: quote_read to see the quote. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"quote_id":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":500},"quantity":{"type":"integer","minimum":1,"maximum":1000000},"unit_price_cents":{"type":"integer","minimum":0,"maximum":10000000000},"position":{"type":"integer"},"unit":{"type":"string","maxLength":50},"discount_bps":{"type":"integer","minimum":0,"maximum":10000},"tax_code":{"type":"string","maxLength":20,"enum":["standard","zero_rated","exempt","out_of_scope","sales_10","sales_5","service_8","service_6"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quote-items/{id}":{"get":{"operationId":"quote_item_read","summary":"read quote_item","description":"Executes the catalog action quote_item.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The quote_item id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/quote_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/quote-items":{"get":{"operationId":"quote_item_list","summary":"list quote_item","description":"Executes the catalog action quote_item.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/quote_item_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/quote_item_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/sales-settings":{"put":{"operationId":"sales_settings_upsert","summary":"upsert sales_settings","description":"Saves your business identity and document defaults (one row per business; scope is 'default'). timezone is the business clock: an invoice turns overdue at midnight in that zone after its due day, and days_overdue counts days there; unset means Asia/Singapore. Left out, timezone and the text fields keep their saved value, but defaulted fields (default_currency, default_tax_rate_bps, payment_terms_days, invoice_prefix, quote_prefix, template_style) reset, so resend them from sales_settings_read. An agent call waits for the owner's approval. Refuses an unlisted timezone or currency, or a tax rate outside 0-10000, with VALIDATION_ERROR before it waits for approval: send a listed value. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","enum":["default"]},"business_name":{"type":"string","maxLength":200},"business_address":{"type":"string","maxLength":500},"business_email":{"type":"string","maxLength":320},"business_phone":{"type":"string","maxLength":50},"tax_id":{"type":"string","maxLength":50},"default_currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"default_tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"payment_terms_days":{"type":"integer"},"invoice_prefix":{"type":"string","maxLength":10},"quote_prefix":{"type":"string","maxLength":10},"payment_instructions":{"type":"string","maxLength":1000},"bank_name":{"type":"string","maxLength":100},"bank_account":{"type":"string","maxLength":100},"template_style":{"type":"string","enum":["clean","professional","modern"]},"brand_primary_color":{"type":"string","maxLength":7},"brand_accent_color":{"type":"string","maxLength":7},"timezone":{"type":"string","maxLength":64,"enum":["Asia/Singapore","Asia/Kuala_Lumpur","Asia/Kuching","Asia/Brunei","Asia/Jakarta","Asia/Pontianak","Asia/Makassar","Asia/Jayapura","Asia/Bangkok","Asia/Ho_Chi_Minh","Asia/Phnom_Penh","Asia/Vientiane","Asia/Yangon","Asia/Manila","Asia/Dili","Asia/Hong_Kong","Asia/Shanghai","Asia/Taipei","Asia/Tokyo","Asia/Seoul","Asia/Kolkata","Asia/Dubai","Australia/Perth","Australia/Sydney","Europe/London","Europe/Berlin","America/New_York","America/Los_Angeles","UTC"]},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst","none"]}},"required":["scope"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/sales_settings_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":true,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"sales_settings_list","summary":"list sales_settings","description":"Executes the catalog action sales_settings.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/sales_settings_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/sales_settings_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/sales-settings/numbering_set":{"post":{"operationId":"sales_settings_numbering_set","summary":"numbering_set sales_settings","description":"Sets where a document type's numbers continue, for example after moving from another invoicing tool. doc_type: invoice, quote, credit_note, debit_note or receipt. next_number is the sequence number the next document gets (42 prints as INV-2026-042). Numbering only moves forward: a number at or below the last one used or skipped is refused with VALIDATION_ERROR naming that number, and nothing changes. prefix sets the credit_note, debit_note or receipt prefix; invoice and quote prefixes are invoice_prefix and quote_prefix on sales_settings_upsert. An agent call waits for the owner's approval. Read the current numbers with sales_settings_numbering_read. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"scope":{"type":"string","enum":["default"]},"business_name":{"type":"string","maxLength":200},"business_address":{"type":"string","maxLength":500},"business_email":{"type":"string","maxLength":320},"business_phone":{"type":"string","maxLength":50},"tax_id":{"type":"string","maxLength":50},"default_currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"default_tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"payment_terms_days":{"type":"integer"},"invoice_prefix":{"type":"string","maxLength":10},"quote_prefix":{"type":"string","maxLength":10},"payment_instructions":{"type":"string","maxLength":1000},"bank_name":{"type":"string","maxLength":100},"bank_account":{"type":"string","maxLength":100},"template_style":{"type":"string","enum":["clean","professional","modern"]},"brand_primary_color":{"type":"string","maxLength":7},"brand_accent_color":{"type":"string","maxLength":7},"timezone":{"type":"string","maxLength":64,"enum":["Asia/Singapore","Asia/Kuala_Lumpur","Asia/Kuching","Asia/Brunei","Asia/Jakarta","Asia/Pontianak","Asia/Makassar","Asia/Jayapura","Asia/Bangkok","Asia/Ho_Chi_Minh","Asia/Phnom_Penh","Asia/Vientiane","Asia/Yangon","Asia/Manila","Asia/Dili","Asia/Hong_Kong","Asia/Shanghai","Asia/Taipei","Asia/Tokyo","Asia/Seoul","Asia/Kolkata","Asia/Dubai","Australia/Perth","Australia/Sydney","Europe/London","Europe/Berlin","America/New_York","America/Los_Angeles","UTC"]},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst","none"]}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/sales_settings_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":true,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/sales-settings/{id}":{"get":{"operationId":"sales_settings_read","summary":"read sales_settings","description":"Executes the catalog action sales_settings.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["sales"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The sales_settings id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/sales_settings_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/settlement-proposals/propose_cross_tenant":{"post":{"operationId":"settlement_proposal_propose_cross_tenant","summary":"propose_cross_tenant settlement_proposal","description":"Record a payment obligation against a KYB-verified partner tenant's settlement_proposals — the record-don't-move on-ramp: this writes the row only, no money moves until a later settlement-rails door executes it. amount_cents is a nonzero integer CENTS (positive = you owe them, negative = a refund/reversal record) and currency must be a 3-letter code. Requires the payee's cross_tenant_settlement consent grant and both sides KYB-approved; payee-side failures refuse identically to block probing, but your OWN unapproved KYB answers distinctly. Your tenant is injected as payer_tenant_id and cannot be spoofed. NEXT: settlement_proposal_accept moves it to accepted on the payee side. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payer_tenant_id":{"type":"string","maxLength":40},"consent_grant_id":{"type":"string","maxLength":40},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"description":{"type":"string","maxLength":1000},"related_entity_type":{"type":"string","maxLength":60},"related_entity_id":{"type":"string","maxLength":40},"status":{"type":"string","enum":["proposed","accepted","settled"]},"accepted_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/settlement_proposal_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/settlement-proposals/accept":{"post":{"operationId":"settlement_proposal_accept","summary":"accept settlement_proposal","description":"Accept a settlement obligation recorded against your tenant as payee — moves status proposed to accepted and stamps accepted_at under the registry's transition guard. Calling it again on an already-accepted row is idempotent (accepted_at simply re-stamps); once a proposal reaches settled the guard refuses any further move, since settled is terminal. Recording agreement only: no money moves here, settlement execution is a later rail's door. NEXT: settlement_proposal_read to verify the accepted row. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"payer_tenant_id":{"type":"string","maxLength":40},"consent_grant_id":{"type":"string","maxLength":40},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"description":{"type":"string","maxLength":1000},"related_entity_type":{"type":"string","maxLength":60},"related_entity_id":{"type":"string","maxLength":40},"status":{"type":"string","enum":["proposed","accepted","settled"]},"accepted_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/settlement_proposal_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/settlement-proposals":{"get":{"operationId":"settlement_proposal_list","summary":"list settlement_proposal","description":"Executes the catalog action settlement_proposal.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/settlement_proposal_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/settlement_proposal_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/settlement-proposals/{id}":{"get":{"operationId":"settlement_proposal_read","summary":"read settlement_proposal","description":"Executes the catalog action settlement_proposal.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["network"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The settlement_proposal id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/settlement_proposal_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/spreadsheet-files/create":{"post":{"operationId":"spreadsheet_file_create","summary":"create spreadsheet_file","description":"Register a spreadsheet file row in the library for bytes that already sit in R2: r2_key must be a spreadsheets/<your tenant>/ key minted by the upload route or spreadsheet.create_with_content — a caller-invented, foreign-tenant, or wrong-domain key is refused. sheet_count, row_count, and column_count are unverified client-reported hints, since nothing server-side parses the binary. NEXT: spreadsheet.create_with_content stores the bytes and registers the row together. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"r2_key":{"type":"string","maxLength":200},"title":{"type":"string","maxLength":255},"original_filename":{"type":"string","maxLength":255},"file_size":{"type":"integer"},"sheet_count":{"type":"integer"},"row_count":{"type":"integer"},"column_count":{"type":"integer"},"sheet_names":{"type":"string","maxLength":2000},"folder_id":{"type":"string","maxLength":40},"tags":{"type":"string","maxLength":2000},"source":{"type":"string","enum":["upload","ai-generated","agent"]},"ai_prompt":{"type":"string","maxLength":2000},"last_analyzed_at":{"type":"integer","description":"Unix epoch milliseconds."},"analysis_summary":{"type":"string","maxLength":5000},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/spreadsheet_file_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/spreadsheet-files/update":{"post":{"operationId":"spreadsheet_file_update","summary":"update spreadsheet_file","description":"Edit a spreadsheet file's metadata — title, tags, folder_id, or the AI-analysis fields — without touching the underlying R2 object. r2_key and source are birth facts: including either field in the call at all, even set to its current value, is refused — re-upload as a new file to change custody or provenance. Moving folder_id re-verifies the target folder belongs to your tenant. NEXT: spreadsheet_file_read to confirm the change landed. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"r2_key":{"type":"string","maxLength":200},"title":{"type":"string","maxLength":255},"original_filename":{"type":"string","maxLength":255},"file_size":{"type":"integer"},"sheet_count":{"type":"integer"},"row_count":{"type":"integer"},"column_count":{"type":"integer"},"sheet_names":{"type":"string","maxLength":2000},"folder_id":{"type":"string","maxLength":40},"tags":{"type":"string","maxLength":2000},"source":{"type":"string","enum":["upload","ai-generated","agent"]},"ai_prompt":{"type":"string","maxLength":2000},"last_analyzed_at":{"type":"integer","description":"Unix epoch milliseconds."},"analysis_summary":{"type":"string","maxLength":5000},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/spreadsheet_file_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/spreadsheet-files/delete":{"post":{"operationId":"spreadsheet_file_delete","summary":"delete spreadsheet_file","description":"Soft-delete a spreadsheet file: stamps deleted_at on the row so it drops out of the library and folder listings, while the row and its R2 object both survive untouched — there is no purge or restore lane yet, so this cannot be reversed through any current door. Requires the file id; an empty id is refused before anything is touched. NEXT: spreadsheet_file_read to confirm deleted_at is now set — the generic list tool still includes soft-deleted rows. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"r2_key":{"type":"string","maxLength":200},"title":{"type":"string","maxLength":255},"original_filename":{"type":"string","maxLength":255},"file_size":{"type":"integer"},"sheet_count":{"type":"integer"},"row_count":{"type":"integer"},"column_count":{"type":"integer"},"sheet_names":{"type":"string","maxLength":2000},"folder_id":{"type":"string","maxLength":40},"tags":{"type":"string","maxLength":2000},"source":{"type":"string","enum":["upload","ai-generated","agent"]},"ai_prompt":{"type":"string","maxLength":2000},"last_analyzed_at":{"type":"integer","description":"Unix epoch milliseconds."},"analysis_summary":{"type":"string","maxLength":5000},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/spreadsheet_file_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/spreadsheet-files/{id}":{"get":{"operationId":"spreadsheet_file_read","summary":"read spreadsheet_file","description":"Executes the catalog action spreadsheet_file.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The spreadsheet_file id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/spreadsheet_file_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/spreadsheet-files":{"get":{"operationId":"spreadsheet_file_list","summary":"list spreadsheet_file","description":"Executes the catalog action spreadsheet_file.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/spreadsheet_file_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/spreadsheet_file_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/spreadsheet-files/search":{"get":{"operationId":"spreadsheet_file_search","summary":"search spreadsheet_file","description":"Executes the catalog action spreadsheet_file.search (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/spreadsheet_file_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/spreadsheet_file_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/spreadsheet-folders":{"post":{"operationId":"spreadsheet_folder_create","summary":"create spreadsheet_folder","description":"Executes the catalog action spreadsheet_folder.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"color":{"type":"string","maxLength":20}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/spreadsheet_folder_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"spreadsheet_folder_list","summary":"list spreadsheet_folder","description":"Executes the catalog action spreadsheet_folder.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/spreadsheet_folder_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/spreadsheet_folder_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/spreadsheet-folders/{id}":{"patch":{"operationId":"spreadsheet_folder_update","summary":"update spreadsheet_folder","description":"Executes the catalog action spreadsheet_folder.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The spreadsheet_folder id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":100},"color":{"type":"string","maxLength":20},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/spreadsheet_folder_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"spreadsheet_folder_delete","summary":"delete spreadsheet_folder","description":"Executes the catalog action spreadsheet_folder.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The spreadsheet_folder id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/spreadsheet_folder_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"spreadsheet_folder_read","summary":"read spreadsheet_folder","description":"Executes the catalog action spreadsheet_folder.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["spreadsheets"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The spreadsheet_folder id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/spreadsheet_folder_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/sticky-notes":{"post":{"operationId":"sticky_note_create","summary":"create sticky_note","description":"Executes the catalog action sticky_note.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","maxLength":2000},"color":{"type":"string","enum":["amber","rose","verdigris","sky","onyx"]},"position_x":{"type":"integer"},"position_y":{"type":"integer"},"triggers_at":{"type":"integer","description":"Unix epoch milliseconds."},"z_index":{"type":"integer"},"width":{"type":"integer"},"height":{"type":"integer"}},"required":["content"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/sticky_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"sticky_note_list","summary":"list sticky_note","description":"Executes the catalog action sticky_note.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/sticky_note_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/sticky_note_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/sticky-notes/{id}":{"patch":{"operationId":"sticky_note_update","summary":"update sticky_note","description":"Executes the catalog action sticky_note.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The sticky_note id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","maxLength":2000},"color":{"type":"string","enum":["amber","rose","verdigris","sky","onyx"]},"position_x":{"type":"integer"},"position_y":{"type":"integer"},"triggers_at":{"type":"integer","description":"Unix epoch milliseconds."},"z_index":{"type":"integer"},"width":{"type":"integer"},"height":{"type":"integer"},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/sticky_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"sticky_note_delete","summary":"delete sticky_note","description":"Executes the catalog action sticky_note.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The sticky_note id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/sticky_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/sticky-notes/due":{"post":{"operationId":"sticky_note_due","summary":"due sticky_note","description":"Read this tenant's sticky notes whose reminder time (triggers_at) has arrived — the poll the desktop host runs to know what to fire as a local notification, since the web itself has no send channel. Read-only, no arguments: now is always the server's clock, never a caller-supplied value, and only notes with triggers_at set and <= now come back, soonest-due first, capped at 200. NEXT: sticky_note_dismiss clears triggers_at once you've notified, so the same note stops showing up here. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","maxLength":2000},"color":{"type":"string","enum":["amber","rose","verdigris","sky","onyx"]},"position_x":{"type":"integer"},"position_y":{"type":"integer"},"triggers_at":{"type":"integer","description":"Unix epoch milliseconds."},"z_index":{"type":"integer"},"width":{"type":"integer"},"height":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/sticky_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/sticky-notes/dismiss":{"post":{"operationId":"sticky_note_dismiss","summary":"dismiss sticky_note","description":"Clear a sticky note's reminder (triggers_at back to NULL) so it drops out of the sticky_note_due poll — call this after the host fires the local notification for it. Runs through the same tenant-scoped write path as every entity update, but via a clear-properties op: ordinary updates ignore null values, so this is the only way to null the column. Idempotent — dismissing an already-cleared note just re-nulls a NULL and succeeds. NEXT: sticky_note_due to see what's still outstanding. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["desk"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"content":{"type":"string","maxLength":2000},"color":{"type":"string","enum":["amber","rose","verdigris","sky","onyx"]},"position_x":{"type":"integer"},"position_y":{"type":"integer"},"triggers_at":{"type":"integer","description":"Unix epoch milliseconds."},"z_index":{"type":"integer"},"width":{"type":"integer"},"height":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/sticky_note_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/stock-items":{"post":{"operationId":"stock_item_create","summary":"create stock_item","description":"Executes the catalog action stock_item.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["stock"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"quantity":{"type":"integer"},"unit":{"type":"string","maxLength":50},"low_stock_threshold":{"type":"integer"},"cost_per_unit_cents":{"type":"integer"},"sell_price_cents":{"type":"integer"},"category":{"type":"string","maxLength":100},"expiry_date":{"type":"string","maxLength":30},"notes":{"type":"string","maxLength":5000},"is_active":{"type":"integer"}},"required":["name"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/stock_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"stock_item_list","summary":"list stock_item","description":"Executes the catalog action stock_item.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["stock"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/stock_item_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/stock_item_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/stock-items/adjust":{"post":{"operationId":"stock_item_adjust","summary":"adjust stock_item","description":"Move stock in or out by id or item name, in one atomic write with its movements-ledger row: stock-out clamps at zero (never negative) and applied_quantity reports what actually moved. An unmatched name CREATES the item at quantity 0 first so the delivery still lands as an audited ledger row; a name matching multiple active items refuses with the candidate ids. Concurrent adjusts on the same item retry instead of losing a write. NEXT: stock_item_list to see the item's updated balance in the full inventory. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["stock"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"quantity":{"type":"integer"},"unit":{"type":"string","maxLength":50},"low_stock_threshold":{"type":"integer"},"cost_per_unit_cents":{"type":"integer"},"sell_price_cents":{"type":"integer"},"category":{"type":"string","maxLength":100},"expiry_date":{"type":"string","maxLength":30},"notes":{"type":"string","maxLength":5000},"is_active":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/stock_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/stock-items/{id}":{"patch":{"operationId":"stock_item_update","summary":"update stock_item","description":"Executes the catalog action stock_item.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["stock"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The stock_item id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"quantity":{"type":"integer"},"unit":{"type":"string","maxLength":50},"low_stock_threshold":{"type":"integer"},"cost_per_unit_cents":{"type":"integer"},"sell_price_cents":{"type":"integer"},"category":{"type":"string","maxLength":100},"expiry_date":{"type":"string","maxLength":30},"notes":{"type":"string","maxLength":5000},"is_active":{"type":"integer"},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/stock_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"stock_item_read","summary":"read stock_item","description":"Executes the catalog action stock_item.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["stock"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The stock_item id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/stock_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/stock-items/delete":{"post":{"operationId":"stock_item_delete","summary":"delete stock_item","description":"Soft-delete a stock item by id: sets is_active to 0 while its movements-ledger history stays intact. stock_item_adjust then refuses the id as NOT_FOUND and stops resolving it by name, so a later delivery under the same name creates a fresh item instead of reviving this one. stock_item_list and stock_item_read still return it with is_active: 0 — only the dashboard's stats header excludes it. Restore by running a normal update that sets is_active back to 1; there is no separate restore door. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["stock"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"quantity":{"type":"integer"},"unit":{"type":"string","maxLength":50},"low_stock_threshold":{"type":"integer"},"cost_per_unit_cents":{"type":"integer"},"sell_price_cents":{"type":"integer"},"category":{"type":"string","maxLength":100},"expiry_date":{"type":"string","maxLength":30},"notes":{"type":"string","maxLength":5000},"is_active":{"type":"integer"}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/stock_item_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/stock-items/search":{"get":{"operationId":"stock_item_search","summary":"search stock_item","description":"Executes the catalog action stock_item.search (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["stock"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/stock_item_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/stock_item_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio-characters":{"post":{"operationId":"studio_character_create","summary":"create studio_character","description":"Executes the catalog action studio_character.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":1000},"prompt_suffix":{"type":"string","maxLength":500},"reference_image_key":{"type":"string","maxLength":300},"color_tag":{"type":"string","maxLength":20}},"required":["name","description"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_character_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"studio_character_list","summary":"list studio_character","description":"Executes the catalog action studio_character.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/studio_character_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/studio_character_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio-characters/{id}":{"get":{"operationId":"studio_character_read","summary":"read studio_character","description":"Executes the catalog action studio_character.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The studio_character id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_character_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"patch":{"operationId":"studio_character_update","summary":"update studio_character","description":"Executes the catalog action studio_character.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The studio_character id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":1000},"prompt_suffix":{"type":"string","maxLength":500},"reference_image_key":{"type":"string","maxLength":300},"color_tag":{"type":"string","maxLength":20},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_character_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"studio_character_delete","summary":"delete studio_character","description":"Executes the catalog action studio_character.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The studio_character id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_character_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio-environments":{"post":{"operationId":"studio_environment_create","summary":"create studio_environment","description":"Executes the catalog action studio_environment.create (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":1000},"prompt_suffix":{"type":"string","maxLength":500},"reference_image_key":{"type":"string","maxLength":300},"color_tag":{"type":"string","maxLength":20}},"required":["name","description"],"additionalProperties":false}}}},"responses":{"201":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_environment_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"studio_environment_list","summary":"list studio_environment","description":"Executes the catalog action studio_environment.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/studio_environment_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/studio_environment_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio-environments/{id}":{"get":{"operationId":"studio_environment_read","summary":"read studio_environment","description":"Executes the catalog action studio_environment.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The studio_environment id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_environment_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"patch":{"operationId":"studio_environment_update","summary":"update studio_environment","description":"Executes the catalog action studio_environment.update (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The studio_environment id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":1000},"prompt_suffix":{"type":"string","maxLength":500},"reference_image_key":{"type":"string","maxLength":300},"color_tag":{"type":"string","maxLength":20},"expected_updated_at":{"type":"integer","description":"Optional compare-and-set guard: the updated_at you last read. Mismatch returns CONFLICT with the current value."}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_environment_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"studio_environment_delete","summary":"delete studio_environment","description":"Executes the catalog action studio_environment.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The studio_environment id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_environment_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio-projects/create":{"post":{"operationId":"studio_project_create","summary":"create studio_project","description":"Create a video studio project — the composition document (scenes, tracks, clips, captions) starts empty and is built up afterward through the studio.* director tools. thumbnail_key is server-owned: send thumbnail_data_url instead, and this door externalizes it into a content-addressed R2 key through the media hygiene kit (magic bytes decide the type; SVG refuses). Free. NEXT: studio_project_read to verify. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"status":{"type":"string","enum":["draft","generating","ready","exporting","exported"]},"thumbnail_key":{"type":"string","maxLength":300}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_project_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio-projects/{id}":{"get":{"operationId":"studio_project_read","summary":"read studio_project","description":"Executes the catalog action studio_project.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The studio_project id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_project_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"studio_project_delete","summary":"delete studio_project","description":"Executes the catalog action studio_project.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The studio_project id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_project_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio-projects":{"get":{"operationId":"studio_project_list","summary":"list studio_project","description":"Executes the catalog action studio_project.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/studio_project_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/studio_project_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio-projects/update":{"post":{"operationId":"studio_project_update","summary":"update studio_project","description":"Rename a project, change its status, or replace its thumbnail on a project you own — send thumbnail_data_url, never thumbnail_key, which is server-owned and computed by this door the same way studio_project_create does. status here is UI-summary-only by design: it never gates render or generation, which are tracked separately by the export job row and the composition document's own scene status. Free. NOT_FOUND when the id is outside your scope — list first with studio_project_list. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["studio"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":255},"status":{"type":"string","enum":["draft","generating","ready","exporting","exported"]},"thumbnail_key":{"type":"string","maxLength":300}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/studio_project_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/user-settings":{"put":{"operationId":"user_setting_upsert","summary":"upsert user_setting","description":"Executes the catalog action user_setting.upsert (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["account"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"key":{"type":"string","maxLength":128},"value":{"type":"string","maxLength":4000},"value_type":{"type":"string","enum":["text","integer","boolean","json"]}},"required":["key","value"],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/user_setting_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"get":{"operationId":"user_setting_list","summary":"list user_setting","description":"Executes the catalog action user_setting.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["account"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/user_setting_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/user_setting_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/user-settings/{id}":{"get":{"operationId":"user_setting_read","summary":"read user_setting","description":"Executes the catalog action user_setting.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["account"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The user_setting id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/user_setting_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"user_setting_delete","summary":"delete user_setting","description":"Executes the catalog action user_setting.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["account"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The user_setting id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/user_setting_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/user-settings/search":{"get":{"operationId":"user_setting_search","summary":"search user_setting","description":"Executes the catalog action user_setting.search (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["account"],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string"},"description":"Search text (substring match over the entity's text properties; %/_ are literal)."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/user_setting_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/user_setting_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/workflows/create":{"post":{"operationId":"workflow_create","summary":"create workflow","description":"Create a workflow — an AI operator's job: validates definition_json (a { nodes, edges, schedule? } graph) against the platform's node vocabulary, refusing unknown node types and any comms/message-shaped step that isn't a prepare_output node, since the platform prepares outputs but never sends them. trigger_type 'schedule' requires a schedule block; next_run_at is then computed server-side from it, never from a caller value. is_active defaults to 0 (draft) — going live is a separate explicit choice. NEXT: workflow_update to fix a rejected definition or flip is_active. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["operators"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":500},"role_name":{"type":"string","maxLength":60},"definition_json":{"type":"string","maxLength":40000},"trigger_type":{"type":"string","enum":["manual","webhook","schedule"]},"is_active":{"type":"integer"},"next_run_at":{"type":"integer","description":"Unix epoch milliseconds."},"imported_from":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/workflow_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/workflows/update":{"post":{"operationId":"workflow_update","summary":"update workflow","description":"Edit a workflow's fields or its definition graph: every call re-validates the definition — yours if resent, else the stored one decoded back — against the resulting trigger_type, so a plain rename can fail if that stored graph no longer validates, and flipping to 'schedule' without a schedule block fails here rather than at the scheduler. When trigger_type ends as 'schedule' and is_active as 1, next_run_at recomputes from schedule and now on every call, even one touching neither field; any value you send for it is ignored. Optional expected_updated_at compare-and-set: a stale value refuses CONFLICT — re-read, merge, retry. NEXT: workflow_read to confirm the new next_run_at. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["operators"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":500},"role_name":{"type":"string","maxLength":60},"definition_json":{"type":"string","maxLength":40000},"trigger_type":{"type":"string","enum":["manual","webhook","schedule"]},"is_active":{"type":"integer"},"next_run_at":{"type":"integer","description":"Unix epoch milliseconds."},"imported_from":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/workflow_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/workflows/{id}":{"get":{"operationId":"workflow_read","summary":"read workflow","description":"Executes the catalog action workflow.read (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["operators"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The workflow id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/workflow_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."},"delete":{"operationId":"workflow_delete","summary":"delete workflow","description":"Executes the catalog action workflow.delete (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["operators"],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"The workflow id."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/workflow_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/workflows":{"get":{"operationId":"workflow_list","summary":"list workflow","description":"Executes the catalog action workflow.list (same executor as the MCP tool of the same name). Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["operators"],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":200},"description":"Page size 1-200. Omitting BOTH limit and cursor returns the legacy bare array (first 200, newest first); passing either returns { items, next_cursor, limit }."},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"Opaque page cursor from a previous response's next_cursor — pass back verbatim."}],"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"oneOf":[{"type":"array","items":{"$ref":"#/components/schemas/workflow_row"}},{"type":"object","description":"Returned when limit and/or cursor was passed.","properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/workflow_row"}},"next_cursor":{"type":["string","null"],"description":"Pass back verbatim as ?cursor= for the next page; null = no further pages."},"limit":{"type":"integer"}},"required":["items","next_cursor","limit"]}]}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/workflows/prepared_outputs":{"post":{"operationId":"workflow_prepared_outputs","summary":"prepared_outputs workflow","description":"List this tenant's APPROVED prepared outputs: drafts a workflow's prepare_output nodes parked for review, which a human then approved in the platform inbox. Pending and rejected drafts never appear here — approval happens only in the inbox, never through this call. Optional limit 1-100 (default 50), newest-decided first. This is the platform-prepares-never-sends handoff: the desktop harness pulls approved drafts here and sends them locally. Tenant-scoped: ownership comes from your credential — tenant_id/user_id in the payload are ignored.","tags":["operators"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":500},"role_name":{"type":"string","maxLength":60},"definition_json":{"type":"string","maxLength":40000},"trigger_type":{"type":"string","enum":["manual","webhook","schedule"]},"is_active":{"type":"integer"},"next_run_at":{"type":"integer","description":"Unix epoch milliseconds."},"imported_from":{"type":"string","maxLength":40}},"required":[],"additionalProperties":false}}}},"responses":{"200":{"description":"Success envelope.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","enum":[true]},"data":{"$ref":"#/components/schemas/workflow_row"}},"required":["ok","data"]}}}},"default":{"description":"Error envelope (closed code union).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}},"security":[{"bearer_token":[]},{"session_cookie":[]}],"x-simpler-cost-class":"free","x-simpler-requires-approval":false,"x-simpler-min-trust-level":0,"x-simpler-allowed-actor-types":["human","agent"],"x-simpler-latency-ms-range":null,"x-simpler-idempotency":"Agents: auto-derived key (identical payload within 24h replays the recorded result). Humans: opt in via the Idempotency-Key header."}},"/api/studio/projects/{id}/assets":{"post":{"operationId":"studio_asset_upload","summary":"Upload studio media in one request (up to 16 MB)","description":"Raw media bytes as the body. Magic bytes decide the type (mp4, mov, m4a, webm, ogg, wav, mp3, or an image up to 10 MB). The optional filename query parameter is the name your stored files list under (GET /api/studio/uploads); without it the file is listed as upload.<ext>. Counts against the workspace's 20 GB studio upload quota. Larger files use the multipart upload.","tags":["studio"],"security":[{"bearer_token":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"filename","in":"query","required":false,"schema":{"type":"string","maxLength":200}}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"201":{"description":"{ok, data:{r2Key, servePath, mediaType, contentType, brand, probe, bytes}}"},"default":{"description":"Error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}}}},"/api/studio/projects/{id}/uploads":{"post":{"operationId":"studio_upload_begin","summary":"Begin a multipart upload (up to 2 GB)","description":"Reserves the bytes against the 20 GB quota and returns the part plan: fixed 64 MB parts (the last may be shorter), each PUT with its exact Content-Length. Uploads idle for 24 hours are cancelled.","tags":["studio"],"security":[{"bearer_token":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string","maxLength":200},"bytes":{"type":"integer","minimum":1,"maximum":2147483648},"mime":{"type":"string","enum":["video/mp4","video/x-m4v","video/quicktime","audio/mp4","audio/m4a","audio/x-m4a","video/webm","video/x-matroska","audio/webm","audio/ogg","application/ogg","audio/wav","audio/x-wav","audio/wave","audio/vnd.wave","audio/mpeg","audio/mp3","image/jpeg","image/png","image/gif","image/webp"]}},"required":["filename","bytes","mime"]}}}},"responses":{"201":{"description":"{ok, data: plan}"},"default":{"description":"Error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}}}},"/api/studio/projects/{id}/uploads/{uploadId}":{"get":{"operationId":"studio_upload_status","summary":"Read an upload's parts received and missing (resume)","description":"Lists which parts have arrived, so an interrupted upload sends only the rest.","tags":["studio"],"security":[{"bearer_token":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"uploadId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ok, data:{status, partsReceived, partsMissing, ...}}"},"default":{"description":"Error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}}},"delete":{"operationId":"studio_upload_cancel","summary":"Cancel an open upload","description":"Releases its reservation and deletes the parts already stored.","tags":["studio"],"security":[{"bearer_token":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"uploadId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ok, data:{uploadId, status}}"},"default":{"description":"Error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}}}},"/api/studio/projects/{id}/uploads/{uploadId}/parts/{n}":{"put":{"operationId":"studio_upload_part","summary":"Send one part","description":"The part's raw bytes with its exact Content-Length (64 MB, the last part the remainder). Resending a part replaces it.","tags":["studio"],"security":[{"bearer_token":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"uploadId","in":"path","required":true,"schema":{"type":"string"}},{"name":"n","in":"path","required":true,"schema":{"type":"integer"}}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"{ok, data:{uploadId, part, bytes}}"},"default":{"description":"Error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}}}},"/api/studio/projects/{id}/uploads/{uploadId}/complete":{"post":{"operationId":"studio_upload_complete","summary":"Complete a multipart upload","description":"Assembles the parts, re-checks the stored bytes (the moov box is read wherever it sits) and counts them against the quota. A file whose bytes differ from the declared type is deleted and refused. Repeating it returns the same result.","tags":["studio"],"security":[{"bearer_token":[]},{"session_cookie":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"uploadId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ok, data:{r2Key, servePath, mediaType, contentType, brand, probe, bytes}}"},"default":{"description":"Error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}}}},"/api/studio/assets/{key}":{"delete":{"operationId":"studio_asset_delete","summary":"Delete an uploaded file","description":"Deletes a stored upload (URL-encoded r2Key) and gives its bytes back to the quota. Refused (409 SIMPLER_STUDIO_ASSET_IN_USE, naming the versions) while any kept version of the project's composition uses it, since Restore can bring an older version back. The uploader can still delete a file whose project was deleted.","tags":["studio"],"security":[{"bearer_token":[]},{"session_cookie":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"{ok, data:{r2Key, bytesFreed}}"},"default":{"description":"Error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}}}},"/api/studio/uploads":{"get":{"operationId":"studio_upload_list","summary":"List your stored uploads and open uploads against the quota","description":"The workspace's counted and reserved bytes and its limit, your stored files (largest first, including files of deleted projects) with the DELETE path that frees each, and your open uploads with the path that cancels each.","tags":["studio"],"security":[{"bearer_token":[]},{"session_cookie":[]}],"responses":{"200":{"description":"{ok, data:{bytesUsed, bytesReserved, bytesLimit, files, filesTruncated, openUploads, scope}}"},"default":{"description":"Error envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/simpler_error_envelope"}}}}}}},"/health":{"get":{"operationId":"platform_health","summary":"Liveness probe","tags":["platform"],"responses":{"200":{"description":"{ok:true, service, build, time}"}}}},"/mcp":{"post":{"operationId":"mcp_jsonrpc","summary":"MCP endpoint (JSON-RPC 2.0)","description":"Model Context Protocol over HTTP. tools/list is anonymous (open catalog) and currently generates 318 tools from the metadata catalog; tools/call requires a tenant-scoped bearer token (closed data). Methods: initialize, ping, tools/list, tools/call. Errors use the -32xxx grammar with the platform envelope in error.data.envelope.","tags":["platform"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"type":["string","integer","null"]},"method":{"type":"string"},"params":{"type":"object"}},"required":["jsonrpc","method"]}}}},"responses":{"200":{"description":"JSON-RPC result or error frame."}},"x-simpler-tool-count":318}}},"components":{"schemas":{"simpler_error_envelope":{"type":"object","description":"The ONE platform error shape — REST and MCP (error.data.envelope) both carry it.","properties":{"ok":{"type":"boolean","enum":[false]},"error":{"type":"object","properties":{"code":{"type":"string","enum":["UNAUTHORIZED","SESSION_EXPIRED","FORBIDDEN","APPROVAL_REQUIRED","TRUST_REQUIRED","NOT_FOUND","VALIDATION_ERROR","BAD_REQUEST","PAYLOAD_TOO_LARGE","CONFLICT","INSUFFICIENT_CREDITS","PAYMENT_REQUIRED","RATE_LIMITED","SERVICE_UNAVAILABLE","TIMEOUT","INTERNAL_ERROR"]},"message":{"type":"string"},"requestId":{"type":"string"},"fields":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}},"required":["code","message"]}},"required":["ok","error"]},"agent_note_row":{"type":"object","description":"A agent_note row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"from_tenant_id":{"type":"string","maxLength":40},"consent_grant_id":{"type":"string","maxLength":40},"subject":{"type":"string","maxLength":200},"body":{"type":"string","maxLength":4000},"related_entity_type":{"type":"string","maxLength":60},"related_entity_id":{"type":"string","maxLength":40},"status":{"type":"string","enum":["unread","read"]},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","from_tenant_id","body","status","created_at","updated_at"]},"brand_assets_row":{"type":"object","description":"A brand_assets row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"scope":{"type":"string","maxLength":32},"logo_key":{"type":"string","maxLength":512},"colors_json":{"type":"string","maxLength":2000},"fonts_json":{"type":"string","maxLength":1000},"tone_json":{"type":"string","maxLength":2000},"industry":{"type":"string","maxLength":120},"tagline":{"type":"string","maxLength":300},"source_url":{"type":"string","maxLength":2048},"extracted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","scope","created_at","updated_at"]},"consent_grant_row":{"type":"object","description":"A consent_grant row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"scope":{"type":"string","enum":["sbin_participation","green_extraction","cross_tenant_comm","cross_tenant_settlement"]},"status":{"type":"string","enum":["granted","revoked"]},"claims_json":{"type":"string","maxLength":2000},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","scope","status","created_at","updated_at"]},"contact_row":{"type":"object","description":"A contact row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"status":{"type":"string","enum":["lead","contacted","qualified","customer","vip","inactive"]},"source":{"type":"string","enum":["manual","import","invoice","sync"]},"tags":{"type":"string","maxLength":2000},"last_contact_at":{"type":"integer","description":"Unix epoch milliseconds."},"provenance":{"type":"string","enum":["user_entered","api_import","invoice_extraction","crm_sync","forecast_ingestion","network_inferred","bank_observed"]},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","status","created_at","updated_at"]},"contact_note_row":{"type":"object","description":"A contact_note row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"contact_id":{"type":"string","maxLength":40},"content":{"type":"string","maxLength":5000},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","contact_id","content","created_at","updated_at"]},"desk_surface_row":{"type":"object","description":"A desk_surface row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"kind":{"type":"string","enum":["widget","artifact"]},"widget_key":{"type":"string","enum":["calendar-money-month","fx-converter","from-ai-inbox","assignments","market-discovery","sticky-notes","quick-start","coin-flip","interests"]},"content_ref":{"type":"string","maxLength":64},"x":{"type":"integer"},"y":{"type":"integer"},"w":{"type":"integer"},"h":{"type":"integer"},"z_index":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","kind","created_at","updated_at"]},"edit_project_row":{"type":"object","description":"A edit_project row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":120},"canvas_json":{"type":"string","maxLength":150000},"thumbnail_key":{"type":"string","maxLength":300},"width":{"type":"integer"},"height":{"type":"integer"},"version":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","canvas_json","created_at","updated_at"]},"expense_row":{"type":"object","description":"A expense row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"expense_date":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_key":{"type":"string","maxLength":200},"ocr_json":{"type":"string","maxLength":8000},"notes":{"type":"string","maxLength":2000},"tags_json":{"type":"string","maxLength":2000},"subtotal_cents":{"type":"integer"},"tax_amount_cents":{"type":"integer"},"tax_rate_bps":{"type":"integer"},"tax_type":{"type":"string","enum":["GST","SST","VAT","PPN"]},"status":{"type":"string","enum":["draft","pending","approved","rejected","reimbursed"]},"submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"approved_by":{"type":"string","maxLength":40},"approved_at":{"type":"integer","description":"Unix epoch milliseconds."},"rejection_reason":{"type":"string","maxLength":500},"rejected_at":{"type":"integer","description":"Unix epoch milliseconds."},"reimbursed_at":{"type":"integer","description":"Unix epoch milliseconds."},"recurrence_id":{"type":"string","maxLength":40},"provenance":{"type":"string","enum":["user_entered","api_import","invoice_extraction","crm_sync","forecast_ingestion","network_inferred","bank_observed"]},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","vendor","amount_cents","status","created_at","updated_at"]},"expense_budget_row":{"type":"object","description":"A expense_budget row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"category_id":{"type":"string","maxLength":40},"monthly_limit_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"alert_at_pct":{"type":"integer"},"is_active":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","monthly_limit_cents","created_at","updated_at"]},"expense_category_row":{"type":"object","description":"A expense_category row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"slug":{"type":"string","maxLength":50},"name":{"type":"string","maxLength":100},"icon":{"type":"string","maxLength":10},"color":{"type":"string","maxLength":7},"sort_order":{"type":"integer"},"is_default":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","slug","name","created_at","updated_at"]},"expense_recurrence_row":{"type":"object","description":"A expense_recurrence row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"vendor":{"type":"string","maxLength":200},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"category_id":{"type":"string","maxLength":40},"notes":{"type":"string","maxLength":2000},"frequency":{"type":"string","enum":["daily","weekly","monthly","yearly"]},"day_of_month":{"type":"integer"},"day_of_week":{"type":"integer"},"next_due":{"type":"integer","description":"Unix epoch milliseconds."},"is_active":{"type":"integer"},"last_generated_at":{"type":"integer","description":"Unix epoch milliseconds."},"total_generated":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","vendor","amount_cents","frequency","next_due","created_at","updated_at"]},"image_folder_row":{"type":"object","description":"A image_folder row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":100},"color":{"type":"string","maxLength":32},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","created_at","updated_at"]},"image_library_row":{"type":"object","description":"A image_library row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"url":{"type":"string","maxLength":2048},"r2_key":{"type":"string","maxLength":512},"width":{"type":"integer"},"height":{"type":"integer"},"format":{"type":"string","maxLength":8},"prompt":{"type":"string","maxLength":2000},"provider":{"type":"string","maxLength":64},"source":{"type":"string","enum":["generated","upload","edit"]},"folder_id":{"type":"string","maxLength":64},"title":{"type":"string","maxLength":200},"tags":{"type":"string","maxLength":4000},"is_favorite":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","url","created_at","updated_at"]},"interaction_row":{"type":"object","description":"A interaction row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"contact_id":{"type":"string","maxLength":40},"interaction_type":{"type":"string","enum":["meeting","call","email","message","visit","payment","other"]},"summary":{"type":"string","maxLength":2000},"occurred_at":{"type":"integer","description":"Unix epoch milliseconds."},"source_ref":{"type":"string","maxLength":80},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","contact_id","interaction_type","summary","created_at","updated_at"]},"invoice_row":{"type":"object","description":"A invoice row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"client_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","paid","cancelled"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"due_date":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"payment_terms":{"type":"string","maxLength":500},"source_type":{"type":"string","enum":["quote","recurring","quick_sale"]},"source_id":{"type":"string","maxLength":40},"cash_sale":{"type":"integer"},"payment_method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"sent_at":{"type":"integer","description":"Unix epoch milliseconds."},"paid_at":{"type":"integer","description":"Unix epoch milliseconds."},"counterparty_tenant_id":{"type":"string","maxLength":40},"provenance":{"type":"string","enum":["user_entered","api_import","invoice_extraction","crm_sync","forecast_ingestion","network_inferred","bank_observed"]},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1},"fx_rate_to_sgd_ppm":{"type":"integer","minimum":1,"maximum":1000000000},"fx_rate_date":{"type":"string","maxLength":10},"promised_payment_date":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","invoice_number","status","created_at","updated_at"]},"invoice_adjustment_row":{"type":"object","description":"A invoice_adjustment row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"invoice_id":{"type":"string","maxLength":40},"adjustment_type":{"type":"string","enum":["credit_note","write_off","discount_post_issue","dispute_settlement"]},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"reason":{"type":"string","maxLength":500},"occurred_at":{"type":"integer","description":"Unix epoch milliseconds."},"recorded_by_actor":{"type":"string","enum":["human","agent"]},"provenance":{"type":"string","enum":["user_entered","api_import","invoice_extraction","crm_sync","forecast_ingestion","network_inferred","bank_observed"]},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"document_number":{"type":"string","maxLength":40},"reason_code":{"type":"string","maxLength":40,"enum":["goods_returned","damaged_or_defective","pricing_error","discount","service_not_rendered","cancellation","other"]},"credit_outcome":{"type":"string","maxLength":20,"enum":["reduce_balance","refunded_outside"]},"tax_cents":{"type":"integer","minimum":0}},"required":["id","tenant_id","user_id","invoice_id","adjustment_type","amount_cents","recorded_by_actor","created_at","updated_at"]},"invoice_client_row":{"type":"object","description":"A invoice_client row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":200},"company":{"type":"string","maxLength":200},"email":{"type":"string","maxLength":320},"phone":{"type":"string","maxLength":50},"address":{"type":"string","maxLength":500},"notes":{"type":"string","maxLength":1000},"contact_id":{"type":"string","maxLength":40},"counterparty_tenant_id":{"type":"string","maxLength":40},"counterparty_linked_at":{"type":"integer","description":"Unix epoch milliseconds."},"counterparty_link_source":{"type":"string","enum":["deal_acceptance","explicit_link"]},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"reminder_cadence":{"type":"string","maxLength":16,"enum":["standard","from_due","overdue_only","off"]},"message_language":{"type":"string","maxLength":8,"enum":["en","ms","zh"]}},"required":["id","tenant_id","user_id","name","created_at","updated_at"]},"invoice_item_row":{"type":"object","description":"A invoice_item row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"invoice_id":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":500},"quantity":{"type":"integer","minimum":1,"maximum":1000000},"unit_price_cents":{"type":"integer","minimum":0,"maximum":10000000000},"position":{"type":"integer"},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"quantity_milli":{"type":"integer","minimum":1,"maximum":1000000000},"unit":{"type":"string","maxLength":50},"discount_bps":{"type":"integer","minimum":0,"maximum":10000},"tax_code":{"type":"string","maxLength":20,"enum":["standard","zero_rated","exempt","out_of_scope","sales_10","sales_5","service_8","service_6"]}},"required":["id","tenant_id","user_id","invoice_id","description","unit_price_cents","created_at","updated_at"]},"invoice_payment_row":{"type":"object","description":"A invoice_payment row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"invoice_id":{"type":"string","maxLength":40},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"occurred_at":{"type":"integer","description":"Unix epoch milliseconds."},"method":{"type":"string","enum":["cash","transfer","ewallet","other"]},"source":{"type":"string","enum":["operator_declared","counterparty_confirmed","bank_observed","gateway"]},"recorded_by_actor":{"type":"string","enum":["human","agent"]},"note":{"type":"string","maxLength":500},"provenance":{"type":"string","enum":["user_entered","api_import","invoice_extraction","crm_sync","forecast_ingestion","network_inferred","bank_observed"]},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"receipt_number":{"type":"string","maxLength":40}},"required":["id","tenant_id","user_id","invoice_id","amount_cents","source","recorded_by_actor","created_at","updated_at"]},"invoice_recurring_row":{"type":"object","description":"A invoice_recurring row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"client_id":{"type":"string","maxLength":40},"title":{"type":"string","maxLength":200},"items_json":{"type":"string","maxLength":8000},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"frequency":{"type":"string","enum":["weekly","monthly","yearly"]},"day_of_month":{"type":"integer"},"day_of_week":{"type":"integer"},"next_due":{"type":"integer","description":"Unix epoch milliseconds."},"is_active":{"type":"integer"},"notes":{"type":"string","maxLength":2000},"last_generated_at":{"type":"integer","description":"Unix epoch milliseconds."},"total_generated":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst","none"]},"ends_on":{"type":"integer","description":"Unix epoch milliseconds."},"max_invoices":{"type":"integer","minimum":1,"maximum":1000}},"required":["id","tenant_id","user_id","title","items_json","frequency","next_due","created_at","updated_at"]},"market_signal_row":{"type":"object","description":"A market_signal row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"signal_type":{"type":"string","enum":["buy","sell","swap","capacity_offer","capacity_request"]},"product":{"type":"string","maxLength":200},"quantity":{"type":"string","maxLength":100},"price_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"deadline":{"type":"integer","description":"Unix epoch milliseconds."},"location":{"type":"string","maxLength":120},"notes":{"type":"string","maxLength":1000},"status":{"type":"string","enum":["open","fulfilled","closed"]},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","signal_type","product","status","created_at","updated_at"]},"myinvois_customer_row":{"type":"object","description":"A myinvois_customer row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":255},"tin":{"type":"string","maxLength":30},"brn":{"type":"string","maxLength":50},"sst_number":{"type":"string","maxLength":50},"contact_number":{"type":"string","maxLength":50},"email":{"type":"string","maxLength":320},"address":{"type":"string","maxLength":500},"city":{"type":"string","maxLength":100},"state_code":{"type":"string","maxLength":10},"postal_code":{"type":"string","maxLength":20},"country_code":{"type":"string","maxLength":3},"notes":{"type":"string","maxLength":2000},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","tin","created_at","updated_at"]},"myinvois_invoice_row":{"type":"object","description":"A myinvois_invoice row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"customer_id":{"type":"string","maxLength":40},"invoice_number":{"type":"string","maxLength":40},"invoice_type":{"type":"string","enum":["01","02","03","04"]},"status":{"type":"string","enum":["generated","submitted"]},"issue_date":{"type":"string","maxLength":10},"currency":{"type":"string","maxLength":3},"subtotal_cents":{"type":"integer"},"tax_cents":{"type":"integer"},"total_cents":{"type":"integer"},"buyer_name":{"type":"string","maxLength":255},"buyer_tin":{"type":"string","maxLength":30},"invoice_data":{"type":"string","maxLength":200000},"reference_invoice_id":{"type":"string","maxLength":40},"lhdn_uuid":{"type":"string","maxLength":100},"lhdn_long_id":{"type":"string","maxLength":200},"lhdn_submitted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","invoice_number","invoice_type","status","issue_date","currency","subtotal_cents","tax_cents","total_cents","buyer_name","buyer_tin","invoice_data","created_at","updated_at"]},"myinvois_settings_row":{"type":"object","description":"A myinvois_settings row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"scope":{"type":"string","enum":["default"]},"company_name":{"type":"string","maxLength":255},"tin":{"type":"string","maxLength":30},"brn":{"type":"string","maxLength":50},"sst_number":{"type":"string","maxLength":50},"tourism_tax_number":{"type":"string","maxLength":50},"contact_number":{"type":"string","maxLength":50},"email":{"type":"string","maxLength":320},"msic_code":{"type":"string","maxLength":10},"business_activity":{"type":"string","maxLength":500},"address_line1":{"type":"string","maxLength":500},"address_line2":{"type":"string","maxLength":500},"city":{"type":"string","maxLength":100},"postal_code":{"type":"string","maxLength":20},"state_code":{"type":"string","maxLength":10},"country_code":{"type":"string","maxLength":3},"invoice_prefix":{"type":"string","maxLength":10},"default_currency":{"type":"string","maxLength":3},"default_payment_terms":{"type":"string","maxLength":500},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","scope","company_name","tin","brn","contact_number","email","msic_code","business_activity","address_line1","city","postal_code","state_code","created_at","updated_at"]},"myinvois_template_row":{"type":"object","description":"A myinvois_template row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":100},"description":{"type":"string","maxLength":500},"line_items_json":{"type":"string","maxLength":8000},"payment_terms":{"type":"string","maxLength":500},"notes":{"type":"string","maxLength":2000},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","line_items_json","created_at","updated_at"]},"quote_row":{"type":"object","description":"A quote row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"client_id":{"type":"string","maxLength":40},"quote_number":{"type":"string","maxLength":40},"status":{"type":"string","enum":["draft","sent","accepted","declined","converted"]},"issue_date":{"type":"integer","description":"Unix epoch milliseconds."},"valid_until":{"type":"integer","description":"Unix epoch milliseconds."},"currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"notes":{"type":"string","maxLength":2000},"converted_invoice_id":{"type":"string","maxLength":40},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst"]},"prices_include_tax":{"type":"integer","minimum":0,"maximum":1}},"required":["id","tenant_id","user_id","quote_number","status","created_at","updated_at"]},"quote_item_row":{"type":"object","description":"A quote_item row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"quote_id":{"type":"string","maxLength":40},"description":{"type":"string","maxLength":500},"quantity":{"type":"integer","minimum":1,"maximum":1000000},"unit_price_cents":{"type":"integer","minimum":0,"maximum":10000000000},"position":{"type":"integer"},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"quantity_milli":{"type":"integer","minimum":1,"maximum":1000000000},"unit":{"type":"string","maxLength":50},"discount_bps":{"type":"integer","minimum":0,"maximum":10000},"tax_code":{"type":"string","maxLength":20,"enum":["standard","zero_rated","exempt","out_of_scope","sales_10","sales_5","service_8","service_6"]}},"required":["id","tenant_id","user_id","quote_id","description","unit_price_cents","created_at","updated_at"]},"sales_settings_row":{"type":"object","description":"A sales_settings row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"scope":{"type":"string","enum":["default"]},"business_name":{"type":"string","maxLength":200},"business_address":{"type":"string","maxLength":500},"business_email":{"type":"string","maxLength":320},"business_phone":{"type":"string","maxLength":50},"tax_id":{"type":"string","maxLength":50},"default_currency":{"type":"string","maxLength":3,"enum":["USD","EUR","GBP","JPY","CNY","AUD","HKD","INR","SGD","MYR","IDR","THB","PHP","VND","BND","MMK"]},"default_tax_rate_bps":{"type":"integer","minimum":0,"maximum":10000},"payment_terms_days":{"type":"integer"},"invoice_prefix":{"type":"string","maxLength":10},"quote_prefix":{"type":"string","maxLength":10},"payment_instructions":{"type":"string","maxLength":1000},"bank_name":{"type":"string","maxLength":100},"bank_account":{"type":"string","maxLength":100},"template_style":{"type":"string","enum":["clean","professional","modern"]},"brand_primary_color":{"type":"string","maxLength":7},"brand_accent_color":{"type":"string","maxLength":7},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."},"timezone":{"type":"string","maxLength":64,"enum":["Asia/Singapore","Asia/Kuala_Lumpur","Asia/Kuching","Asia/Brunei","Asia/Jakarta","Asia/Pontianak","Asia/Makassar","Asia/Jayapura","Asia/Bangkok","Asia/Ho_Chi_Minh","Asia/Phnom_Penh","Asia/Vientiane","Asia/Yangon","Asia/Manila","Asia/Dili","Asia/Hong_Kong","Asia/Shanghai","Asia/Taipei","Asia/Tokyo","Asia/Seoul","Asia/Kolkata","Asia/Dubai","Australia/Perth","Australia/Sydney","Europe/London","Europe/Berlin","America/New_York","America/Los_Angeles","UTC"]},"tax_scheme":{"type":"string","maxLength":10,"enum":["sg_gst","my_sst","none"]}},"required":["id","tenant_id","user_id","scope","created_at","updated_at"]},"settlement_proposal_row":{"type":"object","description":"A settlement_proposal row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"payer_tenant_id":{"type":"string","maxLength":40},"consent_grant_id":{"type":"string","maxLength":40},"amount_cents":{"type":"integer"},"currency":{"type":"string","maxLength":3},"description":{"type":"string","maxLength":1000},"related_entity_type":{"type":"string","maxLength":60},"related_entity_id":{"type":"string","maxLength":40},"status":{"type":"string","enum":["proposed","accepted","settled"]},"accepted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","payer_tenant_id","amount_cents","currency","status","created_at","updated_at"]},"spreadsheet_file_row":{"type":"object","description":"A spreadsheet_file row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"r2_key":{"type":"string","maxLength":200},"title":{"type":"string","maxLength":255},"original_filename":{"type":"string","maxLength":255},"file_size":{"type":"integer"},"sheet_count":{"type":"integer"},"row_count":{"type":"integer"},"column_count":{"type":"integer"},"sheet_names":{"type":"string","maxLength":2000},"folder_id":{"type":"string","maxLength":40},"tags":{"type":"string","maxLength":2000},"source":{"type":"string","enum":["upload","ai-generated","agent"]},"ai_prompt":{"type":"string","maxLength":2000},"last_analyzed_at":{"type":"integer","description":"Unix epoch milliseconds."},"analysis_summary":{"type":"string","maxLength":5000},"deleted_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","r2_key","title","created_at","updated_at"]},"spreadsheet_folder_row":{"type":"object","description":"A spreadsheet_folder row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":100},"color":{"type":"string","maxLength":20},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","created_at","updated_at"]},"sticky_note_row":{"type":"object","description":"A sticky_note row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"content":{"type":"string","maxLength":2000},"color":{"type":"string","enum":["amber","rose","verdigris","sky","onyx"]},"position_x":{"type":"integer"},"position_y":{"type":"integer"},"triggers_at":{"type":"integer","description":"Unix epoch milliseconds."},"z_index":{"type":"integer"},"width":{"type":"integer"},"height":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","content","created_at","updated_at"]},"stock_item_row":{"type":"object","description":"A stock_item row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":255},"quantity":{"type":"integer"},"unit":{"type":"string","maxLength":50},"low_stock_threshold":{"type":"integer"},"cost_per_unit_cents":{"type":"integer"},"sell_price_cents":{"type":"integer"},"category":{"type":"string","maxLength":100},"expiry_date":{"type":"string","maxLength":30},"notes":{"type":"string","maxLength":5000},"is_active":{"type":"integer"},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","created_at","updated_at"]},"studio_character_row":{"type":"object","description":"A studio_character row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":1000},"prompt_suffix":{"type":"string","maxLength":500},"reference_image_key":{"type":"string","maxLength":300},"color_tag":{"type":"string","maxLength":20},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","description","created_at","updated_at"]},"studio_environment_row":{"type":"object","description":"A studio_environment row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":1000},"prompt_suffix":{"type":"string","maxLength":500},"reference_image_key":{"type":"string","maxLength":300},"color_tag":{"type":"string","maxLength":20},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","description","created_at","updated_at"]},"studio_project_row":{"type":"object","description":"A studio_project row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":255},"status":{"type":"string","enum":["draft","generating","ready","exporting","exported"]},"thumbnail_key":{"type":"string","maxLength":300},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","created_at","updated_at"]},"team_assignment_row":{"type":"object","description":"A team_assignment row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"assigned_to":{"type":"string","maxLength":64},"title":{"type":"string","maxLength":200},"description":{"type":"string","maxLength":2000},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"status":{"type":"string","enum":["pending","accepted","in_progress","completed","declined"]},"due_at":{"type":"integer","description":"Unix epoch milliseconds."},"accepted_at":{"type":"integer","description":"Unix epoch milliseconds."},"started_at":{"type":"integer","description":"Unix epoch milliseconds."},"completed_at":{"type":"integer","description":"Unix epoch milliseconds."},"declined_at":{"type":"integer","description":"Unix epoch milliseconds."},"decline_reason":{"type":"string","maxLength":500},"completion_notes":{"type":"string","maxLength":2000},"attachment_key":{"type":"string","maxLength":200},"attachment_name":{"type":"string","maxLength":200},"attachment_type":{"type":"string","maxLength":100},"photos_json":{"type":"string","maxLength":4000},"artifact_id":{"type":"string","maxLength":64},"previous_assignee":{"type":"string","maxLength":64},"previous_status":{"type":"string","enum":["pending","accepted","in_progress","completed","declined"]},"reassigned_by":{"type":"string","maxLength":64},"reassigned_at":{"type":"integer","description":"Unix epoch milliseconds."},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","assigned_to","title","created_at","updated_at"]},"user_interest_row":{"type":"object","description":"A user_interest row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"interest":{"type":"string","maxLength":100},"created_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","interest","created_at"]},"user_setting_row":{"type":"object","description":"A user_setting row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"key":{"type":"string","maxLength":128},"value":{"type":"string","maxLength":4000},"value_type":{"type":"string","enum":["text","integer","boolean","json"]},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","key","value","created_at","updated_at"]},"workflow_row":{"type":"object","description":"A workflow row. Server-provided fields (ids, tenancy, timestamps) are never caller-writable.","properties":{"id":{"type":"string"},"tenant_id":{"type":"string"},"user_id":{"type":"string"},"name":{"type":"string","maxLength":120},"description":{"type":"string","maxLength":500},"role_name":{"type":"string","maxLength":60},"definition_json":{"type":"string","maxLength":40000},"trigger_type":{"type":"string","enum":["manual","webhook","schedule"]},"is_active":{"type":"integer"},"next_run_at":{"type":"integer","description":"Unix epoch milliseconds."},"imported_from":{"type":"string","maxLength":40},"created_at":{"type":"integer","description":"Unix epoch milliseconds."},"updated_at":{"type":"integer","description":"Unix epoch milliseconds."}},"required":["id","tenant_id","user_id","name","definition_json","created_at","updated_at"]}},"securitySchemes":{"bearer_token":{"type":"http","scheme":"bearer","description":"Tenant-scoped bearer token (agents). Token issuance lands with identity (Wave 2); discovery needs no auth."},"session_cookie":{"type":"apiKey","in":"cookie","name":"simpler_access","description":"Browser session cookie (humans). State-changing requests additionally require a same-origin Origin header (CSRF)."}}},"tags":[{"name":"account","description":"Per-user account preferences and typed settings consumed by every surface."},{"name":"crm","description":"A deliberately small contacts-only CRM: one contact entity with a fixed 6-state lifecycle (the status tabs ARE the pipeline), notes, and one activity spine that powers freshness — who's going silent, not deal value."},{"name":"desk","description":"Personal working surface — quick notes and day-to-day capture."},{"name":"expenses","description":"Expense tracking for SEA SMB operators: log spending manually or by snapping a receipt (AI vision extraction), categorize from the tenant's own category table, run the team approval workflow, set monthly budgets with alerts, and define cron-materialized recurring templates."},{"name":"images","description":"Image generation + permanent library (folders, favorites, the picker every vertical composes) and the tenant brand kit. Agent lane: the curated image.* platform tools — the raw namespace tools are human-only by recorded decision."},{"name":"myinvois","description":"Malaysia LHDN e-invoicing as a form helper: one-time supplier profile, buyer registry, line-item presets, and sealed e-invoices with the credit/debit/refund-note reference gate. Each e-invoice carries a portal field sheet (myinvois_invoice_read) that the owner keys into the LHDN MyInvois portal form, then pastes the UUID the portal assigns back. Simpler never submits to LHDN. A UBL 2.1 XML copy is kept for records."},{"name":"network","description":"The B2B matching marketplace for verified operators: platform-introduced matches that unlock deal chat (no cold contact, no browse-everyone directory), an 8-slot market wish bar visible to matched partners, monthly market-discovery reports, consent-gated cross-tenant agent actions, and one scoped consent model."},{"name":"operators","description":"Hire AI operators — a workflow is the operator's job: durable node graphs over platform actions, with human approval gates and prepared (never sent) outputs."},{"name":"sales","description":"Invoices, quotes, recurring billing, receivables and quick cash sales — create-and-download delivery: Simpler produces correct documents and status truth; the operator delivers them (link or file), no email lane."},{"name":"spreadsheets","description":"A spreadsheet library (folders, tags, search) over R2 binaries with an in-browser editor and a bounded AI loop: analyze, chat-with-your-data (proposed cell modifications reviewed before apply), generate-from-prompt, and extract-calculator-widget. Storage and editing are free; only AI calls bill."},{"name":"stock","description":"Minimal inventory for 1–5-staff operators: items with quantity, unit costs/prices in integer CENTS, categories and a low-stock threshold; every quantity move lands in an append-only movements ledger. Free — no credits."},{"name":"studio","description":"The create surface: the /edit canvas studio (projects, the image.* edit ops ride the root MCP surface as platform tools)."},{"name":"platform","description":"Platform endpoints (health, MCP)."}],"x-simpler-counts":{"entities":40,"actions":224,"mcp_tools":318,"namespaces":12,"services":16,"services_live":15,"rest_operations":204}}