# Automations

A automation is a batch of AI posts generated at once and auto-scheduled across a posting window. You set a cadence (posts per day, for how many days), Viraloop generates one post per slot using the workspace's brand context, you review the batch, and launching turns every post into a scheduled post at its slot. Automation endpoints need the `automations:read` and `automations:write` scopes.

## Lifecycle

`draft` -> `generating` -> `review` -> `active` -> `completed` or `cancelled`

- `draft`: created and fully editable, no posts yet; a generation run that produces nothing also falls back here
- `generating`: posts are being generated; poll `GET /automations/{id}` until the automation leaves this status
- `review`: the batch is ready; inspect the posts, tweak settings or regenerate, then launch
- `active`: launched; posts render server-side and publish automatically at their slots
- `completed`: the posting window has run its course
- `cancelled`: cancelled; unsent posts were removed

## Quota

The monthly automation quota depends on the plan. `GET /automations` returns it alongside the list:

```json
{
	"quota": {
		"monthlyLimit": 8,
		"usedThisMonth": 2,
		"remaining": 6
	}
}
```

Once the quota is used up, starting another automation fails with error type `usage_limit_reached`; see [errors and rate limits](/developers/docs/errors-and-rate-limits).

```bash
curl -s "https://viraloop.io/api/v1/automations" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop automations list --json
```

## 1. Create

`POST /automations` creates the automation in `draft` (scope `automations:write`, supports the `Idempotency-Key` header). Only `name` is required; everything else can be set now or later via `PATCH`:

- `cadence`: `postsPerDay` (1 to 10), `lengthDays` (1 to 90), `startDate` (first posting day, defaults to tomorrow), `timezone` (IANA name) and optional `timeSlots` like `["09:00", "15:00"]`
- `selectedAccounts`: platform keys mapping to arrays of account ids from `GET /accounts`, with at least one non-empty platform array. Every post in the automation publishes to all selected accounts.
- `settings`: generation settings, all optional with sensible defaults: `contentMix` (format weights, keys `walloftext`, `slideshow`, `greenscreen`, `hookdemo`), `remixRatio`, `angleDistribution`, `mentionBusiness`, `genderPreference`, `ownMediaMix`, `influencerFrequency`
- `ownerType` (`brand` or `influencer`; `influencerId` is required when `influencer`), `tiktokMode` (`direct` or `inbox`; inbox sends TikTok drafts to the inbox instead of publishing) and `workspaceId`

```bash
curl -s -X POST "https://viraloop.io/api/v1/automations" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "July launch week",
    "cadence": { "postsPerDay": 2, "lengthDays": 7, "timezone": "America/New_York" },
    "selectedAccounts": { "tiktok": ["665f1b2a9c31a2b3c4d5e700"] }
  }'
```

```bash
viraloop automations create --name "July launch week" --posts-per-day 2 --length-days 7 \
  --timezone America/New_York --accounts tiktok:<accountId> --json
```

## 2. Generate

`POST /automations/{id}/generate` generates `postsPerDay x lengthDays` AI posts, each assigned a schedule slot. It is asynchronous: the response is `202` immediately (rate limited to 5 requests per 3600 seconds):

```json
{
	"success": true,
	"data": {
		"id": "665f1b2a9c31a2b3c4d5e710",
		"kind": "automation",
		"status": "generating",
		"totalPosts": 14,
		"generatedCount": 0,
		"statusUrl": "/api/v1/automations/665f1b2a9c31a2b3c4d5e710"
	}
}
```

Poll `GET /automations/{id}` until the automation leaves `generating`: `review` means the batch is ready; back to `draft` means nothing was generated. Calling generate again while a run is in flight is a no-op that reports progress (`generatedCount` against `totalPosts`). Regenerating a automation in `review` replaces its posts.

```bash
curl -s -X POST "https://viraloop.io/api/v1/automations/<id>/generate" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
curl -s "https://viraloop.io/api/v1/automations/<id>" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop automations generate <id> --json
viraloop automations get <id> --json
```

## 3. Review

`GET /automations/{id}/posts` lists the generated posts in schedule order. Each carries `caption`, `postCaption`, `hashtags`, its rationale and its assigned `scheduledTime`:

```bash
curl -s "https://viraloop.io/api/v1/automations/<id>/posts" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop automations posts <id> --json
```

To tweak the automation, `PATCH /automations/{id}` updates `name`, `cadence`, `selectedAccounts`, `settings`, `ownerType`, `influencerId` or `tiktokMode`. Editing is only allowed while the automation is in `draft` or `review`; any other status returns `409` with error type `conflict`. Sub-objects are replaced wholesale, so send the complete `cadence`, `selectedAccounts` or `settings` object, not just the changed keys.

```bash
curl -s -X PATCH "https://viraloop.io/api/v1/automations/<id>" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"selectedAccounts": {"tiktok": ["665f1b2a9c31a2b3c4d5e700"]}}'
```

```bash
viraloop automations update <id> --accounts tiktok:<accountId> --json
```

If the content itself is off rather than the settings, regenerate instead: it replaces the batch.

## 4. Launch

`POST /automations/{id}/launch` converts every generated post into a scheduled post at its slot and activates the automation. It requires status `review` and at least one selected account:

```json
{
	"success": true,
	"data": {
		"id": "665f1b2a9c31a2b3c4d5e710",
		"kind": "automation",
		"status": "active",
		"scheduled": 14,
		"failed": 0,
		"statusUrl": "/api/v1/automations/665f1b2a9c31a2b3c4d5e710"
	}
}
```

Posts render server-side after the call returns and publish automatically at their slots; nothing more is required. Track them with `GET /posts?automationId=<id>` or the calendar from [posts and scheduling](/developers/docs/posts-and-scheduling).

```bash
curl -s -X POST "https://viraloop.io/api/v1/automations/<id>/launch" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop automations launch <id> --json
```

## Cancelling

`POST /automations/{id}/cancel` cancels the automation and removes its unsent posts. Content that already went out stays live. Cancelling is idempotent: a cancelled or completed automation returns `cancelledPosts: 0`.

```bash
curl -s -X POST "https://viraloop.io/api/v1/automations/<id>/cancel" \
  -H "Authorization: Bearer $VIRALOOP_API_KEY"
```

```bash
viraloop automations cancel <id> --json
```
