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; live API qualification remains pending.

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.
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.

Source-only directory corrections

The following staff-authorization and organization-uniqueness corrections are 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 either published beta package.

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.

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 created_at, then numeric ID. 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.

Retries and guarded updates

Creation replay

Idempotency-Key applies only to ticket creation. The suffixless and .json routes share its namespace.

Condition Result
First successful creation Stores the response; x-idempotency-lookup: miss.
Replay Returns the original ticket/audit snapshot; x-idempotency-lookup: hit. Later ticket edits do not change it.
Changed canonical parsed parameters HTTP 400 IdempotentRequestError.
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 the first success, checked after an automatic tick. Hits do not extend it.

Only the known response URL is rendered for the current validated origin. The cache survives restart and is 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.

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 verification process.