Overview
The BoldDesk MCP Server provides tools that MCP clients such as Claude, ChatGPT, and in-house agents, can use to interact with the help desk. Tools fall into the following groups:
| Group | Tools | Purpose |
|---|---|---|
| Session & metadata | 3 | Resolve who the caller is and determine which statuses and fields are available in their tenant |
| Tickets | 9 | List, read, create, patch, and transition tickets |
| Ticket conversation | 2 | Read the message log and append replies/notes |
| Activities | 5 | List, read, create and patch task activities |
| Approvals | 4 | List, read, raise, and respond to approval requests |
| Directory lookup | 5 | Resolve agents, contacts, groups, and companies; create contacts |
| Knowledge base | 5 | List sections and categories, list and search KB articles, and create or read individual articles. |
Call get_user_info once at the start of the session. Almost every other tool depends on IDs it returns:
- userId for “my tickets”
- currentBrand.id for status
- field lookups, formInfo[].id for field discovery
Typical call chains
"my open tickets" get_user_info → get_ticket_statuses(brandId) → list_tickets(assigneeId, statusIds)
"create a ticket" get_user_info → [get_ticket_fields(brandId, formId)] → create_ticket
"patch a field" get_ticket(ticketId) → get_ticket_fields(brandId, formId) → update_ticket
"assign to someone" search_agents(query) → update_ticket(fields:{agentId})
"move status" get_ticket_statuses(brandId) → update_ticket_status
Conventions
Identifiers
All IDs are integers.
Dates and times
- All timestamps in responses are ISO 8601 with offset: 2026-08-21T13:10:08.624593+00:00.
- All date inputs use UTC and must be in the format yyyy-MM-ddTHH:mm:ss (no offset suffix).
- Callers must convert local time to UTC using get_user_info.user.timeZone. For Asia/Kolkata, “today” is T-1 18:30:00 → T 18:29:59 UTC.
Pagination
| Pattern | Tools | Request | Response |
|---|---|---|---|
| Page-number | list_tickets, list_activities, list_approval_requests | page, limit | items[], totalEstimate, isLast |
| Page-number + cursor echo | search_agents, search_contacts, search_groups, search_contact_groups, list_kb_articles | page, limit | items[], cursor (next page number as string), totalEstimate, isLast |
| Opaque cursor | get_ticket_messages, search_kb_articles | cursor, limit | items{}, cursor, isLast |
The limit is 1–100 for all tools; the default is 25.
Custom fields
Ticket custom fields use the cf_ prefix and are identified by apiName, not by label or ID. Discover them with get_ticket_fields(brandId, formId).
They appear in get_ticket responses under customFields as a flat map, including null values.
Validation modes
create_ticket, update_ticket, and update_ticket_status accept strictValidation (default: false).
- false — lenient. The write proceeds with minimal input; fields marked as required by the form are not enforced.
- true — all required fields on the resolved form must be present or the call fails.
Agents creating tickets from partial natural-language input generally want false. Migration and bulk-import jobs generally want true.
Shared enumerations
Eight enums recur throughout the API surface. IDs are integers; Message type is the only enum whose values are strings.
| Enum | Supplied as | Values |
|---|---|---|
| Priority | priorityId, priorityIds, activity priority | 1 Low · 2 Normal (returned as Medium) · 3 High · 4 Critical |
| Content type | contentTypeId | 1 HTML · 2 Plain text · 3 Markdown |
| Message type | messageType | publicReply · publicNote · internalNote · systemMessage |
| Activity status | status on create_activity | 1 Open · 2 In Progress · 3 On Hold · 4 Closed · 5 Cancelled · 6 Waiting for Requester |
| Approval policy | approvalRequestTypeId | 1 Everyone must approve · 2 Anyone can approve · 3 Majority must approve |
| Approval response | approveTypeId | 2 Approve · 3 Reject · 4 Cancel |
| Approval status | statusIds on list_approval_requests | 1 Pending · 2 Approved · 3 Rejected |
| Approval view | approvalRequestViewId | 1 Assigned to me · 2 Requested by me · 3 All approvals |
Ticket statuses are tenant-defined
Status IDs vary by tenant and brand. Always resolve via get_ticket_statuses(brandId).
Key points:
- Statuses are grouped into three fixed categories: Pending, Hold, and Closed.
- Categories are not filterable values.
- Requests such as “pending tickets” must be expanded to include all statuses in the Pending category.
Example resolution for brand 1:
| Category | Status IDs |
|---|---|
| Pending | 1 (New), 2 (Open) |
| Hold | 3 (Waiting for Customer), 8 (Snoozed), 6 (On Hold) |
| Closed | 4 (Solved), 5 (Closed) |
Permission scoping
Every tool is scoped to the authenticated caller’s tenant and role.
- get_user_info.hasFullAccess indicates whether the caller sees all brands or a subset.
- Several list_tickets parameters are role-gated: assigneeId, requesterId, and tags are agent-only; includeOrganizationTickets is contact-only.
Tool index
| Tool | Type | Summary |
|---|---|---|
| get_user_info | Read | Caller identity, brands, forms, capabilities |
| get_ticket_statuses | Read | Status IDs and names for a brand |
| get_ticket_fields | Read | Field schema and options for a form |
| list_tickets | Read | Paginated ticket list with filters |
| get_ticket | Read | Full details of one ticket |
| list_ticket_history | Read | Ticket history |
| list_ticket_links | Read | List ticket links by type |
| create_ticket_web_link | Write | Add external web link to ticket |
| create_ticket_link | Write | Create or modify ticket links |
| create_ticket | Write | Create a ticket |
| update_ticket | Write | Patch fields on a ticket |
| update_ticket_status | Write | Transition ticket status |
| get_ticket_messages | Read | Conversation log |
| add_ticket_message | Write | Append reply or note |
| list_activities | Read | Paginated activity list |
| get_activity | Read | Full details of one activity |
| create_activity | Write | Create a task activity |
| create_activity_comments | Write | Append a comment |
| update_activity | Write | Patch fields on an activity |
| list_approval_requests | Read | Paginated approval list |
| get_approval_request | Read | Full details of one approval |
| create_approval_request | Write | Raise an approval on a ticket |
| submit_approval_response | Write | Approve, reject, or cancel |
| list_worklogs | Read | Paginated worklog list with filters |
| add_worklog | Write | Log time on a ticket or activity |
| search_agents | Read | Resolve agent IDs |
| search_contacts | Read | Resolve contact IDs |
| search_groups | Read | Resolve assignment group IDs |
| search_contact_groups | Read | Resolve company / org IDs |
| get_section_tree_view | Read | Category and section hierarchy as a tree |
| list_kb_articles | Read | Paginated KB article list with filters and sort |
| search_kb_articles | Read | Free-text KB search with brand and category filters |
| get_kb_article_details | Read | Full details of one KB article |
| create_kb_article | Write | Create a KB article |
Session and metadata
get_user_info
Returns the identity, organization, brand access, ticket form information, and capabilities of the current user. Call once per session; the result is stable for the duration of the session.
Input: none.
Output
| Field | Type | Description |
|---|---|---|
| user.id | integer | Caller’s user ID. Use as assigneeId or requesterId for self-references |
| user.name | string | Display name |
| user.userType | string | agent or contact; determines which role-gated filters apply |
| user.timeZone | string | IANA zone; use for all local-to-UTC conversion |
| user.email | string | Caller’s email |
| brands[] | array | Other brands the caller can access |
| brands[].id | integer | Brand ID |
| brands[].name | string | Brand name |
| brands[].defaultFormId | integer | Form used when formId is omitted |
| brands[].formInfo[] | array | { id, name, isDefault } per form |
| currentBrand | object | Same shape as brands[]; represents the caller’s active brand |
| hasFullAccess | boolean | Whether the caller has tenant-wide access |
Example response
{
"user": {
"id": 1003,
"name": "Jane Agent",
"userType": "agent",
"timeZone": "Asia/Kolkata",
"email": "jane.agent@example.com"
},
"brands": [
{
"id": 2,
"name": "Internal Support",
"defaultFormId": 3,
"formInfo": [{ "id": 3, "name": "Internal Support", "isDefault": true }]
}
],
"currentBrand": {
"id": 1,
"name": "Customer Support",
"defaultFormId": 1,
"formInfo": [
{ "id": 1, "name": "Default Form", "isDefault": true },
{ "id": 19, "name": "Migration Request", "isDefault": false }
]
},
"hasFullAccess": false
}
currentBrand is not repeated inside brands[]. To build a complete brand picker, concatenate currentBrand with brands[].
get_ticket_statuses
Returns status IDs and names for a brand, grouped by category.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| brandId | integer | Yes | — | Brand ID. Use currentBrand.id unless the user specifies a brand |
Output
| Field | Type | Description |
|---|---|---|
| items[] | array | One entry per category |
| items[].categoryName | string | Pending, Hold, or Closed |
| items[].statuses[] | array | Statuses in that category |
| items[].statuses[].statusId | integer | Used in statusIds filters and toStatusId |
| items[].statuses[].statusName | string | Display label |
| totalEstimate | integer | Total status count |
| isLast | boolean | Always true — this endpoint is unpaginated |
Example response
{
"items": [
{
"categoryName": "Pending",
"statuses": [
{ "statusId": 1, "statusName": "New" },
{ "statusId": 2, "statusName": "Open" }
]
},
{
"categoryName": "Closed",
"statuses": [
{ "statusId": 4, "statusName": "Solved" },
{ "statusId": 5, "statusName": "Closed" }
]
}
],
"totalEstimate": 12,
"isLast": true
}
get_ticket_fields
Returns the fields, data types, and available options for a ticket form, or retrieves custom dropdown fields that can be used for filtering.
Use this tool in two modes:
- Form fields mode (getTicketFilterFields = false): Returns all fields for a specific ticket form. Required before create_ticket or update_ticket when setting anything beyond subject, description, or priority.
- Filter fields mode (getTicketFilterFields = true): Returns custom dropdown fields (single-select or multi-select) that can be used as filters in list_tickets.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| brandId | integer | No | — | Brand ID. Required when getTicketFilterFields is false |
| formId | integer | No | — | Ticket form ID from get_user_info. Required when getTicketFilterFields is false |
| getTicketFilterFields | boolean | No | false | When true, returns custom dropdown fields for filtering in list_tickets instead of form fields. Allows brandId and formId to be omitted |
Output
| Field | Type | Description |
|---|---|---|
| formId | integer | Echo of the requested form |
| fieldInfo[] | array | One entry per field on the form |
| fieldInfo[].fieldId | integer | Internal field ID |
| fieldInfo[].apiName | string | The key to use in fields |
| fieldInfo[].label | string | Display label shown to agents |
| fieldInfo[].fieldType | string | UI control, e.g. Textbox (single-line), RichText, Dropdown (single-select), Yes/No, Tag |
| fieldInfo[].fieldDataType | string | string, long, boolean, list_of_string |
| fieldInfo[].options | object? | Present on dropdowns only |
| fieldInfo[].options.key | string | Matches apiName |
| fieldInfo[].options.value[] | array | { id, name, isDefault? } |
Example response
{
"formId": 1,
"fieldInfo": [
{
"fieldId": 23,
"apiName": "subject",
"label": "Subject",
"fieldType": "Textbox (single-line)",
"fieldDataType": "string"
},
{
"fieldId": 26,
"apiName": "typeId",
"label": "Type",
"fieldType": "Dropdown (single-select)",
"fieldDataType": "long",
"options": {
"key": "typeId",
"value": [
{ "id": 1, "name": "Query", "isDefault": true },
{ "id": 2, "name": "Bug Report"}
]
}
},
{
"fieldId": 1056,
"apiName": "cf_billing_type",
"label": "Billing Type",
"fieldType": "Dropdown (single-select)",
"fieldDataType": "long",
"options": {
"key": "cf_billing_type",
"value": [
{ "id": 1700, "name": "Invoice Inquiries" }
]
}
}
]
}
get_field_options
Retrieves predefined field option values for Ticket and Activity modules. Use this tool to fetch valid option values before creating, updating, or filtering records.
Supported Option Types
| Value | Option Type | Usage |
|---|---|---|
| 1 | TicketCategory | Ticket filtering |
| 2 | TicketType | Ticket filtering |
| 3 | TicketSource | Ticket filtering |
| 4 | Timezone | Activity create/update |
| 5 | ActivityType | Activity create/update |
| 6 | TicketCustomField | Ticket filtering |
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| optionTypeId | integer | Yes | — | Field option type ID (see Supported Option Types table above) |
| apiName | string | No | — | Required when optionTypeId is 6 (TicketCustomField). The API name of the custom field (e.g., "cf_billing_type") |
Output
| Field | Type | Description |
|---|---|---|
| [] | array | List of field options |
| [].id | long | Unique identifier of the field option |
| [].name | string | Display name or label of the field option (e.g., "Bug Report", "Email", "EST") |
| [].description | string? | Optional description. Only populated for timezone options (e.g., "Eastern Standard Time") |
| [].shortCode | string? | Optional short code. Only populated for timezone options (e.g., "EST", "PST", "UTC") |
Example request
Get ticket types:
{
"optionTypeId": 2
}
Get custom field options:
{
"optionTypeId": 6,
"apiName": "cf_billing_type"
}
Example response
Ticket types:
[
{
"id": 1,
"name": "Query",
"description": null,
"shortCode": null
},
{
"id": 2,
"name": "Bug Report",
"description": null,
"shortCode": null
},
{
"id": 3,
"name": "Feature Request",
"description": null,
"shortCode": null
}
]
Timezones:
[
{
"id": 1,
"name": "EST",
"description": "Eastern Standard Time",
"shortCode": "EST"
},
{
"id": 2,
"name": "PST",
"description": "Pacific Standard Time",
"shortCode": "PST"
},
{
"id": 3,
"name": "UTC",
"description": "Coordinated Universal Time",
"shortCode": "UTC"
}
]
Tickets
list_tickets
Paginated ticket list. All filters are combined using AND logic.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| statusIds | integer[] | No | — | Resolve via get_ticket_statuses |
| priorityIds | integer[] | No | — | 1 Low, 2 Normal/Medium, 3 High, 4 Critical |
| brandId | integer[] | No | — | brand ids |
| assigneeId | integer | No | — | Agent-only; ignored for contacts |
| requesterId | integer | No | — | Agent-only; contact or agent user ID |
| agentGroupIds | integer[] | No | — | Resolve via search_groups |
| contactGroupIds | integer[] | No | — | Resolve via search_contact_groups |
| tags | string[] | No | — | Agent-only; tag names, case-insensitive |
| categoryIds | integer[] | No | — | Agent-only; Resolve IDs using get_field_options with optionTypeId=1. |
| typeIds | integer[] | No | — | Agent-only; Resolve IDs using get_field_options with optionTypeId=2. |
| sourceIds | integer[] | No | — | Agent-only; Resolve IDs using get_field_options with optionTypeId=3 |
| createdDate | object | No | — | { from, to }, UTC yyyy-MM-ddTHH:mm:ss. Both keys required |
| lastModifiedOnRange | object | No | — | { from, to }, UTC yyyy-MM-ddTHH:mm:ss. Both keys required |
| customFields | object | No | — | Agent-only; Filter by custom dropdown field values using { apiName: [fieldOptionIds] }. Resolve field API names via get_ticket_schema (getTicketFilterFields=true) and field option IDs via get_field_options (optionTypeId=6). |
| isOverdue | boolean | No | — | Response or resolution due is past |
| isDueToday | boolean | No | — | Due today in the caller’s timezone |
| isDueTomorrow | boolean | No | — | Due tomorrow in the caller’s timezone |
| includeOrganizationTickets | boolean | No | — | Contact-only; ignored for agents |
| sortField | string | No | createdDate | createdDate, priority, status, subject, responseDue, resolutionDue, modifiedDate, repliedDate |
| sortOrder | string | No | desc | asc or desc |
| limit | integer | No | 25 | 1–100 |
| page | integer | No | 1 | 1-based |
Set at most one of isOverdue, isDueToday, or isDueTomorrow.
Output
| Field | Type | Description |
|---|---|---|
| items[].id | integer | Ticket ID |
| items[].title | string | Subject line |
| items[].statusName | string | Current status label |
| items[].priorityName | string | Priority label |
| items[].createdAt | string | ISO 8601 |
| items[].description | string | Full body — not truncated |
| items[].assigneeName | string | Assigned agent |
| items[].requesterName | string | Requester |
| items[].url | string | Deep link to the ticket |
| totalEstimate | integer | Approximate match count |
| isLast | boolean | Whether this is the final page |
The description field returns the full ticket description. Requests with a limit of 100 can produce very large responses when tickets contain lengthy descriptions. Keep limit low when the caller only needs ticket titles.
Example
// request
{ "assigneeId": 1003, "statusIds": [1, 2], "isDueToday": true, "limit": 25 }
// response
{
"items": [
{
"id": 814800,
"title": "Product not delivered",
"statusName": "Open",
"createdAt": "2026-02-19T10:41:51.100921+00:00",
"description": "Could you please refrain from archiving...",
"priorityName": "Critical",
"assigneeName": "John Agent",
"requesterName": "Alex Requester",
"url": "https://support.example.com/support/tickets/814800"
}
],
"totalEstimate": 1,
"isLast": true
}
get_ticket
Full detail of one ticket.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticketId | integer | Yes | — | Numeric ticket ID |
Output
| Field | Type | Description |
|---|---|---|
| id | integer | Ticket ID |
| title | string | Subject |
| createdAt / updatedAt / lastRepliedAt | string | ISO 8601 |
| lastStatusChangedAt | string | ISO 8601 |
| responseDue | string | SLA response deadline, set automatically on creation |
| dueDate | string | SLA resolution deadline, set automatically on creation |
| brand | object | { id, name } |
| status | string | Status name, not ID |
| priority | string | Priority name |
| category | string | Category name |
| type | string | Ticket type name |
| group | string | Assignment group name |
| requester | string | Requester name |
| assignee | string | Assignee name |
| createdBy | string | Creator name |
| source | string | agentPortal, email, or mcp for records created through this server |
| state | string | e.g. active |
| tags | string[] | Tag names |
| customFields | object | Flat { cf_apiName: value } map, nulls included |
| isVisibleInCustomerPortal | boolean | Portal visibility |
| isSpam | boolean | Spam flag |
| watchers[] | array | { id, name, userType } |
| updatesCount | integer | Public replies |
| notesCount | integer | Note count |
| totalWorkLogged | integer | Logged work |
| ticketForm | object | { id, name } — needed for get_ticket_fields |
| webUrl | string | Deep link |
Example response
{
"id": 12267,
"title": "Product not delivered",
"createdAt": "2021-10-14T07:23:29.86908+00:00",
"updatedAt": "2026-03-10T12:47:04.901012+00:00",
"brand": { "id": 1, "name": "Bold Desk" },
"status": "On Hold",
"priority": "Medium",
"category": "Ticketing System",
"type": "Query",
"group": "Support",
"requester": "Alex Requester",
"assignee": "John Agent",
"source": "agentPortal",
"state": "active",
"tags": ["internal-request"],
"customFields": { "cf_device_type": null, "cf_order_id": null },
"isVisibleInCustomerPortal": true,
"isSpam": false,
"watchers": [{ "id": 1000, "name": "Tim Watcher", "userType": "agent" }],
"updatesCount": 4,
"notesCount": 1,
"totalWorkLogged": 0,
"ticketForm": { "id": 1, "name": "Default Form" },
"webUrl": "https://support.example.com/support/tickets/12267"
}
list_ticket_history
List the change history for the current ticket, including status changes, field updates, assignee changes, and system events, with pagination support.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticketId | integer | Yes | — | Numeric ticket ID; must be positive |
| limit | integer | No | 25 | Number of items per page (1-100) |
| cursor | string | No | — | Opaque pagination cursor from a previous response for retrieving next page |
Output
Example response
{
"items": [
{
"historyId": 5001,
"changeLogs": [
{
"fieldName": "status",
"description": "Status transitioned",
"oldValue": "Open",
"newValue": "In Progress"
},
{
"fieldName": "priority",
"description": "Priority updated",
"oldValue": "Low",
"newValue": "High"
}
],
"updatedOn": "2026-08-22T10:45:30.123456Z",
"updatedBy": "John Agent",
"url": "https://support.example.com/support/tickets/12267#history-5001"
},
{
"historyId": 5002,
"changeLogs": [
{
"fieldName": "assignee",
"description": "Ticket reassigned",
"oldValue": "Unassigned",
"newValue": "Jane Agent"
}
],
"updatedOn": "2026-08-22T11:00:15.654321Z",
"updatedBy": "Manager User"
},
{
"historyId": 5003,
"changeLogs": [
{
"fieldName": "category",
"description": "Category changed",
"oldValue": "General",
"newValue": "Technical Support"
}
],
"updatedOn": "2026-08-22T09:30:45.789012Z",
"updatedBy": "System"
}
],
"cursor": "v1.eyJ2IjoxLCJ0IjoibGlzdF90aWNrZXRfaGlzdG9yeSIsInBuIjoyfQ.<sig>",
"url": "https://support.example.com/support/tickets/12267#history",
"totalEstimate": 42,
"isLast": false
}
list_ticket_links
Returns links associated with the current ticket, including web links, parent, child, and related ticket links. Supports pagination and filtering by link type.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Numeric ticket ID |
| linkType | integer | Yes | — | Type of link: 1 = web links, 2 = related ticket links, 3 = parent ticket link, 4 = child ticket link |
| page | integer | No | 1 | 1-based |
| perPage | integer | No | 25 | Items per page (default 25, max 100) |
Output
Example response
{
"items": [
{
"linkId": 101,
"linkType": 2,
"ticketId": 21,
"linkedTicketId": 22,
"title": "Similar issue reported",
"status": "Open",
"priority": "High"
},
{
"linkId": 102,
"linkType": 3,
"ticketId": 21,
"linkedTicketId": 20,
"title": "Parent issue - system outage",
"status": "Resolved",
"priority": "Critical"
}
],
"cursor": "v1.eyJ2IjoxLCJ0IjoiZ2V0X3RpY2tldF9saW5rcyIsInBuIjoyfQ.<sig>",
"totalEstimate": 2,
"isLast": true
}
create_ticket_web_link
Adds an external web link to a ticket. Web links are URLs pointing to external resources (documentation, knowledge base articles, third-party tools, etc.) that are attached to a ticket for reference.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Numeric ticket ID |
| name | string | Yes | — | Display name |
| url | string | Yes | — | Web URL |
Output
Example response
{
"linkId": 201,
"ticketId": 21,
"name": "Knowledge Base: Password Reset",
"url": "https://kb.example.com/articles/password-reset",
"createdAt": "2026-08-22T11:15:30.456789+00:00",
"message": "Web link added successfully"
}
create_ticket_link
Create a link between the current ticket and another ticket, such as a related ticket, parent ticket, or child ticket. The tool establishes the specified ticket relationship between the current ticket and the target ticket.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Numeric ticket ID |
| linkTypeId | integer | Yes | — | Link type: 2 (RelatedTicket), 3 (ParentTicket), 4 (ChildLink) |
| destinationId | integer | Yes | — | Numeric id of destination ticket |
Output
Example response
{
"linkId": 103,
"sourceTicketId": 21,
"destinationTicketId": 22,
"linkTypeId": 2,
"createdAt": "2026-08-22T10:30:45.123456+00:00",
"message": "Ticket link created successfully"
}
create_ticket
Creates a ticket. Runs in lenient mode by default.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| brandId | integer | Yes | — | Brand the ticket is filed under |
| subject | string | Yes | — | ≤ 255 characters |
| description | string | Yes | — | Body content |
| contentTypeId | integer | No | — | 1 HTML, 2 plain text, 3 Markdown |
| formId | integer | No | brand default | Ticket form |
| priorityId | integer | No | — | 1–4 |
| requesterId | integer | Conditional | — | Existing contact or agent ID. Required unless requesterEmail and requesterName are supplied |
| requesterEmail | string | No | — | Use with requesterName when the contact has no ID |
| requesterName | string | No | — | Paired with requesterEmail |
| assigneeId | integer | No | — | Resolve via search_agents |
| parentTicketId | integer | No | — | Links the new ticket as a child |
| strictValidation | boolean | No | false | Enforce required-field validation |
| additionalFields | object | No | — | { apiName: value } for everything else |
additionalFields accepts the following: categoryId, typeId, groupId, ticketFormId, dueDate, tag, cc, ccEmails, phoneNumber, contactGroupId, linkTypeId, linkedTicketId, attachments, and any cf_* custom field. Discover exact names via get_ticket_fields.
Identify the requester explicitly. Supply exactly one of requesterId, or requesterEmail and requesterName together. A call that supplies neither, or both, is rejected.
Output
Example response
{
"ticketId": 21,
"status": "New",
"webUrl": "https://your-tenant.bolddesk.com/support/tickets/21",
"brand": "Customer Support",
"priority": "Normal",
"requester": "Alex",
"title": "Product not delivered"
}
update_ticket
Patches one or more fields on an existing ticket.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticketId | integer | Yes | — | Ticket to update |
| fields | object | Yes in practice | — | { apiName: value }. null clears a field |
| strictValidation | boolean | No | false | Enforce required-field validation |
Recognized field keys
| Key | Type | Notes |
|---|---|---|
| subject | string | |
| priorityId | long | 1–4 |
| categoryId | long | From get_ticket_fields options |
| typeId | long | From get_ticket_fields options |
| agentId | long | Assignee; resolve via search_agents |
| groupId | long | Resolve via search_groups |
| requesterId | long | Resolve via search_contacts |
| resolutionDue | string | UTC |
| isVisibleInCustomerPortal | boolean | |
| tagsAdd | string[] | Appends without reading the current set |
| tagsRemove | string[] | Removes named tags without reading the current set |
| cf_* | varies | Custom fields, typed per fieldDataType |
tagsAdd and tagsRemove apply changes differentially; every other key performs a full overwrite. Prefer them over read-modify-write operations on tags to avoid overwriting concurrent edits.
Output: confirmation of the patched ticket.
Example response
{
"id": 21,
"title": "Product not delivered",
"createdAt": "2026-08-21T18:20:12.488601+00:00",
"updatedAt": "2026-08-22T02:13:50.020122+00:00",
"lastRepliedAt": "2026-08-21T18:35:17.788464+00:00",
"lastStatusChangedAt": "2026-08-21T18:26:10.985592+00:00",
"responseDue": "2026-08-22T00:20:12.488601+00:00",
"dueDate": "2026-08-24T18:20:12.488601+00:00",
"brand": { "id": 1, "name": "Customer Support" },
"status": "Open",
"priority": "Normal",
"type": "Query",
"requester": "Alex",
"createdBy": "Alex",
"source": "mcp",
"state": "active",
"tags": [],
"customFields": {},
"isVisibleInCustomerPortal": true,
"isSpam": false,
"updatesCount": 3,
"notesCount": 0,
"totalWorkLogged": 0,
"ticketForm": { "id": 1, "name": "Default Form" },
"webUrl": "https://your-tenant.bolddesk.com/support/tickets/21"
}
Returns the full get_ticket payload, keyed id. Patched fields come back with their new values, so the response is the cheapest way to confirm a tagsAdd merge landed as intended.
update_ticket_status
Moves a ticket to one of its currently legal next statuses.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticketId | integer | Yes | — | Ticket to transition |
| toStatusId | integer | Yes | — | Target status from get_ticket_statuses |
| additionalFields | object | No | — | { apiName: value } for fields the transition requires |
| strictValidation | boolean | No | false | Enforce required-field validation |
Some transitions require fields to be populated, for example, a resolution code when closing a ticket. Supply those through additionalFields.
When strictValidation is false, a transition may still succeed even if those fields are missing, leaving the ticket incomplete.
Example response
{
"webUrl": "https://your-tenant.bolddesk.com/support/tickets/21",
"status": "Open"
}
Returns the new status and a link. When processing a batch of transitions, correlate responses using the ticketId you submitted, or extract it from webUrl.
Ticket conversation
get_ticket_messages
Returns a ticket’s conversation log, including public replies and public notes.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticketId | integer | Yes | — | Numeric ticket ID |
| messageType | string | No | all | publicReply, publicNote |
| onlyCustomerMessages | boolean | No | false | Returns only messages authored by the requester |
| limit | integer | No | 25 | 1–100 |
| cursor | string | No | — | Opaque token from a prior response. Omit for first page |
Output
| Field | Type | Description |
|---|---|---|
| items.ticketId | integer | Echo of the requested ticket |
| items.totalMessages | integer | Number of messages in this page |
| items.conversation[] | array | Messages, newest first |
| items.conversation[].from | string | agent or customer |
| items.conversation[].author | string | Display name, or System Automation |
| items.conversation[].message | string | Body. May contain HTML and Markdown tables |
| items.conversation[].createdAt | string | ISO 8601 |
| items.conversation[].type | string | publicReply, publicNote |
| items.webUrl | string | Deep link |
| cursor | string | Signed token for the next page |
| isLast | boolean | Whether this is the final page |
items is a single object containing conversation[], rather than an array as used by the other list tools.
Example response
{
"items": {
"ticketId": 12267,
"totalMessages": 2,
"conversation": [
{
"from": "customer",
"author": "John ~~~~Requester",
"message": "What is current refund status?",
"createdAt": "2021-10-28T00:52:42.504274+00:00",
"type": "publicReply"
}
],
"webUrl": "https://support.example.com/support/tickets/12267"
},
"cursor": "v1.eyJ2IjoxLCJ0IjoiZ2V0X3RpY2tldF9tZXNzYWdlcyIsInBuIjoyfQ.<sig>",
"isLast": false
}
add_ticket_message
Appends a message to an existing ticket.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticketId | integer | Yes | — | Ticket to which the message is appended |
| messageToAdd | string | Yes | — | Message body, in plain text or HTML |
| messageType | string | Yes | publicReply | publicReply, publicNote, internalNote |
| contentTypeId | integer | No | — | 1 HTML, 2 plain text, 3 Markdown |
| additionalFields | object | No | — | { apiName: value } |
messageType is required. Always send it explicitly.
publicReply is customer-visible and typically triggers a notification email. For agent-facing automation output, use internalNote. Any agent-authored write path should be routed through human approval before sending a publicReply.
Set contentTypeId to match the format of messageToAdd.
Example response
{
"ticketId": 21,
"totalMessages": 1,
"conversation": [
{
"from": "customer",
"author": "john",
"message": "What is current refund status?",
"createdAt": "2026-08-21T18:35:17.788464+00:00",
"type": "publicReply"
}
],
"webUrl": "https://your-tenant.bolddesk.com/support/tickets/21"
}
Activities
list_activities
Paginated list of activities.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| statusIds | integer[] | No | — | Activity status IDs |
| priorityIds | integer[] | No | — | 1 Low, 2 Normal, 3 High, 4 Critical |
| assigneeId | integer | No | — | Assigned agent’s user ID |
| createdBy | integer | No | — | Creator’s user ID |
| createdDate | object | No | — | { from, to } UTC |
| ticketIds | integer[] | No | — | Filter activities linked to specific ticket IDs |
| sortField | string | No | createdDate | createdDate, priority, modifiedDate |
| sortOrder | string | No | desc | asc or desc |
| limit | integer | No | 25 | 1–100 |
| page | integer | No | 1 | 1-based |
Output
| Field | Type | Description |
|---|---|---|
| items[].id | integer | Activity ID |
| items[].title | string | Subject |
| items[].status | string | Status name |
| items[].type | string | Activity type name, e.g., Task, AI - KB Refresh |
| items[].priority | string | Priority name |
| items[].createdAt | string | ISO 8601 |
| items[].assignee | string | Assigned agent name |
| items[].createdBy | string | Creator name |
| items[].ticketId | integer? | Present only when linked to a ticket |
| items[].ticketTitle | string? | Present only when linked to a ticket |
| items[].url | string | Deep link |
| cursor | string | Next page number as a string |
| totalEstimate | integer | Approximate count |
| isLast | boolean | Final page flag |
Example response
{
"items": [
{
"id": 63723,
"title": "Review laptop memory usage",
"status": "Open",
"createdAt": "2026-08-21T12:50:26.012586+00:00",
"type": "Task",
"priority": "Medium",
"assignee": "Jane Agent",
"createdBy": "Alex Creator",
"ticketId": 867333,
"ticketTitle": "Application hangs when updating value",
"url": "https://support.example.com/agent/activities/63723"
}
],
"cursor": "2",
"totalEstimate": 62656,
"isLast": false
}
get_activity
Full detail of a single activity, including subject, description, status, priority, timestamps, source, and type.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Numeric activity ID |
Output: Activity detail object. Expected fields per the tool description: id, subject / title, description, status, priority, type, source, createdAt, updatedAt, plus link fields when the activity is attached to a ticket or user.
Example response
{
"id": 4476,
"subject": "Enable 2FA",
"description": "Enable 2FA on Entra ID",
"status": "Open",
"type": "Tasks",
"priority": "Normal",
"tag": [],
"createdBy": "Michael",
"createdAt": "2026-08-22T02:23:40.403183+00:00",
"modifiedAt": "2026-08-22T02:23:40.403183+00:00",
"webUrl": "https://your-tenant.bolddesk.com/agent/activities/4476"
}
create_activity
Creates a new activity of any supported type (Task, Call, Meeting). Use get_field_options with optionTypeId=5 to retrieve available activity types for your organization.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| command.activityType | integer | Yes | — | Activity type ID. Retrieve available types using get_field_options with optionTypeId=5. Common types: 1=Task, 2=Call, 3=Meeting |
| command.subject | string | Yes | — | Activity subject |
| command.description | string | No | — | Body |
| command.status | integer | No | — | 1 Open, 2 In Progress, 3 On Hold, 4 Closed, 5 Cancelled, 6 Waiting for Requester |
| command.priority | integer | No | — | 1 Low, 2 Normal, 3 High, 4 Critical |
| command.dueDate | string | No | — | ISO 8601 date-time |
| command.assignedAgent | integer | No | — | Agent ID; resolve via search_agents |
| command.linkedTicket | integer | No | — | Ticket to link |
| command.linkedUser | integer | No | — | Agent or contact to link |
| command.tag | string | No | — | Single tag, not an array |
| command.startDate | string | Conditional | — | ISO 8601 date-time. Required for Call and Meeting types; ignored for other activity types |
| command.endDate | string | No | — | ISO 8601 date-time. Optional for Call and Meeting types; ignored for other activity types |
| command.timezone | integer | No | — | Timezone ID for activity start and end times. Retrieve available timezones using get_field_options with optionTypeId=4. Optional for Call and Meeting types; ignored for other activity types |
| command.collaborators | integer[] | No | — | List of agent or contact user IDs to add as collaborators. Optional for Call and Meeting types; ignored for other activity types |
Request shape - Task activity
{
"command": {
"activityType": 1,
"subject": "Follow up on migration checklist",
"priority": 3,
"status": 1,
"dueDate": "2026-08-25T09:00:00",
"assignedAgent": 1003,
"linkedTicket": 814800
}
}
Request shape - Call activity
{
"command": {
"activityType": 2,
"subject": "Customer follow-up call",
"description": "Discuss implementation timeline",
"priority": 2,
"status": 1,
"startDate": "2026-08-25T10:00:00",
"endDate": "2026-08-25T10:30:00",
"timezone": 1,
"assignedAgent": 1003,
"linkedTicket": 814800,
"collaborators": [1004, 1005]
}
}
Request shape - Meeting activity
{
"command": {
"activityType": 3,
"subject": "Team standup meeting",
"description": "Daily sync with support team",
"priority": 2,
"status": 1,
"startDate": "2026-08-25T14:00:00",
"endDate": "2026-08-25T14:30:00",
"timezone": 4,
"assignedAgent": 1003,
"collaborators": [1002, 1004, 1005]
}
}
Output: the created activity’s ID and details.
Example response
{
"id": 2,
"message": "Activity successfully created.",
"webUrl": "https://your-tenant.bolddesk.com/agent/activities/2"
}
create_activity_comments
Appends a comment to an existing activity.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Numeric ID of the activity to which the comment is appended |
| commentBody | string | Yes | — | Comment text in plain text, HTML, or Markdown format |
| contentTypeId | integer | No | 1 | Content type: 1-HTML (default), 2-Plain Text, 3-Markdown |
| additionalFields | object | No | — | Optional { apiName: value } map for extended inputs |
Request shape
{
"id": 2,
"commentBody": "Please review the migration progress and provide feedback.",
"contentTypeId": 1,
"additionalFields": {
"atMentionedUserIds": [1003, 1004]
}
}
Output: confirmation of the posted comment.
Example response
{
"id": 2,
"commentId": 42,
"message": "Comment posted successfully.",
"webUrl": "https://your-tenant.bolddesk.com/agent/activities/2"
}
The response includes the activity ID, the comment ID, and a confirmation message with a link to the activity.
update_activity
Patches one or more fields on an existing activity.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Activity to update |
| fields | object | Yes in practice | — | { apiName: value }. null clears a field |
| strictValidation | boolean | No | false | Enforce required-field validation |
Recognized field keys
| Key | Type | Notes |
|---|---|---|
| subject | string | |
| description | string | |
| status | integer | 1 Open, 2 In Progress, 3 On Hold, 4 Closed, 5 Cancelled, 6 Waiting for Requester |
| priority | integer | 1 Low, 2 Normal, 3 High, 4 Critical |
| dueDate | string | UTC |
| assignedAgent | integer | Agent ID; resolve via search_agents |
| linkedTicket | integer | Ticket to link |
| linkedUser | integer | Agent or contact to link |
| tag | string | Single tag; overwrites existing tag |
Output: confirmation of the patched activity.
Example response
{
"id": 2,
"subject": "Follow up on migration checklist",
"description": "Updated task description",
"status": 2,
"priority": 3,
"dueDate": "2026-08-25T09:00:00+00:00",
"assignedAgent": 1003,
"linkedTicket": 814800,
"linkedUser": null,
"tags": [],
"webUrl": "https://your-tenant.bolddesk.com/agent/activities/2"
}
Returns the full activity payload, keyed id. Patched fields come back with their new values, so the response is the cheapest way to confirm a tagsAdd merge landed as intended.
Approvals
list_approval_requests
Paginated approval request list.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| statusIds | integer[] | No | — | 1 Pending, 2 Approved, 3 Rejected |
| approvalTypeIds | integer[] | No | — | Approval type IDs |
| approverIds | integer[] | No | — | Agent IDs assigned to approve |
| requesterIds | integer[] | No | — | Users who raised the approval |
| ticketId | integer | No | — | All approvals on one ticket |
| ticketStatusIds | integer[] | No | — | Filter by the related ticket’s status |
| categoryIds | integer[] | No | — | Related ticket’s category |
| brandIds | integer[] | No | — | Related ticket’s brand |
| createdOnRange | object | No | — | { from, to } UTC |
| lastModifiedOnRange | object | No | — | { from, to } UTC |
| sortField | string | No | lastModifiedOn | lastModifiedOn, requestedOn, approvalId |
| sortOrder | string | No | asc | asc or desc |
| limit | integer | No | 25 | 1–100 |
| page | integer | No | 1 | 1-based |
sortOrder defaults to asc here, unlike the other list tools. Set it explicitly for newest-first.
Output
| Field | Type | Description |
|---|---|---|
| items[].approvalRequestId | integer | Approval ID |
| items[].title | string | Approval subject |
| items[].description | string | Body; often the proposed customer reply |
| items[].type | string | Policy name: Everyone, Anyone, Majority |
| items[].status | string | Requested, Approved, Rejected, Cancelled |
| items[].requestedAt | string | ISO 8601 |
| items[].lastModifiedAt | string | ISO 8601 |
| items[].requestedBy | string | Requester name |
| items[].ticketId | integer | Associated ticket |
| items[].ticketTitle | string | Associated ticket subject |
| items[].ticketStatus | string | Associated ticket status name |
| items[].requestedUserCount | integer | Approvers asked |
| items[].approvedUserCount | integer | Approvers who have approved |
| items[].webUrl | string | Browser URL to open approval in agent portal (optional) |
| totalEstimate | integer | Approximate count |
| isLast | boolean | Final page flag |
The filter enum uses Pending, Approved, or Rejected; responses return Requested for the pending state. Map 1 ↔ “Requested” client-side.
Example response
{
"items": [
{
"approvalRequestId": 28801,
"title": "Laptop purchase approval",
"description": "Requesting approval to purchase a new laptop.",
"type": "Everyone",
"status": "Requested",
"requestedAt": "2026-08-21T12:54:20.023386+00:00",
"lastModifiedAt": "2026-08-21T12:54:20.023386+00:00",
"requestedBy": "Sam Agent",
"ticketId": 865064,
"ticketTitle": "Laptop Request",
"ticketStatus": "Open",
"requestedUserCount": 1,
"approvedUserCount": 0,
"webUrl": "https://support.example.com/support/approvals/28801"
}
],
"totalEstimate": 34,
"isLast": false
}
get_approval_request
Full detail of a single approval request, including per-approver responses.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Numeric approval ID |
Output
Includes all fields returned by the list response, plus:
| Field | Type | Description |
|---|---|---|
| ticketCategory | string | Related ticket’s category name |
| brand | object | { id, name } |
| approvers[] | array | Per-approver detail |
| approvers[].name | string | Approver name |
| approvers[].approvalStatus | string | Requested, Approved, Rejected |
| approvers[].approvedAt | string? | ISO 8601; null until a response is provided |
| approvers[].comment | string? | Approver’s comment |
| webUrl | string | Deep link with ?approval=true&approvalid=<id> |
Example response
{
"id": 2,
"title": "Laptop purchase approval",
"description": "Requesting approval to purchase a new laptop.",
"type": "Everyone",
"status": "Approved",
"requestedAt": "2026-08-21T18:28:36.625069+00:00",
"lastModifiedAt": "2026-08-21T18:29:43.833499+00:00",
"requestedBy": "Alex",
"ticketId": 21,
"ticketTitle": "Laptop Request",
"ticketStatus": "Open",
"brand": { "id": 1, "name": "Internal Support" },
"requestedUserCount": 1,
"approvedUserCount": 1,
"approvers": [
{
"name": "John",
"approvalStatus": "Approved",
"approvedAt": "2026-08-21T18:29:43.833499+00:00",
"comment": "Approved. Proceed with the laptop purchase."
}
],
"webUrl": "https://your-tenant.bolddesk.com/agent/tickets/21?approval=true&approvalid=2"
}
create_approval_request
Raises an approval request against an existing ticket.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticketId | integer | Yes | — | Ticket the approval is filed against |
| subject | string | Yes | — | Plain text |
| approvalRequestTypeId | integer | Yes | — | 1 everyone, 2 anyone, 3 majority |
| approvers | integer[] | Yes | — | Agent IDs; resolve via search_agents |
| description | string | No | — | Plain-text body |
| createdOnBehalfOfRequester | boolean | No | false | File on behalf of the ticket requester |
| requesterId | integer | No | — | Required when createdOnBehalfOfRequester is true |
Output:
Example response
{
"id": 2,
"ticketId": 21,
"subject": "Laptop purchase approval",
"createdAt": "2026-08-21T18:28:37.2376656+00:00",
"webUrl": "https://your-tenant.bolddesk.com/agent/tickets/21?view=approvals"
}
submit_approval_response
Records an approver’s decision.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Positive integer |
| approveTypeId | integer | Yes | — | 2 approve, 3 reject, 4 cancel |
| comment | string | No | — | Explanation of the decision |
approveTypeId begins at 2; 1 is not a valid value.
Output: the updated approval request.
Example response
{ "id": 2, "approveTypeId": 2, "message": "Approver approved request." }
Worklogs
list_worklogs
Retrieves a paginated list of worklog entries for tickets or activities with optional filtering and sorting.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| ticketId | integer | No | — | Filter worklogs by specific ticket ID |
| activityId | integer | No | — | Filter worklogs by specific activity ID |
| moduleId | integer | No | — | Module type: 1 for Ticket, 5 for Activity. If omitted, returns worklogs from both modules |
| billable | boolean | No | — | Filter by billable status: true for billable, false for non-billable |
| limit | integer | No | 25 | Records per page; 1–100 |
| page | integer | No | 1 | Page number, 1-based |
Module type reference
- 1 – Ticket: Worklogs associated with ticket activities
- 5 – Activity: Worklogs associated with task activities
Request shape (filter by ticket)
{
"ticketId": 814850,
"limit": 50,
"page": 1
}
Request shape (filter by activity)
{
"activityId": 2,
"moduleId": 5,
"limit": 25,
"page": 1
}
Request shape (filter by billable status)
{
"billable": true,
"limit": 100,
"page": 1
}
Output: paginated list of worklog items with pagination metadata.
Example response
{
"items": [
{
"ticketId": 814850,
"activityId": null,
"minutesSpent": 30,
"billable": true,
"workDateTime": "2026-09-03T10:30:00",
"workDescription": "Investigated issue and identified root cause. Client contacted with resolution options.",
"createdBy": "Jane Agent",
"createdOn": "2026-09-03T10:35:00",
"updatedBy": "Jane Agent",
"lastModifiedOn": "2026-09-03T10:35:00",
"webUrl": "https://your-tenant.bolddesk.com/agent/tickets/814850"
},
{
"ticketId": 814850,
"activityId": null,
"minutesSpent": 45,
"billable": true,
"workDateTime": "2026-09-02T14:00:00",
"workDescription": "Follow-up call with customer and implementation plan",
"createdBy": "Jane Agent",
"createdOn": "2026-09-02T14:10:00",
"updatedBy": null,
"lastModifiedOn": "2026-09-02T14:10:00",
"webUrl": "https://your-tenant.bolddesk.com/agent/tickets/814850"
}
],
"cursor": "2",
"totalEstimate": 12,
"isLast": false
}
Output
| Field | Type | Description |
|---|---|---|
| items[] | array | Array of worklog entries |
| items[].ticketId | integer? | Associated ticket ID (null for activity worklogs) |
| items[].activityId | integer? | Associated activity ID (null for ticket worklogs) |
| items[].minutesSpent | integer | Time logged in minutes |
| items[].billable | boolean | Billable status indicator |
| items[].workDateTime | string | UTC timestamp when work was performed (ISO 8601) |
| items[].workDescription | string? | Work summary or notes (may contain HTML) |
| items[].createdBy | string? | Name of the user who created the worklog |
| items[].createdOn | string | UTC timestamp when worklog was created (ISO 8601) |
| items[].updatedBy | string? | Name of the last modifier (null if never updated) |
| items[].lastModifiedOn | string | UTC timestamp of last modification (ISO 8601) |
| items[].webUrl | string | Direct link to the associated ticket or activity |
| cursor | string | Pagination cursor for next page (if applicable) |
| totalEstimate | integer | Estimated total number of matching records |
| isLast | boolean | Boolean indicating if this is the final page |
add_worklog
Creates a worklog entry to record time spent on work performed on a ticket or activity.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | Yes | — | Ticket ID or Activity ID |
| moduleId | integer | Yes | — | Module type: 1 for Ticket, 5 for Activity |
| minutesSpent | integer | Yes | — | Time spent in minutes (must be positive) |
| workDateTime | string | Yes | — | Date and time the work was performed in UTC format: yyyy-MM-ddTHH:mm:ss |
| workDescription | string | No | — | Optional description of the work performed (plain text or markdown) |
| billable | boolean | No | false | Set to true if the work is billable; defaults to false |
Module type reference
- 1 – Ticket: Use when logging time for ticket-related work
- 5 – Activity: Use when logging time for activity-related work
Request shape (Ticket example)
{
"id": 814850,
"moduleId": 1,
"minutesSpent": 30,
"workDateTime": "2026-09-03T10:30:00",
"workDescription": "Investigated issue and identified root cause. Client contacted with resolution options.",
"billable": true
}
Request shape (Activity example)
{
"id": 2,
"moduleId": 5,
"minutesSpent": 120,
"workDateTime": "2026-09-02T14:00:00",
"workDescription": "Migration planning and documentation",
"billable": false
}
Output: confirmation of the posted worklog.
Example response
{
"message": "Worklog created successfully.",
"webUrl": "https://your-tenant.bolddesk.com/agent/tickets/814850"
}
Response fields
- message – Confirmation message
- webUrl – Direct link to view the ticket or activity
Directory lookup
search_agents
Finds agents by name or email. Use to resolve assigneeId, requesterId, approvers[], and assignedAgent.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | Yes | — | Lookup string, max 200 chars. Matches by prefix |
| limit | integer | No | 25 | 1–100 |
| page | integer | No | 1 | 1-based |
Output: items[] of { id, name, email }, plus cursor, totalEstimate, isLast.
Example response
{
"items": [
{ "id": 316277, "name": "Jane Agent", "email": "jane.agent@example.com" }
],
"cursor": "2",
"totalEstimate": 17,
"isLast": false
}
search_contacts
Resolves contacts (customers) by free-text query across name and email.
Input: identical to search_agents — query, limit, page. query is required and matches by prefix.
Output: items[] of { id, name, email, phoneNo }, plus cursor, totalEstimate, isLast.
Contact directories run large — a two-character query can match thousands of rows. Always pass the most specific string available and never auto-select the first result.
Example response
{
"items": [
{ "id": 313486, "name": "Sam Requester", "email": "sam@example.com", "phoneNo": "5551234567" },
],
"cursor": "2",
"totalEstimate": 2644,
"isLast": false
}
search_groups
Resolves assignment groups by name fragment, or browses all groups when query is omitted. Use to resolve groupId and agentGroupIds.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | No | — | Name fragment; omit to browse all |
| limit | integer | No | 25 | 1–100 |
| page | integer | No | 1 | 1-based |
Output: items[] containing { id, name }, plus cursor, totalEstimate, isLast.
Example response
{
"items": [
{ "id": 400, "name": "Customer Support Dev" },
{ "id": 363, "name": "General Support" },
{ "id": 533, "name": "Migration Team" }
],
"cursor": "2",
"totalEstimate": 15,
"isLast": false
}
search_contact_groups
Resolves contact groups (companies, accounts, organizations) by partial name match. Use to resolve contactGroupId and contactGroupIds.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| query | string | No | — | Name fragment; omit to browse all |
| limit | integer | No | 25 | 1–100 |
| page | integer | No | 1 | 1-based |
Output: items[] of { id, name }, plus cursor, totalEstimate, isLast.
Example response
{
"items": [
{ "id": 199715, "name": "Acme Corp — BS714121_2_2026" },
{ "id": 86958, "name": "Northwind Labs 1 — 690241" },
{ "id": 86959, "name": "Northwind Labs 1 — 690244" }
],
"cursor": "2",
"totalEstimate": 183133,
"isLast": false
}
Knowledge base
The Knowledge Base (KB) domain exposes the section and category hierarchy plus the articles filed under it. All five tools are agent-only; callers must be authenticated as a BoldDesk agent with access to the relevant brands. Use get_section_tree_view to discover the categories and sections available before creating articles.
get_section_tree_view
Retrieves the knowledge_base section and category hierarchy as a tree. You can optionally filter the results by one or more brand IDs.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| brandIds | string? | No | — | Comma-separated brand IDs used to filter the tree (example: "1,2,3"). Omit when no brand restriction is needed. |
Note: Each ID in brandIds must be a positive integer. Invalid values are rejected.
Output
| Field | Type | Description |
|---|---|---|
| nodes[] | array | Category root nodes. Always present; an empty array means the KB has no visible categories for the caller. |
| nodes[].id | string | Unique ID for this node, in the format "c_<n>" for categories and "s_<n>" for sections. Pass the full ID (for example, c_1, c_2, s_1, or s_2) when calling article or search APIs. Do-not remove the c_ or s_ prefix or pass only the number. |
| nodes[].name | string | Display name. |
| nodes[].level | integer | 0 for category roots; otherwise, the section's depth. |
| nodes[].position | integer | Sort order among sibling nodes. |
| nodes[].isCategory | boolean | True for category root nodes; false for all sections. |
| nodes[].isTranslated | boolean | True when the name is a translation rather than the primary language name. |
| nodes[].hierarchy[] | array | path from current category root to this node. Empty for top-level categories. |
| nodes[].hierarchy[].id | string | Unique ID for this node, in the format c_ |
| nodes[].hierarchy[].name | string? | Display name; null when no name is available. |
| nodes[].hierarchy[].level | integer | The original SQL level of this breadcrumb entry. |
| nodes[].children[] | array | Child sections of this node, each with the same structure. Empty when the node has no children. |
Example request
{
"brandIds": "1"
}
Example response
{
"nodes": [
{
"id": "c_1",
"name": "Customer Support",
"level": 0,
"position": 1,
"isCategory": true,
"isTranslated": false,
"hierarchy": [],
"children": [
{
"id": "s_11",
"name": "Getting Started",
"level": 1,
"position": 1,
"isCategory": false,
"isTranslated": false,
"hierarchy": [
{ "id": "c_1", "name": "Customer Support", "level": 0 }
],
"children": [
{
"id": "s_111",
"name": "Account Setup",
"level": 2,
"position": 1,
"isCategory": false,
"isTranslated": false,
"hierarchy": [
{ "id": "c_1", "name": "Customer Support", "level": 0 },
{ "id": "s_11", "name": "Getting Started", "level": 1 }
],
"children": []
}
]
}
]
}
]
}
list_kb_articles
Retrieves a paginated list of knowledge base articles. You can filter and sort the results or list the articles in a specific view
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| cursor | string? | No | — | Token for fetching the next page. Use the cursor value from the previous response. When supplied, the 'page' parameter is ignored. Cursors are short-lived (≤15 minutes). |
| page | integer? | No | 1 | 1-based page number to fetch. Ignored when 'cursor' is supplied. |
| pageSize | integer? | No | 25 | Number of articles per page: (1-100). |
| sortField | string? | No | — | Sort field. Allowed values: articleId, createdOn, publishedOn, lastModifiedOn, status, viewCount, commentCount, likeCount, dislikeCount. |
| sortOrder | string? | No | desc | Sort direction: asc or desc |
| filter | string? | No | — | Text to filter the article list by. |
| view | string? | No | — | Which set of articles to list. Supported values: AllArticles, Draft, Published, Expired, Approved, and MyArticles. |
Note: Page must be ≥ 0; the upstream KB API accepts page=1 as a valid request. pageSize must be between 1 and 100. sortField must be one of the listed values; sortOrder must be asc or desc.
Output
| Field | Type | Description |
|---|---|---|
| items[] | array | One entry per article on this page. |
| items[].id | integer | Article ID. |
| items[].title | string? | Article title. |
| items[].slugTitle | string? | URL-friendly slug. |
| items[].categoryName | string? | Category display name. |
| items[].sectionName | string? | Section display name. |
| items[].status | object? | Lifecycle status as { id, name }. |
| items[].visibility | object? | Visibility option as { id, name }. The name is the enum member name when the value is defined. |
| items[].languageCode | string? | Article language code, for example, "en-US". |
| items[].createdAt | string? | UTC timestamp when the article was created (ISO 8601). |
| items[].createdBy | string? | Display name of the user who created the article. |
| items[].publishedAt | string? | UTC timestamp when the article was published (ISO 8601). |
| items[].publishedBy | string? | Display name of the user who published the article. |
| items[].updatedAt | string? | UTC timestamp when the article was last modified (ISO 8601). |
| items[].lastModifiedBy | string? | Display name of the user who last modified the article. |
| items[].articleExpiry | string? | UTC timestamp when the article expires (ISO 8601). |
| items[].assignee | string? | Display name of the assigned agent. |
| items[].isPublished | boolean | Whether the article is published. |
| items[].url | string? | Browser URL for opening the KB article. |
| cursor | string? | Opaque cursor; pass it back as the 'cursor' argument to fetch the next page. |
| totalEstimate | integer? | Approximate total number of articles, when available. |
| isLast | boolean | Whether this is the final page. |
Example request
{
"page": 1,
"pageSize": 25,
"sortField": "lastModifiedOn",
"sortOrder": "desc"
}
Example response
{
"items": [
{
"id": 814800,
"title": "How to reset your password",
"slugTitle": "how-to-reset-your-password",
"categoryName": "Customer Support",
"sectionName": "Getting Started",
"status": { "id": 1, "name": "Published" },
"visibility": { "id": 2, "name": "Public" },
"languageCode": "en-US",
"createdAt": "2026-08-21T12:50:26.012586+00:00",
"createdBy": "Ada",
"publishedAt": "2026-08-22T08:00:00+00:00",
"publishedBy": "Grace",
"updatedAt": "2026-09-01T10:15:00+00:00",
"lastModifiedBy": "Grace",
"articleExpiry": "2030-01-01T00:00:00+00:00",
"assignee": "Bob",
"isPublished": true,
"url": "https://your-tenant.bolddesk.com/kb/how-to-reset-your-password"
}
],
"cursor": "v1.eyJ2IjoxLCJ0IjoibGlzdF9rYl9hcnRpY2xlcyIsInBuIjoyfQ.<sig>",
"totalEstimate": 124,
"isLast": false
}
search_kb_articles
Search knowledge_base articles using free_text. Returns a paginated list of articles matching the search text. You can narrow the results by brand, category, or excluded article IDs.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| searchText | string | Yes | — | Free-text query used to search KB articles. (Maximum 255 characters). |
| searchIn | integer? | No | — | Search scope: 1 = Title, 2 = Description, 3 = Both. If omitted, both title and description are searched. |
| brandIds | string? | No | — | Comma-separated list of brand IDs used to filter the results. |
| categoryIds | string? | No | — | Comma-separated list of KB category IDs used to filter the results. |
| exclusionIds | string? | No | — | Comma-separated list of article IDs to exclude from the results. |
| cursor | string? | No | — | Token for fetching the next page. Use the cursor value from the previous response. When supplied, the 'page' parameter is ignored. Cursors are short-lived (≤15 minutes). |
| page | integer? | No | 1 | 1-based page number to fetch. Ignored when 'cursor' is supplied. |
| perPage | integer? | No | 25 | Number of articles per page. Values outside 1-100 are clamped to that range. |
| requiresCount | boolean? | No | false | When true, the response includes a total count (totalEstimate). |
Note: SearchText is required and must not exceed 255 characters. searchIn must be 1, 2, or 3 when supplied. brandIds, categoryIds, and exclusionIds are comma-separated lists of integers; any non-integer token is rejected.
Output
| Field | Type | Description |
|---|---|---|
| items[] | array | One entry per matching article on this page. |
| items[].id | integer | Article ID. |
| items[].title | string? | Article title. |
| items[].status | string? | Status display name (For example, "Published"). |
| items[].slugTitle | string? | URL-friendly slug. |
| items[].createdAt | string? | UTC timestamp when the article was created (ISO 8601). |
| items[].url | string? | Agent portal URL for the article. |
| cursor | string? | Token for the next page. Pass it as 'cursor' in your next request. |
| totalEstimate | integer? | Approximate total number of matching articles. Returned when requiresCount is true. |
| isLast | boolean | Whether this is the final page. |
Example request
{
"searchText": "password reset",
"searchIn": 3,
"brandIds": "1,2",
"page": 1,
"perPage": 25,
"requiresCount": true
}
Example response
{
"items": [
{
"id": 814800,
"title": "How to reset your password",
"status": "Published",
"slugTitle": "how-to-reset-your-password",
"createdAt": "2026-08-21T12:50:26.012586+00:00",
"url": "https://your-tenant.bolddesk.com/agent/kb/814800"
}
],
"cursor": "v1.eyJ2IjoxLCJ0Ijoic2VhcmNoX2tiX2FydGljbGVzIiwicG4iOjJ9.<sig>",
"totalEstimate": 14,
"isLast": false
}
get_kb_article_details
Retrieves the complete details of a knowledge base article by ID or title, including metadata, version information, attachment metadata, and engagement metrics. The description body is sanitized to plain text.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| id | integer | No | — | Numeric ID of the article to retrieve; must be greater than zero. |
| title | string | No | — | Title of the article to retrieve. |
Note: Provide either id or title.
Output
| Field | Type | Description |
|---|---|---|
| id | integer | Article ID. |
| title | string? | Article title. |
| slugTitle | string? | URL-friendly slug. |
| description | string? | Article body as plain text, with HTML removed. |
| markdownDescription | string? | Article body in Markdown when the article uses the Markdown editor; otherwise null. |
| categoryName | string? | Category display name. |
| sectionName | string? | Section display name. |
| status | object? | Lifecycle status as { id, name }. |
| visibility | object? | Visibility option as { id, name }.The name is the enum member name when the value is defined. |
| editorType | object? | Editor type as { id, name }; 1 = Markdown, 2 = WYSIWYG. |
| statusIndicator | object? | Status indicator as { id, name }; 1 = None, 2 = New, 3 = Updated. |
| statusIndicatorExpiry | string? | UTC timestamp when the status indicator expires (ISO 8601). |
| isPublished | boolean? | Whether the article is published. |
| currentVersionNumber | string? | Current version, for example, "v2.2". |
| publishedVersionNumber | string? | Published version, for example, "v2.0". |
| createdAt | string? | UTC timestamp when the article was created (ISO 8601). |
| publishedAt | string? | UTC timestamp when the article was published (ISO 8601). |
| updatedAt | string? | UTC timestamp when the article was last modified (ISO 8601). |
| articleExpiry | string? | UTC timestamp when the article expires (ISO 8601); null when the article never expires. |
| createdBy | string? | Display name of the user who created the article. |
| lastModifiedBy | string? | Display name of the user who last modified the article. |
| assignee | string? | Display name of the assigned agent. |
| tags[] | string[]? | Tag names; null when no tags are set. |
| viewCount | integer? | Total number of views. |
| commentCount | integer? | Number of comments; null when comments are not enabled. |
| noteCount | integer? | Number of notes; null when notes are not enabled. |
| feedbackCount | integer? | Number of feedback responses; null when feedback is not enabled. |
| likeCount | integer? | Number of "like" votes; null when voting is disabled. |
| dislikeCount | integer? | Number of "dislike" votes; null when voting is disabled. |
| canEnableComments | boolean? | Whether comments can be enabled on the article. |
| canExcludeInternalSearch | boolean? | Whether the article is excluded from internal KB search. |
| canExcludeExternalSearch | boolean? | Whether the article is excluded from the external customer-portal search. |
| seoTitle | string? | SEO meta title. |
| seoDescription | string? | SEO meta description. |
| seoCanonicalUrl | string? | Canonical URL of the article. |
| ogTitle | string? | Open Graph title for social sharing. |
| ogDescription | string? | Open Graph description for social sharing. |
| webUrl | string? | Browser URL the AI host can hand to a human user for opening this article in the agent portal. |
Example request
{
"id": 814800
}
Example response
{
"id": 814800,
"title": "How to reset your password",
"slugTitle": "how-to-reset-your-password",
"description": "Steps to reset a forgotten password using the customer portal.",
"markdownDescription": null,
"categoryName": "Customer Support",
"sectionName": "Getting Started",
"status": { "id": 1, "name": "Published" },
"visibility": { "id": 2, "name": "Public" },
"editorType": { "id": 2, "name": "WysiwygEditor" },
"statusIndicator": { "id": 2, "name": "New" },
"statusIndicatorExpiry": "2026-10-15T00:00:00+00:00",
"isPublished": true,
"currentVersionNumber": "v2.2",
"publishedVersionNumber": "v2.0",
"createdAt": "2026-08-21T12:50:26.012586+00:00",
"publishedAt": "2026-08-22T08:00:00+00:00",
"updatedAt": "2026-09-01T10:15:00+00:00",
"articleExpiry": "2030-01-01T00:00:00+00:00",
"createdBy": "Ada",
"lastModifiedBy": "Grace",
"assignee": "Bob",
"tags": ["password", "onboarding"],
"viewCount": 1248,
"commentCount": 4,
"noteCount": 1,
"feedbackCount": 17,
"likeCount": 32,
"dislikeCount": 1,
"canEnableComments": true,
"canExcludeInternalSearch": false,
"canExcludeExternalSearch": false,
"seoTitle": "Reset your BoldDesk password",
"seoDescription": "Step-by-step guide to reset a forgotten BoldDesk customer portal password.",
"seoCanonicalUrl": "https://your-tenant.bolddesk.com/kb/how-to-reset-your-password",
"ogTitle": "Reset your BoldDesk password",
"ogDescription": "Step-by-step guide to reset a forgotten BoldDesk customer portal password.",
"webUrl": "https://your-tenant.bolddesk.com/agent/kb/814800"
}
create_kb_article
Creates a new knowledge base article. Returns the new article's ID, a confirmation message, and its URL. Only agents with the Create Article permission can call this tool.
Input
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| title | string | Yes | — | Article title (Maximum 255 characters). |
| description | string? | Conditional | — | Article body/content. Required when editorTypeId is 2 (WYSIWYG). |
| categoryId | integer? | Conditional | — | KB category ID. Required when sectionId is not supplied. |
| sectionId | integer? | Conditional | — | KB section ID. When supplied, the parent category is set automatically. |
| slugTitle | string? | No | — | URL-friendly slug (Maximum 255 characters). |
| editorTypeId | integer? | No | 2 | Editor type: 1 = Markdown, 2 = WYSIWYG. |
| markdownDescription | string? | Conditional | — | Article body in Markdown. Required when editorTypeId is 1 (Markdown) |
| tags | string[]? | No | — | List of article tags. Each tag must not exceed 50 characters. |
| articleExpiry | string? | No | — | Date and time when the article expires (must be a future date, ISO 8601). |
| canEnableComments | boolean? | No | — | Whether comments can be enabled on the article. |
| canExcludeInternalSearch | boolean? | No | — | Whether the article is excluded from internal KB search. |
| canExcludeExternalSearch | boolean? | No | — | Whether the article is excluded from the external customer-portal search. |
| statusIndicatorId | integer? | No | 1 | Status indicator: 1 = None, 2 = New, 3 = Updated. |
| statusIndicatorExpiry | string? | No | — | Date and time when the status indicator expires (must be a future date, ISO 8601). |
| SEO | object? | No | — | SEO metadata (title, description, canonical URL, Open Graph tags). All fields are optional. |
| SEO.title | string? | No | — | SEO meta title (Maximum 255 characters) |
| SEO.description | string? | No | — | SEO meta description (Maximum 300 characters). |
| SEO.canonicalUrl | string? | No | — | Canonical URL for SEO; must be a valid HTTPS URL. |
| SEO.ogTitle | string? | No | — | Open Graph title for social sharing (Maximum 255 characters). |
| SEO.ogDescription | string? | No | — | Open Graph description for social sharing (Maximum 300 characters). Requires SEO.ogTitle. |
| SEO.isSameAsMetaDetails | boolean? | No | false | Reuse the SEO meta title and description as the Open Graph title and description for social sharing. |
Note: At least one of categoryId or sectionId must be supplied and greater than zero. When only sectionId is supplied, the section is used to look up the parent category's visibility. If both are supplied and the section is invalid, the specified category is used. New articles are created in Draft status.
Output
| Field | Type | Description |
|---|---|---|
| id | integer | New article ID. |
| message | string? | Confirmation message returned after the article is created. |
| webUrl | string? | Browser URL the AI host can hand to a human user for opening this article in the agent portal. |
| title | string? | Article title, as submitted in the request. |
| slugTitle | string? | URL-friendly slug, as submitted in the request (when set). |
Example request (WYSIWYG)
{
"title": "How to reset your password",
"description": "<p>Steps to reset a forgotten password using the customer portal.</p>",
"categoryId": 1,
"sectionId": 11,
"slugTitle": "how-to-reset-your-password",
"editorTypeId": 2,
"tags": ["password", "onboarding"],
"canEnableComments": true,
"statusIndicatorId": 2,
"statusIndicatorExpiry": "2026-10-15T00:00:00",
"SEO": {
"title": "Reset your BoldDesk password",
"description": "Step-by-step guide to reset a forgotten BoldDesk customer portal password.",
"canonicalUrl": "https://your-tenant.bolddesk.com/kb/how-to-reset-your-password",
"isSameAsMetaDetails": true
}
}
Example request (Markdown)
{
"title": "How to reset your password",
"markdownDescription": "## Steps
1. Open the customer portal.
2. Click **Forgot password**.
3. Follow the email link.",
"categoryId": 1,
"editorTypeId": 1
}
Example response
{
"id": 21,
"message": "Article successfully created.",
"webUrl": "https://your-tenant.bolddesk.com/agent/kb/21",
"title": "How to reset your password",
"slugTitle": "how-to-reset-your-password"
}
Best practices:
- Discover the available categories and sections with get_section_tree_view before creating an article.
- Prefer sectionId when the article belongs to a specific section; the parent category is set automatically.
- Use statusIndicatorId 2 (New) or 3 (Updated) along with a future statusIndicatorExpiry date, to highlight the article on the customer portal for a limited time.
- Set SEO.isSameAsMetaDetails to
truewhen you want the Open Graph title and description to mirror the SEO meta values without supplying them again.