# Create an automation from a preset

> Creates a draft automation from a preset: an organization automation from a SaaS preset (onboarding, trial_ending, dunning, reengagement, saas_checkout; no…

Source: https://docs.pidgely.com/api-reference/automations/create/

`POST https://api.pidgely.com/automations`

Creates a **draft** automation from a `preset`: an organization automation from a SaaS preset (`onboarding`, `trial_ending`, `dunning`, `reengagement`, `saas_checkout`; no store needed), or an automation of a connected store from a store preset (`cart_abandoned`, `payment_pending`, `post_purchase`, `winback`; pass `store_id`). It gets the preset's steps, goal and settings, and one builder template per e-mail with your brand in English, Portuguese (Brazil) and Spanish (`locale` picks the base language of SaaS presets). Edit the templates in the builder, then [activate](https://docs.pidgely.com/api-reference/automations/activate/) it.

Creates a draft automation from a preset: an organization automation (SaaS presets: onboarding, trial ending, failed payment, re-engagement, abandoned checkout; no store needed) or an automation of a connected store (store presets). It gets the default steps, goal and settings, and one builder template per e-mail with the organization's brand in English, Portuguese (Brazil) and Spanish. Activate it to start. Admins and owners. Needs a plan with automations (Scale or custom; `403 plan_required` otherwise).

**Authorization:** `Bearer pdg_…`. An API key with `full_access`. A `sending_access` key gets `401 restricted_api_key`.

## Body parameters

JSON object.

| Name | Type | Required | Description |
|---|---|---|---|
| `preset` | string | No | Preset to start from (wins over trigger). One of `onboarding`, `trial_ending`, `dunning`, `reengagement`, `saas_checkout`, `cart_abandoned`, `payment_pending`, `post_purchase`, `winback`. |
| `store_id` | string | No | Store of a store preset (required for them; ignored by SaaS presets). UUID. |
| `locale` | string | No | Base language of a SaaS preset's e-mails (default pt-BR); the other two are variants. One of `en`, `pt-BR`, `es`. |
| `timezone` | string | No | IANA time zone of an organization automation's quiet hours and dates (default America/Sao_Paulo). |
| `trigger` | string | No | One of `cart_abandoned`, `payment_pending`, `post_purchase`, `winback`, `event`, `contact_added`, `contact_date`, `inactivity`. |
| `name` | string | No | Display name. |

## Request

This endpoint is not in the [SDKs](https://docs.pidgely.com/sdks/) yet; call it over HTTP.

```bash tab="cURL"
curl -X POST 'https://api.pidgely.com/automations' \
  -H "Authorization: Bearer $PIDGELY_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "preset": "trial_ending",
  "locale": "pt-BR",
  "timezone": "America/Sao_Paulo"
}'
```

## Response

`201 Created`

```json
{
  "object": "automation",
  "id": "0199e3d1-4a5b-7c6d-8e9f-0a1b2c3d4e51",
  "store_id": null,
  "preset": "trial_ending",
  "name": "Teste grátis acabando",
  "trigger": "contact_date",
  "status": "draft",
  "status_reason": "",
  "trigger_options": {
    "property": "trial_ends_at",
    "offset_seconds": -259200,
    "send_hour": 9,
    "yearly": false
  },
  "filter": {
    "segment_id": null,
    "properties": []
  },
  "goal": {
    "event_name": "subscription_started",
    "value_property": "amount"
  },
  "exit_events": [],
  "settings": {
    "quiet_hours": {
      "enabled": true,
      "start": 22,
      "end": 8,
      "timezone": "America/Sao_Paulo"
    },
    "frequency_cap": true,
    "attribution_days": 7,
    "from": "Fexxo <oi@fexxo.com.br>",
    "currency": "BRL"
  },
  "steps": [
    {
      "id": "0199e3d1-4a5c-7a01-8b02-3c4d5e6f7a11",
      "position": 0,
      "kind": "email",
      "wait_seconds": 0,
      "template_id": "0199e3d1-4a50-7b11-9c12-4d5e6f7a8b21",
      "template_name": "Teste grátis acabando · 1",
      "template_subject": "Seu teste grátis termina em 3 dias",
      "subject": "",
      "from": "",
      "coupon_code": "",
      "event_name": "",
      "on_event": "",
      "on_timeout": ""
    },
    {
      "id": "0199e3d1-4a5c-7a02-8b03-3c4d5e6f7a12",
      "position": 1,
      "kind": "wait",
      "wait_seconds": 172800,
      "template_id": null,
      "template_name": "",
      "template_subject": "",
      "subject": "",
      "from": "",
      "coupon_code": "",
      "event_name": "",
      "on_event": "",
      "on_timeout": ""
    },
    {
      "id": "0199e3d1-4a5c-7a03-8b04-3c4d5e6f7a13",
      "position": 2,
      "kind": "email",
      "wait_seconds": 0,
      "template_id": "0199e3d1-4a50-7b12-9c13-4d5e6f7a8b22",
      "template_name": "Teste grátis acabando · 2",
      "template_subject": "Último dia do seu teste grátis",
      "subject": "",
      "from": "",
      "coupon_code": "",
      "event_name": "",
      "on_event": "",
      "on_timeout": ""
    }
  ],
  "currency": "BRL",
  "last_30_days": {
    "enrolled": 412,
    "active": 57,
    "sent": 374,
    "skipped": 2,
    "opened": 198,
    "clicked": 73,
    "exited_goal": 34,
    "exited_other": 7,
    "conversions": 34,
    "revenue": 811190
  },
  "activated_at": null,
  "created_at": "2026-10-12 16:44:41.000000+00",
  "updated_at": "2026-10-12 16:44:41.000000+00"
}
```

### Response fields

| Name | Type | Required | Description |
|---|---|---|---|
| `object` | string | Yes | Object type. One of `automation`. |
| `id` | string | Yes | Unique id (UUID). UUID. |
| `store_id` | string \| null | Yes | Store of a store automation; null for an organization automation (SaaS and apps). UUID. |
| `preset` | string | Yes | Preset it was created from (onboarding, trial_ending, dunning, reengagement, saas_checkout, cart_abandoned, payment_pending, post_purchase, winback), or lifecycle_onboarding, lifecycle_first_send, lifecycle_upgrade and lifecycle_reengagement for the lifecycle automations of the platform organization (provisioned by the bootstrap). |
| `name` | string | Yes | Display name. |
| `trigger` | string | Yes | One of `cart_abandoned`, `payment_pending`, `post_purchase`, `winback`, `event`, `contact_added`, `contact_date`, `inactivity`. |
| `status` | string | Yes | Current status. One of `draft`, `active`, `paused`. |
| `status_reason` | string | Yes | Why it is paused: `plan` = the organization's plan no longer includes automations. One of ``, `manual`, `plan`, `store`. |
| `trigger_options` | object | Yes | `methods` (payment_pending: `pix`, `boleto`), `delivery_fallback_days` (post_purchase: an order paid this many days ago without a delivery event counts as delivered, 1-60), `inactive_days` (winback: days since the last paid order, 14-730; inactivity: days without the event, 1-365), `event_name` (event, inactivity), `segment_id` and `sources` (contact_added), `property`, `offset_seconds`, `send_hour` and `yearly` (contact_date). |
| `trigger_options.methods` | string[] | No | — |
| `trigger_options.delivery_fallback_days` | integer | No | — |
| `trigger_options.inactive_days` | integer | No | winback: 14-730; inactivity: 1-365. |
| `trigger_options.event_name` | string | No | event: the event that enrolls; inactivity: the event whose absence counts (empty = any event). |
| `trigger_options.segment_id` | string \| null | No | contact_added: only contacts added to this segment (null = every new contact). UUID. |
| `trigger_options.sources` | string[] | No | contact_added: sources of new contacts that count (empty = any). |
| `trigger_options.property` | string | No | contact_date: contact property holding the date (YYYY-MM-DD or RFC 3339). |
| `trigger_options.offset_seconds` | integer | No | contact_date: signed offset from the date (-259200 = 3 days before). |
| `trigger_options.send_hour` | integer | No | contact_date: hour of the day for dates without a time, in the automation's time zone (default 9). Between 0 and 23. |
| `trigger_options.yearly` | boolean | No | contact_date: every year on the date (birthdays). |
| `filter` | object | Yes | Entry filter. Only contacts in `segment_id` (when set) whose properties match every condition enter. |
| `filter.segment_id` | string \| null | Yes | Segment the broadcast is sent to. UUID. |
| `filter.properties` | object[] | Yes | Custom properties: up to 100 keys matching `^[A-Za-z_][A-Za-z0-9_]{0,49}$`, values string (up to 2,000 characters), number, boolean, or `null` to delete. |
| `filter.properties[].key` | string | Yes | — |
| `filter.properties[].op` | string | Yes | One of `eq`, `neq`, `exists`, `not_exists`. |
| `filter.properties[].value` | string | No | Compared as text (numbers and booleans as written in JSON). |
| `goal` | object | Yes | The event that ends the enrollment as a success (exit reason `goal`). It counts as a conversion when an e-mail of the automation went out within the attribution window; `value_property` (major units, e.g. 49.90) is summed as revenue. |
| `goal.event_name` | string | Yes | Empty = no goal event (store automations use their orders and payments). |
| `goal.value_property` | string | Yes | — |
| `exit_events` | string[] | Yes | — |
| `settings` | object | Yes | Optional behaviours. Quiet hours hold e-mails between `start` and `end` o'clock in the store's time zone (from its currency; `timezone` overrides it) and send them at `end`. The frequency cap allows one automation e-mail per address per 24 hours across every automation of the organization (later ones wait). Orders placed up to `attribution_days` after an automation e-mail count as recovered revenue. |
| `settings.quiet_hours` | object | Yes | — |
| `settings.quiet_hours.enabled` | boolean | Yes | — |
| `settings.quiet_hours.start` | integer | Yes | Between 0 and 23. |
| `settings.quiet_hours.end` | integer | Yes | Between 0 and 23. |
| `settings.quiet_hours.timezone` | string | No | IANA time zone; empty = the store's (organization automations default to America/Sao_Paulo). |
| `settings.frequency_cap` | boolean | Yes | — |
| `settings.attribution_days` | integer | Yes | Between 1 and 30. |
| `settings.from` | string | No | Default sender of an organization automation's e-mails (a step's sender wins; empty = the template's). |
| `settings.currency` | string | No | ISO 4217 currency of an organization automation's revenue (default BRL). |
| `steps` | object[] | Yes | — |
| `steps[].id` | string | Yes | Unique id (UUID). UUID. |
| `steps[].position` | integer | Yes | — |
| `steps[].kind` | string | Yes | One of `wait`, `email`, `wait_event`. |
| `steps[].wait_seconds` | integer | Yes | wait: duration. |
| `steps[].template_id` | string \| null | Yes | email: builder template (edit it in the template builder). UUID. |
| `steps[].template_name` | string | Yes | — |
| `steps[].template_subject` | string | Yes | The template's subject in the store's language. |
| `steps[].subject` | string | Yes | Subject override; empty = the template's (per language). |
| `steps[].from` | string | Yes | Sender; empty = the store's sender address. |
| `steps[].coupon_code` | string | Yes | `{{{COUPON_CODE}}}`; empty = blocks mentioning the coupon are left out. |
| `steps[].event_name` | string | Yes | wait_event: the event waited for (up to wait_seconds). |
| `steps[].on_event` | string | Yes | wait_event: go on (continue) or end the enrollment (exit, reason event_received) when the event happens. One of ``, `continue`, `exit`. |
| `steps[].on_timeout` | string | Yes | wait_event: go on or end the enrollment (reason timeout) when the wait runs out. One of ``, `continue`, `exit`. |
| `currency` | string | Yes | — |
| `last_30_days` | object | Yes | Counters over a period: customers enrolled, live (`active`: active or held now), e-mails sent and skipped, unique opens and clicks (tracked domains), exits by goal (an order, a payment) and for other reasons, conversions and recovered revenue (minor units of the store currency). |
| `last_30_days.enrolled` | integer | Yes | — |
| `last_30_days.active` | integer | Yes | — |
| `last_30_days.sent` | integer | Yes | — |
| `last_30_days.skipped` | integer | Yes | — |
| `last_30_days.opened` | integer | Yes | — |
| `last_30_days.clicked` | integer | Yes | — |
| `last_30_days.exited_goal` | integer | Yes | — |
| `last_30_days.exited_other` | integer | Yes | — |
| `last_30_days.conversions` | integer | Yes | — |
| `last_30_days.revenue` | integer | Yes | Format: `int64`. |
| `activated_at` | string \| null | Yes | Format: `date-time`. |
| `created_at` | string | Yes | Creation time, `YYYY-MM-DD HH:MM:SS.ffffff+00` (UTC). Format: `date-time`. |
| `updated_at` | string | Yes | Format: `date-time`. |

## Errors

Errors have the shape `{"statusCode", "name", "message"}`. See [Errors](https://docs.pidgely.com/errors/) for the full list.

| Status | Name | When |
|---|---|---|
| 401 | `missing_api_key`, `restricted_api_key` | No `Authorization: Bearer` header, or a `sending_access` key called an endpoint that needs `full_access`. |
| 403 | `invalid_api_key`, `validation_error` | The API key is invalid or revoked, or the request is not allowed for this account (unverified domain, plan limit, paused account). |
| 404 | `not_found` | The resource does not exist in this account (or the id is not a valid UUID). |
| 422 | `validation_error` | A field is missing or invalid; `message` names it. |
| 429 | `rate_limit_exceeded` | Too many requests per second. Wait for `Retry-After` seconds. |
| 403 | `plan_required` | The organization is below the Scale plan (`field` is `automations`). |
| 422 | `store_required` | A store preset without `store_id`. |
| 422 | `validation_error` | Unknown `preset` or `trigger`, or the store is disconnected (`store_disconnected`). |
