---
name: pipedrive-oauth-app
description: Creates a Pipedrive developer sandbox account and registers an app in Developer Hub to obtain OAuth2 client ID and client secret — with the single-callback-URL constraint, the public-vs-private app decision, app-level scope selection, the per-company api_domain, token and refresh behaviour, Marketplace review and a safe credential handoff. Use when asked to get Pipedrive OAuth credentials, create a Pipedrive app or developer sandbox, pick Pipedrive scopes, refresh a Pipedrive client secret, or fix a Pipedrive install error like "Invalid grant", "redirect_uri is invalid" or a 403 on an endpoint the app should be able to reach. For any other vendor's developer portal, use that vendor's skill instead.
---

# Pipedrive OAuth2 App Registration

Get a working Pipedrive OAuth2 client — a developer sandbox account, an app in Developer Hub, the callback URL, the
scope set, client ID and secret — for a platform that connects many customers' Pipedrive accounts.

The form itself is two required fields. Four things around it are expensive to get wrong. **One callback URL per
app** — Pipedrive allows exactly one, so a platform with several regional callback hosts must decide up front
between one app per region and one shared callback (§4). **That same URL also receives uninstall notifications**,
as a `DELETE` with HTTP Basic auth, so a redirect handler that only speaks `GET` silently loses uninstall events
(§4). **Scopes live on the app, not in the authorize URL** — a `scope` parameter on the authorize request does
nothing, the user accepts or denies the whole set, and on an approved public app changing the set sends you back
through review (§5). And **there is no fixed API host**: every company answers on its own domain, handed to you in
the token response (§6).

## Inputs to collect before you start

Ask in one batch. Never invent.

| Input | Notes |
| --- | --- |
| **App name** | Shown on the consent dialog and in the customer's installed-apps list |
| **Account / registration email** | For the developer sandbox that will own the app (§2) |
| **Public or private app?** | Irreversible once chosen (§3) |
| **Callback URL** | Exactly one per app — so this decision comes with §4's regional question |
| **Which objects the connector reads and writes** | Decides the scope set (§5) |
| **App icon, short summary, full description, 3–5 listing images** | Public app only, checked at review (§7) |
| **Website, pricing page, Terms, Privacy Policy, support URL and email** | Public app only, all required at review (§7) |
| **Priority of a Marketplace listing** | A private app serves customers today; a public listing takes weeks (§3, §7) |

## Quick Start

1. Confirm a **new app** is actually needed — the client ID of an existing app can never be changed (§1).
2. Request a **developer sandbox account**; it is the only way to see Developer Hub (§2).
3. **Create an app** and pick public or private — the type cannot be changed later (§3).
4. Fill **App name** and the single **Callback URL**; settle the regional question first (§4).
5. Save; you land on **OAuth & access scopes**, where the scopes and the credentials live (§5, §6).
6. Select only the scopes the connector's endpoints actually need, including `activities:*` if it touches
   activities and `admin` if it manages pipelines, stages or app webhooks (§5).
7. Set the **Installation URL** so your own side starts the flow and can send a `state` value (§4).
8. Capture client ID and secret; wire the exchange as a form-encoded POST with **HTTP Basic** credentials, and store
   the returned `api_domain` per connection (§6).
9. **Install & test** from the sandbox, verify a real round trip and a refresh (§8), then hand the credentials over —
   never commit them (§9).

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

- **Developer Hub (formerly Marketplace Manager) is only reachable from a developer sandbox account.** It sits at
  `https://app.pipedrive.com/developer-hub`, or *Settings → (sandbox company name) → Developer Hub*. A normal
  Pipedrive company account does not show it. The sandbox is requested through a form at
  `https://developers.pipedrive.com/`.
- **One callback URL per app**, stated twice in Pipedrive's own registration docs: *"we allow only one callback URL
  per app"*. There is no multi-redirect-URI field, and this has been a standing developer request for years.
- **App type is public or private, and it cannot be changed after creation.** Private apps skip review entirely and
  install into **any** Pipedrive company through a direct unlisted link; public apps must pass Marketplace review.
  Pipedrive's docs carry no install cap for either.
- **Public app review currently runs up to 21 business days** — a banner on the approval and update pages, last
  edited 2025-11-12. Editing a *critical* field on an approved app (callback URL, scopes, installation URL, app
  extensions) sends the change through review again.
- **Token exchange authenticates with HTTP Basic**, not body credentials: *"your request has to be authenticated via
  HTTP Basic Auth"*, with body credentials documented only as a discouraged fallback. Content type must be
  `application/x-www-form-urlencoded`, and the authorization code expires in **5 minutes**.
- **Access token 60 minutes; refresh token expires after 60 days of non-use.** A refresh returns *the same* refresh
  token with its window reset to 60 days — Pipedrive does not rotate it. Let it lapse and the customer reinstalls.
- **There is no single API host.** The token response carries `api_domain`, the company's own base URL
  (`https://{companydomain}.pipedrive.com`), and customers can change their company domain from Pipedrive's settings.
- **PKCE is not part of the documented flow.** The authorize endpoint takes `client_id`, `redirect_uri` and an
  optional `state` — nothing else. `state` is self-serve, documented, and strongly recommended.
- **Rate limiting is a token/cost budget, not a request count.** A daily budget of 30,000 × plan multiplier × seats,
  plus a 2-second burst window; v2 endpoints cost roughly half their v1 equivalents.
- **API v1 is partly sunset.** A set of v1 endpoints (activities, deals, persons, organizations, products,
  pipelines, stages, search) was deprecated on 2025-04-14 with availability guaranteed only until **2025-12-31** —
  a date now in the past. Other v1 endpoints (files, webhooks, filters, the field endpoints) were not in that list
  and still exist. Webhooks v2 has been the default for new webhooks since **2025-03-17**, with v1 webhooks slated
  for deprecation during 2026.

If Developer Hub does not look like this, stop and report what you actually see rather than clicking on.

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

**A `client_id` can never be changed or refreshed** — Pipedrive's own wording is that the only way to get a new one
is to create a new app, and every existing customer install is bound to the old one. A new app means every customer
reinstalls.

Reuse the existing app for: adding or removing a scope, correcting the callback URL, refreshing a leaked secret,
adding an installation URL, or diagnosing a failing install. On an **approved public app** each of those except the
secret is a *critical field*: saving it creates a private copy with pending changes, that copy goes through review,
and the change merges into the live app only on approval. Plan for the wait; do not start one casually.

Register a **new** app only when the user explicitly wants one: a replacement for a compromised app, a separate app
per callback host (§4), a deliberate public listing alongside an existing private app, or a first app. Say which
path you are taking before you touch anything.

## 2. Account: the developer sandbox is the door

- **Request a developer sandbox** at `https://developers.pipedrive.com/` — a short form asking for an email address
  and first name, and submitting it accepts Pipedrive's Terms of Service, Developer Agreement and Privacy Notice.
  The sandbox behaves as a regular Pipedrive company account, its data is completely separate from any production
  account, and it is what unlocks Developer Hub.
- **Limits worth knowing:** 5 user seats by default; the sandbox is **deleted** if no app is created within 45 days,
  or if no public app is published / no private app made live within six months of signup. Signing back in and
  creating or publishing an app prevents that.
- **Developer Hub** then lives at `https://app.pipedrive.com/developer-hub` (sign-in required) or under
  *Settings → (sandbox company name) → Developer Hub*.
- Apps are owned by that sandbox company. Use a shared, team-controlled account — not a person who might leave —
  and record who owns it.

Hand control back to the user for anything only they can do: the sandbox request form, signup email verification,
2FA, and accepting the **Pipedrive Developer Partner Agreement** (required before submitting a public app). Do not
retry a blocked step in a loop.

Before that agreement is accepted, skim it for anything a founder would want flagged — exclusivity, revenue share,
data-use commitments, restrictions on resale. Boilerplate needs no commentary; anything unusual gets raised first.

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

## 3. Create the app — public or private, and the choice is final

In Developer Hub: **Create an app** → *Create public app* or *Create private app*. Pipedrive's own warning: *"Do
pick your app type carefully, as it cannot be changed later."*

| | **Private app** | **Public app** |
| --- | --- | --- |
| Who can install | Any Pipedrive company, via a direct unlisted installation link | Anyone, from the Marketplace listing |
| Review | None | Mandatory approval before anyone outside your own company can install |
| Statuses | Draft (your company only) → Live | Draft → In review → Unpublished → Published |
| Listing assets | Not required | Icon, 3–5 images, descriptions, pricing page, legal and support URLs |
| Reversibility | Live cannot go back to draft | — |

For a multi-tenant connector that needs to work **now**, a private app is the honest answer: no cap is documented,
and the unlisted link installs into any company. A public listing is a distribution decision, not a technical
prerequisite — raise it as such rather than blocking the integration on review.

Two required fields save a draft: **App name** and **Callback URL**. A non-functioning callback URL is accepted at
draft time and must be replaced before review — and for a private app, before **Change to live**, which validates
it. Live private apps cannot be reverted to draft, and every later save goes live immediately.

Pipedrive also publishes a `create-pipedrive-app` CLI that scaffolds the OAuth flow, including an HMAC-signed
`state`, token exchange and refresh. Useful as a reference implementation; it does not register the app for you.

## 4. The callback URL — one per app, and it has two jobs

This platform serves one callback path per data center:

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

**Pipedrive accepts exactly one of these per app.** That is the decision this section exists for, and it is not
yours to make silently. The options:

1. **One app per callback host** — four apps, four client ID/secret pairs, each region's connections bound to its
   own app. Every later scope change has to be repeated four times, and a public listing would have to be argued
   four times over.
2. **One app, one callback host** — the region that host serves is the only one that can complete an install.
3. **One app whose single callback fans out** — only if the platform already has, or will add, a dispatcher that
   forwards to the right region. That is a platform change, not a portal setting.

Confirm the current list and the intended option with the platform owner before you type anything into the form.

**The same URL receives uninstall callbacks.** When a user uninstalls, Pipedrive's OAuth server sends a `DELETE`
request in JSON to that URL with `client_id`, `company_id`, `user_id` and `timestamp`, authenticated with HTTP Basic
using `client_id:client_secret` so you can verify it. Notes that follow from that: the endpoint must accept `DELETE`
as well as the `GET` redirect; it is a background request, so `localhost` and `127.0.0.1` will never work; and
Pipedrive does not read your response body or status.

Other rules:

- `redirect_uri` on the authorize request must match the registered value, or the install fails before the user
  gets anywhere useful (`Invalid request: redirect_uri is invalid`).
- **Installation URL** (on the *OAuth & access scopes* tab) is a separate, optional field: it is where Pipedrive
  sends a user who clicks "Proceed to install" on a Marketplace listing, or who follows a private app's install
  link. Set it to your own connect entry point when you need to start authorization from your side — which is also
  the documented way to get a `state` value into the flow. Without it, Pipedrive starts the flow itself and your
  platform never gets to set `state`.
- Changing the callback URL on an **approved public app** is a critical-field edit: pending copy, review, merge.

## 5. Scopes — chosen on the app, accepted all-or-nothing

**Scopes are not negotiated in the authorize URL.** The documented authorize parameters are `client_id`,
`redirect_uri` and `state`; a `scope` (or `scopes`) query parameter is not part of the flow, and the `scope` field in
the token response is described as *"List of scopes selected in the app's settings"*. Whatever a client sends is
irrelevant — the app's configuration is the contract. At the consent dialog the user can *"either accept or deny all
scopes"*, so every extra scope is an extra reason for someone's admin to say no.

Shape of the catalogue:

- **`base` is always on** for every app: `GET /users/me`, `/userConnections`, `/userSettings`. That is how a
  connector identifies the account and reads the company domain without asking for anything else.
- **`x:full` includes `x:read`.** `deals:full` grants read access to deals; requesting both is noise.
- **Field scopes only come in `full`**: `deal-fields:full`, `contact-fields:full` (persons *and* organizations),
  `product-fields:full`, `project-fields:full`. There is no read-only variant, so a connector that merely lists
  custom-field definitions still has to ask for write-capable field access. Expect to justify that at review.
- **`admin` is its own thing, not a superset.** It covers creating and editing pipelines and stages, activity types,
  users and permissions, and app webhooks. It also *"requires the user who is installing an app to have admin rights
  within the company"* — and the Marketplace does not stop a non-admin from installing anyway, so the connector has
  to survive a non-admin install. `GET /users/{id}/permissions` is how you find out which one you have.
- **`deals:read` explicitly excludes activities.** Pipedrive's own wording: *"Does not include access to activities
  (except the last and next activity related to a deal)."* Anything that lists, creates or updates activities needs
  `activities:read` / `activities:full`, and no amount of deal or contact scope substitutes for it. This is the
  single most common mis-mapping on a Pipedrive connector.
- **Search is separate**: `search:read` covers `GET /deals/search`, `/persons/search`, `/organizations/search`,
  `/leads/search`, `/products/search`, `/projects/search`.
- **Webhooks**: `webhooks:read` and `webhooks:full` exist as their own scopes; `admin` also carries `GET/POST
  /webhooks` and `DELETE /webhooks/{id}`. Pipedrive's app-webhooks guide still says the app "needs to have the
  admin scope", which predates the dedicated webhook scopes — if webhook creation 403s under `webhooks:full` alone,
  that inconsistency is the first thing to test, not a bug in your code.

A CRM connector's usual set:

| Scope | Why |
| --- | --- |
| `base` | Always granted; identifies the user and yields the company domain |
| `deals:read` / `deals:full` | Deals, their fields, files, notes, filters, pipelines and stages (read) |
| `contacts:read` / `contacts:full` | Persons and organizations and their related fields, notes, files |
| `activities:read` / `activities:full` | Activities/events — **not** covered by deal or contact scopes |
| `leads:read` / `leads:full` | Leads and lead labels |
| `search:read` | Any `/search` endpoint used to serve a query filter |
| `deal-fields:full`, `contact-fields:full` | Custom-field definitions and options |
| `users:read` | Users, their permissions and roles — for owner/assignee mapping |
| `admin` | Creating or editing pipelines and stages; app webhooks |
| `webhooks:full` | App-specific webhooks, if sync uses them |

Others exist (`mail:*`, `products:*`, `projects:*`, `goals:*`, `recents:read`, `phone-integration`, `video-calls`,
`messengers-integration`). Read the scopes reference rather than guessing a name.

> **As of 2026-09-20, this platform's Pipedrive connector** covers companies, contacts, deals, leads, pipelines and
> stages, events/activities, files, custom-field metadata and a taxonomy object, plus webhooks. It sends the
> authorize request with `client_id`, `redirect_uri` and `state` only — no PKCE — and exchanges the code with a
> form-encoded POST authenticated by **HTTP Basic**, taking the per-company host from the token response's
> `api_domain`. Its per-object scope map asks for `deals:read`/`deals:full`, `contacts:read`/`contacts:full`,
> `leads:read`/`leads:full`, `search:read`, `users:read`, `deal-fields:full`, `contact-fields:full`,
> `webhooks:full` and `admin` (for pipeline and stage writes), with `base` on the login flow. **It does not request
> `activities:read` or `activities:full`, although its events object reads and writes `/activities`** — so an app
> registered from that map alone will 403 on every event call. Add the activities scopes, and confirm the current
> map with the connector's owner before submitting. Its object calls are on API **v2** with a few endpoints still on
> v1 (files, webhooks, filters, some field reads); a dormant second-generation build of the same connector, derived
> from the v1 API description, is not wired into the live product. None of that changes registration: v1 and v2
> share one scope catalogue and one OAuth flow — v2 endpoints simply cost about half as many rate-limit tokens.

**Changing scopes later** on an approved public app: a private copy with pending changes is created, you edit
scopes there, the copy goes to review, and on approval you merge it into the live app. Pipedrive's docs do not state
what happens to already-installed users' tokens, and a token carries the scopes granted when it was issued — assume
existing customers keep the old grant until they reinstall, and prove it with a test install before promising either
behaviour.

## 6. Capture the credentials

From Developer Hub → your app → **OAuth & access scopes** → the *Client ID* section: **client ID** and **client
secret**, both re-readable there.

Record:

- **Client ID** and **client secret**, and whether they belong to a public or private app
- Authorize: `GET https://oauth.pipedrive.com/oauth/authorize`
- Token exchange and refresh: `POST https://oauth.pipedrive.com/oauth/token`
- Revoke: `POST https://oauth.pipedrive.com/oauth/revoke` (RFC 7009; also HTTP Basic)
- API base: **per company**, from `api_domain` in the token response — e.g. `https://acme.pipedrive.com`, with
  endpoints under `/api/v1/…` and `/api/v2/…`
- Identity endpoint: `GET /users/me`, which also returns `company_domain`
- The exact scope strings selected on the app

**Exchange mechanics, precisely as documented:**

- `POST https://oauth.pipedrive.com/oauth/token`, content type `application/x-www-form-urlencoded`.
- Credentials go in an **`Authorization: Basic base64(client_id:client_secret)`** header. Body credentials are
  described as a fallback "only when you cannot use HTTP Basic Auth" — if a client sends both, prefer Basic.
- Body: `grant_type=authorization_code`, `code`, `redirect_uri`. The code dies after **5 minutes**.
- Response: `access_token`, `token_type` (always `bearer`), `refresh_token`, `scope`, `expires_in`, **`api_domain`**.
- Pipedrive warns that access-token length grows over time and recommends storing at least `varchar(768)`.

**Token behaviour:**

- **Access token: 60 minutes.** Refresh, do not re-authorize.
- **Refresh: `grant_type=refresh_token` + `refresh_token`, again with Basic auth.** The response returns **the same
  refresh token**, with its expiry window extended by 60 days, plus a fresh `api_domain`. There is no rotation to
  handle — but there *is* an idle clock: a refresh token unused for **60 days** expires, and the customer must
  reinstall from scratch.
- **Revocation is asymmetric.** Revoking the `refresh_token` removes all OAuth data and marks the app uninstalled;
  revoking only the `access_token` leaves the install intact.
- **`api_domain` is per connection and can change.** Customers rename their company domain from Pipedrive's own
  settings. Persist `api_domain` from every token *and refresh* response and use it as the base for every call —
  never a hard-coded host, and never `api.pipedrive.com` for an OAuth token.
- **Migrating an existing API-token integration** is possible with the custom grant `exchange_api_token` (+
  `api_token`, Basic auth). Each API token can be exchanged **once**; the users are emailed that the integration is
  now an OAuth app and must confirm permissions. Delete the API token afterwards. Do not attempt this without an
  explicit plan from the user — there is no second chance per token.

**Refreshing the client secret** ("Refresh" under the Client ID section) does *not* invalidate existing user tokens,
but every exchange and refresh with the old value fails from that moment. Never refresh without explicit go-ahead
and a deployment plan. The client ID cannot be refreshed at all.

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 refreshed, then move on.

## 7. Distribution, review, and limits

**Authorization is per user, not per company.** Pipedrive states it directly: *"authorization is user-based, not
company-based"* — each user installs and consents for themselves, and the resulting token sees only what that user's
permission sets and visibility groups allow. A connection that mysteriously misses records is usually this, not a
scope. Admins can push an app to selected or all users, but each of those users still authorizes individually, and
**app-sharing modes have to be enabled by Pipedrive on request** (by writing to their marketplace developer contact).

**Public app review** is currently quoted at up to 21 business days. The checklist that decides it includes, among
much else: the app *"implements and primarily uses OAuth 2.0"* and *"does not collect, store, or unnecessarily use
the API token of a user"*; it refreshes the access token when the 60-minute lifetime expires; it requests only
necessary scopes; installation **and uninstallation** flows are polished and tested; it handles different user types
and permission sets; it respects rate limits; it uses **v2 webhooks** where possible; and the listing carries a
unique name, a distinct icon, 3–5 annotated images, a separate pricing page, and support and legal URLs.

**Stop and ask** before answering anything you would have to invent: security or compliance questionnaires,
retention periods, subprocessors, customer counts, volume projections, pricing, demo videos, or a named responsible
contact. A plausible guess about compliance is worse than an unanswered question and expensive to retract.

**Rate limits** (worth telling the platform owner about before launch, not after):

| Limit | Value |
| --- | --- |
| Daily budget per company | 30,000 tokens × plan multiplier (Lite 1×, Growth 2×, Premium 5×, Ultimate 7×) × seats |
| Indicative costs | ~2 tokens get-one, ~10 update-one, ~20 list, ~40 search — v2 costs about half of v1 |
| Burst, OAuth apps | 80 / 160 / 400 / 480 requests per 2-second rolling window by plan |
| Burst, API-token access | 20 / 40 / 100 / 120 requests per 2 seconds by plan |
| Search API | 10 requests per 2 seconds, all plans |
| Headers | `x-ratelimit-limit`, `x-ratelimit-remaining`, `x-ratelimit-reset` |
| Over budget | `429`; sustained abusive `api_token` traffic can be cut off with a `403` at the edge |

The budget is **per customer company and shared with everything else they run**, so a full resync can starve the
customer's other integrations. Customers are notified at 75% and 100% of their daily budget — and they will ask.

**App-specific webhooks**, if the connector uses them: created via the API (not visible in Pipedrive's UI), a
maximum of **40 per app user**, deleted automatically when the user uninstalls or the app leaves the Marketplace.
Ten consecutive failed first deliveries ban a webhook for 30 minutes; **three consecutive days with no successful
delivery deletes it**. Webhooks v2 is the default for new subscriptions.

## 8. Verify end-to-end

A registration that half-worked surfaces later as a customer who cannot connect. Prove it:

1. Use **Install & test** in Developer Hub to install the draft app into the sandbox company.
2. Run a real connect through your platform's own flow — not a hand-built URL — and complete the callback.
3. Confirm the connection stored **`api_domain`** and that subsequent calls go to that host, not a default one.
4. Force a **refresh** and confirm the same refresh token still works and the access token changes.
5. Call one endpoint per object the connector maps, including activities, search and a custom-field read — that is
   where a missing scope shows up as a flat `403`.
6. If webhooks are in play, create one, deliver one, and delete it.
7. Install once as a **non-admin** user if the app requests `admin`, and check the failure is handled rather than
   fatal.
8. Trigger an **uninstall** and confirm your callback URL received the `DELETE` and verified its Basic auth header.

| Symptom | Cause |
| --- | --- |
| `Invalid request: redirect_uri is invalid` | The callback sent does not match the one registered — and only one can be registered (§4) |
| `Invalid client: client is invalid` | Wrong client ID/secret, or the secret was refreshed and not redeployed (§6) |
| `Invalid client: cannot retrieve client credentials` | Credentials sent neither as Basic auth nor in the body (§6) |
| `Invalid grant: authorization_code has expired` | More than 5 minutes between callback and exchange (§6) |
| `Invalid grant: authorization_code is invalid` | The code was already exchanged once |
| `Invalid grant: refresh_token is invalid` | Token revoked, user uninstalled, or the 60-day idle window lapsed (§6) |
| `content must be application/x-www-form-urlencoded` | Exchange posted as JSON (§6) |
| 403 on activities only | `activities:read` / `activities:full` not selected on the app (§5) |
| 403 on pipelines, stages, users or webhook creation | `admin` not selected, or the installing user is not an admin (§5) |
| 404s or connection errors against a valid-looking host | Calling a fixed host instead of the connection's `api_domain`, or the customer renamed their company domain (§6) |
| Works for one user, empty for another in the same company | Per-user authorization plus permission sets / visibility groups (§7) |
| `429`, or `403` from the edge, at modest request rates | Daily token budget exhausted, or the 2-second burst window (§7) |
| Uninstall never observed | The callback URL does not handle `DELETE`, or points at a local/unreachable host (§4) |

## 9. 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 the secret store or console.
- If a code change is needed (a callback host, a scope list), keep it secret-free and say plainly what the human must
  set out of band.
- Close with: app name, type (public/private) and the sandbox account that owns it; client ID; where the secret was
  delivered; the authorize, token and revoke URLs plus the fact that the API host is per connection; the exact scope
  strings selected and why; the callback URL registered and which regions it therefore serves; review or live status
  with dates; and anything left for the user to do.

## Stop and ask

Hand back to a human rather than guessing when: the single-callback-URL constraint forces a choice between one app
per region, one region only, or a platform-side dispatcher (§4); an approved public app would have to change a
critical field and go back through review; someone proposes refreshing the client secret, or exchanging API tokens
with the one-shot `exchange_api_token` grant; the app needs `admin` and nobody has confirmed customers will install
as admins; a review or agreement asks for compliance, legal, pricing or volume claims; the sandbox form asks for
company details you were not given; or Developer Hub does not match the **Platform state** section above.

When the portal behaves in a way the docs did not describe, say what you found rather than picking the option that
lets you keep going.

## References

Official Pipedrive docs only; every URL below returned HTTP 200 on 2026-09-20. Developer Hub itself is at
`https://app.pipedrive.com/developer-hub` and requires sign-in to a developer sandbox account.

- Developer sandbox account — https://pipedrive.readme.io/docs/developer-sandbox-account
- Sandbox request form / developer portal — https://developers.pipedrive.com/
- Developer Hub — https://pipedrive.readme.io/docs/developer-hub
- Registering a public app — https://pipedrive.readme.io/docs/marketplace-registering-the-app
- Registering a private app — https://pipedrive.readme.io/docs/marketplace-registering-a-private-app
- Creating an app (public vs private) — https://pipedrive.readme.io/docs/marketplace-creating-a-proper-app
- Client ID and client secret — https://pipedrive.readme.io/docs/client-id-and-client-secret
- OAuth 2.0 overview — https://pipedrive.readme.io/docs/marketplace-oauth-api
- OAuth authorization (flow, Basic auth, token fields, refresh) — https://pipedrive.readme.io/docs/marketplace-oauth-authorization
- State parameter — https://pipedrive.readme.io/docs/marketplace-oauth-authorization-state-parameter
- Scopes and permission explanations — https://pipedrive.readme.io/docs/marketplace-scopes-and-permissions-explanations
- OAuth status codes — https://pipedrive.readme.io/docs/marketplace-oauth-and-api-proxy-status-codes
- App installation flows — https://pipedrive.readme.io/docs/app-installation-flows
- Handling user app uninstallation (and token revocation) — https://pipedrive.readme.io/docs/app-uninstallation
- App sharing: adding apps to multiple users — https://pipedrive.readme.io/docs/app-sharing-adding-apps-to-multiple-users
- App approval process and checklist — https://pipedrive.readme.io/docs/marketplace-app-approval-process
- Updating approved apps (critical vs non-critical fields) — https://pipedrive.readme.io/docs/marketplace-updating-the-existing-app
- Pipedrive Developer Partner Agreement — https://pipedrive.readme.io/docs/marketplace-vendor-agreement
- Migrating existing integration users (`exchange_api_token`) — https://pipedrive.readme.io/docs/marketplace-migrating-existing-integration-users
- Authentication overview — https://pipedrive.readme.io/docs/core-api-concepts-authentication
- Rate limiting (token budget) — https://pipedrive.readme.io/docs/core-api-concepts-rate-limiting
- How to get the company domain — https://pipedrive.readme.io/docs/how-to-get-the-company-domain
- Getting user data (`/users/me`) — https://pipedrive.readme.io/docs/marketplace-getting-user-data
- Webhooks for apps — https://pipedrive.readme.io/docs/webhooks-for-apps
- Guide for Webhooks v2 — https://pipedrive.readme.io/docs/guide-for-webhooks-v2
- API v2 overview — https://pipedrive.readme.io/docs/pipedrive-api-v2
- API v2 migration guide — https://pipedrive.readme.io/docs/pipedrive-api-v2-migration-guide
- Changelog: deprecation of selected API v1 endpoints — https://developers.pipedrive.com/changelog/post/deprecation-of-selected-api-v1-endpoints
- Changelog: Webhooks v2 becomes the default — https://developers.pipedrive.com/changelog/post/breaking-change-webhooks-v2-will-become-the-new-default-version
- create-pipedrive-app CLI — https://pipedrive.readme.io/docs/create-pipedrive-app-cli
- FAQ — https://pipedrive.readme.io/docs/faq
- Changing a company domain (support) — https://support.pipedrive.com/en/article/changing-a-company-domain-in-pipedrive
