---
title: "Set up a recurring post"
method: POST
path: "/api/recurring"
---

# Set up a recurring post

`POST /api/recurring`

## Request

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

Every paid plan (Starter 25, Pro 100, Agency 500, Scale 2,000 at a time; 403 plan_feature on Free). Occurrences are put in the queue up to 7 days ahead (at most 14 at once) as ordinary scheduled posts with payload._recurring: each can be edited (PATCH /api/schedule/{id}) or canceled alone, and goes through the brand's approval rules, the key's limits, X credits and the plan's monthly posts like any post. An occurrence whose time passed while the publisher was not running is never posted late. Answers with warnings when the duplicate guard would skip posts (one text every day with a 3-day guard).

## Request body

- object
  - `platforms` string[], required
  - `text` string: The post, when there is one text.
  - `variants` union[]: Texts used in turn: occurrence n uses variant ((n-1) mod count) + 1.
    - union
      - string
      - object
        - `text` string
        - `per_platform` object
  - `rule` object, required: When it repeats. Daylight saving: a time that does not exist on the day clocks go forward runs that much later (02:30 -> 03:30); a time that happens twice runs the first time.
    - `freq` 'daily' | 'weekly' | 'monthly', required
    - `interval` integer: Every N days / weeks / months, counted from start.
    - `days` string[]: weekly: the weekdays (default: the start date's).
    - `month_days` integer[]: monthly: days of the month; -1 = the last day. 31 falls on the last day of shorter months.
    - `times` string[]: 24-hour HH:MM, 1-4 a day. Default 09:00.
    - `timezone` string: IANA name. Default: the brand's queue timezone, else UTC.
    - `start` string, date: First day (default today); also the anchor of every N.
    - `until` string, date: Last day, inclusive.
    - `count` integer: Stop after N occurrences.
  - `guard_days` integer: When an occurrence is published, a network where the same text went out in the last N days (3-hour margin) is skipped, with code duplicate_recent in its result. 0 = off.
  - `per_platform` object
  - `media` object[]
  - `photo_url` string
  - `video_url` string
  - `options` object
  - `title` string
  - `label` string
  - `brand_id` string, uuid

## Response `201`

{ ok, recurring, queued_now, warnings, message }

## Other responses

- `400`: bad_rule, not_connected, text_required, too_long, media_required
- `403`: plan_feature, recurring_limit, x_paid_plan_required
- `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)
