{"openapi":"3.1.0","info":{"title":"OmniForge Business AI Integration API","version":"1.1.0","description":"Server-to-server API scoped to one workspace. The workspace owner or an admin creates keys at /integrations (Settings → Connections & API keys), picks permissions and an expiry (30, 90 or 365 days); up to 20 active keys per workspace.\n\nAuthentication: Authorization: Bearer ofk_<64 lowercase hex>. A key only sees the workspace of the account that created it.\n\nPermissions: tasks:read, tasks:write, notes:read, notes:write, calendar:read, calendar:write, customers:read, invoices:read.\n\nLimits: 60 requests/minute per key and 300/minute per workspace (fixed one-minute windows). A 429 carries Retry-After: 60.\n\nErrors are JSON {\"error\": \"message\"} with the HTTP status. Responses are Cache-Control: no-store. Unknown body fields are rejected.\n\nWhat the API does not do: it does not run AI employees, approve drafts, send email or texts, create customer bookings, or sync external calendars. Customers and invoices are read-only. Browser cross-origin calls are not enabled; call from your server over HTTPS.\n\nChanges in 1.1.0: customers now include stage and last_contact; new read-only invoices resource and invoices:read permission."},"servers":[{"url":"/","description":"This OmniForge installation"}],"security":[{"ApiKey":[]}],"tags":[{"name":"Tasks","description":"Tasks on the Tasks page. Creating one saves it only: it does not start AI work or send anything."},{"name":"Notes","description":"Private internal notes."},{"name":"Calendar","description":"Internal calendar events. They do not create customer bookings, send invitations or sync to Google/Outlook."},{"name":"Customers","description":"Customers with their pipeline stage. Read-only: POST returns 405."},{"name":"Invoices","description":"Live invoices sent through the connected Stripe account. Amounts are in cents. Read-only: POST returns 405."}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","bearerFormat":"ofk_<64 hex characters>","description":"Workspace-scoped key. Each operation lists the permission it needs."}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string","description":"Human-readable message"}}},"Created":{"type":"object","required":["id","resource"],"properties":{"id":{"type":"string","format":"uuid"},"resource":{"type":"string","enum":["tasks","notes","calendar"]}},"example":{"id":"3f2c1a8e-5b7d-4c1e-9a0f-2d6b8e4c7a11","resource":"tasks"}},"Task":{"type":"object","description":"An internal task on the Tasks page. The same list holds work you give your AI team and your own to-dos.","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"assignee":{"type":"string","description":"\"owner\" or an employee ID"},"priority":{"type":"string","enum":["low","normal","high"]},"due":{"type":"string","description":"UTC ISO 8601 or empty"},"status":{"type":"string","description":"e.g. todo, running, needs_review, reviewing, done"},"checklist":{"type":"string","description":"JSON-encoded array stored as a string"},"source":{"type":"string"},"execution":{"type":"string"},"evidence":{"type":"string"},"version":{"type":"integer"},"created_at":{"type":"string","format":"date-time","description":"Created (UTC)"},"updated_at":{"type":"string","format":"date-time","description":"Last changed (UTC)"}}},"Note":{"type":"object","description":"A private internal note. Never shown to customers.","properties":{"id":{"type":"string"},"task":{"type":"string","description":"Linked task ID or empty"},"title":{"type":"string"},"content":{"type":"string"},"updated_at":{"type":"string","format":"date-time","description":"Last changed (UTC)"}}},"CalendarEvent":{"type":"object","description":"An internal calendar event. Not a customer booking; no invitations are sent.","properties":{"id":{"type":"string"},"task":{"type":"string","description":"Linked task ID or empty"},"title":{"type":"string"},"start":{"type":"string","format":"date-time","description":"UTC start"},"end":{"type":"string","format":"date-time","description":"UTC end"},"status":{"type":"string","enum":["tentative","confirmed"]},"details":{"type":"string"},"created_at":{"type":"string","format":"date-time","description":"Created (UTC)"}}},"Customer":{"type":"object","description":"One customer record (a person reached by call, chat, text, email or web form). The same person can have more than one record, one per way they reached you; stage and last_contact are worked out per person, so they match across those records and match the Customers page.","properties":{"id":{"type":"string"},"name":{"type":"string"},"contact":{"type":"string","description":"Email address or phone number"},"channel":{"type":"string","description":"Where this record came from, e.g. phone, sms, portal (web chat), email, internal"},"stage":{"type":"string","enum":["new","contacted","meeting","quote","won","lost"],"description":"Pipeline stage: new = New lead, contacted = Contacted, meeting = Meeting booked, quote = Quote sent, won = Customer (a live invoice was paid), lost = Lost. Worked out from real activity; an owner can move a customer further along or to Lost on the Customers page, and that choice wins."},"last_contact":{"type":["string","null"],"format":"date-time","description":"Most recent conversation (call, chat, text or web inquiry) with this person, or null if none"},"updated_at":{"type":"string","format":"date-time","description":"Record last changed (UTC)"}},"example":{"id":"c-8d1f","name":"Dana Reyes","contact":"dana@example.com","channel":"phone","stage":"quote","last_contact":"2026-09-22T15:04:11.000Z","updated_at":"2026-09-22T15:04:11.000Z"}},"Invoice":{"type":"object","description":"A live-mode invoice sent from the business's own Stripe account. Test-mode invoices are never returned.","properties":{"id":{"type":"string"},"number":{"type":"string","description":"Stripe invoice number (empty until Stripe assigns one)"},"customer_name":{"type":"string"},"customer_email":{"type":"string"},"amount":{"type":"integer","description":"Total in the smallest currency unit (cents for USD)"},"currency":{"type":"string","example":"usd"},"status":{"type":"string","enum":["creating","open","paid","void","uncollectible","failed"],"description":"open = sent and waiting for payment; paid = Stripe confirmed payment (checked hourly); failed = Stripe did not create it. An open invoice past due_date is overdue."},"due_date":{"type":"string","description":"Due date"},"sent_at":{"type":["string","null"],"format":"date-time","description":"When it was emailed"},"paid_at":{"type":["string","null"],"format":"date-time","description":"When Stripe reported it paid"},"created_at":{"type":"string","format":"date-time","description":"Created (UTC)"},"updated_at":{"type":"string","format":"date-time","description":"Last changed (UTC)"}},"example":{"id":"b1e7c0d2-6a3f-4e59-8c21-7f0a9d3e5b64","number":"A1B2C3D4-0007","customer_name":"Dana Reyes","customer_email":"dana@example.com","amount":45000,"currency":"usd","status":"paid","due_date":"2026-10-06","sent_at":"2026-09-22T16:00:00.000Z","paid_at":"2026-09-24T09:12:40.000Z","created_at":"2026-09-22T16:00:00.000Z","updated_at":"2026-09-24T09:12:40.000Z"}},"TaskInput":{"type":"object","additionalProperties":false,"required":["title"],"properties":{"title":{"type":"string","maxLength":150,"minLength":3},"description":{"type":"string","maxLength":12000,"default":""},"assignee":{"type":"string","maxLength":100,"default":"owner","description":"\"owner\" or the ID of an active employee in this workspace"},"priority":{"type":"string","enum":["low","normal","high"],"default":"normal"},"due":{"type":"string","default":"","description":"UTC ISO 8601 timestamp ending in Z, or empty string"}},"example":{"title":"Follow up on new inquiry","description":"Review the customer request in our CRM.","priority":"normal","due":"2026-10-01T15:00:00Z"}},"NoteInput":{"type":"object","additionalProperties":false,"required":["title","content"],"properties":{"title":{"type":"string","maxLength":150,"minLength":1},"content":{"type":"string","maxLength":16000,"minLength":1},"task":{"type":"string","maxLength":120,"default":"","description":"Optional task ID in this workspace"}},"example":{"title":"Call notes","content":"Customer prefers mornings."}},"CalendarInput":{"type":"object","additionalProperties":false,"required":["title","start","end"],"properties":{"title":{"type":"string","maxLength":150,"minLength":3},"start":{"type":"string","format":"date-time","description":"UTC timestamp ending in Z"},"end":{"type":"string","format":"date-time","description":"UTC timestamp ending in Z; must be after start"},"status":{"type":"string","enum":["tentative","confirmed"],"default":"tentative","description":"Confirmed events may not overlap another confirmed event"},"details":{"type":"string","maxLength":4000,"default":""},"task":{"type":"string","maxLength":120,"default":"","description":"Optional task ID in this workspace"}},"example":{"title":"Site visit prep","start":"2026-10-02T14:00:00Z","end":"2026-10-02T15:00:00Z","status":"tentative"}}}},"paths":{"/api/v1/tasks":{"get":{"tags":["Tasks"],"operationId":"listTasks","summary":"Read tasks","description":"Tasks on the Tasks page. Creating one saves it only: it does not start AI work or send anything. Requires tasks:read. Without id, returns a page ordered by ID (not by date). With id, returns that one record. Only records in the key's workspace are visible.","security":[{"ApiKey":["tasks:read"]}],"parameters":[{"name":"id","in":"query","schema":{"type":"string","maxLength":120},"description":"Return one record as {data: object}."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Page size"},{"name":"after","in":"query","schema":{"type":"string","maxLength":120},"description":"nextCursor from the previous page"}],"responses":{"200":{"description":"A page of records, or one record when id is supplied","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Task"}},"nextCursor":{"type":["string","null"],"description":"Pass as after= to get the next page; null on the last page"}}},{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Task"}}}]}}}},"400":{"description":"Invalid input: a query parameter or body field failed validation, the body is not JSON, or an unknown field was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Please submit a valid request."}}}},"401":{"description":"Missing, malformed, invalid, expired, or revoked key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key is invalid, expired, or revoked."}}}},"403":{"description":"The key does not have the permission this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key does not allow tasks:write."}}}},"404":{"description":"Unknown resource, or no record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Record not found."}}}},"429":{"description":"Rate limit reached (60 requests/minute per key, 300 per workspace).","headers":{"Retry-After":{"schema":{"type":"integer","example":60},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API rate limit reached. Retry in 60 seconds."}}}},"500":{"description":"Unexpected server error. For a create, retry with the same Idempotency-Key so it is never saved twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"We couldn't complete that request. Your saved work is safe; please try again."}}}}}},"post":{"tags":["Tasks"],"operationId":"createTasks","summary":"Create a task","description":"Tasks on the Tasks page. Creating one saves it only: it does not start AI work or send anything. Requires tasks:write. Saves an internal record only: no AI execution, approval, email, SMS or calendar invitation. Send a new UUID Idempotency-Key per new record and reuse it on retries: the same key with the same input returns the original {id, resource} with 200; the same key with different input returns 409.","security":[{"ApiKey":["tasks:write"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"A UUID you generate for this create"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TaskInput"}}}},"responses":{"200":{"description":"Retry of an earlier identical request; the original {id, resource} is returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Created"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Created"}}}},"400":{"description":"Invalid input, a missing or non-UUID Idempotency-Key, an end time not after start, or an assignee that is not \"owner\" or an active employee.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Choose an active employee in this workspace or owner."}}}},"401":{"description":"Missing, malformed, invalid, expired, or revoked key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key is invalid, expired, or revoked."}}}},"403":{"description":"The key does not have the permission this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key does not allow tasks:write."}}}},"404":{"description":"Linked task not found in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Task not found."}}}},"409":{"description":"Idempotency-Key reused with different input, or a confirmed calendar event overlaps another confirmed event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"This Idempotency-Key was already used with different input."}}}},"413":{"description":"Body larger than 60,000 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"This request is too large."}}}},"429":{"description":"Rate limit reached (60 requests/minute per key, 300 per workspace).","headers":{"Retry-After":{"schema":{"type":"integer","example":60},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API rate limit reached. Retry in 60 seconds."}}}},"500":{"description":"Unexpected server error. For a create, retry with the same Idempotency-Key so it is never saved twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"We couldn't complete that request. Your saved work is safe; please try again."}}}}}}},"/api/v1/notes":{"get":{"tags":["Notes"],"operationId":"listNotes","summary":"Read private notes","description":"Private internal notes. Requires notes:read. Without id, returns a page ordered by ID (not by date). With id, returns that one record. Only records in the key's workspace are visible.","security":[{"ApiKey":["notes:read"]}],"parameters":[{"name":"id","in":"query","schema":{"type":"string","maxLength":120},"description":"Return one record as {data: object}."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Page size"},{"name":"after","in":"query","schema":{"type":"string","maxLength":120},"description":"nextCursor from the previous page"}],"responses":{"200":{"description":"A page of records, or one record when id is supplied","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Note"}},"nextCursor":{"type":["string","null"],"description":"Pass as after= to get the next page; null on the last page"}}},{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Note"}}}]}}}},"400":{"description":"Invalid input: a query parameter or body field failed validation, the body is not JSON, or an unknown field was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Please submit a valid request."}}}},"401":{"description":"Missing, malformed, invalid, expired, or revoked key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key is invalid, expired, or revoked."}}}},"403":{"description":"The key does not have the permission this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key does not allow tasks:write."}}}},"404":{"description":"Unknown resource, or no record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Record not found."}}}},"429":{"description":"Rate limit reached (60 requests/minute per key, 300 per workspace).","headers":{"Retry-After":{"schema":{"type":"integer","example":60},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API rate limit reached. Retry in 60 seconds."}}}},"500":{"description":"Unexpected server error. For a create, retry with the same Idempotency-Key so it is never saved twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"We couldn't complete that request. Your saved work is safe; please try again."}}}}}},"post":{"tags":["Notes"],"operationId":"createNotes","summary":"Create a note","description":"Private internal notes. Requires notes:write. Saves an internal record only: no AI execution, approval, email, SMS or calendar invitation. Send a new UUID Idempotency-Key per new record and reuse it on retries: the same key with the same input returns the original {id, resource} with 200; the same key with different input returns 409.","security":[{"ApiKey":["notes:write"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"A UUID you generate for this create"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NoteInput"}}}},"responses":{"200":{"description":"Retry of an earlier identical request; the original {id, resource} is returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Created"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Created"}}}},"400":{"description":"Invalid input, a missing or non-UUID Idempotency-Key, an end time not after start, or an assignee that is not \"owner\" or an active employee.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Choose an active employee in this workspace or owner."}}}},"401":{"description":"Missing, malformed, invalid, expired, or revoked key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key is invalid, expired, or revoked."}}}},"403":{"description":"The key does not have the permission this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key does not allow tasks:write."}}}},"404":{"description":"Linked task not found in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Task not found."}}}},"409":{"description":"Idempotency-Key reused with different input, or a confirmed calendar event overlaps another confirmed event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"This Idempotency-Key was already used with different input."}}}},"413":{"description":"Body larger than 60,000 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"This request is too large."}}}},"429":{"description":"Rate limit reached (60 requests/minute per key, 300 per workspace).","headers":{"Retry-After":{"schema":{"type":"integer","example":60},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API rate limit reached. Retry in 60 seconds."}}}},"500":{"description":"Unexpected server error. For a create, retry with the same Idempotency-Key so it is never saved twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"We couldn't complete that request. Your saved work is safe; please try again."}}}}}}},"/api/v1/calendar":{"get":{"tags":["Calendar"],"operationId":"listCalendar","summary":"Read internal calendar events","description":"Internal calendar events. They do not create customer bookings, send invitations or sync to Google/Outlook. Requires calendar:read. Without id, returns a page ordered by ID (not by date). With id, returns that one record. Only records in the key's workspace are visible.","security":[{"ApiKey":["calendar:read"]}],"parameters":[{"name":"id","in":"query","schema":{"type":"string","maxLength":120},"description":"Return one record as {data: object}."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Page size"},{"name":"after","in":"query","schema":{"type":"string","maxLength":120},"description":"nextCursor from the previous page"}],"responses":{"200":{"description":"A page of records, or one record when id is supplied","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CalendarEvent"}},"nextCursor":{"type":["string","null"],"description":"Pass as after= to get the next page; null on the last page"}}},{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/CalendarEvent"}}}]}}}},"400":{"description":"Invalid input: a query parameter or body field failed validation, the body is not JSON, or an unknown field was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Please submit a valid request."}}}},"401":{"description":"Missing, malformed, invalid, expired, or revoked key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key is invalid, expired, or revoked."}}}},"403":{"description":"The key does not have the permission this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key does not allow tasks:write."}}}},"404":{"description":"Unknown resource, or no record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Record not found."}}}},"429":{"description":"Rate limit reached (60 requests/minute per key, 300 per workspace).","headers":{"Retry-After":{"schema":{"type":"integer","example":60},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API rate limit reached. Retry in 60 seconds."}}}},"500":{"description":"Unexpected server error. For a create, retry with the same Idempotency-Key so it is never saved twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"We couldn't complete that request. Your saved work is safe; please try again."}}}}}},"post":{"tags":["Calendar"],"operationId":"createCalendar","summary":"Create a calendar event","description":"Internal calendar events. They do not create customer bookings, send invitations or sync to Google/Outlook. Requires calendar:write. Saves an internal record only: no AI execution, approval, email, SMS or calendar invitation. Send a new UUID Idempotency-Key per new record and reuse it on retries: the same key with the same input returns the original {id, resource} with 200; the same key with different input returns 409.","security":[{"ApiKey":["calendar:write"]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"A UUID you generate for this create"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CalendarInput"}}}},"responses":{"200":{"description":"Retry of an earlier identical request; the original {id, resource} is returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Created"}}}},"201":{"description":"Created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Created"}}}},"400":{"description":"Invalid input, a missing or non-UUID Idempotency-Key, an end time not after start, or an assignee that is not \"owner\" or an active employee.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Choose an active employee in this workspace or owner."}}}},"401":{"description":"Missing, malformed, invalid, expired, or revoked key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key is invalid, expired, or revoked."}}}},"403":{"description":"The key does not have the permission this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key does not allow tasks:write."}}}},"404":{"description":"Linked task not found in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Task not found."}}}},"409":{"description":"Idempotency-Key reused with different input, or a confirmed calendar event overlaps another confirmed event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"This Idempotency-Key was already used with different input."}}}},"413":{"description":"Body larger than 60,000 characters.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"This request is too large."}}}},"429":{"description":"Rate limit reached (60 requests/minute per key, 300 per workspace).","headers":{"Retry-After":{"schema":{"type":"integer","example":60},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API rate limit reached. Retry in 60 seconds."}}}},"500":{"description":"Unexpected server error. For a create, retry with the same Idempotency-Key so it is never saved twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"We couldn't complete that request. Your saved work is safe; please try again."}}}}}}},"/api/v1/customers":{"get":{"tags":["Customers"],"operationId":"listCustomers","summary":"Read customers","description":"Customers with their pipeline stage. Read-only: POST returns 405. Requires customers:read. Without id, returns a page ordered by ID (not by date). With id, returns that one record. Only records in the key's workspace are visible.","security":[{"ApiKey":["customers:read"]}],"parameters":[{"name":"id","in":"query","schema":{"type":"string","maxLength":120},"description":"Return one record as {data: object}."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Page size"},{"name":"after","in":"query","schema":{"type":"string","maxLength":120},"description":"nextCursor from the previous page"}],"responses":{"200":{"description":"A page of records, or one record when id is supplied","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Customer"}},"nextCursor":{"type":["string","null"],"description":"Pass as after= to get the next page; null on the last page"}}},{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Customer"}}}]}}}},"400":{"description":"Invalid input: a query parameter or body field failed validation, the body is not JSON, or an unknown field was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Please submit a valid request."}}}},"401":{"description":"Missing, malformed, invalid, expired, or revoked key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key is invalid, expired, or revoked."}}}},"403":{"description":"The key does not have the permission this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key does not allow tasks:write."}}}},"404":{"description":"Unknown resource, or no record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Record not found."}}}},"429":{"description":"Rate limit reached (60 requests/minute per key, 300 per workspace).","headers":{"Retry-After":{"schema":{"type":"integer","example":60},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API rate limit reached. Retry in 60 seconds."}}}},"500":{"description":"Unexpected server error. For a create, retry with the same Idempotency-Key so it is never saved twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"We couldn't complete that request. Your saved work is safe; please try again."}}}}}}},"/api/v1/invoices":{"get":{"tags":["Invoices"],"operationId":"listInvoices","summary":"Read live invoices","description":"Live invoices sent through the connected Stripe account. Amounts are in cents. Read-only: POST returns 405. Requires invoices:read. Without id, returns a page ordered by ID (not by date). With id, returns that one record. Only records in the key's workspace are visible.","security":[{"ApiKey":["invoices:read"]}],"parameters":[{"name":"id","in":"query","schema":{"type":"string","maxLength":120},"description":"Return one record as {data: object}."},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"description":"Page size"},{"name":"after","in":"query","schema":{"type":"string","maxLength":120},"description":"nextCursor from the previous page"}],"responses":{"200":{"description":"A page of records, or one record when id is supplied","content":{"application/json":{"schema":{"oneOf":[{"type":"object","required":["data","nextCursor"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"}},"nextCursor":{"type":["string","null"],"description":"Pass as after= to get the next page; null on the last page"}}},{"type":"object","required":["data"],"properties":{"data":{"$ref":"#/components/schemas/Invoice"}}}]}}}},"400":{"description":"Invalid input: a query parameter or body field failed validation, the body is not JSON, or an unknown field was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Please submit a valid request."}}}},"401":{"description":"Missing, malformed, invalid, expired, or revoked key.","headers":{"WWW-Authenticate":{"schema":{"type":"string","example":"Bearer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key is invalid, expired, or revoked."}}}},"403":{"description":"The key does not have the permission this operation requires.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API key does not allow tasks:write."}}}},"404":{"description":"Unknown resource, or no record with that id in this workspace.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"Record not found."}}}},"429":{"description":"Rate limit reached (60 requests/minute per key, 300 per workspace).","headers":{"Retry-After":{"schema":{"type":"integer","example":60},"description":"Seconds to wait before retrying"}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"API rate limit reached. Retry in 60 seconds."}}}},"500":{"description":"Unexpected server error. For a create, retry with the same Idempotency-Key so it is never saved twice.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"},"example":{"error":"We couldn't complete that request. Your saved work is safe; please try again."}}}}}}}}}