Loops logo

Loops API + MCP (2026): 47 paths, 5 SDKs, official MCP server

Last verified Sep 14, 2026

Loops ships one REST API at https://app.loops.so/api under a v1 prefix, an OpenAPI 3.1.0 document covering 47 paths, 5 SDKs, a CLI and, unusually for an email platform this size, a first-party Model Context Protocol server at https://mcp.loops.so. That server is the headline here. The API itself is conventional bearer-token JSON, with two documented absences: no pagination contract, no idempotency contract.

At a glance

v1
API version
OpenAPI 3.1.0, 47 documented paths

5
Official SDKs
JS/TS, PHP, Ruby, Go, Nuxt module

Official
MCP status
Remote server, Streamable HTTP, OAuth

The API still adds whole resource families every few weeks, and it is not a mature enterprise-contract API: no v2, no published deprecation window, no scoped credentials. Teams arriving from SendGrid or Mailgun should budget for that.

MCP integration in 2026

The Model Context Protocol is how an AI agent reaches a third-party product without a bespoke integration. Loops publishes a hosted server for it, which puts it in a small minority of email vendors.

Official Loops MCP server, hosted and OAuth-authenticated

Loops runs a first-party remote MCP server at https://mcp.loops.so over Streamable HTTP, authenticated with OAuth through Client ID Metadata Documents rather than a pasted key. Loops describes the coverage as managing contacts and mailing lists, sending transactional emails, working with events and reaching the rest of the API, effectively the whole REST surface.

A browser OAuth handshake means no long-lived key in an agent config file, and binds the connection to a person rather than a shared secret. The trade is that tool calls go to Loops infrastructure; there is no self-hosted build.

Why four meta tools instead of forty-seven

The server exposes 4 tools, not one per endpoint: Search finds the right API operation, Describe inspects its parameters, Execute runs it against a named team, Teams lists the teams the user can reach. Every REST call goes through Execute.

The design is unusual and correct here. One tool per endpoint would push 47 definitions, each with a full JSON Schema, into the agent’s context before the first user message is read, a large share of the window spent on definitions the agent never calls, with selection accuracy degrading as the list grows. Four tools cost almost nothing and stay constant.

The price is round trips: creating a contact means Search, then Describe, then Execute2 round trips before the first useful call, a third if Teams must resolve the team. Invisible interactively, costly in a high-frequency loop where you should call REST directly. The upside: when Loops added workflow endpoints in July 2026, no server release was needed for an agent to find them.

Installing the Loops MCP server

Commands as published by Loops. The Claude Code one installs at user scope, so the connector is available in every project.

# Claude Code
claude mcp add loops https://mcp.loops.so --scope user --transport http

# Codex CLI (v1.48.0 and later)
codex mcp add loops --url https://mcp.loops.so

For Claude Desktop, Loops sits under Settings › Connectors › Loops; for ChatGPT, in the plugin marketplace. The first call opens a browser window for the OAuth grant.

Available MCP servers

One official server, plus third-party wrappers reaching Loops through automation platforms. Those are not supported by Loops and cover whatever the wrapping platform exposes, typically a small subset of the 47 paths.

Name collision. Several MCP servers published as Loops have nothing to do with loops.so: the smithery.ai entry under loops/loops-server, the useloops.io product, the smogili1/loop_mcp repository and the Loopy MCP Server are unrelated software, and directory search conflates them. The only first-party Loops email server is https://mcp.loops.so.

Why buyers should care. An official MCP server changes what a small team can do without engineering time: contact hygiene, list checks and a one-off transactional test become plain-language requests instead of tickets, and the OAuth grant, scope and uptime are the vendor’s responsibility. It remains rare in 2026: most email platforms are still reached through community or iPaaS wrappers rather than a first-party server.

Loops API v1 essentials

The contract is small and conventional. The last two rows record what the documentation does not say.

Base URLhttps://app.loops.so/api
Path prefixv1 – every documented endpoint sits under it
FormatJSON request bodies, JSON responses
OpenAPI spechttps://app.loops.so/openapi.json – OpenAPI 3.1.0, 47 paths
Spec version1.21.12 as read on September 14, 2026. A rolling build number, not a stable API version.
PaginationNot documented
IdempotencyNot documented


Those are real absences, not omissions on our side: no cursor, page or limit parameter on any list endpoint, and no idempotency key header on any write endpoint. List contacts on a growing account and you have no guarantee how many rows return; a timed-out POST has no documented safe retry. Version against the prefix, never the build number.

Webhooks

Loops pushes events out over HTTP with a Standard Webhooks-shaped signature. Events cover the contact lifecycle (contact.created, contact.unsubscribed, contact.deleted, plus mailing list subscribe and unsubscribe), the send lifecycle (campaign.email.sent, loop.email.sent, transactional.email.sent) and the delivery lifecycle (email.delivered, email.softBounced, email.hardBounced, email.opened, email.clicked, email.unsubscribed, email.resubscribed, email.spamReported), plus testing.testEvent.

Verification is HMAC-SHA256 over id.timestamp.rawBody with a secret prefixed whsec_, using headers Webhook-Signature, Webhook-Id and Webhook-Timestamp. Sign the raw bytes before any JSON parsing, and compare in constant time. The payload carries eventName, webhookSchemaVersion 1.0.0 and eventTime.

Delivery is capped at 10 events per second, your endpoint must respond within 15 seconds, and Loops retries with exponential backoff up to 8 attempts across roughly 28 days. That generous window has a consequence: a four-week-old event can arrive after a newer one, so consumers must de-duplicate on Webhook-Id and never assume ordering. The timeout means enqueue and return, never process inline.

Authentication methods

One mechanism for the REST API, a different one for the MCP server. The split trips people up.

Bearer API key

Every REST call carries Authorization: Bearer YOUR_API_KEY, generated in the dashboard. A missing, malformed or revoked key returns 401. No HTTP Basic fallback, no query-string key, no signed-request scheme.

A dedicated endpoint confirms a key works: GET /v1/api-key returns success and teamName. That second field names the team whose data you are about to write to, catching the staging-key-in-production mistake before anything sends.

No OAuth on the REST API

This is the notable asymmetry. The MCP server authenticates with OAuth and a browser consent flow; the REST API does not offer OAuth at all. A product acting on your own users’ Loops accounts therefore has no authorisation-code flow, each customer generates and pastes a long-lived key, with the handling obligations that implies. Mailchimp and Klaviyo publish OAuth for this case. Loops does not.

No documented scopes. No permission scopes, no read-only keys, no per-endpoint restrictions, so assume any valid key reaches all 47 paths, contact deletion and suppression changes included. Never embed a Loops key where a browser or mobile client can read it, and note that separate keys for reporting and sending restrict neither, they only make revocation cheaper.

Rate limits

Published, per team, enforced by rejection rather than queueing.

LimitValueScope and notes
Standard API10 requests per secondPer team, across the standard endpoints
Content API60 requests per 60 secondsPer team; a separate, tighter budget
Response headersx-ratelimit-limit, x-ratelimit-remainingLet a client track its own budget
Over-limit behaviourHTTP 429Rejected outright. No documented queueing.
Reset signallingNot documentedNo x-ratelimit-reset, no retry-after
Free plan sending10 emails per secondPublished on the pricing page
Webhook delivery10 events per secondOutbound, Loops to your endpoint


The consequence of that fifth row: client-side backoff is mandatory. The headers show remaining budget, but when a 429 lands nothing says when the window reopens. Retry immediately and you burn the next window; retry at a fixed interval across several workers and they synchronise into a thundering herd. Use exponential backoff with full jitter, from 1 second to about 30, plus a token bucket below 10 requests per second.

Limits are per team, not per key: a second key buys no throughput, and a batch importer shares its 10 requests per second with the live signup handler.

Official SDKs

Five official packages under the loops-so GitHub organisation, plus a CLI and agent skills.

LanguagePackageInstallRepo
JavaScript / TypeScriptloops on npmnpm install loopsloops-so/loops-js
PHPloops-so/loops on Packagistcomposer require loops-so/loopsloops-so/loops-php
Rubyloops_sdk on RubyGemsgem install loops_sdkloops-so/loops-rb
Gogithub.com/loops-so/loops-gogo get github.com/loops-so/loops-goloops-so/loops-go
Nuxt (module)nuxt-loops on npmnpm install nuxt-loopsNot documented

The JavaScript SDK requires Node 18.0.0 or later, the only runtime floor Loops publishes.

No published version numbers. Loops states no current version for any of the 5 SDKs: no version table, no minimum-supported-version statement, no deprecation notice. You can read the version from npm, Packagist, RubyGems or the Go proxy, but not whether it is the one the docs describe. Pin exact versions and read repository history before upgrading.

There is no Python SDK

This is the gap that catches Django and FastAPI teams. Loops publishes no PyPI package and no Python client; the documented path is SMTP, with an official Django guide. One caveat, covered in full on this platform’s SMTP settings tab: that relay still expects an API-shaped payload carrying a transactionalId, so it is not a drop-in mail backend. For a native client, generate one from the OpenAPI document.

CLI and agent skills

The official CLI carries 17 subcommands – auth, contacts, campaigns, campaign-groups, audience-segments, components, contact-properties, email-messages, event-patterns, events, lists, themes, transactional, transactional-groups, uploads, workflows, completion – mapping onto the REST resource families, which makes it a fast way to explore the API before writing code. Loops also publishes agent skills: packaged instructions giving a coding agent working knowledge of the platform without a tool connection.

Endpoints reference

The 47 documented paths group into roughly a dozen resource families. The OpenAPI document is authoritative for the full list.

ResourceMethodsDescription
API key test
/v1/api-key
GETValidates the token, returns success and teamName.
Dedicated sending IPs
/v1/dedicated-sending-ips
GETLists dedicated IPs; commercial terms are not published.
Contacts
/v1/contacts/create, /update, /find, /delete
GET, POST, PUTContact lifecycle, in verb-in-path style rather than REST-on-collections.
Suppression list
/v1/contacts/suppression
GET, DELETEReads and clears suppressions; check before debugging a non-delivery.
Contact properties
/v1/contacts/properties
GET, POSTLists and creates custom properties.
Mailing lists
list mailing lists
GETEnumerates lists, whose IDs carry subscription state.
Events
send an event, event patterns
GET, POSTSends behavioural events; reads event patterns by name or ID.
Transactional send
/v1/transactional
POSTSends one email by transactionalId with a dataVariables object.
Transactional templates
list, create, get, update, publish
GET, POSTTemplate management, with ensure-draft and publish steps.
Transactional groups
list, create, get, update
GET, POSTGroups templates; carries transactional preferences.
Campaigns
/v1/campaigns, /{campaignId}
GET, POSTCampaign CRUD, with audience targeting and scheduling.
Audience segments
/v1/audience-segments, /{audienceSegmentId}
GET, POSTLists and creates segments, reads one by ID.
Email messages and Guardian
get, update, send preview, Guardian
GET, POSTEdits content, sends previews, runs Guardian checks.
Themes and components
list, create, get, update
GET, POSTDesign themes and reusable content components.
Workflows (open alpha)
workflows, nodes, branches, connections
GET, POST, DELETEWorkflow and node CRUD, branches, connection rerouting, recursive deletion. Open alpha: the contract can change without notice.

Contact paths are action-oriented, not collection-oriented, so code generators assuming REST conventions need the OpenAPI document. And the newest families are open alpha: isolate them behind your own interface.

Code examples

Two calls worth memorising: proving the key works, and sending one transactional email.

Verify an API key

Run this first in every environment: a 200 with a teamName you recognise means the key is live and aimed at the right team.

curl -s https://app.loops.so/api/v1/api-key \
  -H "Authorization: Bearer YOUR_API_KEY"

# { "success": true, "teamName": "Your Team" }
# A bad, revoked or missing key returns HTTP 401.

Send a transactional email

Transactional sends are addressed by template: you pass a transactionalId for a template that already exists, the recipient address, and a dataVariables object with the values the template interpolates. There is no way to send ad hoc content here.

curl -s -X POST https://app.loops.so/api/v1/transactional \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "transactionalId": "YOUR_TRANSACTIONAL_ID",
    "email": "customer@example.com",
    "dataVariables": {
      "firstName": "Ada",
      "resetUrl": "https://example.com/reset/abc123"
    }
  }'

The official JavaScript SDK wraps the same call as sendTransactionalEmail with an identical argument object, on Node 18.0.0 or later.

Wrap both in a retry that backs off on 429, and treat the transactionalId as configuration: template IDs differ between staging and production, and a hardcoded one is the commonest cause of a reset email rendering the wrong template.

Common gotchas

Directory results for Loops MCP are mostly not Loops

Searching an MCP directory for Loops returns unrelated products: a loops-server entry on smithery.ai, the useloops.io service, the smogili1/loop_mcp repository, a Loopy MCP Server. None are loops.so, and installing one then wondering why your contacts never appear is a predictable half hour lost. Verify the host.

List endpoints have no documented pagination

Nothing describes a cursor, offset, page parameter or result cap for any list endpoint. On a new account that is invisible; on one with tens of thousands of contacts, a list call either returns an unbounded payload or silently truncates, with no way to tell which. Prefer targeted reads such as /v1/contacts/find, and drive bulk state from webhooks.

A 429 does not tell you when to retry

The budget headers help you avoid the ceiling, but nothing documents x-ratelimit-reset or retry-after on the rejection, and there is no queue: an over-limit request is rejected, not delayed. The client owns the retry policy entirely, so backoff with jitter is not optional, without it a multi-worker fleet retries in lockstep and stays over the limit.

Workflow endpoints are open alpha

The workflow family is open alpha, as were the transactional create and edit endpoints in June 2026. The shape can change with no deprecation window, and two of the eight changelog entries last quarter touched workflows, one of them changing a response guarantee. Pin the behaviour you depend on in a test.

The oversized-body error does not name the field

Loops returns the literal string Some body key or value is longer than allowable when a body exceeds its limits. The message names neither the offending key nor the threshold, and the limit is not published. It bites on dataVariables carrying long rendered strings. Validate lengths client-side, log payload size and the largest value on failure, and bisect by removing fields.

Deprecations and changelog

The current quarter of the official changelog, newest first. The pattern is a platform adding whole resource families rather than refining existing ones.

  • July 23, 2026 – audience segment creation, workflow management and event pattern read endpoints added.
  • July 16, 2026 – workflow responses guarantee a non-null rootNodeId.
  • July 8, 2026 – create and update endpoints for themes and components.
  • July 2, 2026 – Guardian endpoint launched, validating message content through the API.
  • July 1, 2026transactionalName added to transactional webhook events.
  • June 22, 2026 – workflow read and node retrieval endpoints, in open alpha.
  • June 19, 2026 – campaign endpoints extended with targeting, groups and scheduling; CC, BCC and language added to email messages.
  • June 5, 2026 – transactional email create and edit endpoints, in open alpha.

No deprecations are listed, and Loops publishes no policy on how much notice a breaking change gets. With two families in open alpha, follow the official API changelog rather than waiting to be told.

Frequently asked questions

Does Loops have an official MCP server?

Yes, at https://mcp.loops.so, over Streamable HTTP with OAuth through Client ID Metadata Documents. Be careful with directory listings: unrelated products are published under the name Loops.

Why does the Loops MCP server only expose four tools?

Because the API has 47 paths, and one tool per endpoint would spend a large share of an agent’s context window on schemas it never uses, degrading tool selection. Search, Describe, Execute and Teams proxy the whole API at constant cost, at the price of two extra round trips before the first useful call.

Can I authenticate the REST API with OAuth?

No. It accepts only Authorization: Bearer YOUR_API_KEY and returns 401 otherwise. OAuth exists on the MCP server only, so a product acting on customers’ accounts needs each customer to hand over a long-lived key.

Is there a Python SDK for Loops?

No. Loops publishes SDKs for JavaScript and TypeScript, PHP, Ruby, Go and a Nuxt module, five, no PyPI package. The documented Python path is SMTP, with an official Django guide. For a native client, generate one from https://app.loops.so/openapi.json.

What are the Loops API rate limits?

10 requests per second per team on standard endpoints, 60 per 60 seconds on the Content API. Responses carry x-ratelimit-limit and x-ratelimit-remaining. Over-limit requests are rejected with 429, with no queue and no documented reset header, so client-side backoff with jitter is required.

How do I verify a Loops webhook signature?

Compute HMAC-SHA256 over id.timestamp.rawBody with the secret prefixed whsec_, then compare in constant time against Webhook-Signature, using Webhook-Id and Webhook-Timestamp for the other components. Sign the raw bytes before any JSON parsing. Respond within 15 seconds and de-duplicate on Webhook-Id: Loops retries up to 8 times over roughly 28 days, out of order.

Changelog (recent)

  • 2026-09-14 API + MCP tab published. Official Loops MCP server inventoried at mcp.loops.so, OpenAPI spec read at build 1.21.12 with 47 paths.
  • 2026-07-23 Audience segment creation, workflow management and event pattern read endpoints added to the Loops API.
  • 2026-07-08 Create and update endpoints shipped for themes and components.
AAlaa Touil RRabeb How we test →

This review follows our email infrastructure testing methodology. We disclose affiliate relationships in our editorial independence policy.