Messaging-API Payload and Design for Complex Transactional Use

This documentation provides a comprehensive guide to designing and structuring payloads for the Messaging API in complex transactional scenarios. It emphasizes the key differences between using internal contacts and external recipients, demonstrates how to add data for internal recipients, explains the use of loops (arrays) in both payload and design, and details how the syntax changes depending on whether data is sourced from the database or directly from the payload.

1. Overview of Messaging API

Messaging API enables sending messages (email only at the moment) to recipients specified either as internal contacts (stored in the Splio database) or as external recipients (not in the database). The API is highly flexible, allowing for advanced personalization by accepting both database-linked and payload-supplied data, supporting custom variables, arrays, and complex objects.


2. Use Cases: Internal Contacts vs. External Recipients

2.1. Internal Contacts

Internal contacts are recipients whose profiles exist within the Splio database. Messages sent to these contacts can leverage all marketing features of Splio, including tracking, analytics, mirror links, list management, and advanced personalization using data from the contact database as well as additional payload-supplied variables.

Key Features:

  • Full marketing and transactional capabilities.
  • Access to all contact fields and custom fields.
  • Consistent use of mirror/unsubscribe links and tracking.
  • Personalization uses both DB fields and optional variables from the API payload.

2.2. External Recipients

External recipients are not present in the Splio contact database. They are typically used for purely transactional messages (e.g., order confirmations, alerts) where marketing features are not required or permitted.

Key Features:

  • Only transactional usage is supported.
  • All personalization must be provided in the API payload.
  • Unsubscribe management via a transactional blacklist, not contact lists.
  • Greater flexibility in variable structure (no need to match Splio data model).

Design Implications:

  • Designs must use variables as provided in the payload.
  • No access to database-driven personalization.
  • Liquid syntax in templates refers only to payload-supplied variables.

3. Structure of the Messaging API Payload

3.1. Basic Structure

A typical payload for a message sent via Messaging API includes the following sections:

  • channel: The communication channel (e.g., "email").
  • recipients: An array of recipient objects, each of which can contain:
    • Contact identifiers (contact_id, email, etc.)
    • Personalization variables (flat or nested, including arrays)
    • Additional resources (e.g., order IDs)
  • properties: Message content (design ID, HTML, subject, etc.)
  • metadata: Campaign or transactional metadata for analytics or tracking.

Example: External Recipient (Transactional)

{
  "channel": "email",
  "transactional": true,
  "recipients": [
    {
      "email": "[email protected]",
      "variables": {
        "firstname": "Julie",
        "lastname": "Dupont",
        "order_id": "order_123",
        "orders": [
          {
            "product_ref": "XXXXXXXX",
            "product_img": "<https://cdn.message-builder.splio.pro/images/pophat/upload/3_1768318932.jpg>",
            "product_name": "Chemise iconique fil à fil femme",
            "product_coloris": "Blue",
            "product_taille": "M",
            "product_quantite": "1",
            "product_prix": "XXXX.XX"
          },
          {
            "product_ref": "XXXXXXXX",
            "product_img": "<https://cdn.message-builder.splio.pro/images/pophat/upload/3_1768318932.jpg>",
            "product_name": "Chemise iconique fil à fil homme",
            "product_coloris": "Pink",
            "product_taille": "M",
            "product_quantite": "1",
            "product_prix": "XXXX.XX"
          }
        ]
      }
    }
  ],
  "metadata": {
    "campaign_name": "merci_pour_votre_commande"
  }
}

Variable names can be freely chosen but should avoid dots (.) to prevent conflicts in JSON path parsing within the design engine.

Example: Internal Contact

{
  "channel": "email",
  "recipients": [
    {
      "contact_id": "142993",
      "variables": [
        { "key": "title", "value": "Mr" },
        { "key": "societe", "value": "MyCompany" }
      ],
      "resources": {
        "order_id": "12355"
      }
    }
  ],
  "properties": {
    "content_id": "51829"
  }
}

Here, variables can supplement existing database fields for richer personalization.


4. Adding Data for Internal Recipients

When targeting internal contacts, the API allows injecting additional variables into the rendering context. These variables are available in the design template alongside the standard contact fields (e.g., {{ contact.firstname }}, {{ contact.email }}).

Example:

{
  "recipients": [
    {
      "contact_id": 1852308,
      "variables": [
        { "key": "order_total", "value": "150.00" }
      ]
    }
  ]
}

In the design:

Bonjour {{ contact.firstname }}, votre commande totalise {{ order_total }} €.

This pattern enables advanced, per-message personalization without altering the core contact data.


5. Using Arrays and Loops in Payload and Design

5.1. Arrays in Payload

To handle complex transactional content (such as order lines or lists of products), the API payload can include arrays of objects under a variable key. This is especially powerful for transaction confirmation emails, where each order may have multiple items.

Example Payload:

"variables": {
  "orders": [
    {
      "product_ref": "001",
      "product_name": "Shirt",
      "product_price": "39.99"
    },
    {
      "product_ref": "002",
      "product_name": "Pants",
      "product_price": "59.99"
    }
  ]
}

5.2. Loops in Design (Liquid Syntax)

In the email design, you can use Liquid templating to iterate over these arrays:

{% for order in orders %}
  <tr>
    <td>{{ order.product_ref }}</td>
    <td>{{ order.product_name }}</td>
    <td>{{ order.product_price }}</td>
  </tr>
{% endfor %}

This approach works identically for both internal contacts and external recipients, as long as the variable structure matches what the design expects.


6. Data Source: Database vs. Payload

6.1. Data from Database (Internal Contacts)

  • Fields such as contact.firstname, contact.lastname, and custom fields defined in Splio are available in the design.
  • Syntax in Liquid: {{ contact.firstname }}, {{ contact.custom_field["my_fields"] }}.
  • Additional variables can be injected via the payload as shown above.

6.2. Data from Payload (External Recipients or Supplementary Data)

  • All variables must be provided in the variables object in the payload.
  • Syntax in Liquid: {{ variable_name }} or, for arrays, {{ variable_name[index].field }}.
  • No access to contact. fields or database-defined fields.

6.3. Syntax Differences

SourceExample Variable in PayloadLiquid Syntax in Design
Database(contact field){{ contact.firstname }}
Payload"order_total": "150.00"{{ order_total }}
Payload Array"orders": [ ... ]{% for order in orders %} ... {% endfor %}

When mixing data sources (internal contacts with payload variables), both can be referenced in the template. For external recipients, only payload variables are available


7. Best Practices and Design Recommendations

  • Avoid dots (.) in variable names in the payload to prevent parsing issues in the design engine; use underscores or nested objects instead.
  • Consistency in variable naming is crucial, especially when looping through arrays. Each object in the array should have the same keys.
  • Test payloads and designs together to ensure variables are correctly rendered and loops display as expected.
  • Use the simplest structure possible for your use case: for purely transactional, external recipient emails, keep everything in the payload; for marketing or mixed use, prefer internal contacts with database fields.

8. Migration and Design Change Summary

  • Trigger-API (legacy) allowed mixing contacts and external recipients but led to inconsistencies. The Messaging API enforces a cleaner separation.
  • Messaging API supports both use cases but recommends not mixing them within a single call or design.
    • For transactional, external recipients, all data must be in the payload.
    • For internal contacts, designs can use both contact fields and payload-supplied variables.
    • Designs must be adapted: use {{ contact.field }} for internal contacts, and {{ variable }} for payload-supplied data. Loops over arrays are supported in both cases if the payload provides them.

9. References