---
title: Decks
description: List, create, copy, personalize, update and delete Signal Decks.
product: signal
section: api
order: 22
---

# Decks

Signal Decks are shareable presentations you send to buyers. Through the API you can create a blank Deck, copy an existing Deck, have ANI personalize a copy for a prospect contact, or build a Deck from a prospect contact's questionnaire answers. Deck content (slides and blocks) is edited in Signal.

## The Deck object

| Field | Type | Notes |
| --- | --- | --- |
| `id` | string | UUID. |
| `number` | string | Workspace-unique reference, such as `DCK-014`. |
| `title` | string | |
| `orientation` | string | `landscape` or `portrait`. |
| `notes` | string or null | Internal notes. |
| `status_id` | string | See [Status IDs](#status-ids). |
| `is_live` | boolean | Whether the Deck's share link is live. |
| `account_id` | string or null | |
| `deal_id` | string or null | |
| `prospect_id` | string or null | |
| `contact_id` | string or null | |
| `plot_id` | string or null | Property module plot. |
| `development_id` | string or null | Property module development. |
| `owner_id` | string or null | User ID of the Deck's owner. |
| `sent_at` | string or null | When the Deck was sent. Read-only. |
| `viewed_at` | string or null | When the Deck was viewed. Read-only. |
| `folder` | string or null | Folder name in the Deck library. |
| `slug` | string or null | |
| `created_at` | string | ISO 8601 timestamp. |
| `updated_at` | string | ISO 8601 timestamp. |

```json
{
  "id": "2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93",
  "number": "DCK-014",
  "title": "Fabrikam Logistics: proposal",
  "orientation": "landscape",
  "notes": null,
  "status_id": "rds_draft",
  "is_live": false,
  "account_id": null,
  "deal_id": null,
  "prospect_id": "e4b7c1d9-2f6a-4b3e-9c8d-5a1f7e2b4c63",
  "contact_id": null,
  "plot_id": null,
  "development_id": null,
  "owner_id": "5b8d1f3a-7e2c-4a9b-b6d4-1c3e5f7a9b20",
  "sent_at": null,
  "viewed_at": null,
  "folder": null,
  "slug": null,
  "created_at": "2026-11-12T09:30:00.000Z",
  "updated_at": "2026-11-12T09:30:00.000Z"
}
```

## Status IDs

| `status_id` | Status |
| --- | --- |
| `rds_draft` | Draft (the default for new Decks) |
| `rds_sent` | Sent |
| `rds_viewed` | Viewed |
| `rds_accepted` | Accepted |
| `rds_archived` | Archived |

---

## List Decks

`GET /decks` · Scope: `decks:read`

### Query parameters

| Parameter | Type | Required | Notes |
| --- | --- | --- | --- |
| `owner_id` | string | No | Only Decks owned by this user. |
| `limit` | integer | No | 1 to 100. Default 20. |
| `cursor` | string | No | `meta.cursor` from the previous page. |

### Example

```bash
curl "https://crm.empiraa.app/api/v1/decks?owner_id=5b8d1f3a-7e2c-4a9b-b6d4-1c3e5f7a9b20" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```js
const res = await fetch(
  "https://crm.empiraa.app/api/v1/decks?owner_id=5b8d1f3a-7e2c-4a9b-b6d4-1c3e5f7a9b20",
  { headers: { Authorization: "Bearer YOUR_API_KEY" } },
);
```

### Response `200`

An array of [Deck objects](#the-deck-object) in `data`; `meta` has `cursor` and `hasMore`.

---

## Create a Deck

`POST /decks` · Scope: `decks:write`

One endpoint, four ways to create a Deck:

| To | Send |
| --- | --- |
| Create a blank Deck | `title`, plus any optional fields |
| Copy an existing Deck | `template_deck_id`, plus any fields to override on the copy |
| Copy a Deck and personalize it for a prospect contact | `template_deck_id`, `personalise: true` and `prospect_id` |
| Build a Deck from a prospect contact's questionnaire | `generate_from_questionnaire: true` and `prospect_id` (and optionally `title`) |

### Request body

| Field | Type | Required | Notes |
| --- | --- | --- | --- |
| `title` | string | For a blank Deck | Optional when copying or generating; it then replaces the copied or generated title. |
| `template_deck_id` | string | To copy | A Deck in this workspace to copy, content included. |
| `personalise` | boolean | No | With `template_deck_id` and `prospect_id`: ANI rewrites the copy's content for the prospect contact, using their name, email and Prospect Company name. Default `false`. |
| `generate_from_questionnaire` | boolean | No | With `prospect_id`: builds a Deck with one section for each checkbox custom field ticked on the prospect contact. Can't be combined with `template_deck_id` or `personalise`. |
| `orientation` | string | No | `landscape` (default) or `portrait`. Blank Decks only. |
| `notes` | string or null | No | |
| `status_id` | string | No | Defaults to `rds_draft` for a blank Deck. |
| `is_live` | boolean | No | Defaults to `false` for a blank Deck. |
| `account_id` | string or null | No | |
| `deal_id` | string or null | No | |
| `prospect_id` | string or null | Required to personalize or generate | A prospect contact in this workspace. |
| `contact_id` | string or null | No | |
| `plot_id` | string or null | No | Blank Decks only. |
| `development_id` | string or null | No | Blank Decks only. |
| `owner_id` | string or null | No | A user ID from `GET /users`. |

### Example: blank Deck

```bash
curl -X POST https://crm.empiraa.app/api/v1/decks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Q1 partner briefing", "orientation": "landscape"}'
```

```js
await fetch("https://crm.empiraa.app/api/v1/decks", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ title: "Q1 partner briefing", orientation: "landscape" }),
});
```

### Example: personalized copy for a prospect contact

```bash
curl -X POST https://crm.empiraa.app/api/v1/decks \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "template_deck_id": "9c1e3a5b-7d9f-4b2d-8f4a-6c8e0a2c4e15",
    "personalise": true,
    "prospect_id": "e4b7c1d9-2f6a-4b3e-9c8d-5a1f7e2b4c63",
    "title": "Fabrikam Logistics: proposal"
  }'
```

```js
await fetch("https://crm.empiraa.app/api/v1/decks", {
  method: "POST",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({
    template_deck_id: "9c1e3a5b-7d9f-4b2d-8f4a-6c8e0a2c4e15",
    personalise: true,
    prospect_id: "e4b7c1d9-2f6a-4b3e-9c8d-5a1f7e2b4c63",
    title: "Fabrikam Logistics: proposal",
  }),
});
```

Personalizing and generating use AI and can take several seconds.

### Response `201`

The new [Deck object](#the-deck-object) in `data`.

### Errors

| Status | Code | When |
| --- | --- | --- |
| 400 | `INVALID_REQUEST` | `title` is missing for a blank Deck; a field has the wrong type; `personalise` is sent without `template_deck_id` or `prospect_id`; or `generate_from_questionnaire` is combined with `personalise` or `template_deck_id`, or sent without `prospect_id`. |
| 400 | `NO_QUESTIONNAIRE_FIELDS` | The prospect contact has no checkbox custom fields ticked. |
| 404 | `NOT_FOUND` | `template_deck_id` or a linked Account, Contact, Deal or prospect contact isn't in this workspace (`title` says which), or `owner_id` isn't an active member of the workspace. |
| 500 | `PERSONALISE_FAILED` | ANI couldn't personalize the copy. Retry later. |
| 500 | `CREATE_FAILED` | The Deck couldn't be created. Retry later. |

**Webhook events:** none.

---

## Get a Deck

`GET /decks/{id}` · Scope: `decks:read`

### Example

```bash
curl https://crm.empiraa.app/api/v1/decks/2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```js
await fetch("https://crm.empiraa.app/api/v1/decks/2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93", {
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
```

### Response `200`

The [Deck object](#the-deck-object) in `data`.

### Errors

| Status | Code | When |
| --- | --- | --- |
| 404 | `NOT_FOUND` | No Deck with that ID in this workspace. |

---

## Update a Deck

`PATCH /decks/{id}` · Scope: `decks:write`

Send only the fields you want to change: `title`, `orientation`, `notes`, `status_id`, `is_live`, `account_id`, `deal_id`, `prospect_id`, `contact_id`, `plot_id`, `development_id`, `owner_id`, `folder` and `slug`. Link fields, `notes`, `folder` and `slug` accept `null` to clear.

### Example

```bash
curl -X PATCH https://crm.empiraa.app/api/v1/decks/2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93 \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"is_live": true, "folder": "Proposals"}'
```

```js
await fetch("https://crm.empiraa.app/api/v1/decks/2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93", {
  method: "PATCH",
  headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ is_live: true, folder: "Proposals" }),
});
```

### Response `200`

The updated [Deck object](#the-deck-object) in `data`.

### Errors

| Status | Code | When |
| --- | --- | --- |
| 404 | `NOT_FOUND` | No Deck with that ID in this workspace, a linked record isn't in it, or `owner_id` isn't an active member of the workspace. |

**Webhook events:** none.

---

## Delete a Deck

`DELETE /decks/{id}` · Scope: `decks:write`

Deletes the Deck. Its share link stops working.

### Example

```bash
curl -X DELETE https://crm.empiraa.app/api/v1/decks/2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93 \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```js
await fetch("https://crm.empiraa.app/api/v1/decks/2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93", {
  method: "DELETE",
  headers: { Authorization: "Bearer YOUR_API_KEY" },
});
```

### Response `204`

No body.

### Errors

| Status | Code | When |
| --- | --- | --- |
| 404 | `NOT_FOUND` | No Deck with that ID in this workspace. |
