Jobs
BlueSuite MCP tools for jobs
See connection and authentication and workflow rules before calling these tools.
Related REST API and behavior.
List jobs with optional pagination and search
| Field | Type / accepted values | Required | Details |
|---|
page | integer | No | Page number (default: 1) |
per_page | integer | No | Results per page (default: 25) minimum: 1. maximum: 100. |
search | string | No | Search jobs |
sort_by | "id", "number", "name", "status", "type", "total", "expected_end_date", "created_at", "modified_at" | No | Field to sort by. Unknown values fall back to the default sort. |
sort_direction | "asc", "desc" | No | Sort direction |
contact_id | integer | No | Filter by contact ID |
quote_id | JSON value | No | Filter by quote ID |
status | array of "draft", "scheduled", "in_progress", "on_hold", "completed", "cancelled" | No | Filter by one or more statuses. |
derived_state | array of "missed", "overdue", "action_required", "needs_invoicing", "unscheduled", "awaiting_payment" | No | Filter by one or more derived conditions: needs_invoicing (work done, not yet invoiced), unscheduled (no appointment booked), missed, overdue, awaiting_payment, action_required. Use this for questions about what needs attention rather than filtering on status. |
tag_ids | array of JSON value | No | Filter to records carrying ANY of these tag IDs (not all). Use list_tags with the matching taggable_type to resolve tag names to IDs first. |
| Field | Type / accepted values | Required | Details |
|---|
data | array of object | Yes | The matching records for this page. |
pagination | object | No | How many more pages of results exist. Absent when the API returned an unpaged result. |
pagination.page | integer | When parent supplied | Current page number, 1-based. |
pagination.per_page | integer | When parent supplied | Number of results per page. |
pagination.total_pages | integer | When parent supplied | Total number of pages available. |
Create a new job
| Field | Type / accepted values | Required | Details |
|---|
name | string | No | Job name/title |
contact_id | integer | No | Associated contact ID |
property_id | JSON value | No | Associated property ID |
request_id | JSON value | No | Associated request ID |
quote_id | JSON value | No | Associated quote ID |
salesperson_id | string | No | UUID of salesperson. Use list_users to resolve names. Format: uuid. |
line_items | array of object or object | No | Array of line item objects. Two shapes are accepted: a regular priced row ({ name, quantity, unit_price }) or an inline image row ({ _type: "image", image_path, image_id, description }). For image rows: first call upload_file with module_type="workspace", category="line_item", is_public=true to upload the image, then pass the returned path as image_path and id as image_id. |
line_items[]._type | "lineItem" | No | For lineItem rows. Defaults to lineItem when omitted. |
line_items[].name | string | For this variant | For lineItem rows. Item name |
line_items[].description | string | No | For lineItem rows. Plain text description for this line item. Omit when not needed. Default: "". |
line_items[].quantity | number | No | For lineItem rows. Quantity Default: 1. |
line_items[].unit_price | number | For this variant | For lineItem rows. Price per unit |
line_items[].taxable | boolean | No | For lineItem rows. Whether the item is taxable |
line_items[].optional | boolean | No | For lineItem rows. Whether the item is optional |
line_items[]._type | "image" | For this variant | For image rows. |
line_items[].image_path | string | For this variant | For image rows. Storage path returned by a prior upload_file call. Upload with module_type="workspace", category="line_item", is_public=true to get a usable path. minLength: 1. |
line_items[].image_id | integer | No | For image rows. Upload link ID (id) returned by the same upload_file call. |
line_items[].description | string | No | For image rows. Caption shown beneath the image in the line items list. |
discount | number | No | Discount amount (default: 0) |
discount_unit | "percent", "amount" | No | How the discount is expressed. One of: 'percent' (a percentage of the subtotal) or 'amount' (a fixed currency amount). Default: 'percent'. |
deposit | number | No | Deposit amount (default: 0) |
deposit_unit | JSON value | No | How the deposit is expressed. One of: 'percent' or 'amount'. Default: 'percent'. |
tax_rate | number | No | Tax rate percentage (default: 0) |
tax_rate_id | JSON value | No | Tax rate preset ID |
total | number | No | Job total |
type | "one-off", "recurring" | No | Job type (default: one-off) |
status | "completed", "cancelled" | No | Initial status. Only completed and cancelled can be set; otherwise status follows the job's appointments. |
billing_type | "per_visit", "manual" | No | How the job gets invoiced. 'per_visit' automatically creates and sends an invoice each time an appointment is completed. 'manual' means the business invoices on its own schedule. Defaults to 'per_visit', ask the user which they want for recurring work rather than assuming, because the default sends real invoices to their client. |
invoice_autopay | boolean | No | Charge the client's saved payment method automatically when an invoice is auto-created. Only meaningful with billing_type='per_visit'. Default: false. |
invoice_payment_terms | "due_on_receipt", "net_7", "net_14", "net_30", "net_60", "net_90" | No | Payment terms applied to invoices generated from this job. |
waive_credit_card_fee | boolean | No | Skip the workspace's online processing fee for this record. Only meaningful when the workspace passes processing fees on to clients. Nothing is charged against a job directly; the waiver rides onto invoices created from it. Default: false. |
expected_end_date | string | No | Expected end date (YYYY-MM-DD) |
custom_fields | object | No | Custom field values |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
Get a single job by ID with expanded details
| Field | Type / accepted values | Required | Details |
|---|
id | integer | Yes | Job ID |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
Update an existing job. For an in-progress job that requires change orders, line items, discounts, and taxes cannot be changed here; create a change order in the dashboard. Omit line_items when only updating job details. Setting status here applies the same completion rules as update_job_status (for example, required forms must be filled in before a job can be completed), so prefer that tool when status is the only change.
| Field | Type / accepted values | Required | Details |
|---|
id | integer | Yes | Job ID |
name | string | No | Job name/title |
status | "completed", "cancelled", "reopen" | No | Change the job status as part of this update. Prefer update_job_status when status is the only thing changing. Draft, Scheduled and Ongoing are derived from appointments and cannot be set. |
contact_id | JSON value | No | Associated contact ID |
property_id | JSON value | No | Associated property ID |
request_id | JSON value | No | Associated request ID |
quote_id | JSON value | No | Associated quote ID |
salesperson_id | string | No | UUID of salesperson. Use list_users to resolve names. Format: uuid. |
line_items | array of object or object | No | Array of line item objects. Two shapes are accepted: a regular priced row ({ name, quantity, unit_price }) or an inline image row ({ _type: "image", image_path, image_id, description }). For image rows: first call upload_file with module_type="workspace", category="line_item", is_public=true to upload the image, then pass the returned path as image_path and id as image_id. |
line_items[]._type | "lineItem" | No | For lineItem rows. Defaults to lineItem when omitted. |
line_items[].name | string | For this variant | For lineItem rows. Item name |
line_items[].description | string | No | For lineItem rows. Plain text description for this line item. Omit when not needed. Default: "". |
line_items[].quantity | number | No | For lineItem rows. Quantity Default: 1. |
line_items[].unit_price | number | For this variant | For lineItem rows. Price per unit |
line_items[].taxable | boolean | No | For lineItem rows. Whether the item is taxable |
line_items[].optional | boolean | No | For lineItem rows. Whether the item is optional |
line_items[]._type | "image" | For this variant | For image rows. |
line_items[].image_path | string | For this variant | For image rows. Storage path returned by a prior upload_file call. Upload with module_type="workspace", category="line_item", is_public=true to get a usable path. minLength: 1. |
line_items[].image_id | integer | No | For image rows. Upload link ID (id) returned by the same upload_file call. |
line_items[].description | string | No | For image rows. Caption shown beneath the image in the line items list. |
discount | number | No | Discount amount |
discount_unit | "percent", "amount" | No | How the discount is expressed. One of: 'percent' (a percentage of the subtotal) or 'amount' (a fixed currency amount). |
deposit | number | No | Deposit amount |
deposit_unit | JSON value | No | How the deposit is expressed. One of: 'percent' or 'amount'. |
tax_rate | number | No | Tax rate percentage |
tax_rate_id | JSON value | No | Tax rate preset ID |
total | number | No | Job total |
type | "one-off", "recurring" | No | Job type |
billing_type | "per_visit", "manual" | No | How the job gets invoiced. 'per_visit' automatically creates and sends an invoice each time an appointment is completed. 'manual' means the business invoices on its own schedule. Defaults to 'per_visit', ask the user which they want for recurring work rather than assuming, because the default sends real invoices to their client. |
invoice_autopay | boolean | No | Charge the client's saved payment method automatically when an invoice is auto-created. Only meaningful with billing_type='per_visit'. |
invoice_payment_terms | "due_on_receipt", "net_7", "net_14", "net_30", "net_60", "net_90" | No | Payment terms applied to invoices generated from this job. |
waive_credit_card_fee | boolean | No | Skip the workspace's online processing fee for this record. Only meaningful when the workspace passes processing fees on to clients. Nothing is charged against a job directly; the waiver rides onto invoices created from it. Default: false. |
expected_end_date | string | No | Expected end date (YYYY-MM-DD) |
custom_fields | object | No | Custom field values |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
Put a job on a recurring appointment schedule, weekly lawn care, quarterly maintenance, and so on. Use this rather than create_event for anything tied to a job: it marks the job recurring, saves the billing settings the completion flow reads, and creates the appointment series in one step. A recurring job created without this stays unscheduled and never generates visits. Confirm the billing_type with the user first, since per_visit sends real invoices to their client after every visit.
| Field | Type / accepted values | Required | Details |
|---|
id | integer | Yes | Job ID to schedule. |
start_date | string | Yes | Date of the first appointment (YYYY-MM-DD). |
end_date | JSON value | No | End date of each appointment, for visits spanning more than one day. |
start_time | string | No | Start time (HH:MM). Required unless all_day is true. |
end_time | JSON value | No | End time (HH:MM). Required unless all_day is true. |
all_day | boolean | No | Whether each visit takes the whole day. |
multi_day | JSON value | No | Whether each visit spans multiple days. |
is_flexible | JSON value | No | Whether scheduling may move the visit within the day. |
duration_minutes | integer | No | Expected length of each visit in minutes. |
assignee_ids | array of string | No | UUIDs of the team members assigned. Use list_users to resolve names. |
billing_type | "per_visit", "manual" | No | How the job gets invoiced. 'per_visit' automatically creates and sends an invoice each time an appointment is completed. 'manual' means the business invoices on its own schedule. Defaults to 'per_visit', ask the user which they want for recurring work rather than assuming, because the default sends real invoices to their client. |
payment_terms | "due_on_receipt", "net_7", "net_14", "net_30", "net_60", "net_90" | No | Payment terms on invoices generated from these visits. |
repeat_frequency | JSON value | No | Interval between visits, used when repeat_frequency_unit is 'custom' (2 with a custom weekly unit means every 2 weeks). Default: 1. |
repeat_frequency_unit | "daily", "weekly", "monthly", "yearly", "custom", "forever", "occurrences" | No | How often the visit repeats: daily, weekly, monthly, yearly, or 'custom'. Default: weekly. |
repeat_frequency_unit_custom | "daily", "weekly", "monthly", "yearly", "custom", "forever", "occurrences" | No | Unit the custom interval counts in. Only used when repeat_frequency_unit is 'custom'. |
repeat_frequency_schedule | object | No | Which days a custom weekly or monthly pattern lands on. Required for those patterns. |
repeat_frequency_schedule.days | array of JSON value | When parent supplied | Days to repeat on: 1-7 for weekdays, 1-31 for days of the month. |
repeat_frequency_schedule.type | "weekDays", "monthWeekDays", "monthDays" | When parent supplied | |
repeat_duration | JSON value | No | How long the schedule runs. With repeat_duration_unit='occurrences' this is a visit count. Required unless it repeats forever. |
repeat_duration_unit | "daily", "weekly", "monthly", "yearly", "custom", "forever", "occurrences" | No | How the schedule ends: 'forever', 'occurrences' (a fixed number of visits), or a time unit. Default: forever. |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
Stop a job's recurring schedule from a given date. Use this when the user says to stop, cancel or end repeating work, do NOT delete the job, which would take its history with it. This is a cutoff, not a delete: visits after the date are removed, while visits on or before it, and anything already completed or invoiced, are kept. Confirm the date with the user, since "stop after this month" and "stop immediately" remove different visits.
| Field | Type / accepted values | Required | Details |
|---|
id | integer | Yes | Job ID whose schedule should end. |
end_date | string | Yes | Last date the schedule runs (YYYY-MM-DD). Visits after this date are removed. |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
Delete a job and everything that hangs off it. Every appointment cascades away, including completed visits, along with expenses and change orders; invoices and time entries survive but lose their link to the job. For a recurring job this destroys the whole visit history, to stop repeating work use end_recurring_job_schedule, which keeps the past and only removes visits after a cutoff. Confirm with the user first; there is no undo.
| Field | Type / accepted values | Required | Details |
|---|
id | integer | Yes | Job ID |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
Place a job on hold with a reason, optional notes, and an optional follow-up date. Confirm whether upcoming unstarted appointments should be cancelled to release their time slots or kept booked. Completed and in-progress visits are preserved. Existing invoices and payments are unaffected. The person placing the hold receives email and dashboard follow-ups when due. For recurring jobs, cancel_appointments=true also pauses new visits; false keeps existing appointments and continues normal generation. Service plans are not supported.
| Field | Type / accepted values | Required | Details |
|---|
id | integer | Yes | Job ID |
reason | "customer", "materials", "approval", "weather", "other" | Yes | |
notes | string | No | maxLength: 2000. |
follow_up_on | string | No | Optional follow-up date, YYYY-MM-DD. Does not automatically resume the job. |
cancel_appointments | boolean | Yes | Required explicit choice: true cancels upcoming unstarted appointments; false keeps them booked. |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
Resume an on-hold job. For recurring jobs whose hold_cancel_appointments is true and whose schedule has not been explicitly ended, resume_on is required: visits restart on the original recurrence pattern from that date without catch-up visits. If all schedules have been explicitly ended, omit resume_on; resuming clears the hold without restarting them. If hold_cancel_appointments is false, omit resume_on; appointments continue unchanged. End dates and occurrence limits stay unchanged. Read the current job first and pass its held_at timestamp so a stale request cannot resume a newer hold. Status is recalculated from existing work. Cancelled records stay in history. Recurring visits are generated again from resume_on; one-off appointments must be scheduled separately.
| Field | Type / accepted values | Required | Details |
|---|
id | integer | Yes | Job ID |
expected_held_at | string | Yes | Exact held_at timestamp from get_job. Format: date-time. |
resume_on | string | No | Required only when hold_cancel_appointments is true on a recurring job with a schedule that has not been explicitly ended: resume appointments on or after this date (YYYY-MM-DD), today or later. |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
Change a job's status with completion rules enforced. Use hold_job and resume_job to manage holds. Draft, Scheduled and Ongoing are derived from the job's appointments and cannot be set by hand. Use "reopen" to bring a completed or cancelled job back; the correct status is then re-derived from its appointments.
| Field | Type / accepted values | Required | Details |
|---|
id | integer | Yes | Job ID |
status | "completed", "cancelled", "reopen" | Yes | completed, cancelled, or reopen. Completing fails if the job has required forms that are not filled in yet. |
| Field | Type / accepted values | Required | Details |
|---|
data | object or null | Yes | The affected record, or the result of the operation. Null when nothing matched. |
The downloadable tool schemas include the full input and output contracts. Tables describe schema-level required fields; cross-field rules still apply.