Create a feed
Register an RSS or Atom URL. Emit polls it every 5 minutes (or on a webhook ping), diffs
against the last etag, and emails any new <item>
to your confirmed subscribers from your verified domain.
Idempotent: a duplicate URL on the same account returns the existing feed with
200 OK instead of 409. Use the
Idempotency-Key header for safe retries.
curl -X POST https://api.rssemit.com/v1/feeds \ -H "Authorization: Bearer $EMIT_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: 7b3f…" \ -d '{ "url": "https://blog.dev/rss.xml", "from": "posts@blog.dev", "schedule": "on_publish", "template": "tmpl_default" }'
{ "id": "feed_8Hk2qR4mA", "object": "feed", "url": "https://blog.dev/rss.xml", "from": "posts@blog.dev", "status": "watching", "schedule": "on_publish", "template": "tmpl_default", "last_etag": null, "last_polled": null, "created_at": "2026-05-25T20:30:29Z" }
Body parameters #
| Field | Type | Description |
|---|---|---|
| url required | string · url |
An HTTP(S) URL returning RSS 2.0 or Atom 1.0. Must be reachable from
3.94.0.0/16 within 5 s. Self-signed certs are rejected.
|
| from required | string · email | Sender address. Domain must be verified — see POST /v1/domains. The local part can be anything you own. |
| schedule optional | enum |
One of on_publish, poll_5m, poll_15m,
poll_1h, manual. Default: poll_5m.
|
| template optional | string · id |
An MJML/HTML template overriding the per-feed default, or the literal
tmpl_default for our maintained plaintext-first design.
|
| filter optional | object |
Skip items matching predicates. Supports tag_in,
tag_not_in, title_regex, and
min_word_count. See filters reference.
|
| throttle_per_hour optional | integer |
Maximum new items emitted per hour from this feed. Anything over this queues for
the next window. Default: 10.
|
ETag +
Last-Modified returned by your feed and replays them on every poll. If your
origin responds 304, the request is free and we don't re-parse — 92%
of polls land here in practice. Make sure your CDN passes these headers.
Returns #
A feed object. The id is stable and safe to store — we never
recycle it, even after a delete.
Status codes
MCP server #
Emit hosts a remote MCP server at https://api.rssemit.com/mcp — there's
nothing to install. Point any MCP-aware client (Claude Code, Cursor, Codex) at the URL
with your API key. It exposes create_account, account,
verify_domain, connect_feed, add_subscriber,
import_subscribers, top_up, and send_broadcast as
tools.
{ "mcpServers": { "emit": { "type": "http", "url": "https://api.rssemit.com/mcp", "headers": { "Authorization": "Bearer sk_live_…" } } } }
Authorization header — the same auth, validation, and rate
limits as the REST API. Your subscribers' data is never proxied through a third
party, and there's no package to keep updated.
Claude Code skill #
The skill is a single static file at https://rssemit.com/skill.md. Save it
into ~/.claude/skills/ and Claude Code will know how to wire Emit into any
blog repo — it reads your CLAUDE.md, finds your RSS feed, verifies your
sending domain (DKIM/SPF/DMARC), imports subscribers, and sends the first broadcast.
mkdir -p ~/.claude/skills/emit curl -fsSL https://rssemit.com/skill.md \ -o ~/.claude/skills/emit/SKILL.md # Then, in any repo: claude "add a newsletter to this blog using emit"