GET /mail/v2/messages/{message_id}

Prev Next

A 202 from the send endpoint confirms queueing only. Delivery then runs asynchronously. Use this endpoint to check the state of a message, including per-recipient progress for multi-recipient sends.

Endpoint and headers

GET https://email.useinsider.com/mail/v2/messages/{message_id}

Header

Value

Purpose

X-INS-AUTH-KEY

API token, in INS.{id}.{secret} format

Authentication. The partner is implicit; a message_id belonging to another partner returns 404.

Request parameter

Below are the parameters required for the request.

Parameter

Description

Data type

Required

message_id

The ID returned by the send endpoint.

String (UUID)

Yes

Code samples

These samples are provided as is, as a starting point for your integration. Insider One does not guarantee that they work in every environment, so test them in your own environment before you use them in production.

Each sample polls one message every 5 seconds and prints the aggregate status and summary until completed_at is set.

  1. Set your API key in the INSIDER_API_KEY environment variable.

  2. Copy the sample for your language into a file named get_message_status.py or get_message_status.mjs.

  3. Run the file with a message_id. Each poll prints a line such as partial: {pending: 1, sent: 2, dropped: 0}, and the sample stops when the message is complete.

Python

Requires Python 3.8 or later and the requests package (pip install requests). Run python get_message_status.py 550e8400-e29b-41d4-a716-446655440000.

"""Poll a message's delivery status with GET /mail/v2/messages/{message_id}.

Sample code, provided as is. Test it in your own environment before you use it in production.
Requires Python 3.8+ and the requests package: pip install requests
"""
import os
import sys
import time

import requests

URL = "https://email.useinsider.com/mail/v2/messages/{message_id}"
# OAuth 2.0: call https://gw.useinsider.com/api/em/v2/tx/messages/{message_id} with "Authorization: Bearer {token}" instead.
HEADERS = {"X-INS-AUTH-KEY": os.environ["INSIDER_API_KEY"], "Content-Type": "application/json"}


def call(method, url, payload=None, retries=3):
    """Send the request. On 429 or 5xx, wait and retry up to `retries` times."""
    for attempt in range(retries + 1):
        response = requests.request(method, url, json=payload, headers=HEADERS, timeout=30)
        if (response.status_code != 429 and response.status_code < 500) or attempt == retries:
            return response
        wait = float(response.headers.get("Retry-After", 2 ** attempt))  # 1, 2, 4 s without Retry-After
        print(f"HTTP {response.status_code}: retrying in {wait:.0f}s")
        time.sleep(wait)


message_id = sys.argv[1]  # The message_id returned by POST /mail/v2/send

while True:
    response = call("GET", URL.format(message_id=message_id))
    if response.status_code == 404:
        raise SystemExit("Unknown message_id, or the send is older than 2 days.")
    if response.status_code != 200:
        raise SystemExit(f"Status request failed ({response.status_code}): {response.text[:300]}")
    status = response.json()
    print(f"{status['status']}: {status['summary']}")
    if status["completed_at"] is not None:  # Every recipient has reached a final state
        break
    time.sleep(5)

Node.js

Requires Node.js 18 or later. No packages are needed. Run node get_message_status.mjs 550e8400-e29b-41d4-a716-446655440000.

// Poll a message's delivery status with GET /mail/v2/messages/{message_id}.
// Sample code, provided as is. Test it in your own environment before you use it in production.
// Requires Node.js 18+ (built-in fetch). No dependencies.

const URL = "https://email.useinsider.com/mail/v2/messages/{message_id}";
// OAuth 2.0: call https://gw.useinsider.com/api/em/v2/tx/messages/{message_id} with "Authorization: Bearer {token}" instead.
const HEADERS = { "X-INS-AUTH-KEY": process.env.INSIDER_API_KEY, "Content-Type": "application/json" };
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

// Send the request. On 429 or 5xx, wait and retry up to `retries` times.
async function call(method, url, payload, retries = 3) {
  for (let attempt = 0; ; attempt++) {
    const response = await fetch(url, {
      method,
      headers: HEADERS,
      body: payload === undefined ? undefined : JSON.stringify(payload),
      signal: AbortSignal.timeout(30000),
    });
    if ((response.status !== 429 && response.status < 500) || attempt === retries) return response;
    const wait = Number(response.headers.get("Retry-After") ?? 2 ** attempt); // 1, 2, 4 s without Retry-After
    console.warn(`HTTP ${response.status}: retrying in ${wait}s`);
    await sleep(wait * 1000);
  }
}

const messageId = process.argv[2]; // The message_id returned by POST /mail/v2/send

for (;;) {
  const response = await call("GET", URL.replace("{message_id}", messageId));
  if (response.status === 404) throw new Error("Unknown message_id, or the send is older than 2 days.");
  if (response.status !== 200) {
    throw new Error(`Status request failed (${response.status}): ${(await response.text()).slice(0, 300)}`);
  }
  const status = await response.json();
  console.log(`${status.status}:`, status.summary);
  if (status.completed_at !== null) break; // Every recipient has reached a final state
  await sleep(5000);
}

Sample responses

The aggregate status is pending (all recipients pending), partial (some sent), or sent (all sent). Per-recipient status is pending or sent; the email is omitted when the recipient was sent by UUID only.

Mid-delivery, some delivered

{
  "message_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "partial",
  "submitted_at": 1700000000,
  "completed_at": null,
  "recipient_count": 3,
  "summary": {
    "pending": 1,
    "sent": 2,
    "dropped": 0
  },
  "recipients": [
    {
      "email": "alice@example.com",
      "status": "sent",
      "last_updated": 1700000100
    },
    {
      "email": "bob@example.com",
      "status": "sent",
      "last_updated": 1700000105
    },
    {
      "status": "pending",
      "last_updated": 1700000000
    }
  ]
}

Finished, all delivered

{
  "message_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "sent",
  "submitted_at": 1700000000,
  "completed_at": 1700000160,
  "recipient_count": 3,
  "summary": {
    "pending": 0,
    "sent": 3,
    "dropped": 0
  }
}

Keep in mind

  • Poll periodically until the status is sent or completed_at is set. Timestamps are Unix seconds; completed_at stays null until every recipient reaches a terminal state.

  • Status is available for 2 days after submission; older IDs return 404.

  • The rate limit is 1000 requests per minute per partner.

For status codes, refer to the Error Codes.