---
title: "Add a feed or a Google Sheet"
method: POST
path: "/api/rss"
---

# Add a feed or a Google Sheet

`POST /api/rss`

## Request

- Base URL: `https://postwire.io`
- URL: `https://postwire.io/api/rss`
- Auth: HTTP bearer

Feeds and sheets per account, both kinds together: Free 1, Starter 25, Pro 100, Agency 500, Scale 2,000. Read no more often than the plan allows: Free every 6 hours, Starter hourly, Pro and above every 30 minutes; asking for faster reads, more items per read or AI writing than the plan has answers 403 with the plan that has it. Find a feed from any site, blog or YouTube channel first with POST /api/rss/discover.

kind rss: the first read happens now and only records what is already in the feed. Each new item (new by its guid AND its link) becomes a post, at most the plan's items per read (Free 1, Starter 3, Pro 5, Agency and Scale 10), queued now or in the brand's next free slot, or sent to approvals; brand approval rules for automations apply too.

kind sheet (a Google Sheets link): the bulk upload's columns plus an optional status column (only Approved or Ready rows). The first read schedules the ready rows ahead (rows in the past are skipped), at most the plan's CSV rows per upload per read; on Free 3 wait in the queue and the rest are saved as held until an upgrade. Each row is scheduled once: a row whose text or time changed after it was scheduled is reported in last_error, never scheduled again. Until sql/pw_sheet_feeds.sql runs on the server a sheet answers 503 automation_unavailable.

A feed is turned off after 10 failed reads in a row.

## Request body

- object
  - `kind` 'rss' | 'sheet': sheet: a Google Sheet (a docs.google.com/spreadsheets link is taken as one even without kind).
  - `url` string, required: RSS 2.0, RSS 1.0 or Atom, or for kind sheet a Google Sheets sharing, Publish to web or export link (stored as that tab's CSV address). http or https on ports 80, 443, 8080 or 8443; private, loopback, link-local and metadata addresses are refused (400 feed_url_blocked), also when a name resolves to one or a redirect points at one; at most 3 redirects, 8 seconds, 2 MB.
  - `timezone` string: kind sheet: the timezone of times without one (a row's timezone column wins). Default: the brand's queue timezone.
  - `title` string
  - `platforms` string[]: Required for a feed. Not YouTube or TikTok (video only). Instagram gets an item only when it has an image. For a sheet: the networks of a row whose networks cell is empty.
  - `template` string: {title}, {link}, {summary}. Fitted to each network's limit as that network counts it: the summary is shortened first, then the title; the link is never cut.
  - `interval_minutes` integer: Default: hourly, or the plan's pace when it is slower (Free: 360). Below the plan's pace: 403 feed_interval_limit.
  - `max_items` integer: New items posted per read, oldest first; the rest wait for the next read. Default 3, or the plan's items per read when lower (Free: 1). Above it: 403 feed_items_limit.
  - `mode` 'auto' | 'approval': approval: every new item waits for approval (paid plans).
  - `post_at` 'now' | 'next_slot'
  - `include_image` boolean
  - `ai_rewrite` boolean: Write each network's post with AI (paid plans; on Free 403 plan_feature feed_ai): one AI draft per item, from the workspace's AI budget, never an extra charge; the template when it is used up or the account's email is not confirmed.
  - `post_latest` boolean: Also post the newest item now. Otherwise the items already in the feed are recorded, not posted.
  - `enabled` boolean
  - `brand_id` string, uuid

## Response `201`

{ ok, feed, first_read: { primed? | posted? | held? | later? | error? }, message }

## Other responses

- `400`: feed_url_blocked, bad_feed_url, bad_sheet_url, bad_timezone, bad_template, media_required, not_connected, platforms_required
- `403`: plan_feature (approvals, feed_ai), rss_feed_limit, feed_interval_limit, feed_items_limit — each with the plan that has it
- `409`: rss_feed_exists
- `503`: automation_unavailable

---

[API](https://skmtc.dev/postwire/apis/postwire-api.md) · [All operations](https://skmtc.dev/postwire/apis/postwire-api/llms.txt) · [OpenAPI document](https://skmtc.dev/postwire/apis/postwire-api/revisions/513a409ab8f7?raw)
