# Connect to Direct Email Send API

To [send email through Direct Email Send API](/docs/marketing/marketing-cloud-growth/guide/mc-manage-transactions-messages-direct-send.md), authenticate with an OAuth Bearer token that has the `sfap_api` scope. Obtain the token by creating an external client app and running an OAuth flow.

## Step 1: Create an External Client App

Before you can authenticate with Direct Email Send API, create an external client app in Setup. This app generates the OAuth credentials that your application uses to request access tokens.

1. In Setup, search for and select **External Client App Manager**.
2. Click **New External Client App**.
3. Enter a name and contact email.
4. Click **Create**.

## Step 2: Configure OAuth Settings

After you create the external client app, configure its OAuth settings to enable token-based authentication. Direct Email Send API requires specific scopes and JWT-based tokens.

1. On the detail page for the external client app, click **Add Consumer**.

2. Select **Enable OAuth Settings**.

3. For **Callback URL**, enter a redirect URL, such as `http://localhost:8082/api/sf/auth/callback`.

   When you deploy remotely, use your production URL.

4. For **Selected OAuth Scopes**, add the scopes that your app requires. Include these scopes:

   - `Access the Salesforce API Platform (sfap_api)`
   - `Manage user data via APIs (api)`
   - `Perform requests at any time (refresh_token)`

   Keep the list of selected scopes as short as possible. An app that requests too many scopes returns `invalid_request: too many scopes requested` when you request a token.

5. Select **Issue JSON Web Token (JWT)-based access tokens for named users**.

   The Salesforce API Platform (SFAP) gateway validates scopes from the JWT payload. Without this setting, the gateway can’t verify the `sfap_api` scope.

6. Save your changes.

7. Copy the **Consumer Key** and **Consumer Secret** for the client app.

## Step 3: Relax IP Restrictions

By default, an external client app allows requests only if they originate from an IP address on an allowlist. To test the API locally, you can relax these restrictions.

1. On the details page for your app, click **Manage**.
2. Click **Edit Policies**.
3. Under **IP Relaxation**, select **Relax IP restrictions**.
4. Save your changes.

When you’re ready to deploy to production, enforce IP restrictions with a defined trusted IP range instead.

## Step 4: Request a Token

Choose the flow that matches your use case. For interactive, user-facing apps that log in through a browser, use the authorization code flow. For server-to-server automation with no user interaction, use the client credentials flow.

### Option 1: Authorization Code Flow

Use an authorization code flow for web applications and mobile apps where users log in with their own Salesforce credentials. This flow requires user interaction through a browser and is ideal when your app needs to act on behalf of a specific user with their individual permissions.

1. Redirect the user to the authorization endpoint:

   ```
   https://YOUR_ORG.my.salesforce.com/services/oauth2/authorize?response_type=code&client_id=YOUR_CONSUMER_KEY&redirect_uri=http://localhost:8082/api/sf/auth/callback&scope=api refresh_token sfap_api
   ```

2. Exchange the returned authorization code for tokens:

   ```bash
   curl -X POST "https://YOUR_ORG.my.salesforce.com/services/oauth2/token" \
     -d "grant_type=authorization_code" \
     -d "code=YOUR_AUTH_CODE" \
     -d "client_id=YOUR_CONSUMER_KEY" \
     -d "client_secret=YOUR_CONSUMER_SECRET" \
     -d "redirect_uri=http://localhost:8082/api/sf/auth/callback"
   ```

   The response contains an `access_token` and a `refresh_token`:

   ```json
   {
     "access_token": "YOUR_JWT",
     "refresh_token": "YOUR_REFRESH_TOKEN",
     "instance_url": "https://YOUR_ORG.my.salesforce.com",
     "token_type": "Bearer",
     "scope": "api refresh_token sfap_api"
   }
   ```

3. When the access token expires, use the refresh token to get a new one:

   ```bash
   curl -X POST "https://YOUR_ORG.my.salesforce.com/services/oauth2/token" \
     -d "grant_type=refresh_token" \
     -d "refresh_token=YOUR_REFRESH_TOKEN" \
     -d "client_id=YOUR_CONSUMER_KEY" \
     -d "client_secret=YOUR_CONSUMER_SECRET"
   ```

### Option 2: Client Credentials Flow

Use a client credentials flow for server-to-server integrations and background jobs where no user interaction is required. This flow type authenticates your application rather than an individual user. All API calls run with the permissions of a designated user.

Before you use the client credentials flow, enable it in Setup, and configure a Run As user.

1. In **External Client App Manager**, open your app and click **Manage**.
2. In the **OAuth Policies** section, under **OAuth Flows and External Client App Enhancements**, select **Enable Client Credentials Flow**.
3. For **Run As**, enter the username whose permissions apply to every call made with this token.
4. Save your changes.

After you enable the client credentials flow, request a token:

```bash
curl -X POST "https://YOUR_ORG.my.salesforce.com/services/oauth2/token" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CONSUMER_KEY" \
  -d "client_secret=YOUR_CONSUMER_SECRET" \
  -d "scope=sfap_api api"
```

The response contains an `access_token` property.

```json
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "instance_url": "https://your-org.my.salesforce.com",
  "token_type": "Bearer",
  "scope": "sfap_api api"
}
```

The client credentials flow doesn’t return a refresh token. When the current token expires, request a new one.

## Call the API with the Token

Pass the token as a Bearer token in the `Authorization` header.

```bash
curl -X POST "https://api.salesforce.com/automation/actions360/messaging/email/v1?sendDefinitionId=YOUR_SEND_DEFINITION_ID" \
  -H "Authorization: Bearer YOUR_BEARER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "individualId": "Individual__dlm/your-individual-id",
    "attributes": {
      "YourApexClass": {
        "firstName": "John",
        "lastName": "Doe"
      }
    }
  }'
```

## Verify a Token

A valid token is a JSON Web Token (JWT) with three dot-separated segments. If your apps encounter authentication issues, verify your token to make sure that it’s well-formed and contains valid data.

At the command line, use this command to confirm the number of segments in the JWT, replacing `YOUR_JWT` with the value of your JWT.

```bash
echo "YOUR_JWT" | tr '.' '\n' | wc -l
```

If the command returns `3`, then the JWT contains the correct number of segments. If the token isn’t a three-segment JWT, open the external app in Setup, and then turn on the **Issue JSON Web Token (JWT)-based access tokens** setting.

After you confirm that the JWT contains three segments, use this command to decode the payload.

```bash
echo "YOUR_JWT" | cut -d. -f2 | base64 -d 2>/dev/null | tr -d '\n' | python3 -m json.tool
```

Confirm that the decoded payload contains these properties:

- An `scp` property that includes `sfap_api`
- An `aud` property that includes `https://api.salesforce.com`
- An `mty` property that has the value `oauth`

## Troubleshooting Authentication Issues

If you encounter errors when authenticating or calling the API, review these common issues and their solutions.

| Error Message or Condition                                      | Resolution                                                                                                                                                                                                                                                                            |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_grant: authentication failure`                         | The consumer key or secret is wrong or the authentication flow isn’t configured properly. For an authorization code flow, confirm the credentials. For a client credentials flow, make sure that client credential flows are enabled and that a **Run As** user is assigned in Setup. |
| `redirect_uri_mismatch`                                         | The `redirect_uri` in the token request doesn’t match the value configured in the external client app. Make sure it matches exactly, including protocol, host, port, and path.                                                                                                        |
| `Access denied: feature not enabled for tenant` or 403 response | Your org isn’t provisioned for the API on the SFAP gateway. Contact your Salesforce account executive and request that they provision High Scale Actions and Direct Email Send for your org.                                                                                          |
| `INVALID_SESSION_ID` or 401 response                            | The token expired. For an authorization code flow, use the refresh token to get a new access token. For a client credentials flow, request a new token.                                                                                                                               |
| IP Restriction Errors                                           | The app is configured to enforce IP restrictions, but your IP address isn’t in the allowlist. In Setup, change the value of the **IP Relaxation** setting to **Relax IP restrictions**, or add your IP to the trusted IP range.                                                       |

## See Also

- [Send Transactional Messages with Direct Email Send API](/docs/marketing/marketing-cloud-growth/guide/mc-manage-transactions-messages-direct-send.md)
- *API Reference*: [Marketing Cloud Send Definitions API](/docs/marketing/marketing-cloud-growth/references/mc-next-email-send-definitions)
- *API Reference*: [Marketing Cloud Direct Send Email API](/docs/marketing/marketing-cloud-growth/references/mc-next-email-direct-send)
