The decision table
| Question | API token | OAuth | |---|---|---| | One internal company? | Often simplest | Useful if user-level consent matters | | Many customer companies? | Poor fit | Designed for installations | | Per-user authorization? | Not the main model | Natural fit | | Token rotation and revocation | Operationally manual | Refresh/access-token lifecycle | | Fast prototype | Fast | More setup | | Production SaaS | Risky as one shared secret | Usually the right boundary |
The word private can be misleading. “Private” may mean an internal integration used by one company, or a private app that is not publicly marketed but still serves several installations. Decide based on ownership and authorization boundaries, not the label.
When an API token is reasonable
An API token can be practical for a script owned by one Pipedrive company: a nightly export, a small internal dashboard, or a controlled back-office automation. The service should store it in a secret manager or protected environment variable, restrict who can deploy it, and avoid placing it in client-side JavaScript.
Create a dedicated owner or service account where the account model permits it. That makes offboarding safer than binding production to a departing employee. Write down the token owner, workflows using it, last rotation date, and the expected recovery procedure.
Use separate tokens or credentials for staging and production when possible. A staging bug should not be able to mutate live deals.
When OAuth is the better boundary
OAuth is appropriate when your application must connect to other companies, support a user authorization screen, or maintain separate grants. Each installation can have its own tokens and lifecycle. A customer can disconnect the app without asking you to replace one global secret used by every tenant.
The authorization-code flow also gives your system a place to explain scopes and consent. Store the resulting tokens server-side, associate them with the correct Pipedrive company, and encrypt them at rest. Do not assume that an access token identifies the tenant safely; validate the returned company or user context and keep it with the connection record.
Header and transport hygiene
For v2 requests, follow the current documentation’s authentication guidance and use HTTPS. Keep authentication out of URLs where possible because URLs can appear in proxy logs and analytics. Redact Authorization headers from application logs and error traces.
An internal request should have a shape like:
Do not paste a live token into a support ticket, code sample, browser console recording, or workflow export. If exposure is suspected, revoke or rotate it promptly and review logs for use.
PATCH https://api.pipedrive.com/api/v2/deals/123
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
Scope and permission testing
An authenticated request can still fail because the token lacks access to the entity or action. Test reads, creates, updates, deletes, and field metadata separately. Record the minimum scope each workflow needs. A read-only reporting job should not share a credential capable of deleting records.
Build an authorization test matrix:
The expected user-facing behavior differs. A revoked grant should prompt reconnection; a missing permission should explain the admin action; a 429 should pause work; a malformed request should be fixed in code.
- Valid credential and permitted endpoint.
- Valid credential with a missing permission.
- Revoked credential.
- Expired access token where OAuth is used.
- Wrong tenant or connection mapping.
- Rate-limited credential.
Rotation and incident response
Treat credentials as replaceable. For API-token integrations, support a configuration change without code deployment and test a new token before revoking the old one. For OAuth, store refresh-token metadata and handle a failed refresh as a connection state that requires reauthorization.
Keep audit records without retaining secrets: credential ID, tenant, created time, rotated time, last successful use, and last failure category. During an incident, disable the affected connection, inspect unusual request volume, rotate or revoke, and replay only idempotent work.
Migration from a token to OAuth
Move in stages. First create a connection table keyed by company and integration installation. Then make the API client accept a credential provider instead of reading one global environment variable. Add an OAuth callback and secure token storage. Migrate one internal tenant, compare records, and retain a carefully controlled fallback while you verify the lifecycle.
Choose by blast radius
Ask what happens if the credential leaks, expires, or is revoked at 4:00 PM on a business day. With one internal token, the answer may be “one company’s automation stops.” With a shared token used for several customers, the answer may include cross-tenant data exposure and a difficult emergency rotation. OAuth does not automatically make an integration secure, but separate grants make containment and reconnection more precise.
Also consider support. An internal administrator can rotate a token through a documented runbook. A customer-facing product needs a connection status page, a reconnect button, clear scope messaging, and a way to identify which installation failed. That operational surface is part of the authentication design, not optional polish added later.
Before choosing, write a one-page threat model: where secrets live, who can read them, how they are rotated, how a connection is revoked, and what audit evidence remains. If the answers differ by tenant, your client should carry tenant context explicitly from the start.
Do not mix credentials silently. A request must carry an explicit tenant context so a background job cannot accidentally use the last token loaded in memory. Add tests that run two tenants concurrently and assert that each request receives the correct Authorization value.
The trap: a token stored in a server environment is safer than a token in front-end code, but it is still one shared blast radius. Security improves when the credential boundary matches the business boundary.
A two-tenant isolation test
Run two jobs at the same time with different company contexts and assert that every outgoing request receives the intended credential. Then revoke one connection and confirm the other continues working. This test exposes the common “last token loaded in memory” defect that a single-tenant smoke test cannot see. Keep the assertion in CI or the integration’s release checklist.
Where these facts come from