# POST /automations/:id/actions

**Resource:** [Automations](./automations.md)  
**Scopes:** `automations:write`  
**Write operation:** yes

Add an action to an automation. action_type and sequence are required.

## Parameters

| Name | In | Type | Required | Description |
|------|----|------|----------|-------------|
| `id` | path | uuid | yes | Automation ID |
| `action_type` | body | string | yes | Action type (send_custom_email, send_gmail_email, send_sms, voice_outbound_call, call_webhook, add_tasks, create_lead, move_deal, attach_to_event_queue, remove_from_event_queue, apply_tags, remove_tags, assign_user, set_custom_field, send_document, send_for_signing, send_form, slack_send_message, trigger_automation, etc.) |
| `sequence` | body | number | yes | Execution order |
| `config` | body | object | no | Action configuration (varies by action_type). Key configs:
send_custom_email: { greeting, customMessage, showReplyButton?, recipient_target?, replyEmail? }
send_gmail_email: { subject, body, recipient_target, sender_mode?, email_config_id?, attachment_ids? } -- body accepts plain text or rich HTML. To embed a clickable image: <a href="URL"><img src="IMAGE_URL" alt="Alt" style="max-width:100%;height:auto;" /></a>. sender_mode: "company" (workspace Gmail from /settings/email) or "assignee" (deal primary assignee personal Gmail). recipient_target: "contact", "account_customer", or "account_supplier". email_config_id: UUID of a gmail-provider email_config to pin which alias sends (omit to use default). attachment_ids: array of crm_documents UUIDs to attach -- resolved server-side from the workspace file library, max 25 MB total. subject and body support {{variable}} placeholders. Gmail signature is auto-appended.
send_sms: { phone_number_id, message_body, recipient_target?, custom_recipient_phone? } -- recipient_target: "contact" (deal primary contact, default), "account_customer", or "custom". For a fixed external recipient (e.g. forward inbound SMS to a staff mobile that is not a TP user), set recipient_target: "custom" AND provide custom_recipient_phone in E.164 format. to_number_source is a legacy alias for recipient_target -- both work.
voice_outbound_call: { voice_agent_outbound_config_id, recipient_target?, variable_mappings?, respect_business_hours? }
add_tasks: { tasks: [{ title, category?, due_offset_days? }] }
call_webhook: { url, method? }
create_lead: { pipeline_id, stage_id }
move_deal: { pipeline_id, stage_id, pipeline_name?, stage_name? } - moves the triggering deal to the specified stage
apply_tags: { tags: [{ name, color? }] } - merges tags onto the deal. Deduplicates by name. Color falls back to tag palette or #6b7280.
remove_tags: { tags: [{ name }] } - removes tags from the deal by name (case-insensitive).
assign_user: { user_id } - assigns a team member as primary deal owner. Aliases: assign_deal_user, set_deal_owner. Demotes any existing primary assignee. Use GET /company/users to find user UUIDs.
set_custom_field (UI: "Set CRM Field") - writes one or more CRM fields in a single action. Multi-write shape: { writes: [{ target_entity: "contact"\|"customer"\|"deal", crm_variable: string, value: any, mode?: "write"\|"overwrite" }] }. crm_variable is the full dot-path e.g. "contact.relationship_started_at", "account.tax_number", "deal.actual_close_date", "contact.metadata.cf_abc123". mode "write" only sets the field when currently empty. Special value tokens: {{today}} = YYYY-MM-DD in company timezone, {{now}} = full ISO datetime. Legacy single-field shape { target_entity, crm_variable, value, mode } and older { target_entity, field_id, value } still work. Newly writable built-in fields: contact.relationship_started_at, contact.landline, contact.contact_type, contact.timezone, account.relationship_started_at, account.landline, account.account_type, account.timezone, deal.actual_close_date. CROSS-ENTITY WRITES: when the trigger fires on one entity (e.g. contact_updated) but you need to write to a different entity (e.g. deal.metadata.X), add a CRM Integration block on the automation with mode "find" or mode "update" and include "id" in find_match_fields or update_contact_match_fields. The engine resolves the linked deal/customer via the trigger entity id automatically -- no email/phone matching needed. |

## Request example

```bash
curl -X POST \
  "https://api.trustpager.com/functions/v1/api/v1/automations/auto-uuid/actions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action_type": "send_gmail_email",
    "sequence": 1,
    "config": {
      "subject": "Following up on {{deal.name}}",
      "body": "Hi {{contact.first_name}},\n\nJust wanted to follow up. Let me know if you have any questions.\n\nBest regards",
      "recipient_target": "contact",
      "sender_mode": "company"
    }
  }'
```

## Response example

```json
{
  "data": {
    "id": "action-uuid-...",
    "automation_id": "auto-uuid-...",
    "action_type": "send_gmail_email",
    "sequence": 1,
    "config": {
      "subject": "Following up on {{deal.name}}",
      "body": "Hi {{contact.first_name}},\n\nJust wanted to follow up.",
      "recipient_target": "contact",
      "sender_mode": "company"
    },
    "created_at": "2026-03-25T05:00:00Z"
  }
}
```

---
Base URL: `https://api.trustpager.com/functions/v1/api/v1` — Auth: `Authorization: Bearer YOUR_API_KEY`