> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dmly.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Automation packs

> Create, fill and publish the automation packs your customers add from their automation gallery, from your own systems.

These endpoints manage the automation packs your agency offers its customers: named sets of
automations a customer adds in one go, paused, from **Automations → New automation → Automation
packs**. They do exactly what the console's **Automation packs** page does, under the same rules;
read [Build automation packs for your customers](/agency/automation-packs) for what each rule is
for.

```bash theme={"dark"}
curl https://dash.dmly.io/api/agency/v1/packs \
  -H "x-api-key: dmly_ag_xxxxxxxxxxxx"
```

<Note>
  There is no endpoint that accepts flow JSON. An automation in a pack is either one of DMLY's
  library automations or a copy of a published automation from one of your sub-accounts, and a
  copy is always cleaned of everything that belonged to that customer or points at your own
  accounts.
</Note>

## Endpoints

| Method | Path | Does |
| - | - | - |
| `GET` | `/packs` | List your packs, each with its automations |
| `POST` | `/packs` | Create a pack (always a draft) |
| `GET` | `/packs/{pack}` | Read one pack |
| `PATCH` | `/packs/{pack}` | Change a pack's details or status |
| `DELETE` | `/packs/{pack}` | Delete a pack |
| `PUT` | `/packs/order` | Put your packs in order |
| `GET` | `/packs/library` | DMLY's automations a pack can include |
| `POST` | `/packs/{pack}/entries` | Add an automation, from the library or copied from a sub-account (copying needs the copy ability) |
| `PATCH` | `/packs/{pack}/entries/{entry}` | Rename an automation, or change its tier or prerequisites |
| `DELETE` | `/packs/{pack}/entries/{entry}` | Remove an automation from a pack |
| `PUT` | `/packs/{pack}/entries/order` | Put a pack's automations in order |
| `GET` | `/packs/import/sources` | Sub-accounts with automations you can copy. Needs the [copy ability](#copying-needs-a-key-with-the-copy-ability) |
| `GET` | `/packs/import/preview` | What copying one automation would clear, or why it can't be copied. Needs the copy ability |
| `GET` | `/packs/visibility` | Whether customers see only your packs |
| `PUT` | `/packs/visibility` | Change it |

`{pack}` and `{entry}` are uuids. A pack belonging to another agency returns `404`, the same as one
that doesn't exist. None of these lists is paginated.

## Copying needs a key with the copy ability

Copying from a sub-account reads that customer's automation, every message in it included, so an
ordinary agency key can't do it. `GET /packs/import/sources`, `GET /packs/import/preview` and a
`POST /packs/{pack}/entries` that copies all need a key generated with **Copy automations out of
sub-accounts into packs** ticked, under **Configuration → API** in the agency console. Only a team
member who holds the **Copy automations from sub-accounts into packs** permission sees that box, and
keys generated before it existed don't have it. Without it those calls return `403`:

```json theme={"dark"}
{ "message": "This API key cannot copy automations out of sub-accounts. Generate a key with that ability in the agency console." }
```

Everything else on this page, adding library automations included, works with any agency key.

## The pack object

```json theme={"dark"}
{
  "uuid": "3f1d2b6e-7a4c-4f0e-9b8d-1c2e3f4a5b6c",
  "name": "Salon Win-Back System",
  "summary": "Bring lapsed clients back and fill quiet days.",
  "industry": "salons",
  "business_type": "salon_spa",
  "status": "published",
  "installed_in": 12,
  "entries": [
    {
      "uuid": "8a7b6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d",
      "source": "library",
      "template_id": "birthday-offer",
      "name": "Birthday treat",
      "library_name": "Birthday offer",
      "name_override": "Birthday treat",
      "description": "Wish each contact a happy birthday with a little treat, sent automatically on the day.",
      "description_override": null,
      "tier": "optional",
      "requires": [],
      "ai": false,
      "catch_all": false,
      "trigger_label": "On a birthday",
      "channels": ["whatsapp", "facebook", "instagram", "sms", "tiktok", "telegram", "livechat", "gbp"],
      "missing": false,
      "slots": []
    },
    {
      "uuid": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
      "source": "custom",
      "template_id": null,
      "name": "Lapsed client: win back",
      "library_name": null,
      "name_override": "Lapsed client: win back",
      "description": "",
      "description_override": null,
      "tier": "core",
      "requires": ["template"],
      "ai": false,
      "catch_all": false,
      "trigger_label": "Keyword: comeback",
      "channels": ["whatsapp"],
      "missing": false,
      "slots": [
        { "node": "n3", "path": "template_id", "label": "the WhatsApp template", "step": "Send template" }
      ]
    }
  ]
}
```

| Field | Meaning |
| - | - |
| `status` | `draft` (customers can't see it), `published`, or `archived` (hidden, kept) |
| `industry` | The industry label on the card, or `null`. See [values](#accepted-values) |
| `business_type` | New customers of this type are given this pack when they connect their first messaging channel, or `null` for nobody. See [Give a pack to new customers](/agency/automation-packs#give-a-pack-to-new-customers) |
| `installed_in` | How many customer workspaces hold at least one automation from this pack |
| `entries` | The pack's automations, in the order customers read them |

Each entry:

| Field | Meaning |
| - | - |
| `source` | `library` (one of DMLY's) or `custom` (copied from a sub-account) |
| `template_id` | The library id for a `library` entry, `null` for a copy |
| `name` | The name customers see and the installed automation gets |
| `library_name` | The library's own name, so a renamed entry can say what it was. `null` for a copy |
| `name_override`, `description_override` | What you set, or `null` for the original |
| `tier` | `core` or `optional`. Customers see an **Optional** label on `optional` |
| `requires` | Prerequisites the customer must meet before it can be switched on. See [values](#accepted-values) |
| `ai` | It has an A.I. step |
| `catch_all` | It answers every message or comment. A pack holds at most one |
| `channels` | The channel types it can install on. A copy is limited to the type it was built on |
| `missing` | A library automation DMLY has since retired. Installs skip it |
| `slots` | For a copy: the steps that were cleared and each customer must fill in. `label` and `step` are the readable part |

## Create and fill a pack

<Steps>
  <Step title="Create the pack">
    ```bash theme={"dark"}
    curl -X POST https://dash.dmly.io/api/agency/v1/packs \
      -H "x-api-key: dmly_ag_xxxxxxxxxxxx" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Salon Win-Back System",
        "summary": "Bring lapsed clients back and fill quiet days.",
        "industry": "salons",
        "business_type": "salon_spa"
      }'
    ```

    `name` is required (up to 120 characters); `summary` (up to 300), `industry` and
    `business_type` are optional. Returns `201` with the pack. It is always a `draft`: a `status`
    sent here is ignored.
  </Step>

  <Step title="Add library automations">
    List what's available with `GET /packs/library`. Each item's `id` is the `template_id` to send:

    ```bash theme={"dark"}
    curl -X POST https://dash.dmly.io/api/agency/v1/packs/{pack}/entries \
      -H "x-api-key: dmly_ag_xxxxxxxxxxxx" \
      -H "Content-Type: application/json" \
      -d '{"template_id": "birthday-offer"}'
    ```

    Returns `201` with the new entry. Its `requires` is pre-filled from the steps it uses; change
    it with `PATCH` if it's wrong for your customers. Library items carry the same `catch_all`,
    `ai` and `requires` hints as entries, plus `industry`, `industry_label`, `trigger_label` and
    `channels`, so you can check the rules before you add.
  </Step>

  <Step title="Or copy one from a sub-account">
    This step needs a key with the [copy ability](#copying-needs-a-key-with-the-copy-ability).
    Find what you can copy with `GET /packs/import/sources`, which returns each of your
    sub-accounts that has at least one published flow automation:

    ```json theme={"dark"}
    {
      "data": [
        {
          "uuid": "11111111-1111-1111-1111-111111111111",
          "name": "Glow Studio",
          "automations": [
            { "uuid": "22222222-2222-2222-2222-222222222222", "name": "Lapsed client: win back", "platform": "whatsapp" }
          ]
        }
      ]
    }
    ```

    Check it first. Nothing is saved by a preview:

    ```bash theme={"dark"}
    curl "https://dash.dmly.io/api/agency/v1/packs/import/preview?workspace=11111111-1111-1111-1111-111111111111&automation=22222222-2222-2222-2222-222222222222" \
      -H "x-api-key: dmly_ag_xxxxxxxxxxxx"
    ```

    ```json theme={"dark"}
    {
      "data": {
        "name": "Lapsed client: win back",
        "platform": "whatsapp",
        "refusals": [],
        "catch_all": false,
        "slots": ["the WhatsApp template in the “Send template” step"]
      }
    }
    ```

    An empty `refusals` means it can be copied; otherwise each string says why not. `slots` is what
    each customer will fill in. Then copy it by sending `workspace` and `automation` instead of
    `template_id`:

    ```bash theme={"dark"}
    curl -X POST https://dash.dmly.io/api/agency/v1/packs/{pack}/entries \
      -H "x-api-key: dmly_ag_xxxxxxxxxxxx" \
      -H "Content-Type: application/json" \
      -d '{
        "workspace": "11111111-1111-1111-1111-111111111111",
        "automation": "22222222-2222-2222-2222-222222222222"
      }'
    ```

    The published version is copied, not a draft, and the copy is a snapshot: later edits in the
    sub-account don't change it.
  </Step>

  <Step title="Publish">
    ```bash theme={"dark"}
    curl -X PATCH https://dash.dmly.io/api/agency/v1/packs/{pack} \
      -H "x-api-key: dmly_ag_xxxxxxxxxxxx" \
      -H "Content-Type: application/json" \
      -d '{"status": "published"}'
    ```

    The pack appears in your customers' galleries straight away. An empty pack can't be published.
  </Step>
</Steps>

## Change a pack

`PATCH /packs/{pack}` takes any of `name`, `summary`, `industry`, `business_type` and `status`;
only the fields you send change. Send `null` to clear `summary`, `industry` or `business_type`.
It returns the updated pack.

`DELETE /packs/{pack}` returns `{"data": {"deleted": true}}`. The pack leaves every customer's
gallery; automations customers already added stay exactly as they are. Set `status` to
`archived` instead if you might want it back.

Nothing on this page changes an automation already in a customer's workspace. An edit only
changes what the next install gets.

### Put your packs in order

`PUT /packs/order` sets the order of your packs. It is the order customers see them in their
gallery (yours always come before DMLY's), and when two of your published packs share a
`business_type`, a new customer of that type is given the higher one.

```bash theme={"dark"}
curl -X PUT https://dash.dmly.io/api/agency/v1/packs/order \
  -H "x-api-key: dmly_ag_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"order": ["3f1d2b6e-7a4c-4f0e-9b8d-1c2e3f4a5b6c", "9c8b7a6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"]}'
```

Packs you leave out keep their place after the ones you name, and drafts and archived packs can
be included. It returns every pack's uuid in the new order:

```json theme={"dark"}
{ "data": ["3f1d2b6e-7a4c-4f0e-9b8d-1c2e3f4a5b6c", "9c8b7a6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d"] }
```

## Change an automation in a pack

`PATCH /packs/{pack}/entries/{entry}` takes any of:

| Field | Value |
| - | - |
| `name` | The name customers see, up to 120 characters, different from every other name in the pack (ignoring capitals). For a `library` entry, `null` or `""` goes back to the library's name. A copy has no other name to fall back on, so a blank one is refused |
| `description` | Up to 500 characters. `null` or `""` goes back to the original |
| `tier` | `core` or `optional` |
| `requires` | The full list of prerequisites, replacing what was there. `[]` for none |

It returns the updated entry.

`DELETE /packs/{pack}/entries/{entry}` removes it:

```json theme={"dark"}
{ "data": { "deleted": true, "pack_status": "draft", "unpublished": true } }
```

Removing the last automation from a published pack sends the pack back to `draft`, and
`unpublished` says so.

`PUT /packs/{pack}/entries/order` sets the order customers read:

```json theme={"dark"}
{ "order": ["1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e", "8a7b6c5d-4e3f-4a2b-9c1d-0e9f8a7b6c5d"] }
```

Entries you leave out keep their place after the ones you name. A uuid that isn't in the pack is
refused with `422`. It returns the pack.

## Show customers only your packs

```bash theme={"dark"}
curl -X PUT https://dash.dmly.io/api/agency/v1/packs/visibility \
  -H "x-api-key: dmly_ag_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"replace_platform": true}'
```

`replace_platform: false` (the default) shows customers your published packs first, then DMLY's.
`true` shows only yours, and a new customer is only ever given one of yours: the pack for their
`business_type`, else your `other` pack, else none. It takes effect once you have at least one
published pack, so turning it on early never leaves customers with nothing. See
[Give a pack to new customers](/agency/automation-packs#give-a-pack-to-new-customers).
`GET /packs/visibility` reads it, and `GET /packs` returns it too, in `meta`:

```json theme={"dark"}
{ "data": [ … ], "meta": { "replace_platform": false, "max_entries": 9 } }
```

## Accepted values

| Field | Values |
| - | - |
| `industry` | `ecommerce`, `real_estate`, `restaurants`, `cleaning`, `salons`, `healthcare`, `education`, `events`, `automotive`, `professional` |
| `business_type` | `salon_spa`, `clinic_wellness`, `retail_ecommerce`, `restaurant_cafe`, `real_estate`, `agency_consultancy`, `education_coaching`, `other` |
| `requires` | `service` (a service or product to sell), `availability` (working hours), `booking_page`, `payment` (a payment method connected), `contact` (at least one contact), `template` (an approved WhatsApp template) |
| `status` | `draft`, `published`, `archived` |
| `tier` | `core`, `optional` |

## Errors

A refused change returns `422` with the reason under the field it concerns, in the usual shape:

```json theme={"dark"}
{
  "message": "A pack holds at most 9 automations. Split it into two packs, or remove one first.",
  "errors": {
    "template_id": ["A pack holds at most 9 automations. Split it into two packs, or remove one first."]
  }
}
```

| Field | When |
| - | - |
| `status` | Publishing a pack with no automations: `Add at least one automation before publishing this pack.` |
| `template_id` | The pack is full (nine automations); a second automation that answers every message; the same library automation twice; an automation of that name already in the pack; an id not in the library; or neither `template_id` nor `workspace` and `automation` sent |
| `automation` | Copying: the automation isn't published, uses a step that can't go into a pack, fails the pack's rules, or has the same name as an automation already in the pack |
| `name` | Renaming: the name is taken in this pack (`An automation called “<name>” is already in this pack. Give one of them a different name.`), or a copy's name was left blank (`A copied automation needs a name.`) |
| `order` | A uuid that isn't in this pack, or for `PUT /packs/order`, a pack that isn't yours |

`403` on the copy endpoints means the key lacks the
[copy ability](#copying-needs-a-key-with-the-copy-ability). `404` comes back as `Pack not found.`,
`Automation not found in this pack.`, `Sub-account not found.` (a workspace that isn't yours) or
`Automation not found.` Authentication errors and the rate limit are the same as everywhere else on
the Agency API; see [Authentication](/api-reference/agency-authentication).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.