GetResponse exposes one documented REST surface — API v3 at https://api.getresponse.com/v3 — covering contacts, campaigns, newsletters, ecommerce objects and the transactional stream, with quotas of 80 requests per second and 30,000 per 10-minute window. The SDK story is thin: the PHP wrapper has not shipped since August 2023. And on agents GetResponse made an unusual choice — as of August 2026 there is no official GetResponse MCP server, its first-party AI tooling shipping as Agent Skills instead.
The Model Context Protocol is how an AI agent discovers and calls a vendor’s tools without bespoke glue code — look up a list, add a contact, queue a newsletter, all as tool calls. GetResponse is a negative on this axis in 2026, but the reason is more interesting than a simple absence.
As of August 19, 2026 nothing on the developer portal, the integrations directory, the GetResponse GitHub organisation or npm publishes an MCP endpoint. What exists instead is first-party but different: GetResponse/public-api-agent-skills, built on the SKILL.md standard, shipping an AI-optimised openapi.json for the contact and newsletter workflow. Agents needing tool-calling today use Zapier MCP, a self-hosted n8n workflow, or raw API v3.
Three routes are worth knowing. Only one is published by GetResponse, and it is not an MCP server at all — it is listed because it is the best machine-readable description of API v3 in existence.
First-party, but Agent Skills rather than MCP. Ships getresponse-newsletter-skill with an AI-optimised OpenAPI spec plus auth and payload references. Install with npx skills add GetResponse/public-api-agent-skills. Very new: 0 stars, 7 commits.
Zapier-built and Zapier-hosted, not a GetResponse product. 8 tools: create, update, remove and find contacts, plus Create Newsletter, Find List and a beta raw API Request. Works with any MCP client. Each call burns 2 Zapier tasks, so cost scales with agent chattiness.
Community template turning the n8n GetResponse node into an MCP server with 5 operations. Self-hosted on your own instance with your own credentials, so no third party holds the API key. Not endorsed by GetResponse.
MCP decides whether your agents can operate the platform without an engineer writing a connector first, which is why it now appears on procurement checklists. GetResponse fails that check literally: there is no vendor-hosted endpoint to point Claude or Cursor at. The Agent Skills repo partly compensates — an OpenAPI spec plus auth docs is most of what an agent needs, and the credential stays in your environment — but it is not a hosted, versioned, permissioned tool surface. If your evaluation weights native MCP heavily, compare Mailchimp, ActiveCampaign and HubSpot first, and treat Zapier as an operating cost line, not a free bridge.
API v3 is a conventional JSON REST API: resources are plural nouns, GET returns a record or a filtered collection, POST creates or modifies, DELETE removes by ID. The version only increments on a backward-incompatible change, which has meant no bump since v3 landed. The most common mistake here is not a payload error but a base-URL error, because MAX and 360 accounts live on a different host entirely.
| Base URL (standard accounts) | https://api.getresponse.com/v3 |
| Base URL (MAX / 360) | https://api3.getresponse360.pl/v3 or https://api3.getresponse360.com/v3 |
| Version / format | v3 ONLY DOCUMENTED · JSON, UTF-8 bodies |
| Pagination | page (default 1) and perPage (default 100, max 1000) |
| Bulk contact import | POST /contacts/batch, cap 1,000 per request, returns 202 Accepted |
| Rate-limit headers | X-RateLimit-Limit / -Remaining / -Reset |
| Webhooks | Yes — HTTP POST JSON, deduplicate on X-Webhook-ID |
| Live quota lookup | GET /accounts/sending-limits |
| Transactional message size | 16 MB plain, 32 MB with attachments; subject cap 512 chars |
Two conventions repay reading before you write code. First, GetResponse calls its contact lists campaigns, so /campaigns is the list endpoint and almost every contact write needs a campaignId. Second, several writes are asynchronous: POST /contacts and POST /contacts/batch answer 202 Accepted and queue the work, so reading a contact back immediately will intermittently 404. And per-account sending quotas are deliberately not static numbers — GET /accounts/sending-limits is the authoritative runtime answer, so build that check into your deploy rather than hard-coding a figure that drifts with the plan.
Two mechanisms, plus extra headers MAX and 360 accounts must send on every request. Both authenticate at account level and neither constrains what the credential may touch.
The route nearly every integration uses. Generate a key under Account › Integrations › API, then send it on X-Auth-Token with the literal api-key prefix:
X-Auth-Token: api-key YOUR_API_KEY Content-Type: application/json
The prefix is mandatory: a bare key fails with a plain 401 and no explanation, which costs people an afternoon more often than it should. Hold one key per integration so you can revoke individually.
Use this when you build something other people install, so you never hold their API key. Authorisation happens at https://app.getresponse.com/oauth2_authorize.html; tokens come from /v3/token. Four grants: Authorization Code, Client Credentials, Implicit and Refresh Token. Tokens travel on the standard header:
Authorization: Bearer ACCESS_TOKEN
Lifetimes differ by grant: an Authorization Code token lives 3600 seconds, a Client Credentials token 86400 seconds, and the authorization code must be exchanged within 10 minutes or it expires unused. Plan the refresh path before shipping — the failure mode is a job that passes testing and dies an hour into production.
OAuth responses return "scope": null. There is no way to issue a token that reads contacts but cannot delete them, so every token and API key is effectively account-wide. Treat any GetResponse credential as a full-privilege secret: keep it out of browser bundles, scope it by rotation rather than permission, and accept that handing one to a third-party agent platform grants complete account access. That is a real difference from Mailchimp and ActiveCampaign when a security review asks about blast radius.
Enterprise accounts change three things at once: the base URL becomes api3.getresponse360.pl/v3 or api3.getresponse360.com/v3; every request must carry X-Domain with the client domain minus the protocol prefix; and OAuth authorises against a custom-domain getresponse360.com endpoint. X-Parent-Login optionally pins one parent account.
X-Auth-Token: api-key YOUR_API_KEY X-Domain: client.example.com X-Parent-Login: parent_account_login
GetResponse publishes its API limits plainly. Three ceilings apply at once and any can be breached independently.
| Limit | Value | Notes |
|---|---|---|
| Requests per 10-minute window | 30,000 | Account-wide sliding window, not per key |
| Requests per second | 80 | Burst ceiling; hit before the window cap in tight loops |
| Parallel connections | 10 | API concurrency only — not an SMTP connection limit |
| Contacts per batch import | 1,000 | POST /contacts/batch, asynchronous |
| Records per collection page | 1,000 | perPage maximum; default is 100 |
| Per-account email sending limit | Runtime value | Read from GET /accounts/sending-limits |
Exceeding a ceiling returns HTTP 429 with currentLimit and timeToReset in the body — sleep for timeToReset rather than applying blind exponential backoff, since the reset is a window boundary and backing off longer only wastes throughput. The workaround for large syncs is structural: batch writes 1,000 at a time through /contacts/batch instead of firing individual POST /contacts calls, cap the worker pool at 10, and pull collections at perPage=1000. A 100,000-contact import done correctly is 100 requests; done naively it is 100,000 and spends most of its life in 429 handling.
The 10 parallel connections figure is an API limit. GetResponse publishes no concurrent-connection ceiling for its SMTP relay and the two must not be conflated — see the SMTP settings tab for what is documented on the relay side.
This is the weakest part of the GetResponse developer story. Five SDK repositories exist, but only two wrap the REST API and both are PHP; the rest are mobile push libraries that do nothing for a server-side integration. No first-party Python, Node, Ruby, Go, Java or .NET client exists.
| Language | Package | Install | Repo |
|---|---|---|---|
| PHP | getresponse/sdk-php | composer require getresponse/sdk-php | sdk-php |
| PHP | getresponse/sdk-php-client | composer require getresponse/sdk-php-client | sdk-php-client |
| Kotlin / Android | MobileSDK-Android | Push SDK | MobileSDK-Android |
| Swift / iOS | MobileSDK-IOS | Push SDK | MobileSDK-IOS |
| Dart / Flutter | MobileSDK-Flutter | Push SDK | MobileSDK-Flutter |
getresponse/sdk-php is at v3.0.0, last released 22 August 2023, and needs PHP 7.3+ with cURL — roughly three years without a release. The API has made no breaking changes since, so it still works, but treat it as frozen with no coverage of resources added after 2023. The mobile SDKs were last updated 13 October 2025. Avoid the older getresponse-api-php (2019) and api-sdk-php (2015): both are dead and predate the current auth model.
Because API v3 is plain JSON REST with a single auth header, most teams skip the SDK layer and use their language’s standard HTTP client, which is what the examples below assume. Where a wrapper helps is in typed languages, and the useful 2026 move is to generate one: GetResponse’s public-api-agent-skills repository publishes an AI-optimised openapi.json that feeds straight into openapi-generator or oapi-codegen, yielding a client matching the current surface rather than the 2023 one. Community packages on npm and PyPI have no real traction or vendor endorsement — audit the source first.
These paths are verified against GetResponse’s own OpenAPI specification. The full resource index is at apidocs.getresponse.com/v3/resources, with webhook payloads at /v3/payloads. Confirm sub-paths and payload fields there before coding against the final row.
| Resource | Methods | Description |
|---|---|---|
| Campaigns (lists) /campaigns | GET, POST | List or create campaigns — GetResponse’s name for contact lists. One must exist before contacts can be added. |
| Campaign /campaigns/{campaignId} | GET | Retrieve one campaign by ID. |
| Contacts /contacts | GET, POST | List or filter contacts by email, campaign or name, or add one. POST upserts on existing email. |
| Contacts batch import /contacts/batch | POST | Up to 1,000 contacts per request. Asynchronous; returns 202 Accepted, not the records. |
| Contact /contacts/{contactId} | GET | Retrieve full details for one contact by ID. |
| Contact custom fields /contacts/{contactId}/custom-fields | POST | Set or update custom field values on a contact. |
| Custom fields /custom-fields | GET, POST | List or create custom field definitions. Check for an existing one to avoid duplicates. |
| Newsletters /newsletters | GET, POST | List by status or campaign, or create and send. Requires fromFieldId and sendSettings. |
| Newsletter /newsletters/{newsletterId} | GET, DELETE | Newsletter details and delivery status, or delete it. |
| Newsletter cancel /newsletters/{newsletterId}/cancel | POST | Cancel a scheduled or in-progress send. |
| Search contacts /search-contacts/contacts | POST | Ad-hoc search on custom field conditions, no saved segment. |
| From fields /from-fields | GET | List verified sender addresses. A valid fromFieldId is mandatory before sending. |
| Account sending limits /accounts/sending-limits | GET | Current API and sending limits at runtime. Authoritative for per-account quotas. |
| OAuth token /token | POST | Exchange an authorization code for an access token, or refresh. |
| Other resource families /autoresponders, /webforms, /landing-pages, /webinars, /shops, /orders, /products, /carts, /tags, /transactional-emails, /suppressions, /workflows, /sms, /statistics | GET, POST, DELETE | Further families on the resource index, same REST convention. Verify sub-paths first. |
Three things catch people here: the api-key prefix, POST /contacts returning 202 rather than the created record, and assuming a quota instead of reading it.
import requests
API_KEY = "YOUR_API_KEY"
BASE = "https://api.getresponse.com/v3"
HEADERS = {
"X-Auth-Token": f"api-key {API_KEY}",
"Content-Type": "application/json",
}
# 1. Find the campaign (list) you want to write into
r = requests.get(f"{BASE}/campaigns", headers=HEADERS,
params={"query[name]": "Newsletter", "perPage": 100})
r.raise_for_status()
campaign_id = r.json()[0]["campaignId"]
# 2. POST /contacts upserts - it updates if the email already exists.
payload = {
"email": "ada@example.com",
"name": "Ada Lovelace",
"campaign": {"campaignId": campaign_id},
"dayOfCycle": "0",
}
r = requests.post(f"{BASE}/contacts", headers=HEADERS, json=payload)
print(r.status_code) # 202 Accepted - queued, not created inline
# 3. Read the live quota rather than assuming a static one.
limits = requests.get(f"{BASE}/accounts/sending-limits", headers=HEADERS).json()
print(limits)
# Budget: 80 req/s, 30000 per 10 min, 10 parallel connections.
# On 429 the body carries currentLimit and timeToReset - sleep timeToReset.Above a handful of contacts use /contacts/batch: cap 1,000 per request, work queued, so treat 202 as success and confirm via the contact import finished webhook rather than polling.
const API_KEY = process.env.GETRESPONSE_API_KEY;
const BASE = "https://api.getresponse.com/v3";
const headers = {
"X-Auth-Token": `api-key ${API_KEY}`,
"Content-Type": "application/json",
};
async function importBatch(campaignId, contacts) {
// Hard cap is 1000 contacts per request
const res = await fetch(`${BASE}/contacts/batch`, {
method: "POST",
headers,
body: JSON.stringify({ campaignId, contacts }),
});
console.log(res.status); // 202 Accepted = queued for async processing
console.log("remaining:", res.headers.get("X-RateLimit-Remaining"));
if (res.status === 429) {
const { timeToReset } = await res.json();
await new Promise((r) => setTimeout(r, timeToReset * 1000));
}
}
importBatch(campaignId, [
{ email: "ada@example.com", name: "Ada Lovelace" },
{ email: "grace@example.com", name: "Grace Hopper" },
]);Unused API keys expire after 90 days and must be regenerated. This bites low-frequency integrations hardest: a quarterly sync finds its credential dead with no code change, throwing auth failures that look exactly like a regression. Exercise the key on a schedule or alert on 401s.
Enterprise accounts do not talk to api.getresponse.com. They use api3.getresponse360.pl/v3 or api3.getresponse360.com/v3 and must carry X-Domain with the protocol prefix stripped. Copy-pasting a working standard-account integration into MAX fails even with valid credentials — usually with an unhelpful auth error rather than a routing one.
Both contact write endpoints return 202 Accepted and queue the work, so reading the contact back immediately will intermittently 404. Drive follow-up from the contact subscribed or contact import finished webhook — never from the POST response body.
No Starter, Marketer or Creator account can obtain SMTP relay credentials: the relay exists only through the Transactional emails add-on, documented as MAX2-only and priced against a monthly send limit through sales. On a standard plan the sending path is domain authentication plus API v3. The add-on is also a sending service only — you supply plain text or HTML, or use your ecommerce CMS templates, with no transactional template editor. Caps: 16 MB per message, 32 MB with attachments, 512-character subject. See the SMTP settings tab.
getresponse/sdk-php (v3.0.0) and its HTTP client. No first-party PHP SDK release since.The product feed is at getresponse.com/about/whats-new; API changes appear at apidocs.getresponse.com/v3, which states the version only increments on a backward-incompatible change. The legacy JSON-RPC v1 and v2 APIs are no longer documented and should be treated as retired.
Generate it under Account › Integrations › API, one key per integration so you can revoke individually. Send it as X-Auth-Token: api-key YOUR_API_KEY — omitting the api-key prefix returns a bare 401. Unused keys expire after 90 days.
Three ceilings apply at once: 30,000 requests per 10-minute window, 80 per second, and 10 parallel connections. Responses carry the X-RateLimit-* headers; a breach returns HTTP 429 with currentLimit and timeToReset — sleep for timeToReset rather than guessing. Per-account sending limits are separate and read at runtime from GET /accounts/sending-limits.
For one contact, POST /contacts with an email and a campaign.campaignId; it upserts, so an existing email is updated rather than duplicated. For bulk, POST /contacts/batch takes up to 1,000 per request. Both are asynchronous and return 202 Accepted, so do not expect the record back. Note GetResponse calls its lists campaigns.
Yes, delivered as HTTP POST JSON. Documented events: message opened, link clicked, SMS link clicked (MAX add-on), contact subscribed (imports excluded), contact copied, moved, unsubscribed or rejected, bounced contact removed, custom field value changed, contact email changed, contact import finished, and custom report file status changed. Every payload carries type, account and an RFC3339 event timestamp. Deduplicate on X-Webhook-ID — X-Request-ID changes on retry.
No official one. As of August 2026 nothing on the developer portal, the integrations directory, the GetResponse GitHub organisation or npm publishes an MCP endpoint. First-party agent tooling is public-api-agent-skills, built on SKILL.md rather than MCP. For MCP itself, your options are Zapier MCP (8 tools, 2 Zapier tasks per call) or a self-hosted n8n template with 5 operations — neither a GetResponse product.
Standard accounts use https://api.getresponse.com/v3. MAX and 360 accounts use https://api3.getresponse360.pl/v3 or https://api3.getresponse360.com/v3, must send X-Domain with the client domain minus the protocol prefix, and may send X-Parent-Login to pin one parent account. MAX OAuth authorises against a custom-domain getresponse360.com URL. Resource paths and payloads are otherwise identical.
This review follows our email infrastructure testing methodology. We disclose affiliate relationships in our editorial independence policy.