Developers
API reference
Basics#
The base URL is https://app.wilmo.ai/api/v2. Send a team API key or an organization key as a Bearer token. Pin the version with Wilmo-Version. Every response carries a Request-Id.
A success answers the object itself. A list answers object: "list" with data, has_more and next_cursor. Pass next_cursor back as cursor, with the same filters, for the next page.
{
"object": "list",
"data": [ { "id": "...", "subject": "Where is my order?" } ],
"has_more": true,
"next_cursor": "eyJyZWNlaXZlZF9hdCI6..."
}{
"error": {
"type": "not_found_error",
"code": "not_found",
"message": "Ticket not found",
"param": null,
"request_id": "req_8Jx2Qm4T",
"doc_url": "https://wilmo.ai/developers/errors#not_found"
}
}Branch on error.code. Each code has its own entry in Errors. Headers, keys and rate limits are on the overview.
Version 2026-11-06. Fetched from https://app.wilmo.ai/api/public/v1/openapi.
Teams
/api/v2/teamsList the teams of the organization
- Scope
read:tickets- MCP tool
list_teams
Every team (store, market or brand) of the caller's Wilmo organization, by id and name, sorted by name. Each team has its own inbox and AI agent. The ids are the team_id that ticket and analytics reads accept to narrow to one team.
Parameters
None.
Response
200The teams, sorted by name
- object"list"required
- dataarray of objectrequired
Fields
- idstringrequired
- namestringrequired
- has_morebooleanrequired
- next_cursorstring | nullrequired
Pass as cursor for the next page.
Errors
| 400 | invalid_input | the input does not match the schema. |
| 400 | team_required | Called without a caller: there are no teams to list. |
| 401 | authentication_required | no valid API key or access token. |
| 429 | rate_limited | too many requests; wait for Retry-After seconds. |
Examples
curl "https://app.wilmo.ai/api/v2/teams" \
-H "Authorization: Bearer $WILMO_API_KEY" \
-H "Wilmo-Version: 2026-11-06"wilmo teams listTickets
/api/v2/ticketsSearch and filter support tickets
- Scope
read:tickets- MCP tool
list_tickets
Support tickets across every team of the caller's organization (or one team with team_id). With q, a free-text search over ticket number, subject, customer, notes and message text, best match first, each row saying where it matched. Without q, the newest received first. Filters: status, channel, tag, received_after, received_before. Each row: id, number, team, subject, status, channel, customer name and email, tags, how it was answered (autopilot, copilot, human), a short AI summary and dates. Pages of up to 50; pass next_cursor back for more. Read one conversation with get_ticket.
Parameters
| Name | Type | Description |
|---|---|---|
| q query | string | Free text, matched like the inbox search: ticket number, subject, customer name or email, notes and message text. Results are ranked best match first.max length 200 |
| team_id query | string | Only this team (an id from list_teams). |
| status query | "pending" | "open" | "resolved" | "spam" | Only tickets with this status. |
| channel query | "email" | "live_chat" | "instagram_dm" | "phone" | "chatbot" | "messenger" | "trustpilot" | "event" | Only tickets that started on this channel. |
| tag query | string | Only tickets carrying this tag (category): its id, or its name (case-insensitive).max length 200 |
| received_after query | string (date) | string (date-time) | Only tickets received at or after this ISO 8601 date or date-time. |
| received_before query | string (date) | string (date-time) | Only tickets received before this ISO 8601 date or date-time (exclusive). |
| limit query | integer | Tickets per page, at most 50.default 25, min 1, max 50 |
| cursor query | string | next_cursor of the previous page, with the same filters.max length 500 |
Response
200A page of tickets
- object"list"required
- dataarray of objectrequiredat most 50 items
Fields
- idstringrequired
- ticket_numbernumberrequired
- team_idstringrequired
- team_namestring | nullrequired
- subjectstringrequired
- status"pending" | "open" | "resolved" | "spam"required
- channel"email" | "live_chat" | "instagram_dm" | "phone" | "chatbot" | "messenger" | "trustpilot" | "event"required
- customer_namestring | nullrequired
- customer_emailstring | nullrequired
- tagsarray of objectrequired
Fields
- idstring (uuid)required
- namestringrequired
- answered_by"human" | "copilot" | "autopilot" | nullrequired
- summarystring | nullrequired
- received_atstringrequired
- updated_atstringrequired
- matchobject | nullrequired
Fields
- source"ticket_number" | "subject" | "contact_email" | "contact_name" | "ticket_note" | "message"required
- previewstring | nullrequired
- has_morebooleanrequired
- next_cursorstring | nullrequired
Pass as cursor for the next page.
Errors
| 400 | invalid_input | the input does not match the schema. |
| 400 | team_required | Called without a caller and without team_id. |
| 400 | invalid | The cursor is not one this list gave, or not for these filters. |
| 401 | authentication_required | no valid API key or access token. |
| 404 | not_found | team_id is not a team the caller reads. |
| 429 | rate_limited | too many requests; wait for Retry-After seconds. |
Examples
curl "https://app.wilmo.ai/api/v2/tickets?limit=10" \
-H "Authorization: Bearer $WILMO_API_KEY" \
-H "Wilmo-Version: 2026-11-06"wilmo tickets list --limit 10/api/v2/tickets/{ticket_id}Read one ticket and its conversation
- Scope
read:tickets- MCP tool
get_ticket
One support ticket (team, subject, status, channel, customer, tags, how it was answered, AI summary) and its sent messages as plain text, oldest first. Each message says who wrote it: customer, ai (Wilmo's AI agent on its own, Autopilot), agent (a person, including an AI draft a person sent: Copilot), note (internal, never sent) or system. Returns the newest messages (25 by default, at most 50), each cut to 4,000 characters (truncated says so); pass older_messages_cursor back for earlier ones.
Parameters
| Name | Type | Description |
|---|---|---|
| ticket_id pathrequired | string | The ticket id (from list_tickets). |
| message_limit query | integer | The newest messages to return, at most 50.default 25, min 1, max 50 |
| cursor query | string | older_messages_cursor of the previous call, for older messages.max length 200 |
Response
200The ticket and a page of its messages
- ticketobjectrequired
Fields
- idstringrequired
- ticket_numbernumberrequired
- team_idstringrequired
- team_namestring | nullrequired
- subjectstringrequired
- status"pending" | "open" | "resolved" | "spam"required
- channel"email" | "live_chat" | "instagram_dm" | "phone" | "chatbot" | "messenger" | "trustpilot" | "event"required
- customer_namestring | nullrequired
- customer_emailstring | nullrequired
- tagsarray of objectrequired
Fields
- idstring (uuid)required
- namestringrequired
- answered_by"human" | "copilot" | "autopilot" | nullrequired
- summarystring | nullrequired
- received_atstringrequired
- updated_atstringrequired
- messagesarray of objectrequiredat most 50 items
Fields
- idstringrequired
- role"customer" | "ai" | "agent" | "note" | "system"required
- author_namestring | nullrequired
- channel"email" | "live_chat" | "instagram_dm" | "phone" | "chatbot" | "messenger" | "trustpilot" | "event"required
- sent_atstringrequired
- subjectstring | nullrequired
- textstringrequired
- truncatedbooleanrequired
- message_countintegerrequiredmin 0
- older_messages_cursorstring | nullrequired
Errors
| 400 | invalid_input | the input does not match the schema. |
| 400 | team_required | Called without a caller: there are no teams to read. |
| 400 | invalid | The cursor is not one this read gave. |
| 401 | authentication_required | no valid API key or access token. |
| 404 | not_found | No ticket with this id in a team the caller reads. |
| 429 | rate_limited | too many requests; wait for Retry-After seconds. |
Examples
curl "https://app.wilmo.ai/api/v2/tickets/<ticket_id>" \
-H "Authorization: Bearer $WILMO_API_KEY" \
-H "Wilmo-Version: 2026-11-06"wilmo ticket get --ticket_id <ticket_id>Skills
/api/v2/skillsList skills
- Scope
read:skills- MCP tool
list_skills
Lists the organization's skills (and its teams' own), newest first, a page at a time (limit up to 100, default 20). search filters by name or slug. Each skill has its name, slug, description, content and folder.
Parameters
| Name | Type | Description |
|---|---|---|
| limit query | integer | min 1, max 100 |
| offset query | integer | min 0 |
| search query | string |
Response
200A page of skills and the total count
- object"list"required
- dataarray of objectrequired
Fields
- contentstringrequired
- created_atstringrequired
- created_by_user_idstring | nullrequired
- deleted_atstring | nullrequired
- descriptionstringrequired
- folder_idstring | nullrequired
- idstringrequired
- kind"router" | "situations" | "facts"required
- namestringrequired
- organization_idstring | nullrequired
- positionnumberrequired
- slugstringrequired
- team_idstring | nullrequired
- updated_atstringrequired
- updated_by_user_idstring | nullrequired
- has_morebooleanrequired
- next_cursorstring | nullrequired
Pass as cursor for the next page.
- total_countintegermin 0
Errors
| 400 | invalid_input | the input does not match the schema. |
| 401 | authentication_required | no valid API key or access token. |
| 429 | rate_limited | too many requests; wait for Retry-After seconds. |
Examples
curl "https://app.wilmo.ai/api/v2/skills?limit=10" \
-H "Authorization: Bearer $WILMO_API_KEY" \
-H "Wilmo-Version: 2026-11-06"wilmo skills list --limit 10Ticket-analytics
/api/v2/ticket-analyticsGet ticket analytics for a period
- Scope
read:analytics- MCP tool
get_ticket_analytics
The analytics numbers for tickets received between date_from and date_to (ISO 8601 with an offset), across every team the caller reads. Optionally one assigned user, one saved ticket view, some tags (tag_ids, any of them) and one channel. analytics_version 'v1': ticket counts by status and by how they were resolved (a person, Copilot, Autopilot), resolution times, the daily trend and the tag distribution. analytics_version 'v2' (workspaces on the new analytics): customer messages answered by Autopilot, Copilot or a person, in total and per day, week or month, and when Autopilot settings changed.
Parameters
| Name | Type | Description |
|---|---|---|
| type query | "tickets" | default "tickets" |
| limit query | number | default 10 |
| offset query | number | default 0 |
| date query | string | |
| filters query | string | |
| assigned_user_id query | string (uuid) | |
| ticket_view_id query | string (uuid) | |
| tag_ids query | array of string (uuid) | |
| channel query | "email" | "live_chat" | "instagram_dm" | "phone" | "chatbot" | "messenger" | "trustpilot" | "event" | |
| date_from queryrequired | string (date-time) | |
| date_to queryrequired | string (date-time) | |
| sort_field query | "created_at" | "endpoint" | "method" | "status_code" | "response_time_ms" | default "created_at" |
| sort_direction query | "asc" | "desc" | default "desc" |
Response
200The numbers for the window
object
Errors
| 400 | invalid_input | the input does not match the schema. |
| 400 | team_required | Called without a caller: the numbers are read for its teams. |
| 401 | authentication_required | no valid API key or access token. |
| 429 | rate_limited | too many requests; wait for Retry-After seconds. |
Examples
curl "https://app.wilmo.ai/api/v2/ticket-analytics?date_from=<date_from>&date_to=<date_to>&limit=10" \
-H "Authorization: Bearer $WILMO_API_KEY" \
-H "Wilmo-Version: 2026-11-06"wilmo ticket-analytics get --date_from <date_from> --date_to <date_to> --limit 10Ticket-counts
/api/v2/ticket-countsGet ticket counts for the dashboard
- Scope
read:team- MCP tool
get_ticket_counts
How many of the caller's tickets are open, pending and resolved right now, across every team it reads, and their total. Spam and deleted tickets are not counted. These are the numbers on the dashboard home screen.
Parameters
None.
Response
200The ticket counts
- openTicketsCountnumberrequired
- pendingTicketsCountnumberrequired
- resolvedTicketsCountnumberrequired
- totalTicketsCountnumberrequired
Errors
| 400 | invalid_input | the input does not match the schema. |
| 400 | team_required | Called without a caller: the counts are read for its teams. |
| 401 | authentication_required | no valid API key or access token. |
| 429 | rate_limited | too many requests; wait for Retry-After seconds. |
Examples
curl "https://app.wilmo.ai/api/v2/ticket-counts" \
-H "Authorization: Bearer $WILMO_API_KEY" \
-H "Wilmo-Version: 2026-11-06"wilmo ticket-counts get