Manage Engage campaigns, email templates, and workspaces.
Engage commands require a workspace context. You can specify a workspace in two ways (in order of priority):
- Command option:
--workspace <name> - Session context:
tdx use engage_workspace <name>
# Set workspace for the current session
tdx use engage_workspace "Marketing Team"
# Now all engage commands use this workspace
tdx engage campaigns
tdx engage campaign create --name "Newsletter" --type email
# Override workspace for a single command
tdx engage campaigns --workspace "Sales Team"# List all campaigns (uses workspace from session context)
tdx engage campaign list
tdx engage campaigns # alias for "campaign list"
# List campaigns in a specific workspace
tdx engage campaign list --workspace "Marketing Team"
# Filter campaigns by pattern (glob pattern with * and ? wildcards)
tdx engage campaign list "test*"
tdx engage campaign list "*_production"
# Filter by campaign type
tdx engage campaign list --type email
tdx engage campaign list --type push
# Filter by status
tdx engage campaign list --status DRAFT
tdx engage campaign list --status ACTIVE
tdx engage campaign list --status PAUSED
tdx engage campaign list --status COMPLETED
# Combine filters
tdx engage campaign list --workspace "Marketing" --type email --status ACTIVE
# Limit results
tdx engage campaign list --limit 10# Show campaign by name
tdx engage campaign show "My Newsletter Campaign"
# Show campaign by UUID
tdx engage campaign show "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"
# Specify workspace when using name
tdx engage campaign show "My Campaign" --workspace "Marketing Team"
# Show full JSON:API response with all fields (emailContent, pushContent, etc.)
tdx engage campaign show "My Campaign" --fullNote: Workspace is required for creating campaigns. Set it via tdx use engage_workspace or --workspace.
# Create an email campaign (workspace from session)
tdx engage campaign create --name "Monthly Newsletter" --type email
# Create with explicit workspace
tdx engage campaign create --name "Monthly Newsletter" --type email \
--workspace "Marketing Team"
# Create with description
tdx engage campaign create --name "Monthly Newsletter" --type email \
--description "Monthly newsletter for subscribers"
# Create with segment targeting (by path)
tdx engage campaign create --name "VIP Campaign" --type email \
--segment "My Audience/VIP Users"
# Create with email sender configuration
tdx engage campaign create --name "Monthly Newsletter" --type email \
--email-sender-id "sender-uuid-123" \
--json-columns "email,name,preferences"
# Create with delivery schedule
tdx engage campaign create --name "Morning Newsletter" --type email \
--start-at "2024-01-15T09:00:00" \
--timezone "Asia/Tokyo"
# Create a push notification campaign
tdx engage campaign create --name "Flash Sale Alert" --type push# Update campaign name
tdx engage campaign update "Monthly Newsletter" --name "Weekly Newsletter"
# Update campaign description
tdx engage campaign update "Monthly Newsletter" --description "Updated description"
# Update segment targeting
tdx engage campaign update "My Campaign" \
--segment "New Audience/Premium Users"
# Update delivery schedule
tdx engage campaign update "My Campaign" \
--start-at "2024-02-01T10:00:00" \
--timezone "UTC"
# Update email sender configuration
tdx engage campaign update "My Campaign" \
--email-sender-id "new-sender-uuid"
# Specify workspace when using name
tdx engage campaign update "My Campaign" --workspace "Marketing" --name "New Name"# Delete campaign by name (prompts for confirmation)
tdx engage campaign delete "Old Campaign"
# Delete campaign by UUID
tdx engage campaign delete "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"
# Skip confirmation prompt
tdx engage campaign delete "Old Campaign" --yes
# Specify workspace when using name
tdx engage campaign delete "My Campaign" --workspace "Marketing"# Launch a campaign (changes status from DRAFT to ACTIVE)
tdx engage campaign launch "Monthly Newsletter"
tdx engage campaign launch "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"
# Pause a running campaign (changes status from ACTIVE to PAUSED)
tdx engage campaign pause "Monthly Newsletter"
# Resume a paused campaign (changes status from PAUSED to ACTIVE)
tdx engage campaign resume "Monthly Newsletter"
# Duplicate a campaign (creates a copy in DRAFT status)
tdx engage campaign duplicate "Monthly Newsletter"Export campaigns from Engage to local YAML + HTML files. This is the starting point for the YAML-based campaign workflow.
# Pull all campaigns from a workspace
tdx engage campaign pull "Marketing Team"
tdx engage campaign pull --workspace "Marketing Team"
# Pull using session context
tdx use engage_workspace "Marketing Team"
tdx engage campaign pull
# Pull a specific campaign by name
tdx engage campaign pull "Marketing Team" --name "Monthly Newsletter"
# Pull only email campaigns
tdx engage campaign pull "Marketing Team" --type email
# Preview what would be written without writing files
tdx engage campaign pull "Marketing Team" --dry-run
# Skip confirmation prompt
tdx engage campaign pull "Marketing Team" --yes| Option | Description |
|---|---|
--workspace <name> | Workspace name |
--name <name> | Pull specific campaign by name |
--type <type> | Filter by campaign type (email, push, line) |
--dry-run | Show what would be written without writing |
-y, --yes | Skip confirmation prompt |
Pulled files are written to campaigns/<workspace-slug>/ under the current directory. Each campaign produces a YAML file and optionally an HTML file (if the campaign has an HTML email override).
Push local YAML campaign files to the Engage API. Matches campaigns by name — existing campaigns are updated, new ones are created.
# Push a single campaign file
tdx engage campaign push path/to/campaign.yaml
# Push all campaign files in a directory
tdx engage campaign push path/to/campaigns/
# Push all campaigns (uses tdx.json for workspace context)
tdx engage campaign push
# Push with explicit workspace
tdx engage campaign push campaign.yaml --workspace "Marketing Team"
# Validate against API without applying changes
tdx engage campaign push campaign.yaml --dry-run
# Skip confirmation prompt
tdx engage campaign push campaign.yaml --yes| Option | Description |
|---|---|
--workspace <name> | Workspace name (overrides tdx.json and session context) |
--dry-run | Show what would be applied without applying |
-y, --yes | Skip confirmation prompt |
Workspace resolution order: --workspace option > tdx.json (engage_workspace field) > session context.
For email campaigns, the email: YAML section may include preheader for inbox preview text. It supports Liquid tags, is limited to 220 characters by the API, and accepts null to clear an existing value.
Validate campaign YAML files locally without pushing to the API.
# Validate all campaign files in current directory
tdx engage campaign validate
# Validate a specific file
tdx engage campaign validate campaign.yaml
# Validate all campaigns in a directory
tdx engage campaign validate path/to/campaigns/
# Show all files including valid ones
tdx engage campaign validate --verbose| Option | Description |
|---|---|
--verbose | Show all files including valid ones |
For API-level validation (resolving references), use tdx engage campaign push --dry-run instead.
# List all email templates (uses workspace from session context)
tdx engage template list
tdx engage templates # alias for "template list"
# List templates in a specific workspace
tdx engage template list --workspace "Marketing Team"
# Filter templates by pattern
tdx engage template list "welcome*"
tdx engage template list "*_newsletter"
# Limit results
tdx engage template list --limit 20# Show template by name
tdx engage template show "Welcome Email"
# Show template by UUID
tdx engage template show "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"
# Specify workspace when using name
tdx engage template show "Welcome Email" --workspace "Marketing"
# Show full JSON:API response with all fields (htmlTemplate, beefreeJson, etc.)
tdx engage template show "Welcome Email" --fullNote: Workspace is required for creating templates. Set it via tdx use engage_workspace or --workspace.
# Create an email template (workspace from session)
tdx engage template create --name "Welcome Email" \
--subject "Welcome to our service!" \
--preheader "Start exploring your new account today." \
--html "<html><body><h1>Welcome!</h1></body></html>"
# Create with explicit workspace
tdx engage template create --name "Welcome Email" \
--subject "Welcome to our service!" \
--html "<html><body><h1>Welcome!</h1></body></html>" \
--workspace "Marketing Team"
# Create from an HTML file
tdx engage template create --name "Welcome Email" \
--subject "Welcome to our service!" \
--html-file ./templates/welcome.html
# Create with plaintext version
tdx engage template create --name "Welcome Email" \
--subject "Welcome to our service!" \
--html "<html><body><h1>Welcome!</h1></body></html>" \
--plaintext "Welcome to our service!"# Update template name
tdx engage template update "Welcome Email" --name "New Welcome Email"
# Update template subject or inbox preview text
tdx engage template update "Welcome Email" --subject "New Subject Line"
tdx engage template update "Welcome Email" --preheader "A concise preview for inboxes"
# Update template HTML
tdx engage template update "Welcome Email" --html "<html><body><h1>Updated!</h1></body></html>"
# Update template HTML from file
tdx engage template update "Welcome Email" --html-file ./templates/updated.html
# Update by UUID
tdx engage template update "01968a3a-ae17-7ef6-9b45-f1a0af1224b4" --name "New Name"
# Specify workspace when using name
tdx engage template update "Welcome Email" --workspace "Marketing" --name "New Name"# Delete template by name (prompts for confirmation)
tdx engage template delete "Old Template"
# Delete template by UUID
tdx engage template delete "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"
# Skip confirmation prompt
tdx engage template delete "Old Template" --yes
# Specify workspace when using name
tdx engage template delete "My Template" --workspace "Marketing"Manage workspace-scoped popup and inline web messages as local YAML definitions. The workflow supports drafts only: it does not launch, pause, finish, or delete messages.
# List messages in the current workspace
# The plural form is an alias for "in-browser-message list"
tdx engage in-browser-message list
tdx engage in-browser-messages
# Filter by glob pattern or type
tdx engage in-browser-message list "summer*" --workspace "Marketing Team"
tdx engage in-browser-message list --type popup
tdx engage in-browser-message list --type inline
# Show by exact name or UUID
tdx engage in-browser-message show "Summer Promo" --workspace "Marketing Team"
tdx engage in-browser-message show "01968a3a-ae17-7ef6-9b45-f1a0af1224b4" --workspace "Marketing Team"
# Show the full JSON:API resource, including HTML and BeeFree state
tdx engage in-browser-message show "Summer Promo" --fullpull writes definitions to in-browser-messages/<workspace-slug>/. Each workspace directory contains tdx.json, a YAML file per message, its HTML companion file, and—for popups returned with editor state—a BeeFree JSON companion file.
in-browser-messages/marketing-team/
├── tdx.json
├── summer-promo.yaml
├── summer-promo.html
├── summer-promo.json
├── homepage-banner.yaml
└── homepage-banner.html# Pull all messages, preview file changes, or select a subset
tdx engage in-browser-message pull "Marketing Team"
tdx engage in-browser-message pull "Marketing Team" --dry-run
tdx engage in-browser-message pull "Marketing Team" --type popup --yes
tdx engage in-browser-message pull "Marketing Team" --name "Summer Promo" --yes
# Validate one definition or every in-browser-message YAML file below a directory
tdx engage in-browser-message validate ./in-browser-messages/marketing-team
# Include valid and skipped files in the output
tdx engage in-browser-message validate ./in-browser-messages/marketing-team --verboseFor pull, the workspace is resolved in this order: positional workspace, --workspace, nearby tdx.json, then the session context. Pull shows a diff for changed files, does not write during --dry-run, and prompts before writing unless --yes is provided. Pulling an empty workspace still creates or updates its tdx.json and sets the workspace context.
Popup messages keep their rendered HTML and optional BeeFree editor state in companion files:
# summer-promo.yaml
type: in_browser_message
name: Summer Promo
message_type: popup
description: Seasonal popup modal
workspace: Marketing Team
parent_segment:
id: segment-uuid
name: Customers
personalization:
id: personalization-uuid
name: Hero Section
html_file: summer-promo.html
beefree_json_file: summer-promo.json
appearance:
position: centerInline messages require a CSS selector and cannot specify popup-only fields:
# homepage-banner.yaml
type: in_browser_message
name: Homepage Banner
message_type: inline
workspace: Marketing Team
html_file: homepage-banner.html
css_selector: "#promo-banner-container"All messages require name, message_type, and html_file. message_type is either popup or inline. Inline messages require css_selector; it cannot be * or begin with >, +, or ~. Popups cannot set css_selector. Inline definitions cannot set appearance or beefree_json_file.
When specified, parent_segment and personalization must each contain the complete id and name metadata returned by Engage. appearance is the backend-shaped popup appearance configuration. Omit it to preserve the server's default appearance settings. The HTML and BeeFree paths must be safe relative paths contained within the YAML definition directory.
push discovers type: in_browser_message YAML files, validates them locally, and matches messages by exact trimmed name within the selected workspace. It creates missing messages as drafts and updates matching drafts.
# Preview create/update actions without API writes
tdx engage in-browser-message push ./in-browser-messages/marketing-team --dry-run
# Push one definition or an entire directory
tdx engage in-browser-message push ./in-browser-messages/marketing-team/summer-promo.yaml --yes
tdx engage in-browser-message push ./in-browser-messages/marketing-team --yes
# Override workspace stored in tdx.json
tdx engage in-browser-message push ./in-browser-messages/marketing-team --workspace "Marketing Team" --yesFor push, workspace resolution is --workspace, then the nearest tdx.json engage_workspace, then the session context. --dry-run reads companion files and reports the intended create/update actions without sending POST or PATCH requests. Normal push prompts for confirmation unless --yes is supplied.
Message type is immutable: a local popup cannot replace an existing inline message (or the reverse). Only DRAFT messages can be updated. Resolve these conditions in Engage before pushing; this command intentionally does not include lifecycle or deletion operations.
Landing Pages use a local static-site workflow. A page belongs to an Engage workspace and requires a Web Domain that has been attached to that workspace. The normal workflow is:
tdx engage domain create --domain-name pages.example.com
tdx engage domain attach pages.example.com --workspace "Marketing Team"
tdx engage landing-page init "Spring Launch" --domain pages.example.com --workspace "Marketing Team"
cd landing-pages/spring-launch
tdx engage landing-page validate
tdx engage landing-page push --dry-run
tdx engage landing-page push --yes
tdx engage landing-page publish "Spring Launch" --workspace "Marketing Team"Web Domains are account-scoped custom subdomains used to host Landing Pages. Create a domain and configure the DNS records shown by show; deployment must be active before a Landing Page can be published. Attach the domain to every workspace that will use it.
# Discover domain status and required DNS records
tdx engage domain list
tdx engage domain show pages.example.com
# Register and attach a domain
tdx engage domain create --domain-name pages.example.com --display-name "Marketing pages"
tdx engage domain attach pages.example.com --workspace "Marketing Team"
# Change display metadata or re-deploy a suspended domain
tdx engage domain update pages.example.com --display-name "Campaign pages"
tdx engage domain deploy pages.example.com
# Remove an unused association or domain
tdx engage domain detach pages.example.com --workspace "Marketing Team"
tdx engage domain delete pages.example.com --yesinit creates a project directory containing tdx.json, a landing-page.yaml definition, and a root site/index.html entrypoint. It does not overwrite an existing directory.
landing-pages/spring-launch/
├── tdx.json
├── landing-page.yaml
└── site/
└── index.htmltype: landing_page
name: Spring Launch
description: Spring campaign site
slug: campaigns/2026/spring
domain: ref:pages.example.com
site_dir: siteThe definition supports only type, name, optional description/slug, domain, and site_dir. A slug uses lowercase letters, numbers, hyphens, and slash-separated path segments. The static site must contain index.html; it permits HTML, CSS, JavaScript, common image/font files, JSON, text, XML, and web manifests. Uploads are limited to 1,000 files, 20 MB per file, and 100 MB in total.
# Create and locally validate a project
tdx engage landing-page init "Spring Launch" --domain pages.example.com --workspace "Marketing Team"
tdx engage landing-page validate [landing-page.yaml]
# Inspect pages in the workspace
tdx engage landing-page list --workspace "Marketing Team"
tdx engage landing-page list "spring*" --status DRAFT --workspace "Marketing Team"
tdx engage landing-page show "Spring Launch" --workspace "Marketing Team"
# Upload a local static site as a draft; it never publishes automatically
tdx engage landing-page push [landing-page.yaml] --workspace "Marketing Team" --dry-run
tdx engage landing-page push [landing-page.yaml] --workspace "Marketing Team" --yes
# Publish or unpublish explicitly
tdx engage landing-page publish "Spring Launch" --workspace "Marketing Team"
tdx engage landing-page unpublish "Spring Launch" --workspace "Marketing Team"
# Delete after unpublishing
tdx engage landing-page delete "Spring Launch" --workspace "Marketing Team" --yespush accepts a path to landing-page.yaml, not a ZIP archive or an HTML file. When the path is omitted, it uses ./landing-page.yaml. The YAML site_dir identifies the directory to upload and must contain <site_dir>/index.html at its root. Workspace resolution is --workspace, then the nearest project tdx.json, then the session context.
# From a pulled or initialized project directory
tdx engage landing-page validate landing-page.yaml
tdx engage landing-page push landing-page.yaml --dry-run
tdx engage landing-page push landing-page.yaml --yes
# Or pass a definition path from another directory
tdx engage landing-page push ./landing-pages/spring-launch/landing-page.yaml --workspace "Marketing Team" --yespull always retrieves the Landing Page configuration as tdx.json and landing-page.yaml. For a published page, it also reads the current published upload attempt's webAssets manifest and downloads every file in that manifest from the page's public URL, including files that are not referenced by HTML or CSS. For a draft or content-less page, it creates a configuration-only project with an empty site/ directory; it does not retrieve a draft upload attempt or draft site files.
pull does not execute JavaScript, crawl navigation links or iframes, or retrieve historical versions. A published page with an invalid or unavailable published manifest fails rather than silently replacing the local site with a configuration-only project.
# Preview a pull without changing local files
tdx engage landing-page pull "Spring Launch" --workspace "Marketing Team" --dry-run
# Replace the project directory after confirmation
tdx engage landing-page pull "Spring Launch" --workspace "Marketing Team"
# Replace a chosen directory without confirmation
tdx engage landing-page pull "Spring Launch" --workspace "Marketing Team" --dir ./spring-launch --yesPull replaces the destination project directory, so files that are not in the pulled project are removed. Public-site crawler requests must not send TD API authorization headers, OAuth credentials, cookies, or any private session data.
# List all workspaces
tdx engage workspace list
tdx engage workspaces # alias for "workspace list"
# Filter workspaces by pattern
tdx engage workspace list "marketing*"
tdx engage workspace list "*_production"
# Limit results
tdx engage workspace list --limit 10# Show workspace by name
tdx engage workspace show "Marketing Team"
# Show workspace by UUID
tdx engage workspace show "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"
# Show full JSON:API response with all fields (workspaceConfig, ownerUser, etc.)
tdx engage workspace show "Marketing Team" --full# Create a workspace
tdx engage workspace create --name "Marketing Team"
# Create with description
tdx engage workspace create --name "Marketing Team" \
--description "Workspace for marketing campaigns"# Update workspace name
tdx engage workspace update "Marketing Team" --name "Marketing Department"
# Update workspace description
tdx engage workspace update "Marketing Team" --description "Updated description"
# Update by UUID
tdx engage workspace update "01968a3a-ae17-7ef6-9b45-f1a0af1224b4" --name "New Name"# Delete workspace by name (prompts for confirmation)
tdx engage workspace delete "Old Workspace"
# Delete workspace by UUID
tdx engage workspace delete "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"
# Skip confirmation prompt
tdx engage workspace delete "Old Workspace" --yes# Set workspace for the current session (alias for "tdx use engage_workspace")
tdx engage workspace use "Marketing Team"
# This is equivalent to:
tdx use engage_workspace "Marketing Team"LINE sender accounts are the LINE Official Account credentials used to send LINE messages. Manage them before creating LINE campaigns.
# List all LINE sender accounts
tdx engage line-sender-account list
# Filter by pattern (glob wildcards supported)
tdx engage line-sender-account list "my-brand*"
# Filter by workspace
tdx engage line-sender-account list --workspace "Marketing Team"# Show by name
tdx engage line-sender-account show "My LINE Account"
# Show by UUID
tdx engage line-sender-account show "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"
# Specify workspace when using name
tdx engage line-sender-account show "My LINE Account" --workspace "Marketing Team"Before creating a LINE imagemap campaign, upload the image to receive a baseUrl.
# Upload a JPEG image
tdx engage line-imagemap-image upload ./banner.jpg
# Upload a PNG image
tdx engage line-imagemap-image upload ./banner.pngConstraints (enforced by LINE):
| Constraint | Value |
|---|---|
| Format | JPEG or PNG |
| Max file size | 10 MB |
| Min width | 1040 px |
Example output:
baseUrl: https://profile.line-scdn.net/0h...
Resized URLs:
240px : https://profile.line-scdn.net/0h.../240
300px : https://profile.line-scdn.net/0h.../300
460px : https://profile.line-scdn.net/0h.../460
700px : https://profile.line-scdn.net/0h.../700
1040px : https://profile.line-scdn.net/0h.../1040
Use baseUrl in your campaign YAML:
line:
messages:
- type: imagemap
base_url: "https://profile.line-scdn.net/0h..."Copy the baseUrl value into your campaign YAML line.messages[].base_url field.
All Engage commands support name-based selection in addition to UUIDs:
- By Name:
tdx engage campaign show "My Campaign"- searches by exact name match - By UUID:
tdx engage campaign show "01968a3a-ae17-7ef6-9b45-f1a0af1224b4"- direct ID lookup
When multiple resources share the same name across workspaces, use --workspace to narrow the search.
All commands support standard tdx output formats:
# JSON output (default)
tdx engage campaign list
# Table format
tdx engage campaign list --format table
# TSV format for scripting
tdx engage campaign list --format tsv
# JSONL format for streaming
tdx engage campaign list --format jsonlAlways-on campaigns run continuously (no scheduling) and support a different lifecycle from regular campaigns: DRAFT → LIVE → PAUSED → FINISHED.
All always-on campaign commands require a workspace context (--workspace or tdx use engage_workspace).
# List all always-on campaigns
tdx engage always-on-campaign list --workspace "Marketing Team"
tdx engage always-on-campaigns --workspace "Marketing Team" # alias
# Filter by pattern
tdx engage always-on-campaign list "welcome*" --workspace "Marketing Team"
# Filter by type or status
tdx engage always-on-campaign list --workspace "Marketing Team" --type email
tdx engage always-on-campaign list --workspace "Marketing Team" --status LIVE
# Combine filters
tdx engage always-on-campaign list --workspace "Marketing" --type email --status DRAFT# Show campaign by name
tdx engage always-on-campaign show "My Campaign" --workspace "Marketing Team"
# Show campaign by UUID
tdx engage always-on-campaign show "01968a3a-ae17-7ef6-9b45-f1a0af1224b4" --workspace "Marketing Team"
# Show full JSON:API response
tdx engage always-on-campaign show "My Campaign" --workspace "Marketing Team" --full# Create an email always-on campaign
tdx engage always-on-campaign create --workspace "Marketing Team" \
--name "Welcome Flow" --type email
# Create with description and audience targeting
tdx engage always-on-campaign create --workspace "Marketing Team" \
--name "Welcome Flow" --type email \
--description "Automated welcome emails" \
--segment "My Audience/New Users"
# Create a push campaign with UTM tracking
tdx engage always-on-campaign create --workspace "Marketing Team" \
--name "Daily Digest" --type push \
--enable-utm-tracking# Update name or description
tdx engage always-on-campaign update "Welcome Flow" --workspace "Marketing Team" \
--name "New Welcome Flow"
tdx engage always-on-campaign update "Welcome Flow" --workspace "Marketing Team" \
--description "Updated description"
# Update audience targeting
tdx engage always-on-campaign update "Welcome Flow" --workspace "Marketing Team" \
--segment "My Audience/Premium Users"Only DRAFT campaigns can be deleted.
# Delete with confirmation prompt
tdx engage always-on-campaign delete "Draft Campaign" --workspace "Marketing Team"
# Skip confirmation
tdx engage always-on-campaign delete "Draft Campaign" --workspace "Marketing Team" --yes# Launch (DRAFT → LIVE)
tdx engage always-on-campaign launch "Welcome Flow" --workspace "Marketing Team"
# Pause (LIVE → PAUSED)
tdx engage always-on-campaign pause "Welcome Flow" --workspace "Marketing Team"
# Resume (PAUSED → LIVE)
tdx engage always-on-campaign resume "Welcome Flow" --workspace "Marketing Team"
# Finish permanently (prompts for confirmation)
tdx engage always-on-campaign finish "Welcome Flow" --workspace "Marketing Team"
tdx engage always-on-campaign finish "Welcome Flow" --workspace "Marketing Team" --yes# Duplicate with a new name (required)
tdx engage always-on-campaign duplicate "Welcome Flow" --workspace "Marketing Team" \
--name "Welcome Flow Copy"Validate YAML files locally without authentication. Useful for checking syntax and required fields before pushing.
# Validate YAML files in a directory
tdx engage always-on-campaign validate ./campaigns
# Verbose mode shows all files including valid ones
tdx engage always-on-campaign validate ./campaigns --verbose
# Validate specific file
tdx engage always-on-campaign validate campaign.yamlExport always-on campaigns from Engage API to local YAML files for editing.
# Pull all campaigns from a workspace
tdx engage always-on-campaign pull --workspace "Marketing Team"
# Pull campaigns with filter by name pattern
tdx engage always-on-campaign pull --workspace "Marketing Team" --name "welcome*"
# Pull campaigns by type (email, push, line, sms)
tdx engage always-on-campaign pull --workspace "Marketing Team" --type email
# Dry-run mode shows what would be pulled without writing files
tdx engage always-on-campaign pull --workspace "Marketing Team" --dry-runOutput directory structure:
always-on-campaigns/
├── Marketing Team/
│ ├── tdx.json # Workspace config
│ ├── welcome-email.yaml # Campaign definition
│ ├── welcome-email.html # Email HTML template (if email type)
│ ├── welcome-email.txt # Email plaintext (optional)
│ └── daily-push.yaml # Push campaignCreate or update always-on campaigns from local YAML files.
# Push a campaign YAML file (creates new or updates existing by name match)
tdx engage always-on-campaign push campaign.yaml --workspace "Marketing Team"
# Push all campaigns in a directory
tdx engage always-on-campaign push ./campaigns --workspace "Marketing Team"
# Dry-run mode shows what would be applied without creating/updating
tdx engage always-on-campaign push campaign.yaml --workspace "Marketing Team" --dry-run
# Skip confirmation prompts
tdx engage always-on-campaign push campaign.yaml --workspace "Marketing Team" --yesYAML File Format — Always-On Campaign:
Always-on campaigns support email, push, LINE, and SMS content types. Unlike one-off campaigns, they run continuously without scheduling.
type: always_on_campaign
name: Welcome Series
campaign_type: email
description: Automated welcome emails
workspace: Marketing Team # optional if set via --workspace
audience: ref:New Users # ref: prefix required
email:
subject: 'Welcome to {{company}}!'
preheader: 'Everything you need to get started'
template: ref:Welcome Template # ref: prefix required
html_file: welcome.html # relative to YAML file
sender_id: ref:Sender ID # ref: prefix required, required for launch
# For push campaigns:
push:
title: Daily Digest
message: Check out today's updates
image_url: https://example.com/image.png
# For LINE campaigns:
line:
line_sender_account_id: ref:LINE Sender
messages:
- type: textV2
text: Hello {{profile.first_name}}!
# For SMS campaigns (Always-On specific):
sms:
sender_id: ACME # SMS sender ID
text: Your code is {{code}}
send_window_timezone: Asia/Tokyo # always-on: required for launch
send_window_start: '09:00:00' # always-on: required for launch
send_window_end: '21:00:00' # always-on: required for launch
send_window_blocked_weekdays: # optional
- Sunday
- Saturday
# Optional sections:
utm:
enabled: true
id: campaign-001
medium: email
source: treasuredataemail.preheader is optional inbox preview text. It supports Liquid tags, is limited to 220 characters by the API, and accepts null to clear an existing value.
Content Types Supported:
| Type | Required fields | Email template | Launch requirements |
|---|---|---|---|
email | subject, html_file, template | HTML file in same directory | sender_id |
push | title, message | — | (none) |
line | line_sender_account_id, messages | — | (none) |
sms | sender_id, text | — | sender_id, text, send_window_timezone, send_window_start, send_window_end |
| Status | Description |
|---|---|
DRAFT | Campaign is being prepared, not yet launched |
LIVE | Campaign is actively running |
PAUSED | Campaign is temporarily paused |
FINISHED | Campaign has been permanently completed |
| Status | Description |
|---|---|
DRAFT | Campaign is being prepared, not yet launched |
ACTIVE | Campaign is currently running |
PAUSED | Campaign is temporarily paused |
COMPLETED | Campaign has finished execution |
| Type | Description |
|---|---|
email | Email marketing campaigns |
push | Push notification campaigns |
line | LINE messaging campaigns |
LINE campaigns use a line: section in the campaign YAML. Two message types are supported.
type: campaign
name: My LINE Campaign
campaign_type: line
line:
line_sender_account_id: '<sender-uuid>' # From: tdx engage line-sender-account list
messages:
- type: textV2
text: 'Hello {{profile.first_name}}! Check out our latest offer.'Upload the image first with tdx engage line-imagemap-image upload, then use the returned baseUrl:
type: campaign
name: My LINE Imagemap Campaign
campaign_type: line
line:
line_sender_account_id: '<sender-uuid>'
messages:
- type: imagemap
base_url: 'https://profile.line-scdn.net/0h...' # From: tdx engage line-imagemap-image upload
alt_text: 'Tap to explore our offers'
base_size:
width: 1040
height: 1040
actions:
# URI action — opens a URL
- type: uri
link_uri: 'https://example.com/offer'
label: 'View Offer'
area: { x: 0, y: 0, width: 1040, height: 1040 }Action types:
| Type | Required fields | Description |
|---|---|---|
uri | link_uri, area | Opens a URL when tapped |
message | text, area | Sends text as a message from the user (not yet supported) |
clipboard | clipboard_text, area | Copies clipboard_text to the user's clipboard (not yet supported) |
The uri action supports an optional label field.
base_size constraints: width must be 1040. height can be any value, but LINE recommends a 1:1 ratio (1040×1040).
Limits: Up to 5 messages per line: section; up to 50 actions per imagemap message.
# 1. Find your LINE sender account
tdx engage line-sender-account list --workspace "Marketing Team"
# 2. Upload imagemap image (if using imagemap type)
tdx engage line-imagemap-image upload ./banner.jpg
# 3. Write campaign YAML (use baseUrl from step 2)
# 4. Validate locally
tdx engage campaign validate my-line-campaign.yaml
# 5. Push to API (dry-run first)
tdx engage campaign push my-line-campaign.yaml --dry-run
tdx engage campaign push my-line-campaign.yaml --yesManage images and assets in the Engage Digital Asset Management (DAM) storage.
# List root directory
tdx engage media ls
# List a specific folder
tdx engage media ls uploads/images
# Find recent matching files, newest first
tdx engage media ls uploads/images --name hero --node-type media_file --date-range last_30_days --sort=-updatedAt
# Page through files uploaded by a specific user
# --limit is a global option; DAM accepts values from 1 through 100
tdx engage media ls --uploaded-by "Admin User" --limit 20 --offset 20
# Upload an image (JPEG, PNG, GIF supported)
tdx engage media upload ./banner.jpg
tdx engage media upload ./banner.jpg --path uploads/images
tdx engage media upload ./banner.jpg --path uploads --conflict replace
# Create a directory
tdx engage media mkdir uploads/images
# Delete a file
tdx engage media rm uploads/images/banner.jpg
# Delete a directory (must be empty)
tdx engage media rmdir uploads/imagestdx engage media ls [path] supports server-side filtering, sorting, and pagination:
| Option | Values | Description |
|---|---|---|
--name <text> | Any text | Case-insensitive partial match on asset or folder name. |
--node-type <type> | media_file, media_folder | Restrict results to files or folders. |
--uploaded-by <name> | Any text | Case-insensitive partial match on the uploader name. This filter returns files only. |
--date-range <range> | last_7_days, last_30_days, all | Restrict results by upload date. |
--sort <order> | updatedAt, -updatedAt, name, -name | Sort results. Prefix with - for descending order; use --sort=-updatedAt when the value starts with -. |
--limit <number> | 1–100 | Maximum matching items to return. This is a global option. |
--offset <number> | Non-negative integer | Number of matching items to skip before returning results. |
JSON and JSONL output include the API's paginationMeta.total and page navigation links, in addition to the directory metadata and listed items.
| Strategy | Behavior |
|---|---|
ask (default) | Fails with HTTP 409 if the file already exists |
replace | Overwrites the existing file |
keep | Auto-renames to avoid conflict (e.g. image_20240427103045.jpg) |