CRM (Twenty) ↔ Hub outbound email templates
How aventora-crm Quick Aventora / Engage by Aventora uses Engagement Hub outbound email templates configured in aventora-admin.
Audience: CRM admins, integrators, workflow authors.
Related docs:
- ENGAGEMENT_HUB_START_API.md — canonical client guide (start + email inline HTML)
- ENGAGEMENT_HUB_OUTBOUND_EMAIL.md — Hub
POST /startemail internals, placeholders, SMTP - AVENTORA_USER_MANUAL.md — §2.5 (Engage by Aventora), §3.11.1 (Admin Outbound Email)
- Aventora-Assistant/docs/twenty-integration.md — CRM ↔ Hub engagement lifecycle, webhooks
Two different “template” concepts
| CRM Quick Aventora templates | Hub outbound email templates | |
|---|---|---|
| Where defined | Built into CRM (aventora-message-templates.ts) | aventora-admin → Account Settings → Outbound Email |
| Purpose | Build instruction text (phone/SMS/email brief) | HTML email body + subject + branding |
| Placeholders | {{firstName}}, meeting fields, etc. | {{CUSTOMER_NAME}}, {{SUBJECT}}, {{ORGANIZATION_NAME}}, optional {{POLICY_NUMBER}}, … |
| Storage | CRM repo | Hub data/email_templates/{domain}.json |
They work together for email:
- CRM quick template → instruction (always sent).
- Hub layout (optional) → branded HTML + SMTP send when
emailTemplateIdis set.
Architecture
sequenceDiagram
participant UI as CRM UI
participant TS as twenty-server
participant Hub as Aventora-Assistant
UI->>TS: GET /rest/aventora/email-templates
TS->>Hub: GET /account-settings/email-templates
Hub-->>TS: templates[]
TS-->>UI: templates[] + customPlaceholderKeys
UI->>TS: POST /rest/aventora/start-engagement
TS->>Hub: POST /integration/start
Hub->>Hub: POST /start
Hub->>Hub: SMTP send
Prerequisites
| Layer | Requirement |
|---|---|
| Admin | Outbound Email: SMTP tested, at least one email template, branding optional |
| Hub | Deployed build with email field pass-through on /integration/start and /start |
| CRM server | AVENTORA_BASE_URL in environment |
| CRM workspace | AVENTORA_API_KEY, assigned domain (Settings → Applications) |
| CRM user | Initiator phone on profile; person has email (and name for {{CUSTOMER_NAME}}) |
CRM REST API
All paths are under the CRM API host (same origin as the CRM app in typical deployments). Authenticate with the workspace member JWT used for other Aventora REST calls.
GET /rest/aventora/email-templates
Lists Hub layouts for the workspace domain.
Response:
{
"templates": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Policy renewal",
"subjectTemplate": "Your policy renewal — {{SUBJECT}}",
"customPlaceholderKeys": ["POLICY_NUMBER", "RENEWAL_DATE"]
}
]
}
customPlaceholderKeys— placeholders found in subject/body excludingSUBJECT,CUSTOMER_NAME,ORGANIZATION_NAME.- Empty
templates— often means SMTP/email not configured for the domain on Hub.
POST /rest/aventora/start-engagement
When channel is email and type is informational:
| Field | Maps to Hub | Purpose |
|---|---|---|
personId | source_record_id | Person UUID |
contactIdentifier | recipient | Email address |
instruction | instruction | Brief (required unless emailBodyHtml or a Hub template is provided) |
clientName | client_name | {{CUSTOMER_NAME}} (optional; server uses person name if omitted) |
emailSubject | email_subject | Subject + {{SUBJECT}} |
emailBodyHtml | email_body_html | Inline HTML body (mutually exclusive with template id/name) |
emailTemplateId | email_template_id | Hub template UUID |
emailTemplateName | email_template_name | Alternative to id |
emailTemplateParams | email_template_params | e.g. { "policy_number": "POL-99" } → {{POLICY_NUMBER}} |
Example:
{
"personId": "uuid-of-person",
"channel": "email",
"type": "informational",
"instruction": "Policy renewal reminder",
"contactIdentifier": "customer@example.com",
"clientName": "Alex Morgan",
"emailSubject": "Your policy renewal",
"emailTemplateId": "550e8400-e29b-41d4-a716-446655440000",
"emailTemplateParams": {
"policy_number": "POL-2026-8842",
"renewal_date": "June 15, 2026"
}
}
Hub also accepts the same fields on POST /integration/start and POST /start (snake_case) for non-CRM integrators.
Integration context (alternative)
{
"phone_number": "customer@example.com",
"domain_name": "aventora",
"source_record_id": "...",
"source_org_id": "...",
"channel": "email",
"type": "informational",
"instruction": "...",
"context": {
"email_template_id": "...",
"email_template_params": { "policy_number": "POL-99" }
}
}
Quick Aventora UI (shipped)
When Channel = Email in Engage by Aventora:
- Email layout (Engagement Hub) — dropdown from
GET /rest/aventora/email-templates. - Email subject — required when a layout is selected.
- Template fields — one input per
customPlaceholderKey. - Instruction — from CRM quick template (unchanged).
Optional developer mapping on CRM quick templates (aventora-message-templates.ts):
hubEmailTemplateName— pre-select Hub layout by name when templates load.defaultEmailSubject— initial subject when pre-selecting.
Without a layout, send still works (instruction-only / Hub LLM path). See ENGAGEMENT_HUB_OUTBOUND_EMAIL.md send paths.
Configuration
CRM server (twenty-server)
| Variable | Required | Description |
|---|---|---|
AVENTORA_BASE_URL | Yes | Hub base URL (e.g. https://hub.example.com) |
CRM workspace (UI)
| Application variable | Required | Description |
|---|---|---|
AVENTORA_API_KEY | Yes | Account Hub API key |
| Assigned domain | Yes | Domain slug for Hub |
CRM frontend (optional)
| Variable | Default |
|---|---|
REACT_APP_AVENTORA_EMAIL_TEMPLATES_ENDPOINT | {REACT_APP_SERVER_BASE_URL}/rest/aventora/email-templates |
REACT_APP_AVENTORA_START_ENDPOINT | {SERVER}/rest/aventora/start-engagement |
Set in packages/twenty-front/.env for local dev only when overriding. Production monolith injects REACT_APP_SERVER_BASE_URL via generate-front-config.ts — leave email-templates unset to use the default path on the same host.
Workflows
- HTTP request step →
POST {CRM_SERVER}/rest/aventora/start-engagementwith person id from trigger + email fields above. - Map workflow variables into
emailTemplateParams. - Confirm Twenty workflow auth can call workspace REST (Bearer token model).
No packaged “Start Aventora email” workflow action exists; REST is the supported integration surface.
Troubleshooting
| Symptom | Check |
|---|---|
| Layout dropdown empty | Admin Outbound Email + SMTP; workspace API key and domain |
| 403 on list/start | AVENTORA_API_KEY, AVENTORA_BASE_URL, APP_SECRET if key is encrypted |
| Layout selected, send fails | Hub logs; template id exists; all template fields filled |
| Wrong customer name | Person name on record; or pass clientName explicitly |
| Placeholder not replaced | Use {{UPPER_SNAKE}} in Hub template; pass snake_case keys in emailTemplateParams |
Documentation map
| Doc | Content |
|---|---|
| ENGAGEMENT_HUB_START_API.md | Canonical client guide — /integration/start, /start, email_body_html |
| ENGAGEMENT_HUB_OUTBOUND_EMAIL.md | Hub email internals, placeholders, branding |
| AVENTORA_USER_MANUAL.md | End-user Engage + Admin setup |
| This file | CRM REST + UI + config |
| twenty-integration.md | Engagements, pause, webhooks |
Deploy order
- Aventora-Assistant —
/integration/start+/startemail fields,email_addressfor email channel. - aventora-crm —
GET /rest/aventora/email-templates, start-engagement pass-through, Engage UI. - aventora-admin — template authoring (unchanged; source of truth).