Changelog

Every change to the documented ThriveDesk Public API surface, newest first.

The version is the value in the specification's info.version, so it moves when the documentation moves rather than when the product ships. A release marked Docs only changed no server behavior: existing calls keep working, but the schema you coded against may have been wrong, and the entry explains how.

1.3.0 — 2026-07-30

Latest

The remaining delete operations

Added — Four deletes that were left out

  • DELETE /v1/conversation/{conversation_id}/force-delete permanently destroys a conversation already in the trash, along with its thread events, messages, attachments, and object-storage files. Calling it on a live conversation returns 404: soft-delete first.
  • DELETE /v1/inboxes/{inbox_id}/automations/{automation_id} removes an automation. Listing and viewing automations were already documented; creating and updating them still are not.
  • DELETE /v1/inboxes/{inbox_id}/custom-views/{custom_view_id} removes a custom view, and only its owner may do so. It answers with {success, message} rather than the usual {message}. Listing and creating views are not part of this surface, so the identifier must come from a first-party client.
  • DELETE /v1/knowledgebases/{knowledgebase_id}/users/{email} revokes one person's access to a help center. The ThriveDesk account is untouched.

Changed — Deletes say what they destroy

  • Each of the four carries a description covering what it removes and whether there is a way back. Conversation deletion is recoverable through PATCH /v1/conversation/{conversation_id}/restore only until the organization's trash lifetime expires, 30 days by default.

1.2.0 — 2026-07-30

Business hours and holidays

Added — Business-hours profiles

  • GET /v1/business-hours lists every profile in the organization, newest first and unpaginated; GET /v1/business-hours/{business_hour} shows one.
  • POST /v1/business-hours creates one and returns 201. A profile is either calendar_24_7 or business_hours with a seven-entry weekly schedule, one entry per weekday, using 24-hour HH:MM times. An end earlier than the start is an overnight shift.
  • PATCH /v1/business-hours/{business_hour} updates one. Omitted keys keep their stored value, an explicit null is ignored, and sending inbox_channels replaces the whole set. DELETE returns 204 and releases the channels the profile covered.
  • A profile can cover the email and livechat channels of any inbox, and a channel belongs to at most one profile. A conflicting bind returns 422 carrying conflicting_business_hour_id, inbox_id, and channel instead of the usual errors object, and rolls the write back.

Added — Holidays

  • GET /v1/holidays lists closures ordered active first, upcoming by start date, then past with the most recent first. GET /v1/holidays/{holiday} shows one.
  • POST /v1/holidays creates one with 201 from a name and inclusive start_date to end_date range; equal dates make a single-day holiday and ranges may overlap. PATCH accepts either date alone and validates against the stored value for the other, always reporting a range violation under end_date. DELETE returns 204.
  • Each holiday carries a read-only status of upcoming, active, or past, derived from today's date in the organization's timezone.

Added — Business-hours fields on the inbox

  • off_hours_auto_reply_subject and off_hours_auto_reply_body are now documented on the inbox, both in GET /v1/inboxes and on the inbox embedded in message and report responses. business_hour_enabled is documented on the inbox list. All three have been returned since business hours shipped.

Writes on both resources are limited to administrators and the account owner; reads are open to any teammate. All ten operations take a personal access token only.

1.1.2 — 2026-07-14

Docs only

Pagination and schema description fixes

Fixed — Simple pagination on inbox tags

  • GET /v1/inboxes/{inbox_id}/tags was described as returning no meta block, with next_page_url and prev_page_url in links. It does return meta. The block omits last_page and total, because the endpoint does not count the full result set, and adds current_page_url. Walk pages with links.next until it is null rather than counting them.

Changed — Schema descriptions

  • Error, PaginationMeta, the bearer-token bearerFormat, and the two camelCase path parameters described themselves in terms of the API's internal framework. They now describe the contract. No field, type, or requirement changed, so the Postman collection and SDKs are byte-identical apart from these strings.

1.1.1 — 2026-07-14

Docs only

Response schemas verified against the live API

No endpoint, request body, scope, or authentication behavior changed. Every documented response body was replayed against the running API and corrected where it had drifted, so the schemas now describe what the API actually returns.

Fixed — Fields the docs described but the API never returns

These were removed or renamed to the field the API really sends:

  • Conversations: assignee_id and contact_id are really assignable_id / assignable_type, and snooze_until is really is_snoozed. The fields is_read and is_trashed do not exist.
  • Thread events were documented as a flat message (type, body, html_body, cc_emails, ...). The API returns event_type, event (the message, null on system events), actor, and extra.
  • Inboxes: channel, from_email, enabled, is_private, and created_at are not returned.
  • Organization on GET /v1/me: name and subdomain are really company and slug.
  • Tags: created_at and organization_id are not returned.
  • Reports: an agent has first_name / last_name / name, not email / avatar_url. Day buckets are year / month / day, not a single date.
  • Listing knowledge-base articles documented a {message} stub. It returns a paginated {data, links, meta}.

Added — Newly documented

  • Responses now document every field returned, including per-folder counts and agents/teams on an inbox; embedded contact, last_message, and custom_field_values on a conversation; the author on a saved reply; and downloadable attachments on a message.
  • GET /v1/inboxes/{inbox_id}/tags uses simple pagination: its meta has no last_page or total, and adds current_page_url.
  • Free-form objects—an inbox's satisfaction-ratings config, an organization's permission matrix, and a conversation's custom-field values—are documented as such instead of invented shapes.

1.1.0 — 2026-07-11

Server change

Trimmed public surface, teammate endpoints, and tag validation

Removed — Dropped from the documented surface

Twenty-six operations that existed for the ThriveDesk web app rather than integrations are no longer documented. The routes still exist and first-party clients are unaffected, but they are not supported for integrations and may change without notice:

  • Session authentication: POST /v1/auth/login and POST /v1/auth/logout. Use a personal access token; integrations should never collect ThriveDesk passwords.
  • Composer mechanics: cancel reply (undo send) and the saved-reply use counter.
  • UI organization: custom-views CRUD, custom-field reorder, and saved-reply folder rename/delete.
  • Redundant bulk twins: POST /v1/settings/tags/update and /delete; use PUT/DELETE /v1/settings/tags/{tag_id}.
  • Irreversible deletion: conversation force-delete and batch force-delete.
  • Admin plane: automation create/update/delete, where list and view remain, plus Knowledge Base member/access management.
  • Dashboard-only reports: recent ratings, agent-team conversations, and agent-team productivity.

Added — New endpoints

  • GET /v1/settings/users lists teammates and pending invitations; GET /v1/settings/users/{user_id} shows one teammate. Both require users:read, which previously had no documented endpoint.
  • POST /v1/conversation/{conversation_id}/draft creates or updates the caller's reply draft and returns the draft_id consumed by reply and attachment upload. This closes the documented reply flow, which already referenced drafts without documenting how to create one.

Changed — Tag validation is now enforced

  • Tag create now enforces what the specification already documented: name is limited to 64 characters and color must be a six-digit hex value (#RRGGBB). Tag merge enforces the same plus a minimum of two source tags; bulk color update requires a hex color. Previously the server accepted any string.

Fixed — Schema corrections

  • ReplyBody no longer documents new_conversation; the server never read it.
  • The User schema now mirrors the API's user serializer: avatar rather than avatar_url, full name/contact fields, presence, preferences under extra, and real role values (Account Owner, Administrator, User).
  • Pagination link fields and avatar fields are typed as URIs instead of date-times, and pagination links are nullable at the edges.

Changed — Tooling

  • The Postman collection is now generated from the OpenAPI specification, with a folder per tag and schema-placeholder examples, instead of being maintained by hand.

1.0.1 — 2026-07-08

Docs only

Accuracy pass against the API implementation

Every operation was re-verified against the API's route table, validators, and response serializers. Several documented shapes did not match the running API and were corrected to what the server actually accepts and returns.

Fixed — Authentication

  • The public API uses a personal access token granted the first-party public scope, which can call every documented endpoint.
  • POST /v1/auth/login is documented as unauthenticated.
  • POST /v1/search requires a token; the authentication guide previously said otherwise.

Fixed — Request bodies

  • Reply requires status. Message content comes from the authenticated user's draft, not the body.
  • Note uses message rather than note. Forward uses body, an array to, and required message_id. Snooze uses snoozed_until plus required type. Split requires thread_event_id, direction, subject, and status.
  • Tag attach/detach take tag. Conversation update takes assign_to / tags. Custom-field values are sent as a flat key-value map.
  • Batch update/delete take conversations; restore/force-delete take conversation_ids. The hard flag never existed.
  • Custom-field and custom-view bodies now mirror validators (key, is_required, structured options, a filters tree, and display).
  • Creating a conversation requires to, status, subject, and message. Contact create persists only email. Attachment upload takes an attachments[] multipart array.
  • Saved-reply folder rename/delete and GET /v1/saved-replies require inbox_id. Tag update requires name.

Fixed — Responses and parameters

  • Single resources are wrapped in {"data": ...}. List endpoints document their real collection shapes, whether paginated or plain arrays.
  • Status enums are Active / Pending / Closed, priority is High / Medium / Low, and custom field types are text / textarea / dropdown / toggle / number.
  • Date-range reports require start_date and end_date. Previously undocumented query parameters, including contact search, tag search, per-page overrides, event_id, agent_id, rating, and view, are now listed.
  • The global limit of 300 requests per minute per client IP is documented in Pagination and rate limits.

1.0.0 — 2026-07-07

Initial release

Initial public release

First publication of the ThriveDesk Public API as an OpenAPI 3.1 specification. It covered the 99 endpoints in the previous Postman collection, plus schema definitions, authentication scopes, the error catalog, pagination contract, and rate-limit documentation.

Added — Documentation

  • Hand-authored OpenAPI 3.1 specification at openapi/openapi.yaml
  • Bundled single-file specification at openapi/bundled.yaml
  • Redoc reference renderer at reference.html
  • Stoplight Elements interactive playground at playground.html
  • Guides for quickstart, authentication and scopes, errors, pagination and rate limits, and changelog

Fixed — Crosscheck against the Postman collection

The Postman collection remains in this repository at api.postman_collection.json. Seven commits in its history record fixes applied during the crosscheck pass:

  1. Fix api.conversation.merge request body — the example body was invented and would have returned 422.
  2. Fix api.settings.tags.merge request body — the same pattern.
  3. Fill empty request-body templates with real schemas — 12 endpoints had placeholder bodies.
  4. Fix api.automations.store and api.automations.update — the body used a nonexistent conditions[] field and the wrong active flag.
  5. Replace fabricated "string" placeholders in report responses — all seven /v1/reports/* endpoints.
  6. Replace api.search response placeholder — corrected shape.
  7. Replace api.me response placeholders — corrected shape.

The Postman collection and OpenAPI specification are intended to remain in lockstep.