MailSlurp logo

Device previews

Review how email renders across devices and clients before signing off on a send.

View MarkdownAgent setup

Device previews render an email in native email clients and webmail surfaces so a team can approve what recipients will actually see before a campaign, product email, or transactional template goes live.

The API works around a few core objects:

Object What it means
Native target A concrete email client and platform, such as ios_mail_physical_device or gmail_android_emulator. Use nativeTargets; the older providers field is deprecated.
Preview run A render job for one email, raw MIME import, HTML import, or render-address submission.
Result The completed run details, target states, and screenshot records.
Screenshot A rendered image for one target. Screenshots can be downloaded through authenticated or shared URLs.
Share link A public tokenized result view that lets reviewers open screenshots without an API key.
Render email address A temporary address that starts a render when an email is sent to it.

Choose a render workflow

Different teams create device preview runs from different source material. Choose the path that matches where the email exists when you start the review.

If you have Use this flow Why
A received or sent MailSlurp email Create a run from the stored emailId Best for tests, CI, and email QA already using MailSlurp inboxes.
A campaign export or .eml fixture Import the MIME or upload the .eml file Preserves the real headers, body parts, and attachments from an external tool.
A template body before it has been sent Create a run from raw HTML Fastest way to preview template markup before a full email pipeline exists.
A campaign tool, ESP, or manual sender Send the email to a render address Lets non-code tools trigger a render by sending email.
A one-off manual review Use the dashboard Useful for stakeholders who need to inspect screenshots without writing code.

SDK setup

Create the MailSlurp client once and call device preview operations through mailslurp.devicePreviewsController.

// Read the API key from the environment so examples can run locally and in CI.
const apiKey = process.env.MAILSLURP_API_KEY || process.env.API_KEY;

// Device render methods live on mailslurp.devicePreviewsController.
const mailslurp = new MailSlurp({ apiKey });

Choose native device targets

List device preview targets before creating a run. Use GET /device-preview-targets for the stable catalog of visible native targets. This catalog route is intended for documentation, UI target pickers, and simple runtime discovery, so call it directly with fetch instead of looking for an SDK method.

// The catalog endpoint is public and does not require an API key.
// Use it to build target selectors without tying the list to worker availability.
const response = await fetch("https://api.mailslurp.com/device-preview-targets");

if (!response.ok) {
  throw new Error(`Could not load device preview targets: ${response.status}`);
}

const targetCatalog = await response.json();
console.log(targetCatalog);
// Rough shape:
// {
//   targets: [
//     {
//       target: "ios_mail_physical_device",
//       client: "Apple Mail",
//       platform: "iOS",
//       formFactor: "phone",
//       engine: "native",
//       creditCost: 1,
//       timeoutSeconds: 120,
//       ...
//     }
//   ]
// }

Use the availability endpoint only when an authenticated workflow also needs current worker health, queue, or status details.

// List native device targets and their current availability before creating a run.
const nativeTargetAvailability =
  await mailslurp.devicePreviewsController.getDevicePreviewNativeTargetAvailability();

console.log(nativeTargetAvailability);
// Rough shape:
// {
//   enabled: true,
//   heartbeatOfflineAfterSeconds: 60,
//   targets: [
//     { target: "ios_mail_physical_device", status: "AVAILABLE", enabled: true, ... }
//   ]
// }
GET /emails/device-previews/native-targets/availability

Get native device preview target availability

Returns live native device preview target availability for authenticated API clients, including worker health, queue, timeout, and status fields. Use `/device-preview-targets` when you need the stable catalog without transient availability data.

Request, parameters, and responses

Responses

StatusSchemaDescription
200DevicePreviewNativeTargetAvailabilityListDtoOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/native-targets/availability HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/native-targets/availability" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);

const result = await devicePreviewsController.getDevicePreviewNativeTargetAvailability();

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_native_target_availability()

For examples and quick tests, pick one known native target. Production code can present the catalog to users or store a small target set for each workflow.

// See /docs/device-previews/ for the current device list.
const nativeTarget = "ios_mail_physical_device";

// Use one native target to keep this example focused and quick to run.
const renderOptions = {
  nativeTargets: [nativeTarget],
};

Use target IDs exactly as returned by the catalog or availability endpoint. Avoid legacy provider names; a provider can map to more than one native target and no longer describes the render surface precisely enough.

If a request includes an unknown native target, MailSlurp rejects the run request with a client error. Use the stable catalog when building forms or saved target sets, and treat availability as a live health signal rather than the source of truth for what MailSlurp supports.

Available render targets

Use the render target catalog to choose the email clients and device contexts that should be included in a device preview run. The table below is rendered at build time and also tries to refresh from /device-preview-targets in the browser. If the live catalog request fails, the static catalog remains visible.

Device preview target catalog

Current native render targets for email client previews. The static table is refreshed in the browser when the live catalog endpoint is reachable.

TargetClientPlatformSurfaceAppearanceTimeoutCredits
apple_mail_macosApple MailmacOSdesktopnative applight120s1
gmail_android_emulatorGmailAndroidmobile tabletnative applight180s1
gmail_ios_physical_deviceGmailiOSmobile tabletnative applight180s1
gmail_chromium_webGmail WebChromiumwebwebmaillight45s1
ios_mail_physical_deviceiOS MailiOSmobile tabletnative applight180s1
ipados_mail_physical_deviceiPadOS MailiPadOSmobile tabletnative applight180s1
outlook_new_windowsNew OutlookWindowsdesktopnative applight150s1
outlook_android_emulatorOutlookAndroidmobile tabletnative applight180s1
outlook_classic_windowsOutlook ClassicWindowsdesktopnative applight150s1
outlook_ios_physical_deviceOutlookiOSmobile tabletnative applight180s1
outlook_macosOutlookmacOSdesktopnative applight120s1
outlook_chromium_webOutlook WebChromiumwebwebmaillight45s1
yahoo_chromium_webYahoo MailChromiumwebwebmaillight45s1

Create runs from stored email

Use this path when the message already exists in MailSlurp. It is the most common automation pattern for tests and CI: create or receive the email, store the emailId, and then render that email on the selected native targets.

// Create a temporary inbox and send it HTML so there is a stored email to render.
const existingInbox = await mailslurp.createInboxWithOptions({
  expiresIn: 300_000,
  name: "device-render-existing-email",
});

await mailslurp.sendEmail(existingInbox.id, {
  to: [existingInbox.emailAddress],
  subject: "Device render from an existing email",
  body: `
    <!doctype html>
    <html>
      <body>
        <h1>Device render from an existing email</h1>
        <p>This email was sent to a MailSlurp inbox first.</p>
      </body>
    </html>
  `,
  isHTML: true,
});

const existingEmail = await mailslurp.waitForLatestEmail(existingInbox.id, 60_000);

// Render the stored email by passing its emailId and native targets.
const existingEmailRun = await mailslurp.devicePreviewsController.createDevicePreviewRun({
  emailId: existingEmail.id,
  createDevicePreviewOptions: {
    nativeTargets: ["ios_mail_physical_device"],
  },
});
POST /emails/{emailId}/device-previews

Create a new device preview run for an email

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
emailIdstring:uuidYes

Request body

CreateDevicePreviewOptions application/json
FieldTypeRequiredDescription
nativeTargetsstring[]NoOptional native mail-client target keys to request for rendering. Null leaves native target selection to ESP configuration. Values are forwarded to ESP so newly deployed ESP targets can be used before this API's enum list is updated.
Request example
{
  "nativeTargets": [
    "apple_mail_macos"
  ]
}

Responses

StatusSchemaDescription
200CreateDevicePreviewRunResultOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/00000000-0000-4000-8000-000000000000/device-previews HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "nativeTargets": [
    "apple_mail_macos"
  ]
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/00000000-0000-4000-8000-000000000000/device-previews" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"nativeTargets":["apple_mail_macos"]}'

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "emailId": "00000000-0000-4000-8000-000000000000",
  "createDevicePreviewOptions": {
    "nativeTargets": [
      "apple_mail_macos"
    ]
  }
};

const result = await devicePreviewsController.createDevicePreviewRun(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    create_device_preview_options = {
      "nativeTargets": [
        "apple_mail_macos"
      ]
    }
    result = devicePreviewsController.create_device_preview_run("00000000-0000-4000-8000-000000000000", create_device_preview_options)

If an email might already have an active run, use ensureDevicePreviewRun. It returns the active run when possible and starts a new one only when needed.

// Ensure reuses an active render for the email when possible; otherwise it starts one.
const ensuredExistingEmailRun = await mailslurp.devicePreviewsController.ensureDevicePreviewRun({
  emailId: existingEmail.id,
  createDevicePreviewOptions: {
    nativeTargets: ["ios_mail_physical_device"],
  },
});
PUT /emails/{emailId}/device-previews/latest

Return active run for email or create one when none exists

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
emailIdstring:uuidYes

Request body

CreateDevicePreviewOptions application/json
FieldTypeRequiredDescription
nativeTargetsstring[]NoOptional native mail-client target keys to request for rendering. Null leaves native target selection to ESP configuration. Values are forwarded to ESP so newly deployed ESP targets can be used before this API's enum list is updated.
Request example
{
  "nativeTargets": [
    "apple_mail_macos"
  ]
}

Responses

StatusSchemaDescription
200CreateDevicePreviewRunResultOK
HTTP and SDK snippets

HTTP

HTTP
PUT /emails/00000000-0000-4000-8000-000000000000/device-previews/latest HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "nativeTargets": [
    "apple_mail_macos"
  ]
}

cURL

cURL
curl -X PUT "https://api.mailslurp.com/emails/00000000-0000-4000-8000-000000000000/device-previews/latest" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"nativeTargets":["apple_mail_macos"]}'

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "emailId": "00000000-0000-4000-8000-000000000000",
  "createDevicePreviewOptions": {
    "nativeTargets": [
      "apple_mail_macos"
    ]
  }
};

const result = await devicePreviewsController.ensureDevicePreviewRun(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    create_device_preview_options = {
      "nativeTargets": [
        "apple_mail_macos"
      ]
    }
    result = devicePreviewsController.ensure_device_preview_run("00000000-0000-4000-8000-000000000000", create_device_preview_options)

Create runs from imported email

Imports are useful when the email was produced outside MailSlurp: a campaign platform export, a local build artifact, a customer-supplied .eml, or a fixture generated by a test.

Import into an inbox first

Import the raw RFC822 message into a MailSlurp inbox, then render the imported email by ID. This gives you a durable stored email record as well as the preview run.

// Import a raw RFC822 email into an inbox, then render the imported email.
const importInbox = await mailslurp.createInboxWithOptions({
  expiresIn: 300_000,
  name: "device-render-inbox-import",
});

const importedRawMime = [
  "From: Example Sender <sender@example.test>",
  `To: ${importInbox.emailAddress}`,
  "Subject: Device render from an inbox import",
  `Message-ID: <device-render-inbox-import-${Date.now()}@example.test>`,
  "MIME-Version: 1.0",
  'Content-Type: text/html; charset="UTF-8"',
  "",
  "<!doctype html><html><body><h1>Device render from an inbox import</h1></body></html>",
].join("\r\n");

const importedEmail = await mailslurp.inboxController.importEmailIntoInbox({
  inboxId: importInbox.id,
  importEmailOptions: {
    rawEmailBase64: Buffer.from(importedRawMime, "utf8").toString("base64"),
    externalId: `inbox-import-${Date.now()}`,
    runPipeline: false,
    overrideMessageId: true,
  },
});

const inboxImportRun = await mailslurp.devicePreviewsController.createDevicePreviewRun({
  emailId: importedEmail.id,
  createDevicePreviewOptions: {
    nativeTargets: ["ios_mail_physical_device"],
  },
});

Import base64 raw MIME directly

Use direct import when you already have the full MIME content and do not need to store it in an inbox first.

// Build a complete RFC822/MIME message and base64 encode it for import.
const rawMimeForBase64Import = [
  "From: Example Sender <sender@example.test>",
  "To: recipient@example.test",
  "Subject: Device render from base64 raw MIME",
  `Message-ID: <device-render-base64-${Date.now()}@example.test>`,
  "MIME-Version: 1.0",
  'Content-Type: text/html; charset="UTF-8"',
  "",
  "<!doctype html><html><body><h1>Device render from base64 raw MIME</h1></body></html>",
].join("\r\n");

const rawMimeImportRun = await mailslurp.devicePreviewsController.createDevicePreviewRunFromImport({
  createDevicePreviewImportOptions: {
    rawEmailBase64: Buffer.from(rawMimeForBase64Import, "utf8").toString("base64"),
    sourceAlias: "raw-mime-base64-example",
    externalId: `raw-mime-import-${Date.now()}`,
    options: {
      nativeTargets: ["ios_mail_physical_device"],
    },
  },
});
POST /emails/device-previews/import

Create a device preview run from imported raw MIME

Request, parameters, and responses

Request body (required)

FieldTypeRequiredDescription
rawEmailBase64stringYesBase64 encoded RFC822/MIME email contents. This should be the full raw email including headers and body, such as the bytes from an `.eml` file.
sourceAliasstringNoOptional source label to attach to the preview run.
externalIdstringNoOptional external source ID for correlating this import with another system.
optionsCreateDevicePreviewOptionsNo
Request example
{
  "rawEmailBase64": "user@example.com",
  "sourceAlias": "value",
  "externalId": "00000000-0000-4000-8000-000000000000",
  "options": {
    "nativeTargets": [
      "apple_mail_macos"
    ]
  }
}

Responses

StatusSchemaDescription
200CreateDevicePreviewRunResultOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/device-previews/import HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "rawEmailBase64": "user@example.com",
  "sourceAlias": "value",
  "externalId": "00000000-0000-4000-8000-000000000000",
  "options": {
    "nativeTargets": [
      "apple_mail_macos"
    ]
  }
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/device-previews/import" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"rawEmailBase64":"user@example.com","sourceAlias":"value","externalId":"00000000-0000-4000-8000-000000000000","options":{"nativeTargets":["apple_mail_macos"]}}'

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "createDevicePreviewImportOptions": {
    "rawEmailBase64": "user@example.com",
    "sourceAlias": "value",
    "externalId": "00000000-0000-4000-8000-000000000000",
    "options": {
      "nativeTargets": [
        "apple_mail_macos"
      ]
    }
  }
};

const result = await devicePreviewsController.createDevicePreviewRunFromImport(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    create_device_preview_import_options = {
      "rawEmailBase64": "user@example.com",
      "sourceAlias": "value",
      "externalId": "00000000-0000-4000-8000-000000000000",
      "options": {
        "nativeTargets": [
          "apple_mail_macos"
        ]
      }
    }
    result = devicePreviewsController.create_device_preview_run_from_import(create_device_preview_import_options)

Upload an EML file

Use multipart import for .eml files from email clients, campaign tools, or fixtures on disk.

// Upload an .eml file as multipart/form-data and create a render from it.
const emlUploadMime = [
  "From: Example Sender <sender@example.test>",
  "To: recipient@example.test",
  "Subject: Device render from EML upload",
  `Message-ID: <device-render-eml-upload-${Date.now()}@example.test>`,
  "MIME-Version: 1.0",
  'Content-Type: text/html; charset="UTF-8"',
  "",
  "<!doctype html><html><body><h1>Device render from an EML upload</h1></body></html>",
].join("\r\n");

const emlUploadFile = new Blob([emlUploadMime], { type: "message/rfc822" });
emlUploadFile.name = "device-render-example.eml";

const emlUploadRun = await mailslurp.devicePreviewsController.createDevicePreviewRunFromMultipartImport({
  file: emlUploadFile,
  sourceAlias: "eml-upload-example",
  externalId: `eml-upload-${Date.now()}`,
  nativeTargets: ["ios_mail_physical_device"],
});
POST /emails/device-previews/import/multipart

Create a device preview run from multipart EML upload

Request, parameters, and responses

Query parameters

NameTypeRequiredDescription
sourceAliasstringNo
externalIdstringNo
nativeTargetsstring[]No

Request body

multipart/form-data

Responses

StatusSchemaDescription
200CreateDevicePreviewRunResultOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/device-previews/import/multipart?sourceAlias=value&externalId=00000000-0000-4000-8000-000000000000&nativeTargets=value HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/device-previews/import/multipart?sourceAlias=value&externalId=00000000-0000-4000-8000-000000000000&nativeTargets=value" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "sourceAlias": "value",
  "externalId": "00000000-0000-4000-8000-000000000000",
  "nativeTargets": [
    "value"
  ]
};

const result = await devicePreviewsController.createDevicePreviewRunFromMultipartImport(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.create_device_preview_run_from_multipart_import(source_alias="value", external_id="00000000-0000-4000-8000-000000000000", native_targets=["value"])

Send raw MIME bytes

Use raw import when the request body should be the RFC822 bytes themselves.

// Send RFC822 bytes directly as the request body for a raw MIME import.
const rawMimeBytes = [
  "From: Example Sender <sender@example.test>",
  "To: recipient@example.test",
  "Subject: Device render from raw MIME bytes",
  `Message-ID: <device-render-raw-bytes-${Date.now()}@example.test>`,
  "MIME-Version: 1.0",
  'Content-Type: text/html; charset="UTF-8"',
  "",
  "<!doctype html><html><body><h1>Device render from raw MIME bytes</h1></body></html>",
].join("\r\n");

const rawMimeBytesFile = new Blob([rawMimeBytes], { type: "message/rfc822" });
rawMimeBytesFile.name = "device-render-raw-bytes.eml";

// The second argument is RequestInit; its body sends the raw MIME bytes.
const rawMimeBytesRun = await mailslurp.devicePreviewsController.createDevicePreviewRunFromRawImport(
  {
    sourceAlias: "raw-mime-bytes-example",
    externalId: `raw-mime-bytes-${Date.now()}`,
    nativeTargets: ["ios_mail_physical_device"],
  },
  {
    body: rawMimeBytesFile,
  },
);
POST /emails/device-previews/import/raw

Create a device preview run from raw MIME bytes

Request, parameters, and responses

Query parameters

NameTypeRequiredDescription
sourceAliasstringNo
externalIdstringNo
nativeTargetsstring[]No

Responses

StatusSchemaDescription
200CreateDevicePreviewRunResultOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/device-previews/import/raw?sourceAlias=value&externalId=00000000-0000-4000-8000-000000000000&nativeTargets=value HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/device-previews/import/raw?sourceAlias=value&externalId=00000000-0000-4000-8000-000000000000&nativeTargets=value" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "sourceAlias": "value",
  "externalId": "00000000-0000-4000-8000-000000000000",
  "nativeTargets": [
    "value"
  ]
};

const result = await devicePreviewsController.createDevicePreviewRunFromRawImport(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.create_device_preview_run_from_raw_import(source_alias="value", external_id="00000000-0000-4000-8000-000000000000", native_targets=["value"])

Create runs from raw HTML

Raw HTML import is best for template QA before a full email has been sent. Provide a subject, sender, recipient, and HTML body so the renderer can build a realistic message envelope.

// Send HTML directly to the device preview API without first storing an email.
const htmlImportRun = await mailslurp.devicePreviewsController.createDevicePreviewRunFromHtmlImport({
  createDevicePreviewHtmlImportOptions: {
    html: `
      <!doctype html>
      <html>
        <body>
          <h1>Device render from raw HTML</h1>
          <p>This render was created directly from an HTML string.</p>
        </body>
      </html>
    `,
    subject: "Device render from raw HTML",
    from: "Example Sender <sender@example.test>",
    to: "recipient@example.test",
    sourceAlias: "raw-html-example",
    externalId: `html-import-${Date.now()}`,
    options: {
      nativeTargets: ["ios_mail_physical_device"],
    },
  },
});

The JavaScript SDK exposes this as createDevicePreviewRunFromHtmlImport. If your generated client does not include the method yet, upgrade the SDK before using HTML imports from code.

POST /emails/device-previews/import/html

Create a device preview run from HTML

Request, parameters, and responses

Request body (required)

FieldTypeRequiredDescription
htmlstringYesHTML body to wrap into a minimal RFC822/MIME message before creating the device preview run.
subjectstringNoOptional email subject for the generated MIME.
fromstringNoOptional From address for the generated MIME.
tostringNoOptional To address for the generated MIME.
sourceAliasstringNoOptional source label to attach to the preview run.
externalIdstringNoOptional external source ID for correlating this import with another system.
optionsCreateDevicePreviewOptionsNo
Request example
{
  "html": "value",
  "subject": "Hello from MailSlurp",
  "from": "user@example.com",
  "to": "user@example.com",
  "sourceAlias": "value",
  "externalId": "00000000-0000-4000-8000-000000000000"
}

Responses

StatusSchemaDescription
200CreateDevicePreviewRunResultOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/device-previews/import/html HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "html": "value",
  "subject": "Hello from MailSlurp",
  "from": "user@example.com",
  "to": "user@example.com",
  "sourceAlias": "value",
  "externalId": "00000000-0000-4000-8000-000000000000"
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/device-previews/import/html" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"html":"value","subject":"Hello from MailSlurp","from":"user@example.com","to":"user@example.com","sourceAlias":"value","externalId":"00000000-0000-4000-8000-000000000000"}'

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "createDevicePreviewHtmlImportOptions": {
    "html": "value",
    "subject": "Hello from MailSlurp",
    "from": "user@example.com",
    "to": "user@example.com",
    "sourceAlias": "value",
    "externalId": "00000000-0000-4000-8000-000000000000"
  }
};

const result = await devicePreviewsController.createDevicePreviewRunFromHtmlImport(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    create_device_preview_html_import_options = {
      "html": "value",
      "subject": "Hello from MailSlurp",
      "from": "user@example.com",
      "to": "user@example.com",
      "sourceAlias": "value",
      "externalId": "00000000-0000-4000-8000-000000000000"
    }
    result = devicePreviewsController.create_device_preview_run_from_html_import(create_device_preview_html_import_options)

Create runs by sending to a render address

A render email address lets any tool start a render by sending an email. This is useful for campaign platforms, QA handoffs, and non-code approval flows.

First create the temporary render address with the native target options you want:

// Create a temporary render email address. Email sent here starts a render run.
const renderEmailAddress = await mailslurp.devicePreviewsController.createDevicePreviewImportAddress({
  createDevicePreviewIngestAddressOptions: {
    options: {
      nativeTargets: ["ios_mail_physical_device"],
    },
  },
});
POST /emails/device-previews/import-addresses

Create a temporary email address for device preview import

Request, parameters, and responses

Request body

FieldTypeRequiredDescription
optionsCreateDevicePreviewOptionsNo
Request example
{
  "options": {
    "nativeTargets": [
      "apple_mail_macos"
    ]
  }
}

Responses

StatusSchemaDescription
200DevicePreviewIngestAddressDtoOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/device-previews/import-addresses HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "options": {
    "nativeTargets": [
      "apple_mail_macos"
    ]
  }
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/device-previews/import-addresses" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"options":{"nativeTargets":["apple_mail_macos"]}}'

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "createDevicePreviewIngestAddressOptions": {
    "options": {
      "nativeTargets": [
        "apple_mail_macos"
      ]
    }
  }
};

const result = await devicePreviewsController.createDevicePreviewImportAddress(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    create_device_preview_ingest_address_options = {
      "options": {
        "nativeTargets": [
          "apple_mail_macos"
        ]
      }
    }
    result = devicePreviewsController.create_device_preview_import_address(create_device_preview_ingest_address_options)

Use the import-address lookup endpoint if you need to confirm the session details after creating the address.

GET /emails/device-previews/import-addresses/{sessionId}

Get temporary device preview import address status

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
sessionIdstring:uuidYes

Responses

StatusSchemaDescription
200DevicePreviewIngestAddressDtoOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/import-addresses/00000000-0000-4000-8000-000000000000 HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/import-addresses/00000000-0000-4000-8000-000000000000" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "sessionId": "00000000-0000-4000-8000-000000000000"
};

const result = await devicePreviewsController.getDevicePreviewImportAddress(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_import_address("00000000-0000-4000-8000-000000000000")

Then send an email to the address. The example below sends from a MailSlurp HTTP inbox, but the same address can receive from another mail client or campaign system.

// Send HTML from a MailSlurp HTTP inbox to the render address.
const mailSenderInbox = await mailslurp.createInboxWithOptions({
  expiresIn: 300_000,
  name: "device-render-mail-sender",
  inboxType: "HTTP_INBOX",
});

await mailslurp.sendEmail(mailSenderInbox.id, {
  to: [renderEmailAddress.emailAddress],
  subject: "Device render through a render email address",
  body: `
    <!doctype html>
    <html>
      <body>
        <h1>Device render through a render email address</h1>
        <p>MailSlurp creates the render run when this email arrives.</p>
      </body>
    </html>
  `,
  isHTML: true,
});

Use the email-run and email-submission wait endpoints when an automation needs to watch render-address mail arrive.

GET /emails/device-previews/email-submissions/wait

Wait for received device preview email submissions

Request, parameters, and responses

Query parameters

NameTypeRequiredDescription
sincestring:date-timeYes
emailDomainIdstring:uuidNo
profileIdstring:uuidNo
localPartstringNo
limitinteger:int32No
timeoutMillisinteger:int64No
pollIntervalMillisinteger:int64No

Responses

StatusSchemaDescription
200DevicePreviewEmailSubmissionWaitResultOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/email-submissions/wait?since=value&emailDomainId=00000000-0000-4000-8000-000000000000&profileId=00000000-0000-4000-8000-000000000000 HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/email-submissions/wait?since=value&emailDomainId=00000000-0000-4000-8000-000000000000&profileId=00000000-0000-4000-8000-000000000000" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "since": "value",
  "emailDomainId": "00000000-0000-4000-8000-000000000000",
  "profileId": "00000000-0000-4000-8000-000000000000"
};

const result = await devicePreviewsController.waitForDevicePreviewEmailSubmissions(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.wait_for_device_preview_email_submissions(since="value", email_domain_id="00000000-0000-4000-8000-000000000000", profile_id="00000000-0000-4000-8000-000000000000")
GET /emails/device-previews/email-runs/wait

Wait for device preview runs created from account email domains

Request, parameters, and responses

Query parameters

NameTypeRequiredDescription
sincestring:date-timeYes
emailDomainIdstring:uuidNo
profileIdstring:uuidNo
localPartstringNo
limitinteger:int32No
timeoutMillisinteger:int64No
pollIntervalMillisinteger:int64No
hydrateThumbnailbooleanNoHydrate each returned run with a nullable primary screenshot thumbnail URL.

Responses

StatusSchemaDescription
200DevicePreviewIngestRunWaitResultOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/email-runs/wait?since=value&emailDomainId=00000000-0000-4000-8000-000000000000&profileId=00000000-0000-4000-8000-000000000000 HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/email-runs/wait?since=value&emailDomainId=00000000-0000-4000-8000-000000000000&profileId=00000000-0000-4000-8000-000000000000" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "since": "value",
  "emailDomainId": "00000000-0000-4000-8000-000000000000",
  "profileId": "00000000-0000-4000-8000-000000000000"
};

const result = await devicePreviewsController.waitForDevicePreviewEmailRuns(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.wait_for_device_preview_email_runs(since="value", email_domain_id="00000000-0000-4000-8000-000000000000", profile_id="00000000-0000-4000-8000-000000000000")

Wait for a run

Render work is asynchronous. Start the run, keep the runId, then poll until the run is complete or partially complete. A partial completion can still contain useful screenshots when one target fails or times out.

// Poll until the run completes or the timeout elapses.
const completed = await mailslurp.devicePreviewsController.waitForDevicePreviewRun({
  runId,
  timeoutMillis: 60_000,
  pollIntervalMillis: 2_000,
});

assert.equal(completed.timedOut, false);
assert.match(completed.run.status, /COMPLETE|PARTIAL_COMPLETE/);
GET /emails/device-previews/{runId}/wait

Wait for device preview run to complete

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes

Query parameters

NameTypeRequiredDescription
timeoutMillisinteger:int64No
pollIntervalMillisinteger:int64No

Responses

StatusSchemaDescription
200DevicePreviewRunWaitResultOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/00000000-0000-4000-8000-000000000000/wait?timeoutMillis=value&pollIntervalMillis=value HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/00000000-0000-4000-8000-000000000000/wait?timeoutMillis=value&pollIntervalMillis=value" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "runId": "00000000-0000-4000-8000-000000000000",
  "timeoutMillis": null,
  "pollIntervalMillis": null
};

const result = await devicePreviewsController.waitForDevicePreviewRun(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.wait_for_device_preview_run("00000000-0000-4000-8000-000000000000", timeout_millis=NaN, poll_interval_millis=NaN)
GET /emails/device-previews/{runId}

Get device preview run status

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes

Responses

StatusSchemaDescription
200DevicePreviewRunDtoOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/00000000-0000-4000-8000-000000000000 HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/00000000-0000-4000-8000-000000000000" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "runId": "00000000-0000-4000-8000-000000000000"
};

const result = await devicePreviewsController.getDevicePreviewRun(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_run("00000000-0000-4000-8000-000000000000")

Handle partial, failed, or unwanted runs

Run status tells you whether the overall preview has finished, but target-level status tells you which clients rendered successfully. A partially completed run can still be useful for review, especially when the important target screenshots are present.

Use these operations when a render needs follow-up:

  • Rerun selected native targets when a target failed or the template changed only for a small client set.
  • Cancel a run that is no longer needed.
  • Delete a run when its screenshots should be removed from account history.
  • Send feedback when a target screenshot looks wrong or a device client needs investigation.
POST /emails/device-previews/{runId}/targets/rerun

Rerun selected failed device preview targets in the same run

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes

Request body (required)

FieldTypeRequiredDescription
targetIdsstring:uuid[]YesDevice preview target IDs to rerun within the existing run. Use target IDs from DevicePreviewRunResultsDto.targets.
failedOnlybooleanYesWhen true, only selected targets in failed terminal states are rerun. Defaults to true.
Request example
{
  "targetIds": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "failedOnly": true
}

Responses

StatusSchemaDescription
200RerunDevicePreviewTargetsResultOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/device-previews/00000000-0000-4000-8000-000000000000/targets/rerun HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "targetIds": [
    "00000000-0000-4000-8000-000000000000"
  ],
  "failedOnly": true
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/device-previews/00000000-0000-4000-8000-000000000000/targets/rerun" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"targetIds":["00000000-0000-4000-8000-000000000000"],"failedOnly":true}'

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "runId": "00000000-0000-4000-8000-000000000000",
  "rerunDevicePreviewTargetsOptions": {
    "targetIds": [
      "00000000-0000-4000-8000-000000000000"
    ],
    "failedOnly": true
  }
};

const result = await devicePreviewsController.rerunDevicePreviewTargets(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    rerun_device_preview_targets_options = {
      "targetIds": [
        "00000000-0000-4000-8000-000000000000"
      ],
      "failedOnly": True
    }
    result = devicePreviewsController.rerun_device_preview_targets("00000000-0000-4000-8000-000000000000", rerun_device_preview_targets_options)
POST /emails/device-previews/{runId}/cancel

Cancel a running device preview run

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes

Request body

FieldTypeRequiredDescription
reasonstringNo
Request example
{
  "reason": "value"
}

Responses

StatusSchemaDescription
200CancelDevicePreviewRunResultOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/device-previews/00000000-0000-4000-8000-000000000000/cancel HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "reason": "value"
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/device-previews/00000000-0000-4000-8000-000000000000/cancel" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"reason":"value"}'

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "runId": "00000000-0000-4000-8000-000000000000",
  "cancelDevicePreviewRunOptions": {
    "reason": "value"
  }
};

const result = await devicePreviewsController.cancelDevicePreviewRun(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    cancel_device_preview_run_options = {
      "reason": "value"
    }
    result = devicePreviewsController.cancel_device_preview_run("00000000-0000-4000-8000-000000000000", cancel_device_preview_run_options)
DELETE /emails/device-previews/{runId}

Delete local device preview run data

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes

Responses

StatusSchemaDescription
200DeleteDevicePreviewRunResultOK
HTTP and SDK snippets

HTTP

HTTP
DELETE /emails/device-previews/00000000-0000-4000-8000-000000000000 HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X DELETE "https://api.mailslurp.com/emails/device-previews/00000000-0000-4000-8000-000000000000" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "runId": "00000000-0000-4000-8000-000000000000"
};

const result = await devicePreviewsController.deleteDevicePreviewRun(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.delete_device_preview_run("00000000-0000-4000-8000-000000000000")
POST /emails/device-previews/feedback

Create device preview feedback

Request, parameters, and responses

Request body (required)

FieldTypeRequiredDescription
sourceenum: API_SERVICE | LAB_USER | END_USER | SYSTEMYes
categoryenum: GENERAL | RUN_QUALITY | SCREENSHOT_QUALITY | PROVIDER_ISSUE | BUG_REPORT | FEATURE_REQUESTYes
statusenum: OPEN | ACKNOWLEDGED | RESOLVED | DISMISSEDNo
ratinginteger:int32No
runIdstring:uuidNo
targetIdstring:uuidNo
screenshotIdstring:uuidNo
providerenum: GMAIL | OUTLOOK | YAHOONo
titlestringNo
commentstringNo
internalNotestringNo
sessionIdstringNo
liveViewUrlstringNo
metadatamap<string, string>No
Request example
{
  "source": "API_SERVICE",
  "category": "GENERAL",
  "status": "OPEN",
  "rating": 1,
  "runId": "00000000-0000-4000-8000-000000000000",
  "targetId": "00000000-0000-4000-8000-000000000000"
}

Responses

StatusSchemaDescription
200DevicePreviewFeedbackDtoOK
HTTP and SDK snippets

HTTP

HTTP
POST /emails/device-previews/feedback HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json
Content-Type: application/json

{
  "source": "API_SERVICE",
  "category": "GENERAL",
  "status": "OPEN",
  "rating": 1,
  "runId": "00000000-0000-4000-8000-000000000000",
  "targetId": "00000000-0000-4000-8000-000000000000"
}

cURL

cURL
curl -X POST "https://api.mailslurp.com/emails/device-previews/feedback" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  --data '{"source":"API_SERVICE","category":"GENERAL","status":"OPEN","rating":1,"runId":"00000000-0000-4000-8000-000000000000","targetId":"00000000-0000-4000-8000-000000000000"}'

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "createDevicePreviewFeedbackOptions": {
    "source": "API_SERVICE",
    "category": "GENERAL",
    "status": "OPEN",
    "rating": 1,
    "runId": "00000000-0000-4000-8000-000000000000",
    "targetId": "00000000-0000-4000-8000-000000000000"
  }
};

const result = await devicePreviewsController.createDevicePreviewFeedback(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    create_device_preview_feedback_options = {
      "source": "API_SERVICE",
      "category": "GENERAL",
      "status": "OPEN",
      "rating": 1,
      "runId": "00000000-0000-4000-8000-000000000000",
      "targetId": "00000000-0000-4000-8000-000000000000"
    }
    result = devicePreviewsController.create_device_preview_feedback(create_device_preview_feedback_options)

List and retrieve runs

Use email-scoped listing when you are showing render history for a single stored email. Use account-scoped listing for overview pages, dashboards, or audit tools.

// Fetch one run directly, then list runs by email and account.
const run = await mailslurp.devicePreviewsController.getDevicePreviewRun({
  runId,
});

const emailRuns = await mailslurp.devicePreviewsController.getDevicePreviewRuns({
  emailId: existingEmail.id,
  limit: 10,
  hydrateThumbnail: true,
});

const accountRuns = await mailslurp.devicePreviewsController.getDevicePreviewRunsForAccount({
  limit: 10,
  hydrateThumbnail: true,
});

const paginatedAccountRuns =
  await mailslurp.devicePreviewsController.getDevicePreviewRunsForAccountOffsetPaginated({
    page: 0,
    size: 10,
    sort: "DESC",
    hydrateThumbnail: true,
  });
GET /emails/{emailId}/device-previews

List previous device preview runs for an email

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
emailIdstring:uuidYes

Query parameters

NameTypeRequiredDescription
limitinteger:int32No
hydrateThumbnailbooleanNoHydrate each returned run with a nullable primary screenshot thumbnail URL.

Responses

StatusSchemaDescription
200DevicePreviewRunDto[]OK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/00000000-0000-4000-8000-000000000000/device-previews?limit=value&hydrateThumbnail=true HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/00000000-0000-4000-8000-000000000000/device-previews?limit=value&hydrateThumbnail=true" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "emailId": "00000000-0000-4000-8000-000000000000",
  "limit": null,
  "hydrateThumbnail": true
};

const result = await devicePreviewsController.getDevicePreviewRuns(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_runs("00000000-0000-4000-8000-000000000000", limit=NaN, hydrate_thumbnail=True)
GET /emails/device-previews

List previous device preview runs for account

Request, parameters, and responses

Query parameters

NameTypeRequiredDescription
limitinteger:int32No
hydrateThumbnailbooleanNoHydrate each returned run with a nullable primary screenshot thumbnail URL.

Responses

StatusSchemaDescription
200DevicePreviewRunDto[]OK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews?limit=value&hydrateThumbnail=true HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews?limit=value&hydrateThumbnail=true" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "limit": null,
  "hydrateThumbnail": true
};

const result = await devicePreviewsController.getDevicePreviewRunsForAccount(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_runs_for_account(limit=NaN, hydrate_thumbnail=True)

Read results and image URLs

Results include the run, targets, screenshot records, and image URLs. Private screenshot URLs require authentication or a signed S3 URL; public URLs come from a share link.

// Results include targets plus screenshot records with private image URLs.
const results = await mailslurp.devicePreviewsController.getDevicePreviewRunResults({
  runId,
});

const imageUrls = results.screenshots
  .flatMap((screenshot) => [
    screenshot.accessUrl,
    screenshot.liveViewUrl,
    screenshot.deepLinkUrl,
  ])
  .filter(Boolean);

console.log(imageUrls);
GET /emails/device-previews/{runId}/results

Get device preview run results

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes

Responses

StatusSchemaDescription
200DevicePreviewRunResultsDtoOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/00000000-0000-4000-8000-000000000000/results HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/00000000-0000-4000-8000-000000000000/results" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "runId": "00000000-0000-4000-8000-000000000000"
};

const result = await devicePreviewsController.getDevicePreviewRunResults(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_run_results("00000000-0000-4000-8000-000000000000")

Download screenshot images

Download private screenshots through the authenticated API when your app needs to store evidence, attach results to a report, or compare images in a test workflow.

// Download a private screenshot image through the authenticated API.
const screenshotImage = await mailslurp.devicePreviewsController.getDevicePreviewRunScreenshot({
  runId,
  screenshotId: primaryScreenshot.screenshotId,
});
GET /emails/device-previews/{runId}/screenshots/{screenshotId}/image

Get a device preview screenshot image

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes
screenshotIdstring:uuidYes

Responses

StatusSchemaDescription
200string:byteOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/00000000-0000-4000-8000-000000000000/screenshots/00000000-0000-4000-8000-000000000000/image HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/00000000-0000-4000-8000-000000000000/screenshots/00000000-0000-4000-8000-000000000000/image" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "runId": "00000000-0000-4000-8000-000000000000",
  "screenshotId": "00000000-0000-4000-8000-000000000000"
};

const result = await devicePreviewsController.getDevicePreviewRunScreenshot(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_run_screenshot("00000000-0000-4000-8000-000000000000", "00000000-0000-4000-8000-000000000000")

Share results publicly

Create a share link when reviewers need a browser-friendly result page without using an API key. Shared results expose public image URLs and can be revoked later.

// Create a share link, then read public image URLs from the shared result.
const shareLink = await mailslurp.devicePreviewsController.createDevicePreviewShareLink({
  runId,
  createDevicePreviewShareLinkOptions: {
    label: "Device render example share link",
  },
});

const shareLinks = await mailslurp.devicePreviewsController.getDevicePreviewShareLinks({
  runId,
});

const sharedResult = await mailslurp.devicePreviewsController.getDevicePreviewSharedResult({
  shareToken: shareLink.token,
});

const publicImageUrls = sharedResult.screenshots
  .map((screenshot) => screenshot.imageUrl)
  .filter(Boolean);

const publicScreenshotImage =
  await mailslurp.devicePreviewsController.getDevicePreviewSharedResultScreenshot({
    shareToken: shareLink.token,
    screenshotId: sharedResult.screenshots[0].screenshotId,
  });

List existing share links before creating a new approval link for the same run. This helps dashboards avoid creating duplicate public links for the same review.

GET /emails/device-previews/{runId}/share-links

List share links for a device preview run

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes

Responses

StatusSchemaDescription
200DevicePreviewShareLinkDto[]OK
HTTP and SDK snippets
POST /emails/device-previews/{runId}/share-links

Create a share link for a device preview run

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
runIdstring:uuidYes

Request body

FieldTypeRequiredDescription
labelstringNo
expiresAtstring:date-timeNo
Request example
{
  "label": "value",
  "expiresAt": "2026-06-21T00:00:00.000Z"
}

Responses

StatusSchemaDescription
200DevicePreviewShareLinkDtoOK
HTTP and SDK snippets
GET /emails/device-previews/share/{shareToken}

Get a public shared device preview result

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
shareTokenstringYes

Responses

StatusSchemaDescription
200DevicePreviewSharedResultDtoOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/share/value HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/share/value" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "shareToken": "value"
};

const result = await devicePreviewsController.getDevicePreviewSharedResult(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_shared_result("value")
GET /emails/device-previews/share/{shareToken}/screenshots/{screenshotId}/image

Get a public shared device preview screenshot image

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
shareTokenstringYes
screenshotIdstring:uuidYes

Responses

StatusSchemaDescription
200string:byteOK
HTTP and SDK snippets

HTTP

HTTP
GET /emails/device-previews/share/value/screenshots/00000000-0000-4000-8000-000000000000/image HTTP/1.1
Host: api.mailslurp.com
x-api-key: YOUR_API_KEY
Accept: application/json

cURL

cURL
curl -X GET "https://api.mailslurp.com/emails/device-previews/share/value/screenshots/00000000-0000-4000-8000-000000000000/image" \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Accept: application/json"

JavaScript SDK

JavaScript SDK
import { Configuration, DevicePreviewsControllerApi } from "mailslurp-client";

const config = new Configuration({ apiKey: "YOUR_API_KEY" });
const devicePreviewsController = new DevicePreviewsControllerApi(config);
const request = {
  "shareToken": "value",
  "screenshotId": "00000000-0000-4000-8000-000000000000"
};

const result = await devicePreviewsController.getDevicePreviewSharedResultScreenshot(request);

Python SDK

Python SDK
import mailslurp_client
from mailslurp_client.api.device_previews_controller_api import DevicePreviewsControllerApi

configuration = mailslurp_client.Configuration()
configuration.api_key["x-api-key"] = "YOUR_API_KEY"

with mailslurp_client.ApiClient(configuration) as api_client:
    devicePreviewsController = DevicePreviewsControllerApi(api_client)
    result = devicePreviewsController.get_device_preview_shared_result_screenshot("value", "00000000-0000-4000-8000-000000000000")
DELETE /emails/device-previews/share-links/{shareLinkId}

Revoke a device preview share link

Request, parameters, and responses

Path parameters

NameTypeRequiredDescription
shareLinkIdstring:uuidYes

Responses

StatusSchemaDescription
200DeleteDevicePreviewShareLinkResultOK
HTTP and SDK snippets

Compare with previous runs

Device previews are most useful when you can compare the current render against an earlier approved version. MailSlurp stores run history, so you can use an earlier run as a baseline and review the new screenshots beside it.

For manual review, open the current and previous result pages or share links and compare the same native target in each run. Focus on layout shifts, missing images, CTA visibility, dark-mode changes, and client-specific spacing differences.

For automated comparison:

  1. Track the approved baseline run ID in your app, or list previous runs for the same stored email.
  2. Fetch results for the baseline run and the current run.
  3. Match target results by native target ID.
  4. Download the private screenshots, or use public screenshot URLs from share links.
  5. Compare the image files in your visual regression tool, then store the current run ID as the next baseline when approved.

Use share links when product, marketing, legal, or customer stakeholders need to compare results without an API key. Revoke a share link after approval if the screenshots should no longer be public.

Trigger device renders from the dashboard

Use the dashboard when you are reviewing a single message, checking a template manually, or giving stakeholders a visual approval path.

flowchart LR
    emailViewer["Dashboard email view"] --> mailslurp["MailSlurp"]
    ingestAddress["Render email address"] --> mailslurp
    emlImport["EML import"] --> mailslurp
    htmlUpload["HTML upload"] --> mailslurp
    apiRequest["API calls"] --> mailslurp

    mailslurp --> deviceGrid["Device and client grid"]
    deviceGrid --> desktop["Desktop previews"]
    deviceGrid --> mobile["Mobile previews"]
    deviceGrid --> webmail["Webmail previews"]
    deviceGrid --> evidence["Shareable render results"]

From the MailSlurp email viewer

Use this path when the email already exists in MailSlurp.

  1. Create a new MailSlurp inbox, or open an existing inbox.
  2. Send the email you want to review to that inbox.
  3. Open the received email in the MailSlurp dashboard.
  4. Click View in Mail Clients to choose render targets and start the preview run.

MailSlurp email detail view with the View in Mail Clients button highlighted

Import an exported email

Use direct import when you have an exported .eml or RFC 822 email file. This is useful for messages produced by another mail client, a campaign platform, or an internal build step.

  1. Export or download the email as an .eml file.
  2. Open Device previews in the MailSlurp dashboard.
  3. Click Import .eml.
  4. Upload the file, choose render targets, and start the preview.

MailSlurp device previews page with the Import .eml action

MailSlurp import form with an .eml file selected for device rendering

Upload HTML

Use HTML upload when you want to preview a template body before it is sent as a complete email. This is useful for design reviews, template QA, or quick checks from a build artifact.

  1. Open Device previews in the MailSlurp dashboard.
  2. Choose the HTML upload option.
  3. Paste or upload the HTML body.
  4. Select render targets and start the preview.

Send to a device render email address

Each account can use a specially assigned address under emailondevice.com. Send an email to that address from any client or campaign tool and MailSlurp starts a device render automatically.

The address has three parts:

marketing@acme.emailondevice.com
|-------| |--| |-----------------|
 profile  subdomain  render domain
  • The local part is the profile, such as marketing, qa, or all.
  • The subdomain is assigned to your account and can be changed to match your organization if the name is available.
  • The domain is emailondevice.com.

Profiles let you create named target sets for projects, teams, or campaigns. Sending to any local part at your subdomain still starts a render using the default target set, so a missed or new profile name does not block the review.

MailSlurp device preview overview showing the render email address and profile management

What to review

Focus on the things that break real launches:

  • layout shifts between clients
  • image scaling and spacing problems
  • CTA visibility and tap targets on mobile
  • typography or fallback styling differences
  • dark or light client behavior if relevant to your audience

Device previews answer "does the email look right in this client?" They do not answer every deliverability question. If you want to know whether a message is likely to land in spam, whether real mailbox providers accepted it, or whether sender reputation is at risk, pair visual rendering with the deliverability features below.

Check inbox placement and blocklists

Use Deliverability tests when you need inbox placement checks, spam-folder signals, and pass/fail release gates across a selected cohort. The Inbox placement and deliverability tests product page explains the broader workflow for checking whether emails reach inboxes or spam folders before a launch.

Use Domain Monitor when you need to watch sender-domain health over time, including SPF, DKIM, DMARC, MX, and DNS drift. For a direct blocklist-style check, use the email blacklist checker alongside Domain Monitor so rendering, placement, and sender reputation are all covered.

Review results

Open the results grid to compare each client render, then open any screenshot to review the full image and download it for approval.

Device preview results grid showing desktop and mobile email renders

Device preview screenshot modal with download and open actions

Result notifications

Device render notifications can send progress and completion messages to Slack or Microsoft Teams. Completion messages can include a link to a shareable result page so reviewers can open the rendered screenshots without needing to search the dashboard.

Typical render notification events include:

  • render started
  • render completed
  • render failed
  • render partially completed

Set up render notifications

Open Device preview notifications in the MailSlurp dashboard to connect Slack or Microsoft Teams, choose where messages should be sent, and send a test notification before using the rule for production reviews.

Slack render notifications

Use Slack when render reviews happen in a Slack channel.

  1. Open Configure Slack from the render notifications page.
  2. Approve the MailSlurp Notifications app in Slack.
  3. Return to MailSlurp, load channels, and add the channel to notify.
  4. Create a notification rule and send a test notification.

Slack OAuth approval screen for MailSlurp Notifications

Slack channel with a MailSlurp device render notification

Microsoft Teams render notifications

Use Microsoft Teams when render reviews happen in a Teams chat or channel.

  1. Open Configure Teams from the render notifications page.
  2. Sign in with a Microsoft work or school account if Teams asks.
  3. Press Send on the prefilled MailSlurp connect message in Teams.
  4. Return to MailSlurp, wait for confirmation, then create a notification rule and send a test notification.

Microsoft Teams chat with a prefilled MailSlurp connect message ready to send

  1. Render the message in the native targets that matter most.
  2. Check the hero, CTA, body copy, footer, and any legally required content.
  3. Fix the template or content if a high-impact rendering issue appears.
  4. Create a share link for approval evidence.
  5. Pair the visual review with Email audit when links and images also need validation.