> ## Documentation Index
> Fetch the complete documentation index at: https://loops.so/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Transactional email API examples

> Code examples for creating transactional emails, updating drafts with content revisions, previewing, publishing, and sending via the Loops API, CLI, and SDKs.

## Create a transactional email

This creates a transactional email and a related draft email message in one request.

Only a `name` value is required.

> [!TIP]
>
> Save the returned `draftEmailMessageContentRevisionId`. Pass it as
> `expectedRevisionId` when updating the draft email message to avoid `409 Conflict` errors caused by stale revisions.

[API reference](https://loops.so/docs/api-reference/create-transactional-email.md)\
[CLI reference](https://loops.so/docs/cli/transactional.md#create)

```js JavaScript theme={"dark"}
const response = await fetch("https://app.loops.so/api/v1/transactional-emails", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <your-api-key>",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    name: "Password reset",
  }),
});

const data = await response.json();
const transactionalId = data.id;
const draftEmailMessageId = data.draftEmailMessageId;
const draftEmailMessageContentRevisionId =
  data.draftEmailMessageContentRevisionId;
```

```js JavaScript SDK theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const data = await loops.createTransactionalEmail({
  name: "Password reset",
});

const transactionalId = data.id;
const draftEmailMessageId = data.draftEmailMessageId;
const draftEmailMessageContentRevisionId =
  data.draftEmailMessageContentRevisionId;
```

```php PHP SDK theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient('<your-api-key>');

$result = $loops->transactional->create(name: 'Password reset');

$transactional_id = $result['id'];
$draft_email_message_id = $result['draftEmailMessageId'];
$draft_email_message_content_revision_id =
  $result['draftEmailMessageContentRevisionId'];
```

```ruby Ruby SDK theme={"dark"}
response = LoopsSdk::Transactional.create(
  name: "Password reset",
)

transactional_id = response["id"]
draft_email_message_id = response["draftEmailMessageId"]
draft_email_message_content_revision_id =
  response["draftEmailMessageContentRevisionId"]
```

```python Python theme={"dark"}
import requests

response = requests.post(
    "https://app.loops.so/api/v1/transactional-emails",
    headers={
        "Authorization": "Bearer <your-api-key>",
        "Content-Type": "application/json",
    },
    json={
        "name": "Password reset",
    },
)

data = response.json()
transactional_id = data["id"]
draft_email_message_id = data["draftEmailMessageId"]
draft_email_message_content_revision_id = data[
    "draftEmailMessageContentRevisionId"
]
```

## Query themes and components for your LMX

You can fetch your available themes and reusable components before building
the `lmx` payload.

List themes [API reference](https://loops.so/docs/api-reference/list-themes.md) [CLI reference](https://loops.so/docs/cli/themes.md#list)\
List components [API reference](https://loops.so/docs/api-reference/list-components.md) [CLI reference](https://loops.so/docs/cli/components.md#list)

```bash CLI theme={"dark"}
loops themes list -o json
loops components list -o json
```

```js JavaScript theme={"dark"}
const [themesResponse, componentsResponse] = await Promise.all([
  fetch("https://app.loops.so/api/v1/themes?perPage=20", {
    method: "GET",
    headers: {
      "Authorization": "Bearer <your-api-key>",
    },
  }),
  fetch("https://app.loops.so/api/v1/components?perPage=20", {
    method: "GET",
    headers: {
      "Authorization": "Bearer <your-api-key>",
    },
  }),
]);

const themes = await themesResponse.json();
const components = await componentsResponse.json();
```

```js JavaScript SDK theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const [themes, components] = await Promise.all([
  loops.listThemes({ perPage: 20 }),
  loops.listComponents({ perPage: 20 }),
]);
```

```php PHP SDK theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient('<your-api-key>');

$themes = $loops->themes->list(per_page: 20);
$components = $loops->components->list(per_page: 20);
```

```ruby Ruby SDK theme={"dark"}
themes = LoopsSdk::Themes.list(perPage: 20)
components = LoopsSdk::Components.list(perPage: 20)
```

```python Python theme={"dark"}
import requests

themes_response = requests.get(
    "https://app.loops.so/api/v1/themes",
    headers={
        "Authorization": "Bearer <your-api-key>",
    },
    params={"perPage": 20},
)

components_response = requests.get(
    "https://app.loops.so/api/v1/components",
    headers={
        "Authorization": "Bearer <your-api-key>",
    },
    params={"perPage": 20},
)

themes = themes_response.json()
components = components_response.json()
```

## Update the draft email message with `contentRevisionId`

Use `draftEmailMessageId` from the transactional email you created as the path parameter, and pass `draftEmailMessageContentRevisionId` as `expectedRevisionId`.

Apply styles or a theme in `<Style />`, and build the email using LMX elements.

Themes and components you queried in the previous step can be referenced by their IDs.

> [!TIP]
>
> Save the returned `contentRevisionId` after each update. Pass it as
> `expectedRevisionId` on the next update to avoid `409 Conflict` errors caused
> by stale revisions.

[API reference](https://loops.so/docs/api-reference/update-email-message.md)\
[CLI reference](https://loops.so/docs/cli/email-messages.md#update)

```bash CLI theme={"dark"}
loops email-messages update $draftEmailMessageId \
  --expected-revision-id $draftEmailMessageContentRevisionId \
  --subject "Reset your password" \
  --preview-text "Your password reset link" \
  --from-name "Loops" \
  --from-email hello \
  --reply-to support@example.com \
  --lmx-file ./email.lmx
```

```js JavaScript theme={"dark"}
const lmxContent = `
<Style themeId="default" />
<Paragraph>
  <Text>Click the link below to reset your password.</Text>
</Paragraph>
<Component componentId="logo" />
<Section>
  ...
</Section>`;

const response = await fetch(
  `https://app.loops.so/api/v1/email-messages/${draftEmailMessageId}`,
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer <your-api-key>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      expectedRevisionId: draftEmailMessageContentRevisionId,
      subject: "Reset your password",
      previewText: "Your password reset link",
      fromName: "Loops",
      fromEmail: "hello",
      replyToEmail: "support@example.com",
      lmx: lmxContent,
    }),
  },
);

const updated = await response.json();
const nextContentRevisionId = updated.contentRevisionId;
```

```js JavaScript SDK theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const lmxContent = `
<Style themeId="default" />
<Paragraph>
  <Text>Click the link below to reset your password.</Text>
</Paragraph>
<Component componentId="logo" />
<Section>
  ...
</Section>`;

const updated = await loops.updateEmailMessage(draftEmailMessageId, {
  expectedRevisionId: draftEmailMessageContentRevisionId,
  subject: "Reset your password",
  previewText: "Your password reset link",
  fromName: "Loops",
  fromEmail: "hello",
  replyToEmail: "support@example.com",
  lmx: lmxContent,
});

const nextContentRevisionId = updated.contentRevisionId;
```

```php PHP SDK theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient('<your-api-key>');

$lmx_content = <<<LMX
<Style themeId="default" />
<Paragraph>
  <Text>Click the link below to reset your password.</Text>
</Paragraph>
<Component componentId="logo" />
<Section>
  ...
</Section>
LMX;

$updated = $loops->emailMessages->update(
  email_message_id: $draft_email_message_id,
  expected_revision_id: $draft_email_message_content_revision_id,
  subject: 'Reset your password',
  preview_text: 'Your password reset link',
  from_name: 'Loops',
  from_email: 'hello',
  reply_to_email: 'support@example.com',
  lmx: $lmx_content,
);

$next_content_revision_id = $updated['contentRevisionId'];
```

```ruby Ruby SDK theme={"dark"}
lmx_content = <<~LMX
  <Style themeId="default" />
  <Paragraph>
    <Text>Click the link below to reset your password.</Text>
  </Paragraph>
  <Component componentId="logo" />
  <Section>
    ...
  </Section>
LMX

updated = LoopsSdk::EmailMessages.update(
  email_message_id: draft_email_message_id,
  expected_revision_id: draft_email_message_content_revision_id,
  subject: "Reset your password",
  preview_text: "Your password reset link",
  from_name: "Loops",
  from_email: "hello",
  reply_to_email: "support@example.com",
  lmx: lmx_content,
)

next_content_revision_id = updated["contentRevisionId"]
```

```python Python theme={"dark"}
import requests

response = requests.post(
    f"https://app.loops.so/api/v1/email-messages/{draft_email_message_id}",
    headers={
        "Authorization": "Bearer <your-api-key>",
        "Content-Type": "application/json",
    },
    json={
        "expectedRevisionId": draft_email_message_content_revision_id,
        "subject": "Reset your password",
        "previewText": "Your password reset link",
        "fromName": "Loops",
        "fromEmail": "hello",
        "replyToEmail": "support@example.com",
        "lmx": "<Email><Style backgroundColor=\"#ffffff\" textBaseColor=\"#111111\" /><Section><Text>Click the link below to reset your password.</Text></Section></Email>",
    },
)

updated = response.json()
next_content_revision_id = updated["contentRevisionId"]
```

## Send a transactional preview

After updating the draft email message, send a test preview to one or more
addresses before publishing. Transactional previews accept `dataVariables` for
personalization.

Use `draftEmailMessageId` from the transactional email you created as the path
parameter.

[API reference](https://loops.so/docs/api-reference/preview-email-message.md)\
[CLI reference](https://loops.so/docs/cli/email-messages.md#preview)

```js JavaScript theme={"dark"}
const previewResponse = await fetch(
  `https://app.loops.so/api/v1/email-messages/${draftEmailMessageId}/preview`,
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer <your-api-key>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      emails: ["you@example.com"],
      dataVariables: {
        loginUrl: "https://example.com/reset?token=abc123",
        firstName: "Alex",
      },
    }),
  },
);

const preview = await previewResponse.json();
```

```js JavaScript SDK theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const preview = await loops.sendEmailMessagePreview(draftEmailMessageId, {
  emails: ["you@example.com"],
  dataVariables: {
    loginUrl: "https://example.com/reset?token=abc123",
    firstName: "Alex",
  },
});
```

```php PHP SDK theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient('<your-api-key>');

$preview = $loops->emailMessages->preview(
  email_message_id: $draft_email_message_id,
  emails: ['you@example.com'],
  data_variables: [
    'loginUrl' => 'https://example.com/reset?token=abc123',
    'firstName' => 'Alex',
  ],
);
```

```ruby Ruby SDK theme={"dark"}
preview = LoopsSdk::EmailMessages.preview(
  email_message_id: draft_email_message_id,
  emails: ["you@example.com"],
  data_variables: {
    loginUrl: "https://example.com/reset?token=abc123",
    firstName: "Alex",
  },
)
```

```python Python theme={"dark"}
import requests

preview_response = requests.post(
    f"https://app.loops.so/api/v1/email-messages/{draft_email_message_id}/preview",
    headers={
        "Authorization": "Bearer <your-api-key>",
        "Content-Type": "application/json",
    },
    json={
        "emails": ["you@example.com"],
        "dataVariables": {
            "loginUrl": "https://example.com/reset?token=abc123",
            "firstName": "Alex",
        },
    },
)

preview = preview_response.json()
```

## Upload an image asset

If your LMX includes `<Image />` tags, upload image files with the Upload API
and use the returned `finalUrl` as the image `src`.

[Create upload API reference](https://loops.so/docs/api-reference/create-upload.md)\
[Complete upload API reference](https://loops.so/docs/api-reference/complete-upload.md)
[Upload CLI reference](https://loops.so/docs/cli/uploads.md#create)

```bash CLI theme={"dark"}
loops uploads create ./header.png -o json
```

```js JavaScript theme={"dark"}
const createResponse = await fetch("https://app.loops.so/api/v1/uploads", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <your-api-key>",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    contentType: "image/png",
    contentLength: imageBuffer.byteLength,
  }),
});

const { emailAssetId, presignedUrl } = await createResponse.json();

await fetch(presignedUrl, {
  method: "PUT",
  headers: {
    "Content-Type": "image/png",
    "Content-Length": String(imageBuffer.byteLength),
  },
  body: imageBuffer,
});

const completeResponse = await fetch(
  `https://app.loops.so/api/v1/uploads/${emailAssetId}/complete`,
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer <your-api-key>",
    },
  },
);

const { finalUrl } = await completeResponse.json();
```

```js JavaScript SDK theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const { emailAssetId, presignedUrl } = await loops.createUpload({
  contentType: "image/png",
  contentLength: imageBuffer.byteLength,
});

await fetch(presignedUrl, {
  method: "PUT",
  headers: {
    "Content-Type": "image/png",
    "Content-Length": String(imageBuffer.byteLength),
  },
  body: imageBuffer,
});

const { finalUrl } = await loops.completeUpload(emailAssetId);
```

```php PHP SDK theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient('<your-api-key>');

$result = $loops->uploads->upload(path: './header.png');

$final_url = $result['finalUrl'];
```

```ruby Ruby SDK theme={"dark"}
response = LoopsSdk::Uploads.upload(path: "./header.png")

final_url = response["finalUrl"]
```

```python Python theme={"dark"}
import requests

create_response = requests.post(
    "https://app.loops.so/api/v1/uploads",
    headers={
        "Authorization": "Bearer <your-api-key>",
        "Content-Type": "application/json",
    },
    json={
        "contentType": "image/png",
        "contentLength": len(image_bytes),
    },
)

create_data = create_response.json()
email_asset_id = create_data["emailAssetId"]
presigned_url = create_data["presignedUrl"]

requests.put(
    presigned_url,
    headers={
        "Content-Type": "image/png",
        "Content-Length": str(len(image_bytes)),
    },
    data=image_bytes,
)

complete_response = requests.post(
    f"https://app.loops.so/api/v1/uploads/{email_asset_id}/complete",
    headers={
        "Authorization": "Bearer <your-api-key>",
    },
)

final_url = complete_response.json()["finalUrl"]
```

## Publish the transactional email

Publish the draft email message so it can be sent with the transactional send endpoint.

[API reference](https://loops.so/docs/api-reference/publish-transactional-email.md)\
[CLI reference](https://loops.so/docs/cli/transactional.md#publish)

```js JavaScript theme={"dark"}
const publishResponse = await fetch(
  `https://app.loops.so/api/v1/transactional-emails/${id}/publish`,
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer <your-api-key>",
    },
  },
);

const published = await publishResponse.json();
```

```js JavaScript SDK theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const published = await loops.publishTransactionalEmail(transactionalId);
```

```php PHP SDK theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient('<your-api-key>');

$published = $loops->transactional->publish(transactional_id: $transactional_id);
```

```ruby Ruby SDK theme={"dark"}
published = LoopsSdk::Transactional.publish(
  transactional_id: transactional_id,
)
```

```python Python theme={"dark"}
import requests

publish_response = requests.post(
    f"https://app.loops.so/api/v1/transactional-emails/{id}/publish",
    headers={
        "Authorization": "Bearer <your-api-key>",
    },
)

published = publish_response.json()
```

## Send a transactional email

Use the transactional `id` from create (or publish) as `transactionalId` in the send request.

[API reference](https://loops.so/docs/api-reference/send-transactional-email.md)\
[CLI reference](https://loops.so/docs/cli/transactional.md#send)

```bash CLI theme={"dark"}
loops transactional send <transactional-id> \
  --email test@example.com \
  --var loginUrl=https://example.com/login
```

```js JavaScript theme={"dark"}
await fetch("https://app.loops.so/api/v1/transactional", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <your-api-key>",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    email: "test@example.com",
    transactionalId: id,
    dataVariables: {
      loginUrl: "https://example.com/login",
    },
  }),
});
```

```js JavaScript SDK theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const response = await loops.sendTransactionalEmail({
  email: "test@example.com",
  transactionalId: "<transactional-id>",
  dataVariables: {
    loginUrl: "https://example.com/login",
  },
});
```

```php PHP SDK theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient("<your-api-key>");

$result = $loops->transactional->send(
  email: 'test@example.com',
  transactional_id: '<transactional-id>',
  data_variables: [
    'loginUrl' => 'https://example.com/login',
  ],
);
```

```ruby Ruby SDK theme={"dark"}
response = LoopsSdk::Transactional.send(
  email: "test@example.com",
  transactional_id: "<transactional-id>",
  data_variables: {
    loginUrl: "https://example.com/login",
  },
)
```

```python Python theme={"dark"}
import requests

response = requests.post(
    "https://app.loops.so/api/v1/transactional",
    headers={
        "Authorization": "Bearer <your-api-key>",
        "Content-Type": "application/json",
    },
    json={
        "email": "test@example.com",
        "transactionalId": id,
        "dataVariables": {
            "loginUrl": "https://example.com/login",
        },
    },
)
```

## Send a transactional email with an array data variable

Learn more about [arrays](https://loops.so/docs/creating-emails/editor.md#arrays).

[API reference](https://loops.so/docs/api-reference/send-transactional-email.md#param-data-variables)\
[CLI reference](https://loops.so/docs/cli/transactional.md#send)

```bash CLI theme={"dark"}
loops transactional send <id> \
  --email test@example.com \
  --json-vars ./vars.json
```

```js JavaScript {11-14} theme={"dark"}
await fetch("https://app.loops.so/api/v1/transactional", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <your-api-key>",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    email: "test@example.com",
    transactionalId: "<id>",
    dataVariables: {
      items: [
        { name: "Item 1", description: "Description of Item 1" },
        { name: "Item 2", description: "Description of Item 2" },
      ],
    },
  }),
});
```

```js JavaScript SDK {9-12} theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const response = await loops.sendTransactionalEmail({
  email: "test@example.com",
  transactionalId: "<id>",
  dataVariables: {
    items: [
      { name: "Item 1", description: "Description of Item 1" },
      { name: "Item 2", description: "Description of Item 2" },
    ],
  },
});
```

```php PHP SDK {9-18} theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient("<your-api-key>");

$result = $loops->transactional->send(
  email: 'test@example.com',
  transactional_id: '<id>',
  data_variables: [
    'items' => [
      [
        'name' => 'Item 1',
        'description' => 'Description of Item 1',
      ],
      [
        'name' => 'Item 2',
        'description' => 'Description of Item 2',
      ],
    ],
  ],
);
```

```ruby Ruby SDK {5-8} theme={"dark"}
response = LoopsSdk::Transactional.send(
  email: "test@example.com",
  transactional_id: "<id>",
  data_variables: {
    items: [
      { name: "Item 1", description: "Description of Item 1" },
      { name: "Item 2", description: "Description of Item 2" },
    ],
  },
)
```

```python Python {13-16} theme={"dark"}
import requests

response = requests.post(
  "https://app.loops.so/api/v1/transactional",
  headers={
    "Authorization": "Bearer <your-api-key>",
    "Content-Type": "application/json",
  },
  json={
    "email": "test@example.com",
    "transactionalId": "<id>",
    "dataVariables": {
      "items": [
        { "name": "Item 1", "description": "Description of Item 1" },
        { "name": "Item 2", "description": "Description of Item 2" },
      ],
    },
  },
)
```

## Send a transactional email with attachments

> [!NOTE]
>
> You must request attachments to be enabled in your account before you can send emails with them.

[API reference](https://loops.so/docs/api-reference/send-transactional-email.md#param-attachments)\
[CLI reference](https://loops.so/docs/cli/transactional.md#send)

```bash CLI theme={"dark"}
loops transactional send <id> \
  --email test@example.com \
  --var loginUrl=https://example.com/login \
  --attachment ./example.pdf
```

```js JavaScript {13-19} theme={"dark"}
await fetch("https://app.loops.so/api/v1/transactional", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <your-api-key>",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    email: "test@example.com",
    transactionalId: "<id>",
    dataVariables: {
      loginUrl: "https://example.com/login",
    },
    attachments: [
      {
        filename: "example.pdf",
        contentType: "application/pdf",
        data: "<base64-encoded-file-content>",
      },
    ],
  }),
});
```

```js JavaScript SDK {11-17} theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const response = await loops.sendTransactionalEmail({
  email: "test@example.com",
  transactionalId: "<id>",
  dataVariables: {
    loginUrl: "https://example.com/login",
  },
  attachments: [
    {
      filename: "example.pdf",
      contentType: "application/pdf",
      data: "<base64-encoded-file-content>",
    },
  ],
});
```

```php PHP SDK {11-17} theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient("<your-api-key>");

$result = $loops->transactional->send(
  email: 'test@example.com',
  transactional_id: '<id>',
  data_variables: [
    'loginUrl' => 'https://example.com/login',
  ],
  attachments: [
    [
      'filename' => 'example.pdf',
      'content_type' => 'application/pdf',
      'data' => base64_encode(file_get_contents('path/to/example.pdf')),
    ],
  ],
);
```

```ruby Ruby SDK {7-13} theme={"dark"}
response = LoopsSdk::Transactional.send(
  email: "test@example.com",
  transactional_id: "<id>",
  data_variables: {
    loginUrl: "https://example.com/login",
  },
  attachments: [
    {
      filename: 'example.pdf',
      content_type: 'application/pdf',
      data: '<base64-encoded-file-content>',
    },
  ],
)
```

```python Python {15-21} theme={"dark"}
import requests

response = requests.post(
    "https://app.loops.so/api/v1/transactional",
    headers={
        "Authorization": "Bearer <your-api-key>",
        "Content-Type": "application/json",
    },
    json={
        "email": "test@example.com",
        "transactionalId": "<id>",
        "dataVariables": {
            "loginUrl": "https://example.com/login",
        },
        "attachments": [
            {
                "filename": "example.pdf",
                "contentType": "application/pdf",
                "data": "<base64-encoded-file-content>",
            },
        ],
    },
)
```

## Send a transactional email with an idempotency key

Add an `Idempotency-Key` header to the request to prevent duplicate requests.

[API reference](https://loops.so/docs/api-reference/send-transactional-email.md#param-idempotency-key)\
[CLI reference](https://loops.so/docs/cli/transactional.md#send)

```bash CLI theme={"dark"}
loops transactional send <id> \
  --email test@example.com \
  --var loginUrl=https://example.com/login \
  --idempotency-key 550e8400-e29b-41d4-a716-446655440000
```

```js JavaScript {6} theme={"dark"}
await fetch("https://app.loops.so/api/v1/transactional", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <your-api-key>",
    "Content-Type": "application/json",
    "Idempotency-Key": "550e8400-e29b-41d4-a716-446655440000",
  },
  body: JSON.stringify({
    email: "test@example.com",
    transactionalId: "<id>",
    dataVariables: {
      loginUrl: "https://example.com/login",
    },
  }),
});
```

```js JavaScript SDK {11-13} theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const response = await loops.sendTransactionalEmail({
  email: "test@example.com",
  transactionalId: "<id>",
  dataVariables: {
    loginUrl: "https://example.com/login",
  },
  headers: {
    "Idempotency-Key": "550e8400-e29b-41d4-a716-446655440000",
  },
});
```

```php PHP SDK {11-13} theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient("<your-api-key>");

$result = $loops->transactional->send(
  email: 'test@example.com',
  transactional_id: '<id>',
  data_variables: [
    'loginUrl' => 'https://example.com/login',
  ],
  headers: [
    'Idempotency-Key' => '550e8400-e29b-41d4-a716-446655440000',
  ],
);
```

```ruby Ruby SDK {7-9} theme={"dark"}
response = LoopsSdk::Transactional.send(
  email: "test@example.com",
  transactional_id: "<id>",
  data_variables: {
    loginUrl: "https://example.com/login",
  },
  headers: {
    'Idempotency-Key' => '550e8400-e29b-41d4-a716-446655440000',
  },
)
```

```python Python {8} theme={"dark"}
import requests

response = requests.post(
    "https://app.loops.so/api/v1/transactional",
    headers={
        "Authorization": "Bearer <your-api-key>",
        "Content-Type": "application/json",
        "Idempotency-Key": "550e8400-e29b-41d4-a716-446655440000",
    },
    json={
        "email": "test@example.com",
        "transactionalId": "<id>",
        "dataVariables": {
            "loginUrl": "https://example.com/login",
        },
    },
)
```

## List transactional emails

[API reference](https://loops.so/docs/api-reference/list-transactional-emails.md)\
[CLI reference](https://loops.so/docs/cli/transactional.md#list)

```bash CLI theme={"dark"}
loops transactional list -o json
```

```js JavaScript theme={"dark"}
await fetch("https://app.loops.so/api/v1/transactional-emails", {
  method: "GET",
  headers: {
    "Authorization": "Bearer <your-api-key>",
  },
});
```

```js JavaScript SDK theme={"dark"}
import { LoopsClient } from "loops";

const loops = new LoopsClient("<your-api-key>");

const response = await loops.listTransactionalEmails();
```

```php PHP SDK theme={"dark"}
use Loops\LoopsClient;

$loops = new LoopsClient("<your-api-key>");

$result = $loops->transactional->list();
```

```ruby Ruby SDK theme={"dark"}
response = LoopsSdk::Transactional.list
```

```python Python theme={"dark"}
import requests

response = requests.get(
    "https://app.loops.so/api/v1/transactional-emails",
    headers={
        "Authorization": "Bearer <your-api-key>",
    },
)
```


## Related topics

- [Sending settings](https://loops.so/docs/creating-emails/sending-settings.md)
- [API Examples](https://loops.so/docs/api-reference/examples.md)
- [Transactional email](https://loops.so/docs/transactional.md)
- [API Introduction](https://loops.so/docs/api-reference/intro.md)
- [Send emails from Bolt.new](https://loops.so/docs/guides/bolt-emails.md)
