Stitchflow
Drip logo

Drip User Management API Guide

API workflow

How to automate user lifecycle operations through APIs with caveats that matter in production.

UpdatedMar 11, 2026

Summary and recommendation

Drip exposes a REST API at https://api.getdrip.com/v2, authenticated via HTTP Basic Auth (API token as username, empty password) or OAuth 2.0 for third-party app flows. All resource URLs require the account_id as a path segment - omitting it returns a 404 with no further detail.

The API operates on a subscriber model, not an internal user/seat model; there is no SCIM endpoint and no IdP integration such as Okta or Entra is documented.

For teams building an identity graph, Drip subscriber records - keyed by email and enriched with custom_fields and tags - are the primary joinable entity across downstream systems.

Rate limits are enforced at 3,600 requests/hour per token with HTTP 429 on breach; headers X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset are returned on every response. The batch subscriber endpoint (POST /v2/{account_id}/subscribers/batches) accepts up to 1,000 records per call and counts as a single request - use it aggressively when syncing large lists.

Pagination uses offset-based page and per_page params with a maximum page size of 1,000.

API quick reference

Has user APIYes
Auth methodHTTP Basic Auth using API token as username, empty password; or Bearer token via OAuth 2.0 for third-party apps
Base URLOfficial docs
SCIM availableNo
SCIM plan requiredN/A

Authentication

Auth method: HTTP Basic Auth using API token as username, empty password; or Bearer token via OAuth 2.0 for third-party apps

Setup steps

  1. Log in to Drip and navigate to Settings > User Settings > API.
  2. Copy your personal API token.
  3. For Basic Auth: Base64-encode ':' and pass as Authorization: Basic .
  4. For OAuth 2.0 (third-party integrations): Register an OAuth application at developer.drip.com, obtain client_id and client_secret, redirect users through the authorization flow to obtain an access token.
  5. Include the account_id (found in Settings > General) in all resource URLs.

Required scopes

Scope Description Required for
read Read access to subscribers, tags, custom fields, and account data. GET operations on subscribers and account resources
write Create and update subscribers, apply tags, record events. POST/PUT operations on subscribers

User object / data model

Field Type Description On create On update Notes
email string Subscriber's email address. Primary identifier. required optional (used to look up record) Must be unique per account.
id string Drip-assigned unique subscriber ID. system-generated read-only Can be used as lookup key instead of email.
first_name string Subscriber's first name. optional optional
last_name string Subscriber's last name. optional optional
address1 string Street address line 1. optional optional
city string City. optional optional
state string State or region. optional optional
zip string Postal/ZIP code. optional optional
country string Country (ISO 3166-1 alpha-2 recommended). optional optional
phone string Phone number. optional optional
tags array[string] List of tag names applied to the subscriber. optional optional Tags are additive on update unless remove_tags is used.
remove_tags array[string] Tags to remove from the subscriber on update. n/a optional Only valid in update/upsert payloads.
custom_fields object Key-value map of custom field identifiers to values. optional optional Keys must match existing custom field identifiers in the account.
status string Subscription status: active, unsubscribed, or undeliverable. optional (defaults to active) optional Setting to unsubscribed opts the subscriber out globally.
time_zone string IANA time zone string (e.g., America/New_York). optional optional
ip_address string IP address at time of opt-in. optional optional
user_agent string Browser/user agent at time of opt-in. optional optional
initial_status string Forces subscriber status on creation (active or unsubscribed). optional n/a Useful for importing pre-existing unsubscribes.
created_at ISO 8601 datetime Timestamp when subscriber was created. system-generated read-only
updated_at ISO 8601 datetime Timestamp of last update. system-generated system-generated

Core endpoints

List subscribers

  • Method: GET
  • URL: https://api.getdrip.com/v2/{account_id}/subscribers
  • Watch out for: Returns up to 1,000 per page. Deleted/unsubscribed records are included unless filtered with status param.

Request example

GET /v2/9999999/subscribers?page=1&per_page=100
Authorization: Basic <base64(api_token:)>

Response example

{
  "subscribers": [{"id":"abc123","email":"user@example.com","status":"active"}],
  "meta": {"page":1,"count":1,"total_pages":1,"total_count":1}
}

Fetch a subscriber

  • Method: GET
  • URL: https://api.getdrip.com/v2/{account_id}/subscribers/{subscriber_id_or_email}
  • Watch out for: Email must be URL-encoded when used as path parameter.

Request example

GET /v2/9999999/subscribers/user%40example.com
Authorization: Basic <base64(api_token:)>

Response example

{
  "subscribers": [{
    "id": "abc123",
    "email": "user@example.com",
    "status": "active",
    "tags": ["customer"]
  }]
}

Create or update a subscriber (upsert)

  • Method: POST
  • URL: https://api.getdrip.com/v2/{account_id}/subscribers
  • Watch out for: This endpoint upserts by email. Existing subscribers are updated, not duplicated. Returns 201 on create, 200 on update.

Request example

POST /v2/9999999/subscribers
Content-Type: application/json
{
  "subscribers": [{
    "email": "user@example.com",
    "first_name": "Jane",
    "tags": ["lead"]
  }]
}

Response example

{
  "subscribers": [{
    "id": "abc123",
    "email": "user@example.com",
    "status": "active"
  }]
}

Batch create or update subscribers

  • Method: POST
  • URL: https://api.getdrip.com/v2/{account_id}/subscribers/batches
  • Watch out for: Max 1,000 subscribers per batch. Response is 201 with no body - errors are not surfaced per-record synchronously.

Request example

POST /v2/9999999/subscribers/batches
Content-Type: application/json
{
  "batches": [{
    "subscribers": [
      {"email":"a@example.com","tags":["vip"]},
      {"email":"b@example.com"}
    ]
  }]
}

Response example

HTTP 201 No Content

Update a subscriber

  • Method: PUT
  • URL: https://api.getdrip.com/v2/{account_id}/subscribers/{subscriber_id}
  • Watch out for: custom_fields are merged, not replaced. To clear a field, pass null as the value.

Request example

PUT /v2/9999999/subscribers/abc123
Content-Type: application/json
{
  "subscribers": [{"email":"user@example.com","custom_fields":{"plan":"pro"}}]
}

Response example

{
  "subscribers": [{"id":"abc123","email":"user@example.com","status":"active"}]
}

Unsubscribe a subscriber

  • Method: POST
  • URL: https://api.getdrip.com/v2/{account_id}/subscribers/{subscriber_id}/unsubscribe
  • Watch out for: Unsubscribing is global across all campaigns for that account. Cannot be reversed via API - subscriber must re-opt-in.

Request example

POST /v2/9999999/subscribers/abc123/unsubscribe

Response example

{
  "subscribers": [{"id":"abc123","email":"user@example.com","status":"unsubscribed"}]
}

Delete a subscriber

  • Method: DELETE
  • URL: https://api.getdrip.com/v2/{account_id}/subscribers/{subscriber_id}
  • Watch out for: Deletion is permanent and irreversible. Deleted subscribers cannot be recovered via API.

Request example

DELETE /v2/9999999/subscribers/abc123
Authorization: Basic <base64(api_token:)>

Response example

HTTP 204 No Content

Tag a subscriber

  • Method: POST
  • URL: https://api.getdrip.com/v2/{account_id}/tags
  • Watch out for: Tags are created automatically if they don't exist. Tag names are case-sensitive.

Request example

POST /v2/9999999/tags
Content-Type: application/json
{
  "tags": [{"email":"user@example.com","tag":"vip"}]
}

Response example

HTTP 201 No Content

Rate limits, pagination, and events

  • Rate limits: Drip enforces rate limits per API token. The documented limit is 3,600 requests per hour (1 request/second sustained). Exceeding the limit returns HTTP 429.
  • Rate-limit headers: Yes
  • Retry-After header: Yes
  • Rate-limit notes: Rate limit headers include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. Batch endpoints (e.g., batch subscriber upsert) count as a single request and support up to 1,000 records per call - use these to stay within limits.
  • Pagination method: offset
  • Default page size: 100
  • Max page size: 1000
  • Pagination pointer: page and per_page
Plan Limit Concurrent
All paid plans 3,600 requests/hour 0
  • Webhooks available: Yes
  • Webhook notes: Drip supports webhooks (called 'Notifications') that POST JSON payloads to a configured URL when subscriber events occur. Configured under Settings > Integrations > Webhooks in the Drip UI.
  • Alternative event strategy: Polling the subscribers list endpoint with updated_at filter as a fallback for event detection.
  • Webhook events: subscriber.created, subscriber.subscribed_to_campaign, subscriber.removed_from_campaign, subscriber.completed_campaign, subscriber.applied_tag, subscriber.removed_tag, subscriber.updated_custom_field, subscriber.unsubscribed_globally, subscriber.unsubscribed_from_campaign, subscriber.bounced, subscriber.marked_as_spam, subscriber.became_lead, subscriber.became_customer, email.sent, email.opened, email.clicked, order.placed, order.paid, order.refunded

SCIM API status

  • SCIM available: No
  • SCIM version: Not documented
  • Plan required: N/A
  • Endpoint: Not documented

Limitations:

  • Drip does not offer a SCIM API. User/subscriber management is handled exclusively through the REST API.
  • No SSO or IdP integration (Okta, Entra, etc.) is documented.

Common scenarios

Three integration patterns cover the majority of production use cases.

Bulk import and tag: Chunk records into batches of up to 1,000 and POST to /subscribers/batches. The endpoint returns HTTP 201 with no body - per-record errors are not surfaced synchronously. Always verify a sample by GETting /subscribers?tags[]=imported after each batch and resubmit failures as individual POSTs for error diagnosis.

Subscriber attribute sync from external system: On a lifecycle event such as a plan upgrade, PUT /subscribers/{subscriber_id} with updated custom_fields and a tags payload. Include remove_tags in the same request to atomically swap tags. Note that custom_fields are merged, not replaced - pass null explicitly to clear a field value.

Unsubscribe event propagation to CRM: Configure a webhook under Settings > Integrations > Webhooks targeting your endpoint and subscribe to subscriber.unsubscribed_globally. Extract the subscriber email from the payload and update CRM opt-out status. Respond with HTTP 200 within 10 seconds and implement idempotency on the event id field, as Drip will retry on non-2xx responses.

Bulk import and tag new subscribers

  1. Chunk subscriber list into batches of up to 1,000 records.
  2. POST each batch to /v2/{account_id}/subscribers/batches with email, name, custom_fields, and tags in the payload.
  3. Receive HTTP 201; wait briefly then GET /v2/{account_id}/subscribers?tags[]=imported to verify records were created.
  4. Handle any missing records by re-submitting individual POSTs to /v2/{account_id}/subscribers for error diagnosis.

Watch out for: Batch endpoint does not return per-record errors. Always verify a sample of records after batch import.

Sync subscriber status changes (e.g., plan upgrade) from external system

  1. On plan upgrade event in external system, PUT /v2/{account_id}/subscribers/{subscriber_id} with updated custom_fields (e.g., {"plan": "pro"}) and new tags (e.g., ["pro-customer"]).
  2. Include remove_tags in the same payload to remove old plan tags (e.g., ["free-customer"]).
  3. Confirm response contains updated custom_fields and tag list.

Watch out for: custom_fields are merged not replaced; explicitly pass null to clear a field value.

Listen for unsubscribe events and update external CRM

  1. Configure a webhook in Drip Settings > Integrations > Webhooks pointing to your endpoint.
  2. Subscribe to the subscriber.unsubscribed_globally event.
  3. On receipt of webhook payload, extract subscriber email and update CRM opt-out status.
  4. Respond with HTTP 200 within 10 seconds to acknowledge receipt.

Watch out for: Drip may retry webhook delivery on non-2xx responses. Implement idempotency using the event's id field to avoid duplicate CRM updates.

Why building this yourself is a trap

The primary API trap is the batch endpoint's silent failure mode: POST /subscribers/batches always returns HTTP 201 with an empty body regardless of per-record outcomes. Teams that treat the 201 as confirmation of successful writes will silently drop records.

A secondary trap is the upsert behavior of the single-subscriber POST - it matches on email and updates the existing record rather than creating a duplicate, which will overwrite fields if the payload is not scoped carefully. Deletion is permanent and irreversible with no soft-delete or recovery endpoint.

Finally, the API token auth uses Basic Auth with an empty password string rather than a Bearer token, which is a common misconfiguration point when integrating with HTTP client libraries that default to Bearer schemes.

Automate Drip workflows without one-off scripts

Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.

Every app coverage, including apps without APIs
60+ app integrations plus browser automation for apps without APIs
IT graph reconciliation across apps and your IdP
Less than a week to launch, maintained as APIs and admin consoles change
SOC 2 Type II. ~2 hours of your team's time

UpdatedMar 11, 2026

* Details sourced from official product documentation and admin references.

Keep exploring

Related apps

Abnormal Security logo

Abnormal Security

API Only
AutomationAPI only
Last updatedMar 2026

Abnormal Security is an enterprise email security platform focused on detecting and investigating threats such as phishing, account takeover (ATO), and vendor email compromise. It does not support SCIM provisioning, which means every app in your stack

ActiveCampaign logo

ActiveCampaign

API Only
AutomationAPI only
Last updatedFeb 2026

ActiveCampaign uses a group-based permission model: every user belongs to exactly one group, and all feature-area access (Contacts, Campaigns, Automations, Deals, Reports, Templates) is configured at the group level, not per individual. The default Adm

ADP logo

ADP

API Only
AutomationAPI only
Last updatedFeb 2026

ADP Workforce Now is a mid-market to enterprise HCM platform that serves as the HR source of record for employee data — payroll, benefits, time, and talent. User access is governed by a hybrid permission model: predefined security roles (Security Maste