Decks
List, create, copy, personalize, update and delete Signal 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. |
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. |
{
"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#
curl "https://crm.empiraa.app/api/v1/decks?owner_id=5b8d1f3a-7e2c-4a9b-b6d4-1c3e5f7a9b20" \
-H "Authorization: Bearer YOUR_API_KEY"
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 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#
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"}'
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#
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"
}'
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 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#
curl https://crm.empiraa.app/api/v1/decks/2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93 \
-H "Authorization: Bearer YOUR_API_KEY"
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 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#
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"}'
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 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#
curl -X DELETE https://crm.empiraa.app/api/v1/decks/2b4d6f80-1a3c-4e5b-8d7f-9a1c3e5b7d93 \
-H "Authorization: Bearer YOUR_API_KEY"
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. |

