openapi: 3.0.3 info: title: 'Corcava Public API Documentation' description: '' version: 1.0.0 servers: - url: 'https://app.corcava.com' tags: - name: 'Bill Rates' description: "\nAPIs for managing user bill rates within projects.\n\nBill rates represent the hourly rate for a user on a specific project, effective from a given start date.\nEach user can have multiple bill rates over time, but only one active rate at any given time." - name: Boards description: "\nAPIs for managing project boards.\n\nBoards group tasks inside a project. Use these endpoints to list, create, update, and delete project boards within your team." - name: 'CRM Emails' description: "\nOne-to-one CRM email drafts and send for contacts (Gmail)." - name: 'CRM Inbox' description: "\nRead synced Gmail inbox threads for reply drafting via MCP / Public API." - name: Clients description: "\nAPIs for managing clients.\n\nClients represent organisations you collaborate with. These endpoints let you list, create, update, and delete clients that belong to your team." - name: 'Contact Notes' description: "\nAPIs for managing notes attached to contacts.\n\nThese endpoints let you list, create, update, and delete notes for a specific contact." - name: 'Contact Tasks' description: "\nAPIs for managing tasks related to a contact.\n\nThese endpoints allow you to list, create, update, and delete tasks\nthat are associated with a specific contact." - name: Contacts description: "\nAPIs for managing contacts.\n\nContacts represent people related to your clients. Use these endpoints to list, create, update, and delete contacts within your team." - name: 'Custom Fields' description: "\nAPIs for managing custom field definitions.\n\nCustom fields allow teams to define additional structured data\nthat can be attached to various entities across the system." - name: 'Deal Flow Columns' description: "\nAPIs for managing deal pipeline columns/stages.\n\nDeal flow columns represent stages in a sales or deal pipeline. These endpoints let you list, create, update, reorder, and delete columns that belong to your team." - name: 'Deals Management' description: "\nAPIs for managing deals\n\nThis controller provides endpoints to create, read, update, delete, and manage the order of deals within the system." - name: 'Email Campaigns' description: "\nAPIs for managing email marketing campaigns.\n\nEmail campaigns allow you to create scheduled email messages,\nconfigure their content (template or text editor),\nand send them to selected recipients." - name: 'Email Templates' description: "\nAPIs for managing email templates.\n\nEmail templates are reusable messages that belong to a team and can be used\nfor sending emails across the system." - name: Endpoints description: '' - name: Expenses description: "\nAPIs for managing business expenses.\n\nTrack business expenses with support for categorization, project assignment, and file attachments.\nAll expenses are scoped to the authenticated user's team." - name: 'HR Candidates' description: "\nPublic API for managing HR candidates.\n\nCandidates belong to HR vacancies and are always scoped to the authenticated user's team." - name: 'HR Interviews' description: "\nAPIs for managing HR interviews.\n\nHR interviews represent scheduled or conducted interviews within your team." - name: 'HR Vacancies' description: "\nAPIs for managing HR vacancies.\n\nVacancies represent open job positions within a team.\nThese endpoints allow authenticated users to list, view,\ncreate, update, and delete vacancies belonging to their team." - name: Healthcheck description: 'Checking API availability' - name: Meetings description: "\nAPIs for managing calendar meetings.\n\nMeetings represent scheduled events within a team. These endpoints allow you to list, create,\nupdate, and delete meetings associated with your team." - name: Outreach description: "\nAPIs for managing outreach activities.\n\nOutreach activities represent sales outreach efforts like calls, emails, and social media interactions.\nThese endpoints let you list, create, update, and delete outreach activities for your team." - name: 'Pay Rates' description: "\nAPIs for managing user pay rates over time.\n\nPay rates represent hourly rates assigned to users with specific start dates.\nUsers can have multiple pay rates over time, but only one rate per date." - name: 'Project Rates' description: "\nAPIs for managing project rates.\n\nProject rates define billing rates for projects. These endpoints let you list, create, update, and delete rates for specific projects." - name: Projects description: "\nAPIs for managing projects.\n\nProjects represent client initiatives. These endpoints let you list, create, update, and delete projects that belong to your team." - name: Reports description: "\nAPIs for querying time tracking reports.\n\nThese endpoints let you query aggregated time tracking data with various filters and grouping options.\nEvery request must be authenticated via an active Public API key or Bearer token." - name: Screenshots description: "\nAPIs for managing time tracking screenshots.\n\nThese endpoints let you list screenshots captured during time tracking sessions. Screenshots are organized by user, project, and date." - name: Tags description: "\nTeam-scoped tags that can be attached to contacts, projects, tasks, and other resources." - name: 'Task Comments' description: "\nAPIs for managing comments on tasks.\n\nComments are stored as TaskEvent records with type='comment'.\nThese endpoints let you list, add, update, and delete comments on tasks.\nEvery request must be authenticated via an active Public API key." - name: 'Task Events' description: "\nAPIs for managing task events (comments, system events).\n\nTask events represent activity history of a task, such as user comments\nor system-generated changes." - name: 'Task Labels' description: "\nAPIs for managing task labels.\n\nTask labels allow you to categorize and organize tasks within a project board. These endpoints let you list board labels and attach/detach labels to specific tasks." - name: Tasks description: "\nAPIs for managing project tasks.\n\nThese endpoints let you list, create, update, and delete tasks that belong to your team.\nEvery request must be authenticated via an active Public API key." - name: 'Team Invoices' description: "\nAPIs for managing team invoices.\n\nInvoices represent bills issued to clients. These endpoints let you list, view, close, and reopen invoices that belong to your team." - name: 'Team Members' description: "\nAPIs for listing team members (users).\n\nTeam members are users who belong to your team. Use these endpoints to search and list members.\nThis endpoint supports fuzzy search - typos, partial names, and accents are handled automatically." - name: Tickets description: "\nAPIs for managing user tickets\n\nThese endpoints allow a user to list, create, update, and delete their own tickets.\nAccess is restricted by API key and user ownership. Use `auth:api` middleware." - name: 'Time Intervals' description: "\nAPIs for managing time intervals.\n\nTime intervals represent periods of tracked work. These endpoints let you list, create, update, delete, and move time intervals." - name: 'Time Tracking' description: "\nAPIs for managing time tracking via external sources (Telegram bot, Slack bot, Web Agent, etc.).\nThese endpoints allow starting and stopping time intervals manually.\n\nOnly users with manual time tracking enabled can use these endpoints." - name: Workflows description: "\nNatural-language automation workflows (compiled SQL + tool actions)." components: securitySchemes: default: type: apiKey name: X-API-Key in: header description: 'You can retrieve your token by visiting your dashboard and clicking Generate API token.' security: - default: [] paths: '/api/v1/projects/{project_id}/users/{user_id}/bill-rates': get: summary: 'Display a paginated list of bill rates for a user in a project.' operationId: displayAPaginatedListOfBillRatesForAUserInAProject description: '' parameters: - in: query name: per_page description: 'Number of results per page. Maximum: 100.' example: 50 required: false schema: type: integer description: 'Number of results per page. Maximum: 100.' example: 50 nullable: false - in: query name: sort description: 'Column used for sorting.' example: started_at required: false schema: type: string description: 'Column used for sorting.' example: started_at nullable: false - in: query name: direction description: 'Sort direction. Allowed: asc, desc.' example: desc required: false schema: type: string description: 'Sort direction. Allowed: asc, desc.' example: desc nullable: false - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 200: description: success content: application/json: schema: type: object example: data: - id: 1 project_id: 1 user_id: 42 rate: 85.5 started_at: '2024-01-01T00:00:00.000000Z' created_at: '2023-12-15T10:30:00.000000Z' updated_at: '2023-12-15T10:30:00.000000Z' status: current - id: 2 project_id: 1 user_id: 42 rate: 75.0 started_at: '2023-07-01T00:00:00.000000Z' created_at: '2023-06-20T14:15:00.000000Z' updated_at: '2023-06-20T14:15:00.000000Z' status: past links: first: 'https://example.com/api/v1/projects/1/users/42/bill-rates?page=1' last: 'https://example.com/api/v1/projects/1/users/42/bill-rates?page=2' prev: null next: 'https://example.com/api/v1/projects/1/users/42/bill-rates?page=2' meta: current_page: 1 from: 1 last_page: 2 path: 'https://example.com/api/v1/projects/1/users/42/bill-rates' per_page: 30 to: 30 total: 45 properties: data: type: array example: - id: 1 project_id: 1 user_id: 42 rate: 85.5 started_at: '2024-01-01T00:00:00.000000Z' created_at: '2023-12-15T10:30:00.000000Z' updated_at: '2023-12-15T10:30:00.000000Z' status: current - id: 2 project_id: 1 user_id: 42 rate: 75 started_at: '2023-07-01T00:00:00.000000Z' created_at: '2023-06-20T14:15:00.000000Z' updated_at: '2023-06-20T14:15:00.000000Z' status: past items: type: object properties: id: type: integer example: 1 project_id: type: integer example: 1 user_id: type: integer example: 42 rate: type: number example: 85.5 started_at: type: string example: '2024-01-01T00:00:00.000000Z' created_at: type: string example: '2023-12-15T10:30:00.000000Z' updated_at: type: string example: '2023-12-15T10:30:00.000000Z' status: type: string example: current links: type: object properties: first: type: string example: 'https://example.com/api/v1/projects/1/users/42/bill-rates?page=1' last: type: string example: 'https://example.com/api/v1/projects/1/users/42/bill-rates?page=2' prev: type: string example: null next: type: string example: 'https://example.com/api/v1/projects/1/users/42/bill-rates?page=2' meta: type: object properties: current_page: type: integer example: 1 from: type: integer example: 1 last_page: type: integer example: 2 path: type: string example: 'https://example.com/api/v1/projects/1/users/42/bill-rates' per_page: type: integer example: 30 to: type: integer example: 30 total: type: integer example: 45 403: description: unauthorized content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' tags: - 'Bill Rates' post: summary: 'Create a new bill rate for a user in a project.' operationId: createANewBillRateForAUserInAProject description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 201: description: success content: application/json: schema: type: object example: id: 3 project_id: 1 user_id: 42 rate: 85.5 started_at: '2024-01-01T00:00:00.000000Z' created_at: '2023-12-20T09:45:00.000000Z' updated_at: '2023-12-20T09:45:00.000000Z' status: future properties: id: type: integer example: 3 project_id: type: integer example: 1 user_id: type: integer example: 42 rate: type: number example: 85.5 started_at: type: string example: '2024-01-01T00:00:00.000000Z' created_at: type: string example: '2023-12-20T09:45:00.000000Z' updated_at: type: string example: '2023-12-20T09:45:00.000000Z' status: type: string example: future 403: description: unauthorized content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 422: description: duplicate_date content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: started_at: - 'The start date already exists for this user.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: started_at: type: array example: - 'The start date already exists for this user.' items: type: string tags: - 'Bill Rates' requestBody: required: true content: application/json: schema: type: object properties: started_at: type: date description: 'The start date when this rate becomes effective (YYYY-MM-DD).' example: '2024-01-01' nullable: false rate: type: numeric description: 'The hourly rate.' example: '85.50' nullable: false required: - started_at - rate parameters: - in: path name: project_id description: 'The ID of the project.' example: 1 required: true schema: type: integer - in: path name: user_id description: 'The ID of the user.' example: 1 required: true schema: type: integer - in: path name: project description: 'The ID of the project.' example: 1 required: true schema: type: integer - in: path name: user description: 'The ID of the user.' example: 42 required: true schema: type: integer '/api/v1/projects/{project_id}/users/{user_id}/bill-rates/{billRate_id}': put: summary: 'Update a bill rate.' operationId: updateABillRate description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 200: description: success content: application/json: schema: type: object example: id: 3 project_id: 1 user_id: 42 rate: 90.0 started_at: '2024-02-01T00:00:00.000000Z' created_at: '2023-12-20T09:45:00.000000Z' updated_at: '2023-12-25T11:20:00.000000Z' status: future properties: id: type: integer example: 3 project_id: type: integer example: 1 user_id: type: integer example: 42 rate: type: number example: 90.0 started_at: type: string example: '2024-02-01T00:00:00.000000Z' created_at: type: string example: '2023-12-20T09:45:00.000000Z' updated_at: type: string example: '2023-12-25T11:20:00.000000Z' status: type: string example: future 403: description: unauthorized content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: not_found content: application/json: schema: type: object example: message: 'Bill rate not found for this user' properties: message: type: string example: 'Bill rate not found for this user' 422: description: duplicate_date content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: started_at: - 'The start date already exists for this user.' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: started_at: type: array example: - 'The start date already exists for this user.' items: type: string tags: - 'Bill Rates' requestBody: required: false content: application/json: schema: type: object properties: started_at: type: date description: 'The start date when this rate becomes effective (YYYY-MM-DD).' example: '2024-02-01' nullable: false rate: type: numeric description: 'The hourly rate.' example: '90.00' nullable: false delete: summary: 'Delete a bill rate.' operationId: deleteABillRate description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 204: description: success content: text/plain: schema: type: string example: 'null' 403: description: unauthorized content: application/json: schema: type: object example: message: 'This action is unauthorized.' properties: message: type: string example: 'This action is unauthorized.' 404: description: not_found content: application/json: schema: type: object example: message: 'Bill rate not found for this user' properties: message: type: string example: 'Bill rate not found for this user' 422: description: cannot_delete content: application/json: schema: type: object example: message: 'The given data was invalid.' errors: error: - 'Current and past bill rate cannot be deleted' properties: message: type: string example: 'The given data was invalid.' errors: type: object properties: error: type: array example: - 'Current and past bill rate cannot be deleted' items: type: string tags: - 'Bill Rates' parameters: - in: path name: project_id description: 'The ID of the project.' example: 1 required: true schema: type: integer - in: path name: user_id description: 'The ID of the user.' example: 1 required: true schema: type: integer - in: path name: billRate_id description: 'The ID of the billRate.' example: 1 required: true schema: type: integer - in: path name: project description: 'The ID of the project.' example: 1 required: true schema: type: integer - in: path name: user description: 'The ID of the user.' example: 42 required: true schema: type: integer - in: path name: billRate description: 'The ID of the bill rate.' example: 3 required: true schema: type: integer /api/v1/boards: get: summary: 'Display a paginated list of project boards.' operationId: displayAPaginatedListOfProjectBoards description: '' parameters: - in: query name: search description: 'Filter boards by partial match in the board title.' example: Marketing required: false schema: type: string description: 'Filter boards by partial match in the board title.' example: Marketing nullable: false - in: query name: project_id description: 'Filter boards that belong to the given project id.' example: 5 required: false schema: type: integer description: 'Filter boards that belong to the given project id.' example: 5 nullable: false - in: query name: per_page description: 'Number of results per page. Maximum: 100.' example: 50 required: false schema: type: integer description: 'Number of results per page. Maximum: 100.' example: 50 nullable: false - in: query name: sort description: 'Column used for sorting. Allowed: id, title, created_at, updated_at.' example: created_at required: false schema: type: string description: 'Column used for sorting. Allowed: id, title, created_at, updated_at.' example: created_at nullable: false - in: query name: direction description: 'Sort direction. Allowed: asc, desc.' example: desc required: false schema: type: string description: 'Sort direction. Allowed: asc, desc.' example: desc nullable: false - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 200: description: success content: application/json: schema: type: object example: data: - id: 10 title: 'Marketing pipeline' description: 'High level marketing workflow.' project_id: 3 user_id: 14 team_id: 8 created_at: '2025-01-10T12:30:00.000000Z' updated_at: '2025-01-10T12:30:00.000000Z' deleted_at: null links: first: 'https://example.com/api/v1/boards?page=1' last: 'https://example.com/api/v1/boards?page=1' prev: null next: null meta: current_page: 1 from: 1 last_page: 1 path: 'https://example.com/api/v1/boards' per_page: 30 to: 1 total: 1 properties: data: type: array example: - id: 10 title: 'Marketing pipeline' description: 'High level marketing workflow.' project_id: 3 user_id: 14 team_id: 8 created_at: '2025-01-10T12:30:00.000000Z' updated_at: '2025-01-10T12:30:00.000000Z' deleted_at: null items: type: object properties: id: type: integer example: 10 title: type: string example: 'Marketing pipeline' description: type: string example: 'High level marketing workflow.' project_id: type: integer example: 3 user_id: type: integer example: 14 team_id: type: integer example: 8 created_at: type: string example: '2025-01-10T12:30:00.000000Z' updated_at: type: string example: '2025-01-10T12:30:00.000000Z' deleted_at: type: string example: null links: type: object properties: first: type: string example: 'https://example.com/api/v1/boards?page=1' last: type: string example: 'https://example.com/api/v1/boards?page=1' prev: type: string example: null next: type: string example: null meta: type: object properties: current_page: type: integer example: 1 from: type: integer example: 1 last_page: type: integer example: 1 path: type: string example: 'https://example.com/api/v1/boards' per_page: type: integer example: 30 to: type: integer example: 1 total: type: integer example: 1 tags: - Boards post: summary: 'Create a new project board.' operationId: createANewProjectBoard description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 201: description: success content: application/json: schema: type: object example: id: 10 title: 'Marketing pipeline' description: 'High level marketing workflow.' project_id: 3 user_id: 14 team_id: 8 created_at: '2025-01-10T12:30:00.000000Z' updated_at: '2025-01-10T12:30:00.000000Z' deleted_at: null properties: id: type: integer example: 10 title: type: string example: 'Marketing pipeline' description: type: string example: 'High level marketing workflow.' project_id: type: integer example: 3 user_id: type: integer example: 14 team_id: type: integer example: 8 created_at: type: string example: '2025-01-10T12:30:00.000000Z' updated_at: type: string example: '2025-01-10T12:30:00.000000Z' deleted_at: type: string example: null 422: description: validation_error content: application/json: schema: type: object example: message: 'Project not found' properties: message: type: string example: 'Project not found' tags: - Boards requestBody: required: true content: application/json: schema: type: object properties: title: type: string description: 'Board title.' example: 'Marketing pipeline' nullable: false description: type: string description: 'Board description.' example: 'High level marketing workflow.' nullable: true project_id: type: integer description: 'Project id the board belongs to.' example: 3 nullable: true user_id: type: string description: '' example: null nullable: false team_id: type: string description: '' example: null nullable: false required: - title '/api/v1/boards/{id}': get: summary: 'Display a single board.' operationId: displayASingleBoard description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 200: description: success content: application/json: schema: type: object example: id: 10 title: 'Marketing pipeline' description: 'High level marketing workflow.' project_id: 3 user_id: 14 team_id: 8 created_at: '2025-01-10T12:30:00.000000Z' updated_at: '2025-01-10T12:30:00.000000Z' deleted_at: null properties: id: type: integer example: 10 title: type: string example: 'Marketing pipeline' description: type: string example: 'High level marketing workflow.' project_id: type: integer example: 3 user_id: type: integer example: 14 team_id: type: integer example: 8 created_at: type: string example: '2025-01-10T12:30:00.000000Z' updated_at: type: string example: '2025-01-10T12:30:00.000000Z' deleted_at: type: string example: null 404: description: not_found content: application/json: schema: type: object example: message: 'Not found' properties: message: type: string example: 'Not found' tags: - Boards put: summary: 'Update a board.' operationId: updateABoard description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 200: description: success content: application/json: schema: type: object example: id: 10 title: 'Marketing pipeline' description: 'High level marketing workflow.' project_id: 3 user_id: 14 team_id: 8 created_at: '2025-01-10T12:30:00.000000Z' updated_at: '2025-01-10T16:45:00.000000Z' deleted_at: null properties: id: type: integer example: 10 title: type: string example: 'Marketing pipeline' description: type: string example: 'High level marketing workflow.' project_id: type: integer example: 3 user_id: type: integer example: 14 team_id: type: integer example: 8 created_at: type: string example: '2025-01-10T12:30:00.000000Z' updated_at: type: string example: '2025-01-10T16:45:00.000000Z' deleted_at: type: string example: null 404: description: not_found content: application/json: schema: type: object example: message: 'Not found' properties: message: type: string example: 'Not found' tags: - Boards requestBody: required: false content: application/json: schema: type: object properties: title: type: string description: 'Board title.' example: 'Marketing pipeline' nullable: false description: type: string description: 'Board description.' example: 'High level marketing workflow.' nullable: true project_id: type: integer description: 'Project id the board belongs to.' example: 3 nullable: true user_id: type: string description: '' example: null nullable: false team_id: type: string description: '' example: null nullable: false delete: summary: 'Delete a board.' operationId: deleteABoard description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 204: description: success content: text/plain: schema: type: string example: 'null' 404: description: not_found content: application/json: schema: type: object example: message: 'Not found' properties: message: type: string example: 'Not found' tags: - Boards parameters: - in: path name: id description: 'Board id.' example: 10 required: true schema: type: integer '/api/v1/boards/{id}/export-activity': get: summary: 'Export board activity with time tracking data.' operationId: exportBoardActivityWithTimeTrackingData description: '' parameters: - in: query name: start_date description: 'Start date for the export range (YYYY-MM-DD).' example: '2025-01-01' required: true schema: type: string description: 'Start date for the export range (YYYY-MM-DD).' example: '2025-01-01' nullable: false - in: query name: end_date description: 'End date for the export range (YYYY-MM-DD).' example: '2025-01-31' required: true schema: type: string description: 'End date for the export range (YYYY-MM-DD).' example: '2025-01-31' nullable: false - in: query name: group_by description: "Grouping option: 'member' or 'task'." example: member required: true schema: type: string description: "Grouping option: 'member' or 'task'." example: member nullable: false - in: query name: time_format description: "Time format: 'seconds' (integer) or 'hms' (HH:MM:SS string). Defaults to 'seconds'." example: hms required: false schema: type: string description: "Time format: 'seconds' (integer) or 'hms' (HH:MM:SS string). Defaults to 'seconds'." example: hms nullable: false - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 200: description: '' content: application/json: schema: oneOf: - description: grouped_by_member_seconds type: object example: 'john doe': - task: 'Marketing campaign' time: 7200 - task: 'Website redesign' time: 3600 'jane smith': - task: 'Marketing campaign' time: 5400 properties: 'john doe': type: array example: - task: 'Marketing campaign' time: 7200 - task: 'Website redesign' time: 3600 items: type: object properties: task: type: string example: 'Marketing campaign' time: type: integer example: 7200 'jane smith': type: array example: - task: 'Marketing campaign' time: 5400 items: type: object properties: task: type: string example: 'Marketing campaign' time: type: integer example: 5400 - description: grouped_by_task_hms type: object example: 'Marketing campaign': - member: 'john doe' time: '02:00:00' - member: 'jane smith' time: '01:30:00' 'Website redesign': - member: 'john doe' time: '01:00:00' properties: 'Marketing campaign': type: array example: - member: 'john doe' time: '02:00:00' - member: 'jane smith' time: '01:30:00' items: type: object properties: member: type: string example: 'john doe' time: type: string example: '02:00:00' 'Website redesign': type: array example: - member: 'john doe' time: '01:00:00' items: type: object properties: member: type: string example: 'john doe' time: type: string example: '01:00:00' 404: description: not_found content: application/json: schema: type: object example: message: 'Not found' properties: message: type: string example: 'Not found' 422: description: validation_error content: application/json: schema: type: object example: message: 'Invalid parameters' properties: message: type: string example: 'Invalid parameters' tags: - Boards requestBody: required: true content: application/json: schema: type: object properties: start_date: type: string description: 'Must be a valid date.' example: '2026-09-15T03:18:22' nullable: false end_date: type: string description: 'Must be a valid date. Must be a date after or equal to start_date.' example: '2052-10-08' nullable: false group_by: type: string description: '' example: task nullable: false enum: - member - task time_format: type: string description: '' example: seconds nullable: true enum: - seconds - hms required: - start_date - end_date - group_by parameters: - in: path name: id description: 'Board id.' example: 10 required: true schema: type: integer '/api/v1/boards/{board_id}/columns': get: summary: 'List columns for a board.' operationId: listColumnsForABoard description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 200: description: success content: application/json: schema: type: object example: data: - id: 1 name: 'To Do' is_todo: true is_done: false project_board_id: 10 team_id: 1 order: 0 - id: 2 name: 'In Progress' is_todo: false is_done: false project_board_id: 10 team_id: 1 order: 1 properties: data: type: array example: - id: 1 name: 'To Do' is_todo: true is_done: false project_board_id: 10 team_id: 1 order: 0 - id: 2 name: 'In Progress' is_todo: false is_done: false project_board_id: 10 team_id: 1 order: 1 items: type: object properties: id: type: integer example: 1 name: type: string example: 'To Do' is_todo: type: boolean example: true is_done: type: boolean example: false project_board_id: type: integer example: 10 team_id: type: integer example: 1 order: type: integer example: 0 404: description: not_found content: application/json: schema: type: object example: message: 'Board not found' properties: message: type: string example: 'Board not found' tags: - Boards post: summary: 'Create a new column in a board.' operationId: createANewColumnInABoard description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 201: description: success content: application/json: schema: type: object example: data: id: 5 name: 'To Do' is_todo: true is_done: false project_board_id: 10 team_id: 1 order: 0 properties: data: type: object properties: id: type: integer example: 5 name: type: string example: 'To Do' is_todo: type: boolean example: true is_done: type: boolean example: false project_board_id: type: integer example: 10 team_id: type: integer example: 1 order: type: integer example: 0 404: description: not_found content: application/json: schema: type: object example: message: 'Board not found' properties: message: type: string example: 'Board not found' tags: - Boards requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: 'Column name.' example: 'To Do' nullable: false is_todo: type: boolean description: 'Whether this is the initial/todo column.' example: true nullable: false is_done: type: boolean description: 'Whether this is the done/completed column.' example: false nullable: false order: type: integer description: 'Column position (0-based).' example: 0 nullable: false required: - name parameters: - in: path name: board_id description: 'Board id.' example: 10 required: true schema: type: integer '/api/v1/boards/{board_id}/columns/{column_id}': put: summary: 'Update a column.' operationId: updateAColumn description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 200: description: success content: application/json: schema: type: object example: data: id: 5 name: 'In Progress' is_todo: false is_done: false project_board_id: 10 team_id: 1 order: 1 properties: data: type: object properties: id: type: integer example: 5 name: type: string example: 'In Progress' is_todo: type: boolean example: false is_done: type: boolean example: false project_board_id: type: integer example: 10 team_id: type: integer example: 1 order: type: integer example: 1 404: description: not_found content: application/json: schema: type: object example: message: 'Column not found' properties: message: type: string example: 'Column not found' tags: - Boards requestBody: required: false content: application/json: schema: type: object properties: name: type: string description: 'Column name.' example: 'In Progress' nullable: true is_todo: type: boolean description: 'Whether this is the initial/todo column.' example: false nullable: false is_done: type: boolean description: 'Whether this is the done/completed column.' example: false nullable: false order: type: integer description: 'Column position (0-based).' example: 1 nullable: false delete: summary: 'Delete a column.' operationId: deleteAColumn description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 204: description: success content: text/plain: schema: type: string example: 'null' 404: description: not_found content: application/json: schema: type: object example: message: 'Column not found' properties: message: type: string example: 'Column not found' 422: description: has_tasks content: application/json: schema: type: object example: message: 'Cannot delete column with tasks. Move or delete tasks first.' properties: message: type: string example: 'Cannot delete column with tasks. Move or delete tasks first.' tags: - Boards parameters: - in: path name: board_id description: 'Board id.' example: 10 required: true schema: type: integer - in: path name: column_id description: 'Column id.' example: 5 required: true schema: type: integer /api/v1/emails: get: summary: 'List CRM emails (drafts or sent).' operationId: listCRMEmailsdraftsOrSent description: '' parameters: - in: query name: status description: 'Filter by status: draft, sent, failed, queued.' example: draft required: false schema: type: string description: 'Filter by status: draft, sent, failed, queued.' example: draft nullable: false - in: query name: contact_id description: 'Filter by contact id.' example: 15 required: false schema: type: integer description: 'Filter by contact id.' example: 15 nullable: false - in: query name: per_page description: 'Results per page (max 50).' example: 20 required: false schema: type: integer description: 'Results per page (max 50).' example: 20 nullable: false - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 401: description: '' content: application/json: schema: type: object example: message: 'Invalid API Key' properties: message: type: string example: 'Invalid API Key' tags: - 'CRM Emails' '/api/v1/emails/{id}': get: summary: 'Show a CRM email.' operationId: showACRMEmail description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: 401: description: '' content: application/json: schema: type: object example: message: 'Invalid API Key' properties: message: type: string example: 'Invalid API Key' tags: - 'CRM Emails' put: summary: 'Update a draft email.' operationId: updateADraftEmail description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: { } tags: - 'CRM Emails' requestBody: required: true content: multipart/form-data: schema: type: object properties: to: type: string description: 'Must be a valid email address. Must not be greater than 255 characters.' example: b nullable: false subject: type: string description: 'Must not be greater than 500 characters.' example: 'n' nullable: true body: type: string description: 'Must not be greater than 50000 characters.' example: g nullable: false scheduled_at: type: string description: 'Must not be greater than 64 characters.' example: z nullable: true cc: type: array description: 'Must be a valid email address. Must not be greater than 255 characters.' example: - m items: type: string bcc: type: array description: 'Must be a valid email address. Must not be greater than 255 characters.' example: - i items: type: string attachments: type: array description: 'Must be a file. Must not be greater than 25600 kilobytes.' items: type: string format: binary remove_attachment_ids: type: array description: '' example: - 16 items: type: integer required: - cc - bcc delete: summary: 'Cancel (discard) a draft email.' operationId: canceldiscardADraftEmail description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: { } tags: - 'CRM Emails' parameters: - in: path name: id description: 'The ID of the email.' example: 1 required: true schema: type: integer /api/v1/emails/draft: post: summary: 'Create a draft email for a contact.' operationId: createADraftEmailForAContact description: '' parameters: - in: header name: X-API-Key description: '' example: '{YOUR_AUTH_KEY}' schema: type: string responses: { } tags: - 'CRM Emails' requestBody: required: true content: multipart/form-data: schema: type: object properties: contact_id: type: integer description: 'Contact to associate the draft with. This field is required when none of reply_to_incoming_email_id and contact_ref are present. The id of an existing record in the contacts table.' example: 15 nullable: true contact_ref: type: object description: '' example: null nullable: true properties: id: type: integer description: '' example: 16 nullable: true email: type: string description: 'Must be a valid email address. Must not be greater than 255 characters.' example: zbailey@example.net nullable: true to: type: string description: 'Recipient email. Defaults to the contact email when omitted. Must be a valid email address. Must not be greater than 255 characters.' example: alex@example.com nullable: true subject: type: string description: 'Email subject line. Must not be greater than 500 characters.' example: 'Following up' nullable: true body: type: string description: 'HTML message body. Use separate

tags per paragraph; use