---
name: zendesk-oauth-app
description: >-
  Registers a Zendesk OAuth client to obtain a client ID (unique identifier)
  and client secret — covering the one thing that decides whether a
  multi-tenant connector works at all: a normal Zendesk OAuth client lives
  inside a single Zendesk account and only authorizes that one subdomain, so
  connecting many customers requires a global OAuth client, which Zendesk
  grants by request and not self-serve. Use when asked to get Zendesk OAuth
  credentials, create a Zendesk OAuth client, request or claim a Zendesk
  global OAuth client, set up a d3v- sponsored developer account, rotate a
  Zendesk client secret, or fix a Zendesk authorization error such as
  invalid_scope, an unrecognised client on a customer's subdomain, or "works
  on our Zendesk, fails on theirs". For any other vendor's developer portal,
  use that vendor's skill instead.
---

# Zendesk OAuth2 App Registration

Get a working Zendesk OAuth client — the account that owns it, the client record, redirect URLs, scopes, unique
identifier and secret — for a platform that connects many customers' Zendesk accounts.

Zendesk's defining trap is ownership. **An OAuth client is created inside one Zendesk account and is scoped to that
account's subdomain.** It authorizes `https://yourcompany.zendesk.com` and nothing else. A customer on
`https://theircompany.zendesk.com` sending your `client_id` to *their* subdomain's authorize endpoint gets an error,
because on their instance that client does not exist. Nothing about the client form hints at this, and it is
invisible until the second customer tries to connect. Authorizing many customer subdomains with one set of
credentials requires a **global OAuth client** (§3), which Zendesk issues on request — developers cannot create one.

Two more things are expensive to get wrong. **The client secret is shown once**, and on conversion to a global client
you lose the administration page entirely (§7). And **token expiry changed on 30 April 2026** (§8): any client
created today issues 30-minute access tokens by default, where older clients issued tokens that never expired — a
connector that never implemented refresh will authorize fine and then stop working half an hour later.

## Inputs to collect before you start

Ask in one batch. Never invent.

| Input | Notes |
| --- | --- |
| **Client name**, description, company, logo | Shown on the consent screen customers see; all are required for a global client (§3) |
| **Unique identifier** | The OAuth `client_id`. Must be the production value, and `zdg-`-prefixed for a global client (§3) |
| **Which Zendesk account owns the client** | An existing account, or a new `d3v-` sponsored/trial account (§2) |
| **Local or global** | One customer / internal use vs many customers — decide before creating anything (§3) |
| **Redirect URLs** | Every callback host your platform serves (§5) |
| **Scope set** | Exactly what the connector calls, no more (§6) |
| **Does the client implement refresh tokens?** | Blocking as of 30 April 2026 (§8) |
| **Is a Marketplace listing wanted or required?** | Separate track from the global client (§9) |

## Quick Start

1. Confirm a **new** client is needed — a new identifier orphans every existing customer connection (§1).
2. Sign in to, or create, the Zendesk account that will own the client; use a `d3v-` subdomain if a global client is
   the goal (§2).
3. **Decide local vs global before creating anything.** This is the whole task for a multi-tenant connector (§3).
4. Create the client: **Admin Center → Apps and integrations → APIs → OAuth clients → Add OAuth client** (§4).
5. Enter **every** redirect URL, newline-separated, https, absolute (§5).
6. Set allowed scopes to the exact set the connector calls (§6).
7. **Record the identifier and the secret now** — the secret is shown once and the page disappears on conversion (§7).
8. Check token expiry, refresh and rate limits against what the client actually implements (§8).
9. If global: submit the request at `https://apps.zendesk.com` → **Global OAuth** → **Request new OAuth** (§3).
10. Verify against a **second, unrelated subdomain** — never only the owning account (§10).
11. Hand the credentials over; never commit them (§11).

## Platform state (verified 2026-09-20 — re-verify before trusting)

- **OAuth clients are scoped to one Zendesk instance.** Zendesk states this plainly: to work across multiple
  instances you need a global OAuth client, and "for security reasons, Zendesk doesn't allow developers to create
  their own global OAuth clients."
- **Token expiry changed on 30 April 2026.** Clients created on or after that date get an `expires_in` of 30 minutes
  applied automatically. Clients created before it ("legacy clients") have no default access-token expiration, and
  must explicitly pass `expires_in` at token creation to use the refresh-token flow at all. Access-token `expires_in`
  must be between 300 seconds (5 min) and 172,800 seconds (48 hours); `refresh_token_expires_in` between 604,800
  seconds (7 days) and 7,776,000 seconds (90 days), defaulting to 2,592,000 seconds (30 days).
- **API tokens are deprecated and being retired in three phases**: 28 July 2026 (tokens unused for 30+ days
  auto-deactivate; new accounts can no longer create them), 27 October 2026 (existing accounts blocked from creating
  new ones), 30 April 2027 (all remaining API tokens permanently deactivated). Any integration still using a
  customer's API token has a hard deadline, and Zendesk's developer terms already prohibit third parties from using
  customers' API credentials.
- **`kind` (public vs confidential) is mandatory** for every new OAuth client created in Admin Center. Public clients
  may only use the authorization code flow; confidential clients may use either.
- **Allowed scopes are enforced at the client.** If the client has an allowed-scopes list, a token request for
  anything outside it fails with `400 Bad Request` / `invalid_scope`. Zendesk sets this list itself for global
  clients, on the principle of least privilege.

If Admin Center or the Marketplace portal does not look like this, stop and report what you actually see.

## 1. Decide: reuse the existing client, or register a new one

The unique identifier **is** the `client_id`. A new client means a new identifier, and every existing customer
connection is bound to the old one — all of them would have to re-authorize. Reuse the existing client for: adding a
redirect URL, widening scopes, rotating a compromised secret, or diagnosing a failure.

Register a **new** client only when the user explicitly wants one: a first client, a replacement for a compromised
one, a separate client for a different product, or a deliberate local → global move. Note that the local → global
conversion is itself one-way and takes the administration page away (§3, §7) — it is a planned cutover, not a tweak.
Say which path you are taking before you touch anything.

## 2. The Zendesk account that owns the client

- **Free trial** — 14 days, from Zendesk's registration page. Fine for a local client and for experimenting; it
  expires, so it is not a home for production credentials.
- **Sponsored developer account** — the right home when a global client or Marketplace listing is the goal. Sign up
  for a trial, **put the `d3v-` prefix on the subdomain**, then submit Zendesk's Sponsored Account Request Form.
  Sponsored accounts do not expire and carry up to 5 agent seats on Suite Enterprise features. Zendesk suspends
  sponsored accounts used to provide real customer support.
- **An existing production account** — normal for an established platform, and fine for a local client. You need
  admin rights (below).
- **Sandbox** — a sandbox has its own subdomain and its own OAuth clients; a client created in a sandbox does not
  exist in production. Useful as the "second subdomain" for §10.

**The `d3v-` prefix is not cosmetic.** Zendesk rejects global-client submissions from non-`d3v-` accounts. Adding it
later means a new subdomain, so get it right at signup.

**Permissions.** Creating and managing OAuth clients requires an admin, or an agent with the **Manage APIs**
permission. One sharp edge: if the admin who created a client later loses those permissions, `authorization_code`
tokens keep working but `client_credentials` tokens stop.

Hand control back for anything only a human can do — signup, email verification, CAPTCHA, 2FA, accepting terms,
submitting the sponsored-account form. Do not retry a blocked step in a loop.

**If this session has no browser automation** (the usual case for a CLI or cloud run), do not pretend to click. Give
the user an exact, ordered click path with the literal values to paste (§5 redirect URLs, §6 scope list), then
continue once they report back with the identifier.

## 3. Local client vs GLOBAL client — read this before creating anything

This decides whether the connector works for customer number two.

**A local OAuth client** is created by an admin inside one Zendesk account, and is valid only on that account's
subdomain. Right for: an internal integration against your own Zendesk, a single-customer build, or the development
phase of anything else. Wrong for a multi-tenant connector — asking every customer to create their own client in
their own Admin Center and hand you the secret is a support burden, and Zendesk's developer terms prohibit
third parties from relying on customers' shared credentials.

**A global OAuth client** is one client identifier that customers on *any* subdomain can authorize. Zendesk creates
it; you request it. Zendesk's own words: "you must request a global OAuth client from Zendesk to create global OAuth
tokens, and for security reasons, Zendesk doesn't allow developers to create their own global OAuth clients."

**What Zendesk requires, and where requests get bounced:**

| Requirement | Detail |
| --- | --- |
| Build first with a local client | The app must be "finished and ready to use across multiple Zendesk accounts" before you request |
| `d3v-` subdomain | "Submissions from non-`d3v-` accounts aren't accepted" (§2) |
| `zdg-` identifier prefix | E.g. `zdg-acmesync`. Must be representative of the product — Zendesk gives `zdg-zendesk` as acceptable and `zdg-global_client1` as not |
| Production-ready identifier | The value you submit is the value you ship. It is not renamed later |
| Every field filled | "Even if a field is labeled optional, it is required for global clients" — description, company, logo included |
| Least-privilege scopes | You state the scopes; Zendesk configures the client's allowed-scopes list from them (§6) |

**How to request:** create the fully-filled local client in the `d3v-` account, **write down the identifier and
secret** (§7), then go to the Marketplace portal at `https://apps.zendesk.com` → **Global OAuth** in the left menu →
**Request new OAuth**. The `d3v-` and `zdg-` values are pre-filled from the local client. Submit, and expect an email
plus a ticket reference; add Zendesk's stated contact address to your allow-list so the correspondence is not lost.

**What changes once it is global — plan for this, it is one-way:**

- **You lose the client administration page.** Zendesk is explicit: note the secret and identifier *before* you
  request, because access to the administration page goes away when the local client is converted.
- **Zendesk owns all subsequent edits.** Redirect URLs, name, logo, scopes — changes go through a support ticket, not
  a form. Get the redirect URL list complete the first time (§5).
- Global clients are surfaced read-only through the API (`GET /api/v2/oauth/global_clients` on a customer account
  lists the global clients that account has authorized); they are not mutable by developers.
- To attach the client to a Marketplace app listing later, the client must first be **claimed** in the developer
  portal (identifier plus the first 6 characters of the secret), then selected under the app's **Details →
  Compliance** tab, answering "Yes" to "Does this app use a global OAuth client?" (§9).

**Scope of the global-client programme:** it covers Zendesk Support and Chat. It does not cover Zendesk Sell, and a
Support global OAuth client cannot be used to build a bot — bots need their own token. If the connector spans those
products, raise it before submitting rather than after.

**Whatever the answer, the authorize and token hosts stay per-customer.** A global client does not give you one
central host; it gives you one identifier that works on every customer's own host:

```
https://{customer_subdomain}.zendesk.com/oauth/authorizations/new    # authorize
https://{customer_subdomain}.zendesk.com/oauth/tokens                # token exchange and refresh
https://{customer_subdomain}.zendesk.com/api/v2                      # API base
```

So the connector must collect each customer's subdomain up front and substitute it into all three. There is no
discovery endpoint for it — it comes from the customer.

## 4. Create the client

**Admin Center → Apps and integrations → APIs → OAuth clients → Add OAuth client.**

| Field | What matters |
| --- | --- |
| **Name** | What customers see on the consent screen and in their list of third-party apps. Required for a global client |
| **Description** | Shown on the consent screen. "Optional" locally, required for a global client |
| **Company**, **Logo** | Same: optional locally, required for a global client. JPG/GIF/PNG, square |
| **Unique identifier** | Auto-filled from the name and editable — **this is your `client_id`**. Set it deliberately; `zdg-`-prefixed for a global client |
| **Client kind** | Mandatory. **Confidential** for a server-side connector that can keep a secret. Public clients are limited to the authorization code flow |
| **Redirect URLs** | §5 |
| **Scopes** | Allowed scopes — the ceiling on what tokens from this client may request. Leaving it empty means all scopes (§6) |
| **Expire tokens** | Token expiry (§8). Behaviour depends on whether the client predates 30 April 2026 |

Do not confuse this page with Admin Center's **external OAuth clients** page — that one is for Zendesk authenticating
*outbound* to other services, and it is not what issues your client ID.

## 5. Redirect URLs

Zendesk's stated rules: redirect URLs "must be absolute and not relative, https (unless localhost or 127.0.0.1), and
newline-separated." The `redirect_uri` your authorize request sends must match a registered value **exactly** — no
subdirectory matching, no trailing-slash forgiveness, no query-string additions.

Register every callback host your platform serves, on its own line. For Unified.to these are one per data centre;
confirm the current list with the platform owner rather than assuming:

```
https://api.unified.to/oauth/code          # us (default)
https://api-eu.unified.to/oauth/code       # eu
https://api-au.unified.to/oauth/code       # au
https://api-dev.unified.to/oauth/code      # dev
```

Notes:

- The same `redirect_uri` must be sent again on the **token exchange**, and it must match what was sent on authorize.
- The redirect URL is your platform's and does not change per customer, even though the authorize host does.
- Get this list complete **before** requesting a global client. After conversion, adding a host means a support
  ticket (§3).
- A client created only for server-side token creation (no browser flow) needs no redirect URLs at all — that is not
  your case for a customer-authorizes-us connector.

## 6. Scopes

Space-separated in the authorize URL. Zendesk has two broad scopes and a long list of resource-specific ones:

| Scope | Meaning |
| --- | --- |
| `read` | All GET endpoints, including sideloaded resources |
| `write` | All POST, PUT and DELETE endpoints |
| `impersonate` | Lets a Support **admin** act on behalf of end users. Admin-only, and a red flag in review — request only if genuinely needed |

Resource-specific scopes follow `{resource}:{action}`, and as of 2026-09-20 include: `account_settings:read|write`,
`ai_agents:chat`, `any_channel:write`, `apps:read|write`, `auditlogs:read`, `automations:read|write`,
`brands:read|write`, `custom_objects:read|write`, `deletion_schedules:read|write`, `dynamic_content:read|write`,
`groups:read|write`, `hc:read|write`, `macros:read|write`, `organizations:read|write`, `requests:read|write`,
`satisfaction_ratings:read|write`, `security:read`, `sla_policies:read|write`, `targets:read|write`,
`themes:read|write`, `ticket_attachments:read|write`, `ticket_views:read|write`, `tickets:read|write`,
`triggers:read|write`, `users:read|write`, `web_widget:write`, `webhooks:read|write`, `zis:read|write`.

**Product fact — as of 2026-09-20, Unified.to's Zendesk connector requests, depending on which objects and
permissions a workspace enables:** `read`, `users:read`, `users:write`, `tickets:read`, `tickets:write`, and
`hc:read`. Ticket and note reads pair `tickets:read` with `users:read`; writes add `tickets:write`; help-centre
pages and spaces use `hc:read`; the broad `read` scope backs the group and messaging objects. Confirm the current
set with the connector's owner before you submit anything — a global-client request freezes the allowed-scopes list,
and a scope you did not ask for cannot be added without a support ticket.

Two failure modes that look like Zendesk being broken:

- **`400 Bad Request` / `invalid_scope`** — the client's allowed-scopes list does not include what you asked for.
  Fixed on the client, not in the request. For a global client that means Zendesk.
- **`403 Forbidden` on a call that authorized fine** — the token's scopes are narrower than the endpoint needs
  (Zendesk's example: a `tickets:read` token cannot create or update tickets). Scopes cannot be changed on an issued
  token; a new token must be minted. And scopes never exceed what the *authorizing user's* role allows — an
  end-user's token succeeds on `/users/me` and fails on tickets, views and ticket fields regardless of scope.

Ask for the narrow set. `read write` on everything is the kind of thing customer security teams and Marketplace
review both push back on.

## 7. Capture the credentials

Capture and hand over:

- **Unique identifier** (the OAuth `client_id`) and **secret** (`client_secret`)
- The owning subdomain, and whether the client is local or global (and, if global, the request/ticket reference)
- The per-subdomain endpoints: `/oauth/authorizations/new`, `/oauth/tokens`, `/api/v2` (§3)
- The exact scope strings and the client `kind`

**The secret is returned in full only at creation.** It cannot be re-read afterwards — only regenerated. And for a
global client, Zendesk's instruction is blunt: note the secret and identifier before you request, because you lose
the administration page once the local client is converted. Record both, in a secret store, before clicking submit.

Regenerating the secret invalidates the old one. Issued access tokens keep working until they expire, but every
token exchange and every refresh fails until the new secret is deployed — and with 30-minute access tokens (§8),
"until they expire" is half an hour. Never rotate without explicit go-ahead and a cutover plan.

Report the secret once so the user can paste it into their secret store, say plainly that it is now in the
transcript and can be regenerated, then move on.

## 8. Tokens, refresh, and rate limits

**Authorization header.** `Authorization: Bearer {access_token}`. Sending an OAuth token with `Basic`, or in the
API-token form, returns 401 — Zendesk lists "a valid access token sent with the wrong scheme" as a top cause.

**The token exchange takes a JSON body, not form encoding.** Zendesk's documented request is a `POST` to
`https://{subdomain}.zendesk.com/oauth/tokens` with `Content-Type: application/json` carrying `grant_type`, `code`,
`client_id`, `client_secret` and `redirect_uri`. A client that form-encodes it because every other provider does
will fail here. The same endpoint and JSON body serve `grant_type: refresh_token`. The authorization code is valid
for about 120 seconds.

**Expiry.** For a client created today, access tokens default to 30 minutes and refresh tokens to 30 days
(§ Platform state for the exact bounds and the legacy-client rule). Establish two things separately, because they
are different failures:

1. **Does the client implement the refresh grant at all?** Without it, a connector built against pre-2026 Zendesk
   behaviour — where tokens simply did not expire — dies 30 minutes after each customer connects.
2. **Does it store the values Zendesk returns?** The response carries `access_token`, `refresh_token`, `expires_in`,
   `refresh_token_expires_in`, `scope` and `token_type`. A refresh token that is never exercised within its window
   expires too, and the customer must re-authorize.

**As of 2026-09-20, Unified.to's Zendesk connector does implement the refresh grant** (it re-posts client
credentials with the refresh token), collects the customer's subdomain and substitutes it into the authorize, token
and API hosts, posts the token request as JSON, and sends the scope list on the exchange as well as on authorize. It
also has shared platform-managed credentials configured for Zendesk, so a workspace may be connecting through those
rather than through a client you are about to create — check with the connector's owner which applies before
registering anything, and before assuming a new client is even needed.

**OAuth tokens vs API tokens.** API tokens are a per-account password (up to 256 active, never expiring, usable to
impersonate anyone in the account including admins) sent as `Basic` with `{email}/token:{api_token}`. They are
deprecated on the timeline in **Platform state**, and third-party integrations are not permitted to use a customer's
API credentials at all. If anyone proposes "just have the customer paste an API token", that is the answer: not
allowed, and dead by 30 April 2027.

**Rate limits are the customer's, not yours.** They apply per Zendesk account and scale with the customer's plan —
roughly 200/min on Team, 400/min on Growth and Professional, 700/min on Enterprise, 2,500/min on Enterprise Plus or
with the High Volume API add-on; legacy Essential is 10/min. Some endpoints are tighter (incremental exports
10/min; ticket updates 30 per 10 minutes per user per ticket). Over the limit returns **429** with a **`Retry-After`**
header in seconds — honour it. A customer on a small plan will rate-limit your connector no matter how the client is
registered, and every other integration on their account shares the same budget.

## 9. Marketplace listing — a separate track

The global OAuth client and a Marketplace listing are related but not the same thing, and conflating them wastes a
cycle. The global client is requested through the Marketplace portal (§3) and can be initiated without a published
listing. A listing is its own submission with its own review.

If a listing is in scope, the client must be **claimed** in the developer portal (identifier + first 6 characters of
the secret) before it can be associated with the app under **Details → Compliance**. Listing questionnaires that ask
for security, privacy, data-residency, support-SLA or commercial commitments are business decisions — collect them
from the user, do not compose them (see **Stop and ask**).

## 10. Verify end-to-end

Authorizing on the account that owns a local client proves nothing about multi-tenancy — that is the one subdomain
where it is guaranteed to work. Test the path a customer takes:

1. Authorize from a **second, unrelated subdomain** (a sandbox or a separate trial) through your platform's real
   connect flow, with the subdomain supplied the way a customer supplies it.
2. Confirm the consent screen shows the name, logo and description you registered, and the scopes you expect.
3. Confirm the token response carries a **`refresh_token`**, an **`expires_in`**, and the **`scope`** you asked for.
4. **Wait out the access token** (or force it) and exercise the refresh grant, then make a read call with the new
   token. This is the check that catches a connector built for never-expiring tokens.
5. Make one read call per object the connector supports, against the customer's `/api/v2` host, to shake out scopes
   that are narrower than the endpoints need.

| Symptom | Cause |
| --- | --- |
| Works on your subdomain, fails on every customer's | Local client, not global — the client does not exist on their instance (§3) |
| Authorize page errors or shows no consent screen | Wrong subdomain in the authorize host, or wrong `client_id` for that instance (§3) |
| Redirect rejected, or the exchange fails after a good authorize | `redirect_uri` not registered exactly, or not identical between authorize and exchange (§5) |
| `400 Bad Request` / `invalid_scope` | Requested scope outside the client's allowed-scopes list; for a global client, Zendesk sets it (§6) |
| Token exchange rejects a well-formed request | Body form-encoded instead of JSON, or the 120-second code window elapsed (§8) |
| Everything works for ~30 minutes, then 401s | Access token expired and the client does not refresh (§8, Platform state) |
| 401 on every call despite a fresh token | Wrong auth scheme — must be `Authorization: Bearer …` (§8) |
| 403 on writes, reads fine | Token has `…:read` but not `…:write`, or the authorizing user's role forbids it (§6) |
| 403 on tickets/views for one customer only | An end user authorized, not an agent or admin (§6) |
| Intermittent 429s | The customer's account-level plan limit, shared with their other integrations (§8) |
| Can no longer edit name, logo or redirect URLs | The client was converted to global; edits go through Zendesk (§3) |

## 11. Hand off — never commit the secret

- **Do not** write the client secret into source control, a test, a fixture, a committed `.env`, a ticket, a PR body
  or a chat channel. Values go to the user, for their secret store or console.
- If a code change is needed (a redirect host, a scope, refresh support), keep it secret-free and say what the human
  must set out of band.
- Close with: client name and unique identifier; local or global, and the owning subdomain; where the secret was
  delivered; the per-subdomain authorize, token and API URL patterns; the exact scope strings; client `kind`; the
  token-expiry and refresh situation and who owns any remaining work; the global-client request reference and what
  is still pending; and anything left for the user to do.

## Stop and ask

Hand back to a human rather than guessing when: the choice between a local and a global client has not been made by
someone who owns the product decision (§3); the connector does not implement the refresh grant (report it — do not
register and hope); a global-client request needs a `d3v-` account that does not exist yet, or a production-final
identifier nobody has approved; converting an existing local client to global would re-authorize live customers; a
scope outside the confirmed set is being proposed, especially `impersonate` or blanket `write`; a Marketplace or
compliance form asks for security, privacy, legal, data-residency or volume claims; someone proposes collecting
customers' API tokens or their own client secrets; or Admin Center and the Marketplace portal do not match the
**Platform state** section above.

## References

- Creating and using OAuth access tokens with the API — https://developer.zendesk.com/documentation/ticketing/working-with-oauth/creating-and-using-oauth-tokens-with-the-api/
- Creating and using OAuth access tokens (API basics) — https://developer.zendesk.com/documentation/api-basics/authentication/creating-and-using-oauth-tokens-with-the-api/
- Using OAuth authentication with your application (Admin Center walkthrough) — https://support.zendesk.com/hc/en-us/articles/4408845965210-Using-OAuth-authentication-with-your-application
- Managing OAuth token access to the API — https://support.zendesk.com/hc/en-us/articles/8889508417946-Managing-OAuth-token-access-to-the-API
- Set up a global OAuth client — https://developer.zendesk.com/documentation/marketplace/building-a-marketplace-app/set-up-a-global-oauth-client/
- Managing global OAuth clients and app associations — https://developer.zendesk.com/documentation/apps/app-developer-guide/managing-global-oauth-clients-and-app-associations/
- Global OAuth Clients API reference — https://developer.zendesk.com/api-reference/ticketing/oauth/global_clients/
- OAuth Clients API reference — https://developer.zendesk.com/api-reference/ticketing/oauth/oauth_clients/
- OAuth Tokens for Grant Types (full scope list, expiry bounds) — https://developer.zendesk.com/api-reference/ticketing/oauth/grant_type_tokens/
- OAuth Tokens API reference — https://developer.zendesk.com/api-reference/ticketing/oauth/oauth_tokens/
- Using OAuth to authenticate Zendesk API requests in a web app — https://developer.zendesk.com/documentation/authentication/using-oauth-to-authenticate-zendesk-api-requests-in-a-web-app/
- Working with OAuth refresh tokens — https://developer.zendesk.com/documentation/api-basics/authentication/refresh-token/
- Migrating from API tokens to OAuth access tokens — https://developer.zendesk.com/documentation/authentication/oauth-migration/
- Security and authentication — https://developer.zendesk.com/api-reference/introduction/security-and-auth/
- Rate limits — https://developer.zendesk.com/api-reference/introduction/rate-limits/
- Getting a trial or sponsored account for development — https://developer.zendesk.com/documentation/api-basics/getting-started/getting-a-trial-or-sponsored-account-for-development/
- Troubleshooting 401 and 403 errors — https://support.zendesk.com/hc/en-us/articles/10306782115610-Troubleshooting-401-and-403-Errors-on-the-Zendesk-Developer-Platform
- Making API requests on behalf of end users (impersonation) — https://developer.zendesk.com/documentation/ticketing/managing-tickets/making-api-requests-on-behalf-of-end-users/
- About Zendesk sandbox environments — https://support.zendesk.com/hc/en-us/articles/6150628316058-About-Zendesk-sandbox-environments
- Managing external OAuth clients (the *other* Admin Center page — not this one) — https://support.zendesk.com/hc/en-us/articles/9447118302362-Managing-external-OAuth-clients
- Zendesk Marketplace developer portal — https://apps.zendesk.com
- Zendesk Marketplace docs — https://developer.zendesk.com/documentation/marketplace/
