Zendesk API reference

The native Zendesk connector supports ticket workflows with directory identities, assignment, comments, audit history, queue search, guarded updates and optional logical closure. It is available in the public beta. Local conformance tests cover the declared subset. Accepted source-bound live pairs qualify narrow mapped claims, including the bounded principal-membership read in the reviewed PR #172 source. The later PR #175 timestamp runtime source has no new provider pair, and full native API qualification remains incomplete. See the build log.

On this page

For setup and test files, see Zendesk workflows. To work through the interface, follow the dashboard guide.

A seed with zendesk.version: 1 selects this profile; zendesk-support-v1 is a bundled example. Seeds without that field retain the separate, simplified legacy desk. URLs, usernames and headers cannot switch a world's profile.

The world API key authenticates the principal configured in its seed. Connector responses use numeric IDs. Admin state and diff keys are strings, and zendesk_profile: "native-v1" identifies native responses even when no records changed.

Run the SDK example

Configure node-zendesk with the endpoint and token supplied for the current run:

import zendesk from "node-zendesk";

const client = zendesk.createClient({
  endpointUri: process.env.WORLDS_ZENDESK_URL,
  username: "admin@example.test",
  token: process.env.WORLDS_ZENDESK_TOKEN,
  oauth: true,
  throttle: false,
  throwOriginalException: true,
});

const me = (await client.users.me()).result;

WORLDS_ZENDESK_URL ends in /api/v2; the SDK adds .json to routes. Bearer and legacy email/token:key Basic authentication both select the world's configured principal. The Basic username does not change that identity.

Native tests use version-2 task files and grade persisted records, comments and audits. The legacy task compiler and shift rubric reject native worlds. Native and combined tests run through both the CLI and dashboard.

Run the example from a source checkout

This contributor example starts a temporary server and world, then uses the pinned SDK to search tickets, read requesters, assign tickets and add private notes. It verifies the resulting state and cleans up afterward. No model key or Zendesk account is needed.

Supported API

Every route supports both suffixless and final .json forms under /api/v2.

Resource Operations Boundary
Users create, list, show, current user, update Create end users with email; name updates; see the packaged identity and permission limits below. Agent/admin identities are seeded.
Groups create, list, show, update Admin writes name/description; membership/default administration is seeded.
Organizations create, list, show, update Admin writes name, external ID, domains, tags and optional group.
Group/organization memberships list, show, user-scoped list Read-only seeded relationships. The reviewed PR #172 source added a principal-only list/show conformance probe over these existing routes; it does not add a route or widen their modeled behavior.
Tickets create, list, show, update Requester, submitter, assignment, organization, subject, status, priority, tags, external ID and plain-text comments.
Comments list per ticket Immutable records; append through a ticket update.
Audits list/show per ticket Immutable Create, Change and Comment events.
Search ticket queue search Explicit type:ticket, status, priority, requester, assignee and tags clauses.

Packaged beta.2 directory behavior

In 0.9.0-beta.2, user email is accepted only on creation. Any supplied email in a user PUT, including the unchanged address, is refused atomically with a worlds: unsupported-field 422; no simultaneous name change is saved. User identity mutations are outside this Worlds subset. This refusal is a local limitation, not Zendesk's email-update behavior or a claim of identity parity.

The beta.2 package still permits an agent to rename other staff members and does not reject duplicate organization names or external IDs. Do not use it to test these authorization or uniqueness rules.

Published beta.1 directory limitations

The published 0.9.0-beta.1 package predates the email-update refusal in beta.2. A user PUT with email replaces the stored primary address, which does not reproduce Zendesk identity behavior. An agent principal can rename other staff members, and organization creates or updates can persist duplicate names or external IDs. Do not use beta.1 to validate email-identity changes, staff-update authorization or organization uniqueness. User creation with email and name-only end-user updates remain available within the locally tested subset.

Packaged beta.3 directory behavior

The frozen published 0.9.0-beta.3 includes these directory corrections, which are also implemented in the source checkout but not included in either 0.9.0-beta.1 or 0.9.0-beta.2. They do not describe the behavior of those earlier packages. Publication does not establish live API qualification. See the release page for the versioned package and its limitations.

For name-only updates, the source profile allows agents to update end users and their own numeric user ID. Updates to another agent or administrator receive a local 403 Forbidden; administrators can update all three roles. Numeric self-update remains an existing local profile assumption. Custom-role permissions and self-edit restrictions are not modeled, and exact provider permissions, error wording and precedence remain unqualified. Existing field, ID, target and name validation runs before the other-staff restriction.

Organization creates and updates reject collisions with another organization for each supplied name or external ID. Names compare exactly after trimming boundary whitespace, including when comparing a seeded name; name comparison is case-sensitive. Nonempty external IDs compare with locale-independent lowercase, retain their supplied spelling and are not trimmed. Null and empty external IDs remain reusable; whitespace is significant, including whitespace-only values. No Unicode normalization is applied.

Historical duplicate seed values are retained. Unrelated updates and omitted fields do not trigger duplicate validation. Collisions receive a local worlds: 422 after existing field/reference validation, with name checked before external ID. These comparison and refusal rules remain unqualified against the provider.

Current-source timestamp behavior

The timestamp precision and cursor rules below describe the beta.4 candidate and current source checkout. The frozen published 0.9.0-beta.3 and published beta.1/beta.2 archives predate those fixes: native seed chronology, history ordering and timestamp pagination compare millisecond-rounded instants, and timestamp cursors use numeric anchors. Do not use those packages to validate ordering or chronology that depends on sub-millisecond differences. Their guarded-update timestamp comparison is separate and already respects fractional precision.

Ticket behavior

Behavior Rule
Assignment Directory relationships constrain assignee and organization changes. Assigning a new ticket changes its status to open.
Solving Requires an assignee. Explicit agent reopening is supported.
Closing Closed tickets are immutable. Seed them as closed or use the configured closure simulation; direct writes to closed are unsupported.
Priority Defaults to null.
Comment privacy Inherits the previous comment; the first defaults to public. Set comment.public explicitly when writing a note or reply.
Empty updates Preserve the ticket, timestamps and history.
History order Exact created_at instant, including sub-millisecond fractions, then numeric ID only for equal instants. This order also selects the previous comment and the audit returned for a no-op.

The profile has no triggers or SLAs, so defaults can differ from a configured Zendesk account.

Ticket mutations commit the ticket, any new requester, comment and audit together. Failed validation commits none of those objects or counters. Native audits participate in state diffs; internal events do not. Native writes do not emit Stripe webhook events.

In a combined world, automatic clock advancement processes Stripe renewals and native closures in one transaction before handler validation. A later handler refusal does not undo that completed clock transaction.

Queue and pagination

Use this query for the active queue:

type:ticket status:new status:open status:pending status:hold

Repeated values of one property combine with OR; different properties combine with AND. Free text, quoting, comparison operators and unlisted fields are refused. Search indexes synchronously and defaults to deterministic ID order. Hosted Zendesk's indexing delay and ordering are not reproduced.

Surface Pagination
Lists Offset and cursor pagination, endpoint-specific sorts, at most 100 records per page, absolute continuation URLs. Cursors bind to resource, filters, sort and seed.
Search Offset only. Exposes the first 1,000 matching records and reports the total count. Requests beyond that window fail explicitly.

In the current source checkout, timestamp sorting compares instants exactly across fractional precision and timezone spellings. Timestamp cursors retain the original timestamp string; older cursors containing a rounded numeric timestamp return the existing 422 RecordInvalid pagination error, so restart that traversal. Existing ID, status and priority cursors remain compatible with the same resource, filters, sort and seed.

Every encoded cursor, including metadata on a terminal page, is limited to 2048 ASCII bytes. A valid seed can contain a fractional timestamp too long to fit that limit; offset pagination still works, while a cursor page requiring that anchor returns the existing pagination error. Seed timestamp precision is not capped or truncated.

Retries and guarded updates

Creation replay

Idempotency-Key applies only to ticket creation. The current source scopes its cache by the literal creation path and key: /api/v2/tickets and /api/v2/tickets.json retain independent entries. The first successful use of a key on the other path creates a separate ticket when that path has no unexpired entry. Returning to either path with the same parameters replays its own unexpired creation snapshot. Independently reviewed, bounded owned-trial controls observed distinct cross-path creations in both directions and immutable same-path replay, including .json. These diagnostic controls informed the correction; they do not qualify the current source or establish general provider parity.

The following table describes current simulator behavior. The registered qualification harness tests only suffixless creation followed by replay and changed parameters on that same path. The broader URL-form behavior remains implemented-unqualified as ticket-creation-replay-url-forms in the conformance inventory, with no mapped raw observations. This source correction is outside the frozen beta archives; see storage compatibility before using retained world files.

The current conformance harness also checks that replay, changed-body refusal and stale guarded refusal preserve ticket event state: every other returned ticket field and the complete returned comments/audits remain equal. The root generated_timestamp may stay equal or advance when it is present and valid in both snapshots; the immutable replay response itself must still match in full. Zendesk's ticket reference distinguishes this system-update timestamp from event-only updated_at. This is a narrow measurement rule, not a claim that the simulator matches provider timestamp values or excludes system-only and external effects. The reviewed PR #172 principal-membership source has accepted narrow qualification; the first conformance5 run remains failed evidence. The URL-form replay group remains unqualified. Neither the later PR #175 source nor this path-scoped runtime correction has a new mapped provider pair.

Condition Result
First successful creation for a path/key pair Stores that pair's response; x-idempotency-lookup: miss.
Same-path replay Returns that path/key pair's original ticket/audit snapshot; x-idempotency-lookup: hit. Later ticket edits do not change it.
First successful use of the same key on the other path, with no unexpired entry there Creates a distinct ticket with an independent snapshot and expiry; x-idempotency-lookup: miss.
Changed canonical parsed parameters on the same path/key pair HTTP 400 IdempotentRequestError; the sibling path's entry is unchanged.
Failed validation or injected failure No response is stored.
Empty key or key on another native route Refused before the clock ticks.
Expiry Two hours of logical time from each pair's first success, checked after an automatic tick. Hits do not extend it; replacement affects only the expired pair.

Only the known response URL is rendered for the current validated origin. Each path's cache entry survives restart and both are cleared by reset. Ticket updates are not deduplicated: repeating a successful comment PUT can append another comment.

Guarded updates

A ticket PUT with safe_update: true requires updated_stamp to be a valid RFC3339 instant equal to the ticket's current updated_at.

  • An older stamp returns HTTP 409 UpdateConflict, including for a no-op.
  • Missing, malformed and future stamps are outside the supported profile.
  • Fractional precision and equivalent timezone offsets are respected.
  • Checks follow identity and closed-ticket validation, before requester allocation.
  • Frozen same-second writes can both succeed with the same exposed stamp.

Omitted, false and string "false" flags use ordinary updates and ignore the stamp. safe_update: true on create is refused before ticking. These flag rules, canonical equality, success-only caching and validation wording are local contracts pending live comparison; they are not certified Zendesk equivalence.

Logical closure and follow-ups

Closure

Closure is disabled unless the seed declares zendesk.lifecycle.closure with after_hours, sweep_phase_seconds and an existing agent/admin author_id. This explicitly configures a simulation actor and schedule; it does not discover tenant configuration.

The first hourly sweep strictly after solving counts as zero. Closure happens after the configured additional hours. Due work runs in due-time/numeric-ID order, updates the ticket, and writes one status Change audit at the boundary. It adds rule-channel provenance without a comment or Stripe event. Clock advancement rolls back completely if either connector's due work fails.

Situation Behavior
Ticket remains solved Keeps its original solve episode.
Ticket reopens Clears the episode; solving again starts a new one.
Seeded ticket is overdue Closes at its past due boundary. Seed history after that boundary is rejected.
Manual-clock update at or after a pending closure Returns 422 RecordInvalid without changing history. Advance the clock before editing.

The last refusal is a simulator safeguard. Hosted scheduler phase, throughput limits and the separate 28-day backstop are not emulated. See the seed reference for metadata and limits.

Follow-ups

Create a follow-up with via_followup_source_id naming a closed ticket. Omitted subject, requester and tags inherit; explicit values, including an inline requester or empty tags, override. Other fields and history use normal creation behavior.

The source ticket remains unchanged; its followup_ids are derived from linked children. A valid nonclosed source creates an ordinary unlinked ticket. Missing or malformed sources fail atomically. Internal source metadata is not returned. API-origin via projection remains a local policy pending raw provenance evidence.

Seed exports include records, history and lifecycle settings, but no request cache. Older incompatible world databases must be recreated from their seeds; in-place migration is not supported.

Deferred behavior

Area Outside this profile
Ticket features Custom fields/statuses, automatic reopening from end-user comments, configurable closed-ticket editing, followers/CCs and deletion.
Content Attachments, HTML comments, Markdown link/emphasis/code syntax and double-curly placeholders. Rendering is not emulated.
Automation Macros, triggers, SLAs, Views and bulk jobs.
Administration Membership administration; broader membership paging, aliases, defaults and authorization parity remain unqualified.

Recognized unsupported writes are refused. Local tests establish the declared simulation contract; negative wording, tenant-dependent rules and complete Zendesk agreement remain unqualified. Dashboard availability and beta publication do not expand that claim. The conformance runbook records the exact principal read and source-bound qualification process. The frozen 0.9.0-beta.2 package predates this tooling; its published behavior and bytes are unchanged.