API Documentation
Deal Triggers ¶
Brand-level deal automation defaults. Each rule is defined on a brand and applied to that brand’s deals (resolved across the brand’s ancestry).
A rule combines a trigger (what schedules it), an action (what it does), and a
wait_for offset. All rules share a set of common fields; each event and action
then accepts a small set of extra fields, documented in the tables below.
Common fields
Every rule accepts these fields regardless of its trigger or action:
| Field | Type | Required | Description |
|---|---|---|---|
trigger |
deal_trigger_event |
yes | What schedules the rule. See Events. |
action |
deal_trigger_action |
yes | What the rule does. See Actions. |
wait_for |
interval | no (default 0) |
Offset used to compute the scheduled due_at, e.g. -3 days, 1 day, 0. |
deal_types |
deal_type[] |
yes (≥ 1) | Deal types the rule applies to: Buying, Selling. |
statuses |
deal_status[] |
yes (≥ 1) | Deal statuses the rule runs for: Active, Pending, Archived, Closed, NoStatus. |
property_types |
uuid[] |
yes (≥ 1) | Brand property type ids the rule applies to. |
statuses is checked at execution time, not when the trigger is materialized:
a rule is scheduled onto a deal regardless of the deal’s current status, and when
its due date arrives it only runs if the deal’s status then matches one of the
configured statuses (otherwise it fails). This lets a rule fire on a status the
deal reaches later — e.g. a send_testimonial_request scheduled by closing_date
runs only when the deal is Closed/Pending at that later point. NoStatus
matches deals that don’t have a status yet (mirroring the is_null deal filter).
Events
trigger selects one of these. Each table lists the fields that event accepts
beyond the common fields.
listing_checklist_added
Fired when a listing checklist is added to a deal.
| Field | Type | Required | Description |
|---|---|---|---|
| (none) | No event-specific fields. |
offer_checklist_added
Fired when an offer checklist is added to a deal.
| Field | Type | Required | Description |
|---|---|---|---|
| (none) | No event-specific fields. |
context_date_arrived
Fired when the watched context date arrives (the date is reached, offset by
wait_for).
| Field | Type | Required | Description |
|---|---|---|---|
context |
string | yes | Deal context key whose date is watched, e.g. closing_date. |
context_set
Fired when a deal context value is set or changes (Text, Number, or Date).
| Field | Type | Required | Description |
|---|---|---|---|
context |
string | no | When set, the rule materializes only when this context key’s value changes, and the materialized trigger carries this key. When omitted, the rule fires on any context change and carries the key that changed. |
condition_operator |
deal_trigger_operator |
no | Compare the new value: lt, lte, gt, gte, eq, neq. |
condition_value_text |
string | no¹ | Threshold for a Text context. |
condition_value_number |
number | no¹ | Threshold for a Number context. |
condition_value_date |
datetime | no¹ | Threshold for a Date context. |
¹ When condition_operator is set, exactly one of the value columns must be
provided — the one matching the context’s data_type — and context must name
the key. The comparison is evaluated at materialization time against the new
value, so the trigger is only scheduled when the condition holds.
Actions
action selects one of these. Each table lists the fields that action accepts
beyond the common fields.
send_email
Emails the configured deal roles/categories using a brand email template.
| Field | Type | Required | Description |
|---|---|---|---|
email |
uuid | yes | Brand email template id to send. |
roles |
deal_role[] |
yes¹ | Concrete deal roles to email (e.g. Buyer, SellerAgent). |
recipients |
deal_trigger_recipient[] |
yes¹ | Recipient categories to email. |
¹ At least one of roles or recipients is required. recipients values are
InternalClients, InternalAgents, ExternalClients, ExternalAgents; they are
resolved against the deal’s deal_type (internal = the deal’s own side). On
double-ended deals (ender_type = AgentDoubleEnder/OfficeDoubleEnder) both
sides are internal, so external categories resolve to no recipients.
set_buyer_address
Sets the deal’s property address on each Buyer/Tenant role’s contact on the
deal’s brand, creating the contact first when none matches the role’s email/phone.
| Field | Type | Required | Description |
|---|---|---|---|
| (none) | No action-specific fields. |
send_testimonial_request
Emails each internal client a link to the primary agent’s testimonial capture
form, rendered from the brand’s TestimonialRequest marketing template.
| Field | Type | Required | Description |
|---|---|---|---|
subject |
string | no | Email subject. Defaults to Leave us a testimonial!. |
set_context
Reads a source context value and writes a target context key equal to that value shifted by an offset.
| Field | Type | Required | Description |
|---|---|---|---|
context |
string | yes² | Source context key whose value is read and shifted. |
set_context_key |
string | yes | Target context key to write. |
set_context_offset |
interval | yes | Offset added to the source value, e.g. 1 year. |
² For the context_set event, context may be omitted — the rule then uses the
key whose value changed as the source. For context_date_arrived, context is
required by the event.
set_tags
Adds tags to the contacts of the configured deal roles/categories.
| Field | Type | Required | Description |
|---|---|---|---|
roles |
deal_role[] |
yes³ | Concrete deal roles whose contacts get tagged. |
recipients |
deal_trigger_recipient[] |
yes³ | Recipient categories whose contacts get tagged. |
tags |
string[] |
yes (≥ 1) | Tags to add to the resolved contacts. |
³ At least one of roles or recipients is required (same categories as
send_email).
subscribe_to_market_report
Subscribes the contacts of the configured deal roles/categories to a recurring
monthly market report for the deal’s zip code, using the brand’s default
MarketReport template.
| Field | Type | Required | Description |
|---|---|---|---|
roles |
deal_role[] |
yes⁴ | Concrete deal roles whose contacts get subscribed. |
recipients |
deal_trigger_recipient[] |
yes⁴ | Recipient categories whose contacts get subscribed. |
⁴ At least one of roles or recipients is required (same categories as
send_email). The deal’s postal_code context resolves the zip-code geography;
contacts already subscribed to that zip are skipped.
add_task
Adds a typed task to the deal’s checklist. The task_type determines which
type-specific reference applies (form, application, or skyslope_form).
| Field | Type | Required | Description |
|---|---|---|---|
task_title |
string | yes | Task title, e.g. Lead Based Paint. |
task_type |
task_type |
yes | Generic, Form, Application, Skyslope, etc. |
task_form |
uuid | no | Form id (for Form tasks). |
task_application |
uuid | no | Application id (for Application tasks). |
task_skyslope_form |
string | no | Skyslope form key (for Skyslope tasks). |
task_required |
boolean | no (default false) |
Whether the task is a required checklist item. |
task_skyslope_form requires task_type = Skyslope and cannot be combined
with task_form.
set_home_anniversary
Sets the deal’s home anniversary on each Buyer role’s contact on the deal’s
brand — the value of the watched context (e.g. closing_date) exactly one
year later — and schedules the recurring anniversary email for that contact.
Roles with no matching contact are skipped, and Tenant roles are never
targeted — a lease ending is not a purchase.
| Field | Type | Required | Description |
|---|---|---|---|
context |
string | yes⁵ | Context key holding the date the anniversary derives from. |
subject |
string | no | Email subject. Defaults to Happy Home Anniversary!. |
⁵ Supplied by the event: context_date_arrived requires it, and context_set
defaults it to the key that changed. The context must be a Date, otherwise the
trigger fails when it runs.
The anniversary is written as the home_anniversary contact attribute, labeled
with the deal title. The action is append-only: it runs once per trigger instance
and writes a new attribute rather than looking up and replacing an earlier one,
so a context_set rule that re-fires on every edit adds one attribute per change.
The email is a recurring contact trigger on the contact’s home_anniversary
attribute, rendered from the brand’s most recent HomeAnniversary marketing
template and sent on the anniversary itself at 08:00 in the assigned agent’s
timezone. It repeats yearly. A contact that already has an anniversary email
scheduled is left alone, and a contact whose trigger was created this way is
skipped by the HomeAnniversary brand trigger worker, so configuring both does
not send two emails. If the brand has no HomeAnniversary template the trigger
fails, after the contact attribute has been written.
Endpoints
Create a brand deal trigger ¶
Create a brand deal triggerPOST/brands/:id/deals/triggers
Example URI
- id
string(required) Example: 277b46ce-dceb-4e8b-a1c7-080d60345e09
Body
{
"trigger": "context_date_arrived",
"context": "review_date",
"action": "send_email",
"email": "6113d215-cbab-46e2-8358-10cedd5ad9e5",
"wait_for": "-3 days",
"deal_types": [
"Buying"
],
"roles": [
"Buyer"
],
"statuses": [
"NoStatus"
],
"property_types": [
"e47de548-b9f9-47fd-9619-0bd385020563"
],
"brand": "277b46ce-dceb-4e8b-a1c7-080d60345e09",
"created_by": "f98d1cbc-4a5b-4906-9c48-d10dd551403d"
}200Body
{
"code": "OK",
"data": {
"id": "f971c61a-644f-4379-973d-d3b8fb9cc80e",
"created_at": 1791656468,
"updated_at": 1791656468,
"deleted_at": null,
"created_by": "f98d1cbc-4a5b-4906-9c48-d10dd551403d",
"brand": "277b46ce-dceb-4e8b-a1c7-080d60345e09",
"trigger": "context_date_arrived",
"context": "review_date",
"wait_for": {
"days": -3
},
"action": "send_email",
"deal_types": [
"Buying"
],
"roles": [
"Buyer"
],
"recipients": [],
"subject": null,
"statuses": [
"NoStatus"
],
"set_context_key": null,
"set_context_offset": null,
"tags": [],
"condition_operator": null,
"condition_value_text": null,
"condition_value_number": null,
"condition_value_date": null,
"task_title": null,
"task_type": null,
"task_form": null,
"task_application": null,
"task_skyslope_form": null,
"task_required": false,
"type": "brand_deal_trigger"
}
}Get a brand's deal triggers ¶
Get a brand's deal triggersGET/brands/:id/deals/triggers
Example URI
- id
string(required) Example: 277b46ce-dceb-4e8b-a1c7-080d60345e09
200Body
{
"code": "OK",
"data": [
{
"id": "f971c61a-644f-4379-973d-d3b8fb9cc80e",
"created_at": 1791656468,
"updated_at": 1791656468,
"deleted_at": null,
"created_by": "f98d1cbc-4a5b-4906-9c48-d10dd551403d",
"brand": "277b46ce-dceb-4e8b-a1c7-080d60345e09",
"trigger": "context_date_arrived",
"context": "review_date",
"wait_for": {
"days": -3
},
"action": "send_email",
"deal_types": [
"Buying"
],
"roles": [
"Buyer"
],
"recipients": [],
"subject": null,
"statuses": [
"NoStatus"
],
"set_context_key": null,
"set_context_offset": null,
"tags": [],
"condition_operator": null,
"condition_value_text": null,
"condition_value_number": null,
"condition_value_date": null,
"task_title": null,
"task_type": null,
"task_form": null,
"task_application": null,
"task_skyslope_form": null,
"task_required": false,
"type": "brand_deal_trigger"
}
],
"info": {
"count": 1,
"total": 0
}
}Update a brand deal trigger ¶
Update a brand deal triggerPUT/brands/:id/deals/triggers/:tid
Example URI
- id
string(required) Example: 277b46ce-dceb-4e8b-a1c7-080d60345e09- tid
string(required) Example: f971c61a-644f-4379-973d-d3b8fb9cc80e- associations
string(required) Example: brand_deal_trigger.property_types
Body
{
"trigger": "listing_checklist_added",
"action": "send_email",
"email": "6113d215-cbab-46e2-8358-10cedd5ad9e5",
"wait_for": "0",
"deal_types": [
"Buying"
],
"roles": [
"Buyer"
],
"statuses": [
"NoStatus"
],
"property_types": [
"e47de548-b9f9-47fd-9619-0bd385020563"
],
"id": "f971c61a-644f-4379-973d-d3b8fb9cc80e"
}200Body
{
"code": "OK",
"data": {
"id": "f971c61a-644f-4379-973d-d3b8fb9cc80e",
"created_at": 1791656468,
"updated_at": 1791656468,
"deleted_at": null,
"created_by": "f98d1cbc-4a5b-4906-9c48-d10dd551403d",
"brand": "277b46ce-dceb-4e8b-a1c7-080d60345e09",
"trigger": "listing_checklist_added",
"context": null,
"wait_for": {},
"action": "send_email",
"deal_types": [
"Buying"
],
"roles": [
"Buyer"
],
"recipients": [],
"subject": null,
"statuses": [
"NoStatus"
],
"set_context_key": null,
"set_context_offset": null,
"tags": [],
"condition_operator": null,
"condition_value_text": null,
"condition_value_number": null,
"condition_value_date": null,
"task_title": null,
"task_type": null,
"task_form": null,
"task_application": null,
"task_skyslope_form": null,
"task_required": false,
"type": "brand_deal_trigger",
"property_types": [
{
"id": "e47de548-b9f9-47fd-9619-0bd385020563",
"created_at": 1791656468.161637,
"updated_at": 1791656468.161637,
"deleted_at": null,
"brand": "277b46ce-dceb-4e8b-a1c7-080d60345e09",
"label": "Residential Lease",
"is_lease": true,
"order": 0,
"required_roles": [
{
"title": "Tenant",
"checklist_types": [
"Offer",
"Buying"
],
"transaction_type": [
"Lease"
],
"role": "Tenant",
"type": "deal_role_definition"
},
{
"title": "Landlord",
"checklist_types": [
"Selling"
],
"transaction_type": [
"Lease"
],
"role": "Landlord",
"type": "deal_role_definition"
}
],
"optional_roles": [
{
"title": "Title",
"checklist_types": [
"Offer",
"Buying"
],
"transaction_type": [
"Sale"
],
"role": "Title",
"type": "deal_role_definition"
}
],
"type": "brand_property_type",
"checklists": [
{
"id": "6023d1db-e092-4b8b-a4da-e32036f9cc65",
"created_at": 1791656467.791538,
"deleted_at": null,
"brand": "277b46ce-dceb-4e8b-a1c7-080d60345e09",
"title": "Listing",
"order": 0,
"is_terminatable": false,
"tab_name": null,
"is_deactivatable": false,
"property_type": "e47de548-b9f9-47fd-9619-0bd385020563",
"checklist_type": "Selling",
"inbox": "778ef7d0-7ef6-4410-951d-ef7c7ab30fae",
"type": "brand_checklist",
"tasks": null
},
{
"id": "07f6f9cb-22ed-4c79-9a3d-c619101876dd",
"created_at": 1791656467.791538,
"deleted_at": null,
"brand": "277b46ce-dceb-4e8b-a1c7-080d60345e09",
"title": "Contract",
"order": 0,
"is_terminatable": false,
"tab_name": null,
"is_deactivatable": false,
"property_type": "e47de548-b9f9-47fd-9619-0bd385020563",
"checklist_type": "Buying",
"inbox": "b2e6f02e-4542-4295-a4a2-184c3fdf5afd",
"type": "brand_checklist",
"tasks": null
},
{
"id": "992e0a7c-ce9d-471d-8ff1-26ce3e49feb5",
"created_at": 1791656467.791538,
"deleted_at": null,
"brand": "277b46ce-dceb-4e8b-a1c7-080d60345e09",
"title": "Checklist 1",
"order": 2,
"is_terminatable": true,
"tab_name": null,
"is_deactivatable": true,
"property_type": "e47de548-b9f9-47fd-9619-0bd385020563",
"checklist_type": "Offer",
"inbox": "b2e6f02e-4542-4295-a4a2-184c3fdf5afd",
"type": "brand_checklist",
"tasks": null
}
]
}
]
}
}Delete a brand deal trigger ¶
Delete a brand deal triggerDELETE/brands/:id/deals/triggers/:tid
Example URI
- id
string(required) Example: 277b46ce-dceb-4e8b-a1c7-080d60345e09- tid
string(required) Example: f971c61a-644f-4379-973d-d3b8fb9cc80e
204Body
Brand defaults are materialized onto each deal as scheduled instances. All of a
deal's triggers are exposed via the `deal.triggers` association; the context-date
subset is additionally grouped per context key under `deal_context.triggers`
(event triggers like `listing_checklist_added` have no context, so they only
appear under `deal.triggers`). Either can be rescheduled or cancelled for the
individual deal.
An instance whose action failed when it ran carries `failed_at` and the action's
error in `failure`; it can be executed again on demand once the cause is fixed.Get a deal's scheduled triggers ¶
Get a deal's scheduled triggersGET/deals/:id?associations[]=deal.triggers
Example URI
- id
string(required) Example: 17822f8c-7a73-4021-8fd7-ddde5b3ce79c- associations
string(required) Example: deal.triggers
200Body
{
"code": "OK",
"data": {
"id": "17822f8c-7a73-4021-8fd7-ddde5b3ce79c",
"created_at": 1791656468.277534,
"updated_at": 1791656468.277534,
"deleted_at": null,
"listing": null,
"deal_type": "Buying",
"number": 7,
"faired_at": null,
"title": "[Draft]",
"type": "deal",
"attention_requested_at": null,
"is_draft": true,
"roles": null,
"context": {
"property_type": {
"id": null,
"type": "deal_context_item",
"created_at": null,
"created_by": null,
"approved_by": null,
"approved_at": null,
"key": "property_type",
"text": "Residential Lease",
"number": null,
"date": null,
"data_type": "Text",
"deal": "17822f8c-7a73-4021-8fd7-ddde5b3ce79c",
"checklist": null,
"source": "PropertyType",
"definition": "3fd76b66-0b6a-41d4-a29f-c69dcd13452b",
"searchable": "'leas':2 'residenti':1",
"deleted_at": null
},
"review_date": {
"id": "f12ffdf3-0a53-4642-be08-b28bd74179d6",
"type": "deal_context_item",
"created_at": "2026-10-10T18:21:08.375057+00:00",
"created_by": "f98d1cbc-4a5b-4906-9c48-d10dd551403d",
"approved_by": null,
"approved_at": null,
"key": "review_date",
"text": "2017/12/06",
"number": null,
"date": 1512518400,
"data_type": "Date",
"deal": "17822f8c-7a73-4021-8fd7-ddde5b3ce79c",
"checklist": "71cfa315-96fb-4bb5-8840-b4082f49a39f",
"source": "Provided",
"definition": "8a68a7be-32b9-41b7-9e03-e6b0c6eeb697",
"searchable": "'2017/12/06':1",
"deleted_at": null
},
"type": "deal_context"
},
"new_notifications": null,
"attention_requests": 0,
"has_active_offer": true,
"triggers": [
{
"id": "d24d5a92-0651-40bc-baa7-e33c5d0b13bd",
"created_at": 1791656468,
"updated_at": 1791656468,
"deleted_at": null,
"created_by": "f98d1cbc-4a5b-4906-9c48-d10dd551403d",
"deal": "17822f8c-7a73-4021-8fd7-ddde5b3ce79c",
"checklist": "71cfa315-96fb-4bb5-8840-b4082f49a39f",
"brand_deal_trigger": "f971c61a-644f-4379-973d-d3b8fb9cc80e",
"trigger": "context_date_arrived",
"context": "review_date",
"action": "send_email",
"wait_for": {
"days": -3
},
"effective_at": 1791656468,
"due_at": 1512259200,
"executed_at": null,
"failed_at": null,
"failure": null,
"roles": [
"Buyer"
],
"recipients": [],
"subject": null,
"statuses": [
"NoStatus"
],
"set_context_key": null,
"set_context_offset": null,
"tags": [],
"task_title": null,
"task_type": null,
"task_form": null,
"task_application": null,
"task_skyslope_form": null,
"task_required": false,
"type": "deal_trigger"
}
],
"email": "[email protected]"
}
}Reschedule / retarget a scheduled trigger ¶
Reschedule / retarget a scheduled triggerPUT/deals/:id/triggers/:tid
Body accepts wait_for (interval offset) and/or email (brand email template id).
Example URI
- id
string(required) Example: 17822f8c-7a73-4021-8fd7-ddde5b3ce79c- tid
string(required) Example: d24d5a92-0651-40bc-baa7-e33c5d0b13bd
Body
{
"wait_for": "-1 day",
"email": "6113d215-cbab-46e2-8358-10cedd5ad9e5"
}200Body
{
"code": "OK",
"data": {
"id": "d24d5a92-0651-40bc-baa7-e33c5d0b13bd",
"created_at": 1791656468,
"updated_at": 1791656468,
"deleted_at": null,
"created_by": "f98d1cbc-4a5b-4906-9c48-d10dd551403d",
"deal": "17822f8c-7a73-4021-8fd7-ddde5b3ce79c",
"checklist": "71cfa315-96fb-4bb5-8840-b4082f49a39f",
"brand_deal_trigger": "f971c61a-644f-4379-973d-d3b8fb9cc80e",
"trigger": "context_date_arrived",
"context": "review_date",
"action": "send_email",
"wait_for": {
"days": -1
},
"effective_at": 1791656468,
"due_at": 1512432000,
"executed_at": null,
"failed_at": null,
"failure": null,
"roles": [
"Buyer"
],
"recipients": [],
"subject": null,
"statuses": [
"NoStatus"
],
"set_context_key": null,
"set_context_offset": null,
"tags": [],
"task_title": null,
"task_type": null,
"task_form": null,
"task_application": null,
"task_skyslope_form": null,
"task_required": false,
"type": "deal_trigger"
}
}Execute a failed trigger ¶
Execute a failed triggerPOST/deals/:id/triggers/:tid/execute
Clears the trigger’s failed_at/failure and makes it due right away, so it gets
executed again. Only a trigger that failed — and therefore never ran or got
cancelled — can be executed this way; any other trigger is refused with a 400.
Example URI
- id
string(required) Example: 17822f8c-7a73-4021-8fd7-ddde5b3ce79c- tid
string(required) Example: d24d5a92-0651-40bc-baa7-e33c5d0b13bd
200Body
{
"code": "OK",
"data": {
"id": "d24d5a92-0651-40bc-baa7-e33c5d0b13bd",
"created_at": 1791656468,
"updated_at": 1791656468,
"deleted_at": null,
"created_by": "f98d1cbc-4a5b-4906-9c48-d10dd551403d",
"deal": "17822f8c-7a73-4021-8fd7-ddde5b3ce79c",
"checklist": "71cfa315-96fb-4bb5-8840-b4082f49a39f",
"brand_deal_trigger": "f971c61a-644f-4379-973d-d3b8fb9cc80e",
"trigger": "context_date_arrived",
"context": "review_date",
"action": "send_email",
"wait_for": {
"days": -1
},
"effective_at": 1791656468,
"due_at": 1791656468,
"executed_at": null,
"failed_at": null,
"failure": null,
"roles": [
"Buyer"
],
"recipients": [],
"subject": null,
"statuses": [
"NoStatus"
],
"set_context_key": null,
"set_context_offset": null,
"tags": [],
"task_title": null,
"task_type": null,
"task_form": null,
"task_application": null,
"task_skyslope_form": null,
"task_required": false,
"type": "deal_trigger"
}
}