> For the complete documentation index, see [llms.txt](https://docs.thewalletcrew.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.thewalletcrew.io/connectors/email-provider/adobe-marketing-cloud/marketo-engage-transactional-email-api.md).

# Marketo Engage (Transactional Email API)

Send The Wallet Crew transactional emails via Marketo Engage using the script email provider.

Use this option when the organization uses **Marketo Engage** and wants transactional sends tracked in Marketo activity logs.

Before going further, make sure the script provider model used by The Wallet Crew is clear. Start with [Adobe Marketing Cloud](/connectors/email-provider/adobe-marketing-cloud.md) and the prerequisite [EmailSender extensibility](/connectors/custom-connector/emailsender-extensibility.md).

### When to use this

This is often the simplest REST model, but it assumes the email template is managed and approved in Marketo.

### Setup required in Marketo

Create the email asset to send and get it approved. Approval rules vary by Marketo setup.

Then decide how The Wallet Crew output is mapped:

* Use Marketo tokens or variables to inject `Subject` and `Body`.
* Or keep the subject and body in Marketo and only pass contextual data.

### Implementation notes (token + send)

Marketo instances are region-specific. The script usually requests a Marketo access token, then calls the transactional send endpoint for the chosen email asset.

Store these values as secrets before testing:

* `marketo-baseUrl` (example: `https://123-ABC-456.mktorest.com`)
* `marketo-clientId`
* `marketo-clientSecret`
* `marketo-emailId` (the Marketo email asset identifier to send)

{% hint style="info" %}
Marketo OAuth token endpoints can differ slightly by instance and configuration. When the Marketo token endpoint requires query parameters or a specific HTTP method, adapt the authentication settings accordingly.
{% endhint %}

{% code title="Marketo Engage example (SendEmail implementation)" %}

```javascript
import { getSecret } from "neo/secrets";

const CUSTOM_DOMAIN = "wallet.brand.com";
const TENANTID = "brand";

async function sendEmail(recipient, emailTemplate, data, cultures, buildEmail) {
  const email = recipient;
  const countryCode = data["country"] || "fr";
  const language = `${cultures[0]?.toLowerCase()?.substring(0, 2) || "fr"}_${countryCode.toLowerCase()}`;
  const customerId = data["id.customerId"];

  if (!customerId) {
    throw new Error('Missing "id.customerId" in email data.');
  }

  const url = `https://${CUSTOM_DOMAIN}/${TENANTID}/pass?id.customerId=${encodeURIComponent(customerId)}`;
  const rendered = await buildEmail(emailTemplate);

  const baseUrl = await getSecret("marketo-baseUrl");
  const clientId = await getSecret("marketo-clientId");
  const clientSecret = await getSecret("marketo-clientSecret");
  const marketoEmailId = await getSecret("marketo-emailId");

  const sendUrl = `${baseUrl}/rest/v1/email/${encodeURIComponent(marketoEmailId)}/send.json`;

  // Your runtime `fetch` handles OAuth client credentials and attaches the token.
  const result = await fetch(sendUrl, {
    Method: "POST",
    Authentication: {
      mode: "OAuth2.0",
      grantType: "clientCredentials",
      sendCredentialsAsFormParams: true,
      accessTokenUrl: `${baseUrl}/identity/oauth/token`,
      clientId,
      clientSecret,
    },
    Headers: {
      "Content-Type": "application/json",
    },
    Body: JSON.stringify({
      input: [
        {
          email,
          variables: [
            { name: "url", value: url },
            { name: "language", value: language },
            { name: "subject", value: rendered.Subject },
            { name: "body", value: rendered.Body },
            { name: "customerId", value: customerId },
            { name: "template", value: emailTemplate },
          ],
        },
      ],
    }),
    ThrowOnError: false,
  });

  if (result.StatusCode < 200 || result.StatusCode >= 300) {
    throw new Error(`Marketo send call failed (${result.StatusCode}): ${result.ResponseText}`);
  }
}

export default function (context) {
  context.register("runtime.scriptable.emailEngine", {
    SendEmail: sendEmail,
  });
}
```

{% endcode %}

{% hint style="info" %}
Marketo requires the email asset to exist (and often to be approved) before it can be used for sends.
{% endhint %}

### What to validate

Trigger a real transactional email, then validate these points:

* The email asset exists and is approved.
* Marketo accepts the send call.
* Variables map to what the Marketo template expects.

### FAQ

<details>

<summary><strong>Does the email template have to be created in Marketo?</strong></summary>

Yes. Marketo requires an existing email asset for transactional sends, and many setups require the asset to be approved. The script can still pass variables, but Marketo needs the container asset.

</details>

<details>

<summary><strong>Can The Wallet Crew still render the HTML?</strong></summary>

Yes. `buildEmail()` can be called and `subject` and `body` passed as variables. The Marketo email must be built to inject those variables into the right places.

</details>

<details>

<summary><strong>What is the quickest way to troubleshoot?</strong></summary>

First check that the asset is approved, then check the Marketo API response body for a specific error code. If the API call succeeds but the email renders badly, validate that the Marketo template expects the same variable names that are sent.

</details>

<details>

<summary><strong>Can different Marketo instances be used per environment?</strong></summary>

Yes. Configure different secrets and endpoints per tenant (staging vs production). Keep variable naming consistent across environments to avoid template drift.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.thewalletcrew.io/connectors/email-provider/adobe-marketing-cloud/marketo-engage-transactional-email-api.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
