This is a hand-written guide. The canonical, always-current reference is generated from the live OpenAPI spec → api-reference.html.
API/v1/Feeds/Create

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.

POST https://api.rssemit.com/v1/feeds stable · since v1.0

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.

Request curl
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"
  }'
200 OK · application/json 12 ms
{
  "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.
i
Conditional GET is on by default. Emit stores the 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

200 existed (idempotent)
201 created
400 invalid url
402 balance < $1.00
403 domain not verified
422 feed unparseable

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.

~/.claude/mcp.json copy
{
  "mcpServers": {
    "emit": {
      "type": "http",
      "url":  "https://api.rssemit.com/mcp",
      "headers": { "Authorization": "Bearer sk_live_…" }
    }
  }
}
!
The server runs inside the Emit API: every tool call executes against your account using the key in your 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.

terminal zsh
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"
← previous
Authentication
getting-started
next →
List feeds
GET /v1/feeds