
Drip exposes two concurrent HTTP surfaces, the general-purpose REST API v2 and the ecommerce-only Shopper Activity API v3-plus four official clients in Ruby, Node.js, PHP and .NET. There is no message-transport endpoint anywhere in it: you push people, tags and commerce events in, and Drip renders and sends the mail. On the agent side Drip is ahead of most peers, having shipped a first-party remote MCP server at api.getdrip.com/mcp in the June & July 2026 release. OAuth, approval-gated writes, free, with one blocker that costs people an afternoon, because Drip support must switch it on first.
Model Context Protocol lets an AI client such as Claude or ChatGPT call a vendor’s tools directly instead of a human copying data between tabs. For an ecommerce CRM that matters more than usual: Drip’s value sits in segments, workflow enrolment and revenue reporting, all tedious to query by hand. Drip answered in mid-2026 with a first-party server.
Drip MCP runs at https://api.getdrip.com/mcp and is added in Claude as a custom connector. Auth is OAuth with a guided login and account picker, no API keys change hands. Scope is set at connect time as read-only, write-only or both, per subaccount, and every write waits for human approval. Drip states it is included with your Drip account at no extra cost. The catch: Drip must turn it on per account first.
Announced August 11, 2026, it reads every subscriber, tag and custom field, pulls opens, clicks and revenue data, and reads any campaign email in full. Writes cover tagging, updating and bulk-importing up to 1,000 subscribers, drafting campaigns, test sends and workflow enrolment.
Enablement is not self-serve. The connector will not complete its OAuth handshake until Drip enables MCP on your account, and the setup article tells you to contact support@drip.com. The same applies to the Metrics API. Ask for both before you build, or lose an afternoon to a handshake failure unrelated to your client config.
One official server plus two third-party options worth knowing (a third, viaSocket, resells a hosted Drip endpoint). They stay relevant because GravityKit uses an API key rather than OAuth, which suits headless and CI contexts where nobody can click a consent screen, and Zapier MCP chains Drip actions to the rest of a Zapier account.
Drip’s own remote server at api.getdrip.com/mcp. OAuth with account picker, per-subaccount read/write scoping, approval-gated writes, free with any account. Must be enabled by Drip support before the first connect.
Zapier-hosted endpoint exposing Drip actions (create or update subscriber, add and remove tag, subscribe to or remove from campaign, trigger event) through a per-user dynamic URL, with onward reach to 30,000+ actions.
Self-hosted Node.js server (npm @gravitykit/drip-mcp-server, Node 20+) wrapping the REST API with 30+ tools across subscribers, tags, campaigns, workflows and ecommerce. API-key auth. Lightly maintained.
Why buyers should care. An official MCP server is still a differentiator rather than table stakes in 2026, and Drip’s arrived only in August 2026-any comparison written earlier is stale here. Check the same box on Klaviyo, Customer.io, ActiveCampaign and Omnisend before treating it as decisive.
The key structural fact: v2 and v3 are two different surfaces under one host, not two generations of the same one. v3 did not supersede v2, it was added alongside as a schema-bound commerce pipeline and replaces the legacy v2 Orders resource. Merge them in your mental model and you will send orders to the wrong path.
| Property | Value |
|---|---|
| REST base URL | https://api.getdrip.com/v2/:account_id/ |
| Shopper Activity base URL | https://api.getdrip.com/v3/:account_id/shopper_activity/ |
| Account discovery | GET /v2/accounts START HERE-the only v2 path omitting :account_id |
| Response format | JSON |
| Required header | User-Agent in the form Your App Name (www.yourapp.com) |
| Pagination | Page-number, default 100 per page via ?page= |
| Pagination metadata | meta.page, meta.count, meta.total_pages, meta.total_count |
| Batch endpoints | Up to 1,000 records, answered with 202 Accepted and request_ids |
The v2 surface spans roughly 18 resource families, but almost every external write lands in three. Subscribers, Tags and Events, because those are what segmentation and workflow triggers read. v3 has exactly three: cart, order and product, each with a /batch sibling. Collections paginate identically: request ?page=1, read meta.total_pages, loop. Batch endpoints return 202 Accepted and request_ids-queued, not applied.
Two credential models, chosen by whether you act on your own account or someone else’s.
The standard method for private integrations, identical on v2 and v3. Pass the API token as the username with an empty password-in curl, curl -u YOUR_API_KEY:, the trailing colon doing the work. The token lives in your Drip user settings and is account-scoped, treat it as a full-access secret.
For public integrations acting on behalf of other Drip accounts. Authorize at https://www.getdrip.com/oauth/authorize, exchange at https://www.getdrip.com/oauth/token, then send Authorization: Bearer YOUR_ACCESS_TOKEN. The MCP connector uses this same path, which is why MCP access can be scoped per subaccount in a way an API token cannot.
A descriptive User-Agent is required on every request. Drip’s examples use the form Your App Name (www.yourapp.com), not a default library string. The client must also support SNI over HTTPS. Both are cheap to satisfy and expensive to diagnose.
API tokens are not scoped. The MCP connector grants read-only or write-only access per subaccount; a raw API token carries full account permissions and there is no published read-only key. If a reporting tool or agent needs a restricted credential, OAuth or MCP is the only documented route.
Drip runs two independent request pools, and the batch pool is far smaller than intuition suggests. Both reset hourly.
| Limit | Value | Notes |
|---|---|---|
| Individual API requests | 3,600 per hour | Roughly 60 per minute sustained across standard endpoints |
| Batch API requests | 50 per hour | Counted in a separate pool from individual requests |
| Records per batch request | Up to 1,000 | Effective ceiling of 50,000 records per hour |
| Rate-limit headers | X-RateLimit-Limit, X-RateLimit-Remaining | Limit header returns e.g. 3600 |
| Over-limit response | HTTP 429, rate_limit_error | “API rate limit exceeded. Please try again in an hour.” |
| Email sending volume | Not capped | Drip: “We don’t cap your number of sends” |
The workaround for a large import is arithmetic, not engineering. Loading 40,000 subscribers one at a time burns 40,000 calls against a 3,600-per-hour budget and takes over 11 hours; as 40 batch calls of 1,000 it finishes inside one hour. Batch every migration and nightly sync, never retry-loop a batch call, and count each pool separately.
Four official clients, all MIT licensed, all under the DripEmail organisation, and not equally maintained: Ruby and Node.js are current, PHP and .NET have not moved in a year.
| Language | Package | Install | Repo |
|---|---|---|---|
| Ruby | drip | gem install drip | DripEmail/drip-ruby |
| JavaScript / Node.js | drip-nodejs | npm install drip-nodejs --save | DripEmail/drip-nodejs |
| PHP | dripemail/drip-php | composer require dripemail/drip-php | DripEmail/drip-php |
| C# / .NET | drip-dot-net | See repository README | DripEmail/drip-dot-net |
Ruby is the most actively maintained (updated August 11, 2026). The Node.js client was updated February 11, 2026, latest release 3.1.4, and is the only official client covering both v2 REST and v3 Shopper Activity, the default for a new ecommerce integration.
Two clients are stale, and one has a silent breaking change. PHP was last updated March 12, 2025 and .NET June 16, 2025; both wrap REST API v2.0 only, and the PHP README does not claim v3 coverage. From drip-nodejs 3.1.2 responses also expose .data instead of .body, so upgrading breaks every handler with an undefined property rather than an error.
There is no official Python client, which surprises people given how much ecommerce plumbing runs on Python. Community PyPI wrappers exist but none is endorsed by Drip or tracks v3 reliably, so call the REST API directly with requests-Basic auth, plain JSON, under 50 lines. Same for Go and Java. The GravityKit MCP server above is the one useful third-party project: its 30+ tools double as a readable reference implementation.
These fifteen paths cover essentially everything an external system does with Drip; full schemas and error codes live in the official Drip API reference. Note the version prefix on the last two rows, separate v3 surface, not a v2 sub-resource. Outside the list sit /forms, /users, /conversions, /event_actions and /v3/:account_id/shopper_activity/product.
| Resource | Methods | Description |
|---|---|---|
| Accounts /v2/accounts | GET | List reachable accounts. The only v2 path without :account_id; call it first. |
| Subscribers /v2/:account_id/subscribers | GET, POST, DELETE | Core people resource. POST upserts on email; address people by ID or encoded email. |
| Subscribers (batch) /v2/:account_id/subscribers/batches | POST | Bulk upsert up to 1,000 subscribers. Async, returns 202. The migration path. |
| Unsubscribes /v2/:account_id/unsubscribes/batches | POST | Globally unsubscribe from all mailings, singly or in batches of 1,000. |
| Tags /v2/:account_id/tags | GET, POST, DELETE | List, apply and remove tags. Drip’s main segmentation primitive. |
| Custom Fields /v2/:account_id/custom_field_identifiers | GET | List field identifiers. Values are written via the subscriber custom_fields object. |
| Events /v2/:account_id/events | GET, POST | Generic behavioural log. Needs email and action; free-form properties. |
| Events (batch) /v2/:account_id/events/batches | POST | Up to 1,000 events per async call. The documented backfill path. |
| Broadcasts /v2/:account_id/broadcasts | GET, POST, PATCH, DELETE | Single-email campaigns. Drafts creatable via API with the Custom HTML builder since June/July 2026. Creates a campaign object, not a send. |
| Email Series Campaigns /v2/:account_id/campaigns | GET, POST | List, activate or pause multi-email series and subscribe someone. The main enrolment call. |
| Workflows /v2/:account_id/workflows | GET, POST, DELETE | List, activate or pause workflows; start or remove a subscriber. |
| Metrics /v2/:account_id/metrics | GET | Opens, clicks, delivery and revenue. Shipped April/May 2026. Enablement required. |
| Webhooks /v2/:account_id/webhooks | GET, POST, DELETE | Register, list and delete outbound subscriptions for near-real-time event push. |
| Shopper Activity. Cart /v3/:account_id/shopper_activity/cart | POST, PATCH | v3 surface. Requires provider, action, occurred_at. Powers abandoned-cart flows. |
| Shopper Activity. Order /v3/:account_id/shopper_activity/order | POST, PATCH | v3 surface. Actions: placed, updated, fulfilled, refunded, canceled. Replaces v2 Orders. |
curl -u YOUR_API_KEY: -H "User-Agent: SMTPedia Example (www.smtpedia.com)" https://api.getdrip.com/v2/accounts
# 200 => {"accounts":[{"id":"9999999","name":"Example Store", ...}]}
# 401 => wrong token, or you dropped the trailing colon that supplies
# the empty password Basic auth requires.import os, requests
API_KEY = os.environ["DRIP_API_KEY"]
ACCOUNT = os.environ["DRIP_ACCOUNT_ID"]
HEADERS = {"Content-Type": "application/json",
"User-Agent": "SMTPedia Example (www.smtpedia.com)"}
AUTH = (API_KEY, "") # API key as username, empty password
v2 = f"https://api.getdrip.com/v2/{ACCOUNT}"
v3 = f"https://api.getdrip.com/v3/{ACCOUNT}/shopper_activity"
# 1. Upsert a subscriber (POST to the collection keys on email)
requests.post(f"{v2}/subscribers", auth=AUTH, headers=HEADERS, timeout=30,
json={"subscribers": [{"email": "shopper@example.com",
"tags": ["vip"],
"custom_fields": {"first_name": "Ada"}}]}).raise_for_status()
# 2. Generic behavioural event
requests.post(f"{v2}/events", auth=AUTH, headers=HEADERS, timeout=30,
json={"events": [{"email": "shopper@example.com",
"action": "Viewed sizing guide"}]}).raise_for_status()
# 3. Orders go to v3, never to /v2/events, or revenue attribution
# and abandoned-cart flows will never see them.
order = requests.post(f"{v3}/order", auth=AUTH, headers=HEADERS, timeout=30,
json={"provider": "my_custom_platform",
"email": "shopper@example.com",
"action": "placed",
"occurred_at": "2026-08-19T10:15:00Z",
"order_id": "ORD-1001",
"grand_total": 79.90,
"currency": "USD",
"items": [{"product_id": "SKU-42", "name": "Trail Runner",
"quantity": 1, "price": 79.90}]})
print(order.status_code, order.json()) # 202 Accepted + request_ids// npm install drip-nodejs --save
const client = require('drip-nodejs')({
token: process.env.DRIP_API_KEY,
accountId: process.env.DRIP_ACCOUNT_ID,
});
// Since v3.1.2 responses expose `.data`, not `.body`.
async function main() {
await client.createUpdateSubscriber({ email: 'shopper@example.com', tags: ['vip'] });
// v3 Shopper Activity: the only path that feeds revenue reporting.
await client.createUpdateOrder({
provider: 'my_custom_platform',
email: 'shopper@example.com',
action: 'placed',
occurred_at: new Date().toISOString(),
order_id: 'ORD-1001',
grand_total: 79.9,
currency: 'USD',
items: [{ product_id: 'SKU-42', name: 'Trail Runner', quantity: 1, price: 79.9 }],
});
}
main().catch((err) => {
// 429 => rate_limit_error. Two pools: 3,600 individual, 50 batch per hour.
console.error(err.response ? err.response.status : err);
process.exit(1);
});Intuition says bulk endpoints get a bigger budget. Drip inverts that: 3,600 individual requests per hour but only 50 batch requests of up to 1,000 records. Batching is mandatory for volume and fatal if you retry-loop it-50 failed attempts lock you out for the hour with rate_limit_error.
POST /v2/:account_id/events accepts any action with free-form properties, so it swallows an order payload and returns success while contributing nothing. Revenue attribution, abandoned-cart automations, product segmentation and the Product Library are fed exclusively by /v3/:account_id/shopper_activity/. Both are asynchronous, so a 202 Accepted means queued, not applied, the failure stays silent until you notice an empty revenue column.
Nothing in the UI says so. The Metrics API from the April & May 2026 release requires account enablement by Drip, and MCP requires emailing support@drip.com before OAuth will succeed. Developers lose hours debugging 403s on features that are simply off server-side. Request both up front.
There is no official Python SDK, and of the four that exist, PHP (March 2025) and .NET (June 2025) target v2 only. drip-nodejs also moved responses from .body to .data at 3.1.2, so an innocuous upgrade breaks every handler with an undefined property rather than an exception.
Drip publishes dated release notes rather than a formal API changelog. The official release notes are the record; deprecation labels appear in the API reference.
The API token lives in your Drip user settings. The account ID is easier to fetch than to hunt for: call GET https://api.getdrip.com/v2/accounts with the token as the Basic auth username and an empty password. It is the only v2 path that needs no account ID in the prefix, so it is the standard first call.
Two separate hourly pools: 3,600 individual requests and 50 batch requests of up to 1,000 records each. Exceeding either returns HTTP 429 with rate_limit_error. Batch bulk operations, never retry-loop a batch call, and read X-RateLimit-Remaining.
POST /v2/:account_id/events is a generic behavioural log needing only email and action. /v3/:account_id/shopper_activity/{cart|order|product} is a schema-bound commerce pipeline requiring provider, action and occurred_at. Only v3 feeds revenue attribution, abandoned-cart flows and the Product Library, an order sent as a v2 event succeeds and accomplishes nothing.
No. The official clients are Ruby, Node.js, PHP and .NET only. For Python, call the REST API directly with requests: Basic auth with the API key as username and an empty password, JSON payloads, a descriptive User-Agent. Community PyPI packages exist but none is endorsed by Drip.
POST /v2/:account_id/subscribers with a {"subscribers":[{...}]} body. It upserts on email, so one call creates or updates, and you can set tags and custom_fields in the same request. Beyond a handful of records use /subscribers/batches: 1,000 per call, returning 202 Accepted.
Yes, a first-party remote server at https://api.getdrip.com/mcp, announced August 11, 2026. OAuth with an account picker, read/write scoped per subaccount, every write approval-gated, free. One blocker: Drip must enable MCP on your account first, and the setup article tells you to email support@drip.com. Alternatives: Zapier MCP and the API-key-based GravityKit server.
This review follows our email infrastructure testing methodology. We disclose affiliate relationships in our editorial independence policy.