Integrations

Cordial: Telltide Seed Address Guide

Place Telltide seeds in Cordial audiences and orchestrations.

Cordial is a cross-channel messaging platform that uses a contact-centric model where the subscribeStatus field controls email deliverability. Lists in Cordial are boolean contact attributes; a contact is "on" a list by having that attribute set to true. Automations are triggered by events, list additions (with Date Tracking enabled), or API calls. The most important constraint for seed management: Cordial has AI-powered Frequency Optimization that dynamically caps the number of weekly emails per contact based on engagement history, and a seed with minimal engagement history may be suppressed by the cap after 12 weeks of account data accumulates.

Quick reference

Send typeWhere to add seedsComplexity
Scheduled (Broadcast)Create seed contact with subscribeStatus = subscribed; target via Audience Builder conditionLow
Ongoing (Automation)Create seed contact; trigger via event, list attribute change, or API triggerMedium

1. Scheduled / one-off sends (Broadcasts)

Cordial Broadcasts are one-time email sends. The audience is built with the Audience Builder using contact attributes, list memberships, events, and purchase history. Seeds must be contacts with subscribeStatus = subscribed.

Where to add seed addresses

The simplest approach: set a custom boolean attribute internal_test_user = true on seed contacts. In the Broadcast Audience Builder, add this as an OR condition: internal_test_user is true alongside the main audience rules.

Non-technical path

For CRM managers without API access. All of these options live inside the Cordial UI.

  1. Add a Contact directly. Navigate to Contacts > Contacts, click + New Contact, enter the seed email address, set channels.email.subscribeStatus to subscribed, add the custom attribute internal_test_user: true, assign the contact to any relevant Lists, and save.
  2. CSV import via Contact Import. Build a CSV with columns for email, subscribeStatus, internal_test_user, and any list keys. Navigate to Contacts > Contact Imports, upload the CSV, and map columns to attributes.
  3. Sign-up form. If your account uses a Cordial-hosted sign-up form or JavaScript Listener form, submit the seed email through the same form your real subscribers use. This guarantees the seed runs through the exact welcome path.
  4. Manual Audience or List add. Navigate to Contacts > Lists, open the trigger List, and use Add Contacts to attach the seed. For Audiences, save the seed as a Contact first, then verify the Audience preview shows the seed when the OR clause is in place.

Technical path

For email-dev and ops. Cordial's REST API base URL depends on your account region: https://api.cordial.io/v2/ for accounts on admin.cordial.io, or https://api.usw2.cordial.io/v2/ for accounts on usw2.admin.cordial.io. Authentication is HTTP Basic: pass the encoded API key (generated under Settings > API Keys) as the username and leave the password blank.

Upsert a seed contact

POST https://api.cordial.io/v2/contacts
Content-Type: application/json
Authorization: Basic {{base64_encoded_api_key}}

{
  "channels": {
    "email": {
      "address": "seed@example.com",
      "subscribeStatus": "subscribed"
    }
  },
  "first_name": "Seed",
  "last_name": "Monitor",
  "internal_test_user": true
}

subscribeStatus values: "subscribed" (receives marketing emails), "unsubscribed" (excluded from all sends), "none" (excluded from sends; the default if omitted).

Custom attribute requirement: Contact attributes must be created in the account before they can be populated. Navigate to Contacts > Attributes to create internal_test_user (boolean type) if it does not already exist.

Upsert behavior: If a contact matching the identifier already exists, the record is updated. Otherwise a new contact is created.

forceSubscribe: true: Add this field to re-subscribe a contact that was previously unsubscribed:

POST https://api.cordial.io/v2/contacts
Authorization: Basic {{base64_encoded_api_key}}

{
  "channels": {
    "email": {
      "address": "seed@example.com",
      "subscribeStatus": "subscribed"
    }
  },
  "forceSubscribe": true
}

Add the seed to a List via API

Lists are stored as a key/value map on the contact. Set the list key to true to add, false to remove:

POST https://api.cordial.io/v2/contacts
Authorization: Basic {{base64_encoded_api_key}}

{
  "channels": {"email": {"address": "seed@example.com", "subscribeStatus": "subscribed"}},
  "lists": {
    "newsletter": true,
    "vip": true
  }
}

Push a behavioral event for the seed

Cordial Events are recorded via POST /v2/contactactivities. The action name lives in the a field, the contact identifier in email (or cID), and event data in properties:

POST https://api.cordial.io/v2/contactactivities
Authorization: Basic {{base64_encoded_api_key}}

{
  "a": "browse",
  "email": "seed@example.com",
  "ats": "2026-05-01 09:30:00",
  "properties": {
    "category": "Electronics",
    "title": "Widget Pro",
    "url": "https://yourstore.com/products/widget",
    "price": 49.99
  }
}

Profile attributes required

Seeds need:

  • Email address
  • channels.email.subscribeStatus = "subscribed" (contacts with unsubscribed or none status are excluded from broadcast audience counts and sends)
  • Values for any custom attributes referenced in the message template

Ensuring seeds receive the same version as real recipients

Dynamic Audience Builder rules: Audiences are evaluated in real time. If the broadcast uses rules based on purchase history, engagement, or other behavioral data, the seed must satisfy those conditions OR be included via the internal_test_user = true OR condition.

A/B split in Broadcasts: Cordial supports retargeting broadcasts (resend to contacts who did or did not open or click). For initial A/B variant testing, the seed is assigned to one branch. Use multiple seed contacts to monitor all variants.

Gotchas

Frequency Optimization may suppress seeds. Cordial's AI-powered Frequency Optimization caps weekly email sends per contact based on engagement data. After 12 weeks of data accumulates in the account, seeds with low engagement scores may have their weekly cap reduced and be excluded from sends. The cap can be turned off during specific periods. Monitor whether seeds are showing as "Skipped" in Message Reports due to the frequency cap.

forceSubscribe: true is required to re-subscribe. A contact that was previously unsubscribed (via an unsubscribe link, spam complaint, or manual update) has subscribeStatus = unsubscribed. Updating their status to subscribed without forceSubscribe: true may not re-enable delivery. Always include forceSubscribe: true when reactivating seed accounts.


2. Ongoing / automated journeys (Automations)

Cordial Automations are triggered messaging sequences. Three sending methods are available: Event Triggered, Recurring, and API Triggered.

Automation trigger types

Trigger typeHow it firesSeed approach
Event Triggered, eventFires when a contact triggers a defined event (e.g., cart, purchase)Track the event via /v2/contactactivities or a connected store
Event Triggered, added to listFires when a contact is added to a list (requires Date Tracking on the list)Add seed to the trigger list via API or UI
Event Triggered, attribute changeFires when a contact attribute value changesUpdate the trigger attribute on the seed contact
RecurringRuns on a schedule; checks conditions on each runSeed must qualify at the scheduled check time
API TriggeredFired via POST /v2/automationtemplates/{key}/sendCall the API trigger endpoint with seed contact data

Always-on flow coverage

Always-on Automations only deliver to seeds when the seed satisfies the same Audience and entry conditions as a real contact. Bake seed coverage into the automation primitives directly:

  • Audience entry condition. Open the Automation, inspect the Audience attached to the entry step, and add an OR clause internal_test_user is true so seed contacts qualify regardless of behavioral history. For dynamic Audiences referenced inside Recurring Automations, add the same OR clause to the Audience definition under Audiences > [name] > Edit Rules.
  • List trigger. When the trigger is "added to list," confirm the target List has Date Tracking enabled before the seed is ever attached. Add the seed via POST /v2/contacts with lists: {"<list_key>": true} so the List Date is captured fresh.
  • Event trigger. When the trigger is an Event, push the same event name and required properties keys via POST /v2/contactactivities for the seed. If the Automation filters on event property values (for example properties.totalValue >= 50), the seed event payload must satisfy those filters.
  • Attribute change trigger. Update the watched attribute on the seed (birth_date, last_purchase_date, etc.) so the change event fires. Re-entry is gated by the Automation's re-entry rule, not the API.
  • Frequency Optimization bypass. For monitoring-critical Automations, mark the message type as transactional or essential so Cordial's frequency cap does not silently skip the seed.

Creating trap profiles per journey type

Welcome / onboarding (Added to list trigger)

  • Trigger: Contact is added to a specific list (list must have "Date Tracking" enabled)
  • Seed requirements: Contact with subscribeStatus = subscribed
  • How to enable Date Tracking on a list: Navigate to the list settings in Cordial and enable "Date Tracking." This records the timestamp when a contact is added, which is used to fire the trigger.
  • How to trigger: Add the seed contact to the trigger list via the API:
POST https://api.cordial.io/v2/contacts
Content-Type: application/json
Authorization: Basic {{base64_encoded_api_key}}

{
  "channels": {
    "email": {
      "address": "seed@example.com",
      "subscribeStatus": "subscribed"
    }
  },
  "lists": {
    "welcome-trigger-list": true
  }
}

Where welcome-trigger-list is the key name of your trigger list. The list key must already exist in the account.

Abandoned cart (Cart event trigger)

  • Trigger: cart event recorded for the contact, containing items array
  • Seed requirements: Contact with subscribeStatus = subscribed
  • How to trigger via the contact activities API:
POST https://api.cordial.io/v2/contactactivities
Content-Type: application/json
Authorization: Basic {{base64_encoded_api_key}}

{
  "a": "cart",
  "email": "seed@example.com",
  "ats": "2026-05-01 09:30:00",
  "properties": {
    "cartId": "CART-TEST-001",
    "totalValue": 95.00,
    "currency": "USD",
    "items": [
      {
        "productId": "SKU-123",
        "name": "Widget Pro",
        "price": 95.00,
        "quantity": 1,
        "imageUrl": "https://yourstore.com/img/widget.jpg",
        "productUrl": "https://yourstore.com/products/widget"
      }
    ]
  }
}

The exact event name and required properties depend on how your Cordial account's abandoned cart event type is configured.

Browse abandonment (Browse event trigger)

  • Trigger: Browse event recorded when the contact views a product or category
  • Seed requirements: Contact with subscribeStatus = subscribed
  • How to trigger:
POST https://api.cordial.io/v2/contactactivities
Authorization: Basic {{base64_encoded_api_key}}

{
  "a": "browse",
  "email": "seed@example.com",
  "ats": "2026-05-01 09:30:00",
  "properties": {
    "productId": "SKU-123",
    "title": "Widget Pro",
    "category": "Electronics",
    "url": "https://yourstore.com/products/widget",
    "imageUrl": "https://yourstore.com/img/widget.jpg",
    "price": 49.99
  }
}

Winback / re-engagement (Recurring trigger)

  • Trigger: Recurring automation running daily or weekly; conditions filter contacts with last_purchase_date older than the lapse threshold
  • Seed requirements: Contact with last_purchase_date attribute set to a date older than the threshold

Set the attribute:

POST https://api.cordial.io/v2/contacts
Authorization: Basic {{base64_encoded_api_key}}

{
  "channels": {"email": {"address": "seed@example.com", "subscribeStatus": "subscribed"}},
  "last_purchase_date": "2026-01-15"
}

The attribute key must match what is configured in the automation's condition rules.

Post-purchase (Purchase event trigger)

  • Trigger: purchase event recorded for the contact
  • Seed requirements: Contact with subscribeStatus = subscribed
  • How to trigger:
POST https://api.cordial.io/v2/contactactivities
Authorization: Basic {{base64_encoded_api_key}}

{
  "a": "purchase",
  "email": "seed@example.com",
  "ats": "2026-05-01 09:30:00",
  "properties": {
    "orderId": "TEST-ORD-001",
    "orderTotal": 149.99,
    "currency": "USD",
    "items": [
      {
        "productId": "SKU-123",
        "name": "Widget Pro",
        "quantity": 1,
        "price": 149.99
      }
    ]
  }
}

Birthday / anniversary (Attribute change trigger)

  • Trigger: Contact attribute value changes on birth_date (or equivalent date attribute)
  • Seed requirements: Contact with birth_date attribute; trigger fires when the attribute is first set or updated
  • Alternative: Recurring trigger that checks anniversary_of(birth_date) = today

Set birthday attribute:

POST https://api.cordial.io/v2/contacts
Authorization: Basic {{base64_encoded_api_key}}

{
  "channels": {"email": {"address": "seed@example.com", "subscribeStatus": "subscribed"}},
  "birth_date": "1990-04-15"
}

The attribute change trigger fires when this value is written. For anniversary-based recurring triggers: set the date to today's month and day so the recurring check matches.


API Triggered automations

For automations that use the API Triggered method, the request body uses a to envelope containing a contact object plus optional extVars for template personalization, and an identifyBy field that names the lookup identifier:

POST https://api.cordial.io/v2/automationtemplates/{automation_key}/send
Content-Type: application/json
Authorization: Basic {{base64_encoded_api_key}}

{
  "identifyBy": "channels.email.address",
  "to": {
    "contact": {
      "channels": {
        "email": {
          "address": "seed@example.com",
          "subscribeStatus": "subscribed"
        }
      }
    },
    "extVars": {
      "orderID": "TEST-ORD-001",
      "orderTotal": 149.99
    }
  }
}

Replace {automation_key} with the automation template key visible in the Cordial automation settings. Values inside extVars are accessible in the template as {$extVars.orderID}. Use this method for any automation where simulating the natural trigger event is impractical.


How to reset seeds for repeated testing

Event-triggered automations: Track the trigger event again via /v2/contactactivities. Cordial typically allows re-entry unless the automation has a re-entry restriction configured.

List-triggered automations: Remove the seed from the trigger list (lists: {"welcome-trigger-list": false}), wait for processing, then re-add the seed to the list.

Recurring automations: The automation re-evaluates on its next scheduled run. Update the seed's qualifying attributes between cycles as needed.

API Triggered automations: Call the API trigger endpoint again.


3. Platform-specific considerations

API options

Base URLs by region:

  • https://api.cordial.io/v2/ for accounts on admin.cordial.io
  • https://api.usw2.cordial.io/v2/ for accounts on usw2.admin.cordial.io

Create or update contact (upsert):

POST https://api.cordial.io/v2/contacts
Authorization: Basic {{base64_encoded_api_key}}

Batch upsert contacts:

POST https://api.cordial.io/v2/contactimports

Record a contact activity (event):

POST https://api.cordial.io/v2/contactactivities

Trigger an API-driven automation:

POST https://api.cordial.io/v2/automationtemplates/{key}/send

API key location: Settings > API Keys > Generate Key. The IP address used to call the API must be whitelisted at key creation time. Pass the encoded key as the username in HTTP Basic Auth, with an empty password.

Rate limits

Cordial does not publish specific rate limits publicly. Implement exponential backoff on 429 responses. For large bulk operations, use the contactimports batch endpoint or the Asynchronous API. Cordial also exposes per-account throttling settings inside the platform that govern outbound batch send rate.

Channel coverage

Cordial supports email, SMS, mobile push, in-app, and a generic REST channel for direct mail or call-center integrations. Seed monitoring is email-only; SMS and push seeds require channel-specific identifiers (channels.sms.address, channels.push.tokens) and cannot be served by Telltide's email seed pipeline.

Duplicate contact handling

Contacts are matched by an ordered identifier priority list: cID (Cordial-assigned internal ID) first, then configured secondary identifiers (email, custom ID). If a match is found on any identifier, the existing contact is updated. If no match, a new contact is created.

The identifiersPriority parameter on the upsert request lets you control the lookup order explicitly.

Platform-specific terminology

Cordial termWhat it means
ContactA person record in Cordial (equivalent to a Subscriber or Profile in other platforms).
subscribeStatusThe email marketing opt-in state: subscribed, unsubscribed, none.
BroadcastA one-time email send (equivalent to a Campaign or Blast in other platforms).
AutomationA triggered or recurring messaging sequence.
ListA boolean contact attribute; a contact is "on" a list by having the list attribute set to true.
Date TrackingA list setting that records the timestamp when a contact is added. Required for "added to list" automation triggers.
Contact activity (Event)A behavioral signal tracked for a contact (e.g., cart, purchase, browse), recorded via /v2/contactactivities.
Audience BuilderThe drag-and-drop rule builder used to define broadcast audiences from contact attributes, lists, events, and orders.
SupplementsAuxiliary data collections (product catalog, store locations, coupon codes) referenced in templates and audience rules.
Frequency OptimizationCordial's AI-driven per-contact weekly email cap. Requires 12 weeks of send history for accurate modeling.
Unsubscribe Risk AICordial's feature that scores each contact on 4-week unsubscribe likelihood.
forceSubscribeAPI parameter that overrides a previously set unsubscribe flag to re-enable a contact's email delivery.
cIDCordial's system-assigned internal contact identifier. The highest-priority deduplication key.

Known limitations and workarounds

Frequency Optimization silently suppresses sends. After 12 weeks of account data, seeds with low engagement may be skipped by the frequency cap. Monitor the "Skipped" count in Message Reports. Turn off Frequency Optimization during critical monitoring periods or configure transactional or essential message types to bypass the cap.

List Date Tracking must be enabled before the trigger can fire. If you add a seed to a list and then enable Date Tracking, the seed's previous addition event is not captured. Enable Date Tracking on lists before adding seeds.

Custom attributes must be created before population. Attempting to set an attribute that does not exist in the account's attribute schema fails silently or returns an error. Always verify attribute existence before creating seed contacts with custom fields.

forceSubscribe: true is required to re-subscribe previously unsubscribed contacts. Standard attribute updates without this flag may not override the unsubscribed state. Include it on all seed re-activation calls.

API key IP allowlist. Cordial API keys are bound to the IP addresses whitelisted at key creation. Calls from any other origin return an auth error even with valid credentials. Plan ingress IPs ahead of seed automation.

Start monitoring your Cordial sends

Place a Telltide seed in your Cordial audience, and we will tell you when an expected email did not land.

Start free