Transactional Messaging Guide for Developers

Solve transactional messaging jobs with the Transactional Messaging API. Automate efficient delivery of non-promotional messages, including:

  • Purchase confirmation.
  • Multi-factor authentication.
  • Security alerting.

This guide assumes that you're familiar with the Salesforce Marketing Cloud (SFMC) API environment. We recommend the Get Started with Transactional Messaging API document, if you need a refresher.

Make send definitions via Transactional Send Journeys in Journey Builder. The out-of-the-box (OOB) features of Transactional Send Journeys user interface (UI) meet many functional requirements for developers, and their organizations. Using the Transactional Messaging API, create send definitions that are available in the UI, as well as many that are not available there (see options.createJourney).

Like other features of SFMC that use send definitions, the Transactional Messaging API requires content to exist as a message in the appropriate channel (email, SMS, push, and so on). You optionally specify additional components of the send definition. See this documentation for a description of email channel send definition creation. For an email channel, the Transactional Messaging API requires a send classification of type transactional, as described here.

Send requests pass through these SFMC layers:

  1. API Layer.
  2. Service Layer, also known as the Transactional Messaging Service Layer.
  3. OMM Layer, also known as the Message Composition Layer, or Outbound Mail Management.
  4. MTA Layer, or Message Transmission Layer.

The rest of this section describes each layer in turn.

The API layer handles REST API requests from your application to SFMC endpoints to the Transactional Messaging API service. Create, read, update, and delete (CRUD) methods for send definitions, and sending and queue management resources differ by channel. For example, email has a different set of CRUD endpoints than SMS. See “TransactionalMessaging” in this list of SFMC REST resources or this Postman public workspace.

Endpoints send synchronously, except for:

  • POST /messaging/v1/[channel]/messages
  • POST /messaging/v1/[channel]/messages/{messageKey}

Send requests require a value for messageKeys. The value must be unique among all requests over the prior 72 hours. In a single-send request, you must generate the messageKeys externally, and include it in the URL for the POST command. In a multiple-send request, if a messageKey value is omitted from any recipient's payload, Salesforce auto generates the messageKey. Please see Client Application Best Practices later in this document.

If there are errors, they are returned in the Response body. Synchronous request errors are syntax-based, data-based, or procedural. Requests to send are asynchronous, and return either an error for authentication failure, syntax issues, or unavailable service. A successful response only confirms receipt of the request.

The service layer converts the inbound send request data payload into the format that the OMM requires. It also records the converted data as specified in the send definition’s Data Extension, when configured to do so. Validation checks occur against values found in the data payload. Examples include:

  • Ensuring the email address is valid.
  • Ensuring attribute values conform to the configuration defined in that SFMC tenant.

The service layer is asynchronous. When a request to send is accepted by the API, it is queued in the Service Layer. Requests exit the queue as units of work for the OMM layer, specifically a Batch of Subscribers to be delivered through a Job:

  • Job: The process used to deliver messages for an active Send Definition, representing the most recent configuration of that send definition and uniquely identified by JobID. Changing configuration results in creation of a new Job and JobID.
  • Subscriber: The representation of a Contact within a particular channel. A SubscriberID (a.k.a. ContactID) or a SubscriberKey (a.k.a. ContactKey) uniquely identifies a Subscriber. SFMC generates a SubscriberID and an external process provides a SubscriberKey.
  • Batch: The collection of one or more subscribers simultaneously processed as an attempt to build and deliver a message within a particular Job. A BatchID uniquely identifies a Batch.

Messages to an individual via the Transactional Messaging API are uniquely identifiable by JobID + BatchID + SubscriberID. In combination with messageKey and the Event Notification Service, you can build and persist a comprehensive picture of SFMC behavior by any client application. Please see the sections Message Disposition and Client Application Best Practices that follow.

The queueing mechanism of the Service Layer is designed to support the goal of processing in less than 5 seconds. Errors that occur during validation of data values in queued requests don't return to the client application directly. They are available using follow-on requests and the Event Notification Service. Please see the sections Message Disposition and Client Application Best Practices further on in this article.

The OMM layer uses the normalized data values from the originating API request’s payload to build the message content. For example, with HTML for email, it attempts to deliver to each recipient. Behavior in the OMM layer is identical across all SFMC sending technologies. For example:

  • Journey Builder.
  • Automation Studio.
  • Classic Triggered Sends.

The OMM evaluates the send definition content in the configured message and related options. It evaluates them against each subscriber’s attribute value. After scripting, personalization, and other content finalization, the rendered message passes to the MTA layer.

Errors can occur during message construction. A logic error, for example, in scripted message content. These errors are not returned to the client application, but are accessible via follow-on requests and the Event Notification Service as with the Service Layer. For more on this topic, please see the sections Message Disposition and Client Application Best Practice further on in this document.

Performance at this layer depends on:

  • The complexity of the message content.
  • The SFMC tenant’s data environment.
  • External systems.

For example, if a scripted function calls a loop to use HTTP Get requests targeting an external service, then the number of loop cycles, and the capabilities of that external service influence the time needed to build each message.

The MTA layer is the final step, and behaves the same across all SFMC sending technologies:

  • The rendered message is moved from SFMC to the corresponding recipient resources. Examples include
    • Email server.
    • SMS aggregator.
  • The Event Notification Service (ENS) raises any errors in delivery. For more on errors, see the Message Disposition section further on in this document.
  • Query errors using Automation Studio and API resources are not discussed in this document.

Before the Transactional Messaging API, SFMC transactional messaging was handled by Classic Triggered Send SOAP Web Services and the messageDefinitionSends resource. These resources served transactional sending needs, but not fully. Both technologies persist today. Neither was purpose-built to the requirements of transactional sends. Understanding the differences between Classic Triggered Send and Transactional Messaging lets you select the best technology for a particular use case.

Using Transactional Messaging eliminates the need for a developer or client application to handle concepts like:

  • Asynchronous versus synchronous processing.
  • Message and request prioritization.
  • Request disposition.

With legacy technology, solving for these aspects made it harder to deploy a transactional messaging process. The following are all significant differences from Classic Triggered Sends when moving to the Transactional Messaging API.

Area of DifferenceDifference Description in Transactional Messaging API
Configuration options and features- The user interface exists in Journey Builder, not Email Studio.
- It is optional for each Send Definition to be accessible via user interface.
- The messages must be created using Content Builder.
- The send definitions do not support send logging.
- Webhook style data surfacing is available via the ENS, including request disposition.
- Exclusion filters and definition-specific suppression lists are not used (auto-suppression lists still apply).
- Header and footer content, From Name, and Reply options are controlled via send classification, message content, or both.
- Send throttling is not used.
API Layer- The messageKey value is required as a unique identifier for all requests made in the previous 72 hours.
- There is true RESTful operation of API resources.
- There is a consistent endpoint and request syntax across messaging channels (Email, Push, and SMS).
- Send request status is available from ENS instead of an asynchronous HTTP post-back.
- Object access is controlled by authentication token context, not Client.ID property within request’s Body.
- All requests are processed equally, with no need to solve for priority.
- A PATCH request applies updated configuration to later send requests through definition.
Service Layer- Updates to definitions result in an automatic refresh of the configuration for future sends (“Publish” not required).
- All requests are processed equally, so there's no need to prioritize, or choose between asynchronous and synchronous handling.
- Errors are surfaced in real time via the ENS.
- The queue consistently processes in under 5 seconds from end to end.
OMM Layer- Errors are surfaced in real time via the ENS.
MTA Layer- Bounce and delivery receipts are surfaced in real time via the ENS.
Other- The Send Definition object used in SFMC’s application data is a Triggered Send type but is distinct from Classic Triggered Sends.
- Requests to the SOAP Web Services TriggeredSend object do not interact with Transactional Messaging API definitions.
- Custom reports or data extracts usually need adaptation to return data for Transactional Messaging API.

Other than the differences mentioned in this table, send behavior handled by the Transactional Messaging API is no different than other SFMC sending technologies. The Messaging Composition Layer (OMM), in particular, behaves identically. So, if you're converting a use case from Classic Triggered Sends to Transactional Messaging API, you can expect your scripted message content to behave in the same way for identical data payloads handled by the two technologies. The existing message content used with Classic Triggered Sends can be used without change in the Transactional Messaging API build-out.

Understanding each request’s status within the SFMC platform improves client applications functionality. SFMC provides webhooks through the Event Notification Service (ENS). With ENS, requests via the Transactional Messaging API provide real-time notification to client applications for significant status events (examples are Sent, NotSent, and Bounced). They also provide feedback on events of recipient engagement (for example, Click, Open). See a full list of supported event types.

To receive events from ENS, the client application establishes a subscription and defines the event types to receive (Get Started with Event Notification Service). Events are directed to a callback URL. A callback URL is a URL exposed from a listener service maintained by or accessible to the client application. It is possible to configure ENS to filter events at SFMC so that only events from particular send definitions are emitted to the callback URL. A typical basic workflow for an ad-hoc demonstration of Transactional Messaging with ENS looks like:

  1. The developer establishes the Installed Package, Message Content, and other necessary assets in the SFMC tenant.
  2. The developer sets up a third-party webhook listener service obtained from a web search for “webhook tester”.
    • The developer records, for future use, the listener service URL.
  3. The developer configures an API testing utility (for example Postman) for use with SFMC APIs.
    • The developer creates a test Collection with the ability to authenticate successfully into an SFMC tenant.
  4. The developer builds requests in a test Collection capable of Postman reference:
    1. The developer creates a new transactional messaging send definition in the email channel.
    2. The developer sends an email message using that send definition.
    3. The developer creates an ENS callback URL, verifying the callback, and creating a subscription.
  5. The developer initiates an HTTP Post from the API testing utility to the ENS to create a callback for the listener URL.
    • The developer records, for future use, the callbackId value from the response.
  6. The listener process receives the verification event from the ENS.
  7. The developer examines the verification event in the listener.
    • The developer records, for future use, the verificationKey value from the event.
  8. The developer initiates an HTTP POST to verify the callback using the callbackId and the verificationKey values.
    • The developer receives a 200 response, confirming that the callback is ready for use.
  9. The developer initiates an HTTP POST, using the callbackId value to create Subscription for Sent, NotSent, Bounce, and Open events.
    • A 200 response confirms Subscription established
  10. The developer initiates an HTTP POST to the Txn Msg API to create a new Send Definition
    • The developer records, for future use, the definitionKey value used in the request.
  11. The developer initiates HTTP POST to Txn Msg API to send email with the definitionKey value recorded in step 10.
    1. The developer records, for future use, the messageKey value used in the request.
    2. The developer records, for future use, the values for jobId, batchId, listId, subscriberId from the event.
  12. The Listener receives the Sent event from the ENS.
  13. The developer examines the Sent event response to confirm that the messageKey value matches the value used in the send request
  14. The developer accesses the email in their inbox, clicking links, or viewing images to validate them.
  15. The listener receives an Open event from the ENS.
  16. The developer examines the Open event to confirm that the values for jobId, batchId, listId, and subscriberId match the values found in the Sent event.

There are many ways to implement an application that uses the Transactional Messaging API. Here are some best practices.

In a Transactional Messaging API request to send, you must provide a data payload value for messageKey. If the message key value isn't unique across all sends within the prior 72 hours for the SFMC Business Unit, then Salesforce throws an error. Even though SFMC can sometimes generate this value, it is a best practice to have the client application handle the value instead.

All send-requests originate from an application whose code is under your control. Therefore, development of those applications includes a process that ensures each request contains a proper value for messageKey. A best practice is to use a true unique identifier in the local data environment as the value for messageKey. Doing so empowers messageKey to become the building block for comprehensive reporting and real-time awareness of message disposition and engagement.

An advantage of using a true unique identifier as the messageKey value is the support it provides for localized storage of request data payloads. Each request to send includes preliminary data collection and generation. Some of this data is required as attribute values in the request’s data payload, supporting message personalization within SFMC. Some of this data describes the context of the triggering event, such as the source of the event (for example, a particular web form submission or the point-of-sale system), and the time at which it occurred. All data, both attribute and context, can be transmitted and stored in SFMC using a Data Extension associated with the send definition. However, that is not best practice as doing so has very limited utility, and degrades end-to-end performance. Instead, that data is stored locally to the client application, using the messageKey value as the primary key value to uniquely identify each stored payload. The following common use cases are made possible by adhering to this model for local storage of data payloads:

  1. Replaying the request as part of error handling.
  2. Extracting relevant data points for follow-on messaging campaigns (examples are purchase history or activity logs).
  3. Combining triggering-event data with behavioral or engagement data (for example, in an external data lake).
  4. Analysis of error behavior or performance trends across triggering-events.

Using a true unique identifier value as messageKey works well with SFMC’s webhook feature: Event Notification Service (ENS). A client application configured with a listener service and subscription to TransactionalSendEvents uses the messageKey value as the initial correlation data point between local data and events returned from ENS. For example, as described in the Message Disposition section above, the Sent event returned contains both the messageKey value used in the original request and the identifiers generated by SFMC: jobId, batchId, listId, and subscriberId.

When the Sent event is received by the listener service, identification of the request’s corresponding local data store, via messageKey, is completed. After the corresponding stored data is found, it's updated to include jobId, batchId, listId, subscriberId. These values are found in the composite data contained in the Sent event’s payload. It's up to the development team to decide if this storage location is the same point where the original data payload from the request is stored or if separate locales exist for disposition and original data. In either case, a messageKey as a unique identifier enables correct identification of the request and its surrounding data across all business unit environments.

Imagine that the listener service receives a Bounce event, or the subscription also supports engagement events, such as Click or Open for email. In such cases, the local data storage can be put to further use. As with Sent events, Bounce events are correlated using messageKey and local storage annotated to reflect the messageKey value. A common use-case would be for failed delivery from a Bounce event to drive a follow-on request to send using an alternative messaging channel. Engagement events require correlation via the values of jobId, batchId, listId, subscriberId. Therefore, the listener service must first capture these values from a Sent event, then later use them to identify the corresponding local data to update, reflecting the fact that a recipient opened the message at a particular time.

Using a true unique identifier value as the messageKey enables robust error handling capabilities in the client application. It's a best practice for a Transactional Messaging API deployment to pair the sending application with a listener service for SFMC’s ENS API. The listener is enabled with a subscription to all TransactionalSendEvent types: Sent, NotSent, and Bounced. If an issue arises at the API or Service layers with handling the send request, the ENS returns a NotSent event to the listener. Similarly, an error arising during the message build in the OMM layer produces a NotSent event. An example of a NotSent event would be from improper attribute data in the payload.

These NotSent events include a messageKey in the payload, allowing the listener to inform the client application of which particular request failed to send. The implementation depends on the development team's plan to process the various error states. For example, the application could incur a short delay, then replay the message, using the original data payload stored locally, or alert local teams or systems of the problem.

It's a best practice is to take advantage of the ENS to gain visibility into request and message disposition. If a Sent event is received, the local application can refrain from error handling. Similarly, if a NotSent event is received, an appropriate action in response to that error can proceed. But, like all distributed systems, communication failures and similar unforeseen disruptions can prevent or delay complete awareness at all times. In situations where a Sent or NotSent event is anticipated, but has not been received for an atypical time period, it's appropriate to directly request the status of the request or message via a GET to the sending service for the appropriate channel. These GET requests to the send service use messageKey in the URL to enable SFMC to return details about that request.

Because messageKey is unique within SFMC for only 72 hours, the GET procedure to return status must be done within that time period. It's detrimental to performance and stability to continually poll this service via a series of GET requests. So, the service is rate-limited for GET requests. Instead, use the ENS for real-time visibility, and only attempt a GET for message status when there's an unusual delay in response from the ENS. For example, if Sent or NotSent events are typically received within 30 seconds of the originating request, a delay of 120-seconds warrants checking status via a GET. Error handling within the local environment reacts to states, and backs off GET requests, instead throwing alerts to monitoring teams. Examples are:

  • Many GET requests for status due to frequent/continual lack of response via the ENS.
  • Failure to receive response from GET request to message-send service.
  • Failure to receive response from POST request to message-send service.

The Transactional Messaging Service offers the highest capacity, compared to other SFMC solutions for API based sending.

The time required from message request to delivery depends on:

  • Internet and ESP architecture factors outside of direct control by the developer or SFMC.
  • The complexity of message content.

Teams responsible for content are assumed to observe best practices and performance guidelines within their domain.

For a team responsible for a Transactional Messaging API application, observing the following guidelines maintains performance:

  • SFMC testing and observation of real-world use cases has shown:
    • Using simple message content, requests handled per second are above 1000 (reference).
    • A POST to the message-send service maintains less than 200-ms response time during peak load.
    • Using simple message content, keeps end-to-end processing time below 5 seconds (reference).
  • All of the guidelines mentioned here are for requests containing a single recipient.
  • None of these guidelines are service level agreement (SLA) or operational level agreement (OLA) guarantees, but are benchmarks for performance goals of a well-structured process.

The following guidelines apply when constructing the data payload of POST requests to the send message service:

  • Avoid the use of Request Attributes.
  • Requests with multiple recipients per request take more time to process.
    • Prefer singleton requests, unless they contain hundreds of recipients.
    • Understand that for requests with many recipients, throughput is reduced.
  • Include only the attribute values needed for message content.
    • Use different API requests, in bulk, or an Import Activity from a file, to transfer attribute values not specifically needed for message content.