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

# Email status

> Check delivery status with getEmailStatus. Understand status values, the submission-to-delivery lifecycle, and how to poll for updates.

After you send an email with `sendEmail`, use `getEmailStatus` to track its progress through the BosonMail system. The method queries the API for the current state and delivery status of a specific message. It always resolves, even on failure, and returns an `EmailStatusResult` object.

## Signature

```typescript theme={null}
getEmailStatus(messageId: string): Promise<EmailStatusResult>
```

## Parameters

**messageId** `string` *required*

The message identifier returned by `sendEmail` in `Result.messageId`. Must be a non-empty string after trimming.

> [!NOTE]
>
> The SDK does not validate email address format, but it does validate `messageId` before making a request. If `messageId` is empty or not a string, the method returns `{ success: false, errorCode: "invalid_id", errorMessage: "'messageId' must be a non-empty string" }` with no network call.

## Endpoint and authentication

```text theme={null}
GET {baseUrl}/emails/{encodeURIComponent(messageId.trim())}/status
```

The request includes:

* `Authorization: Bearer <apiKey>`
* `Accept: application/json`

The full default URL is `https://webmail.bosonware.com/api/v1/emails/:id/status`.

The API key needs `email:read` or `email:send` scope. The exact scope requirements are documented in the BosonMail README. Contact BosonWare at [support@bosonware.com](mailto:support@bosonware.com) to confirm which scope your key requires.

## Return value

### EmailStatusResult

**success** `boolean` *required*

`true` when the status was retrieved successfully. `false` for any validation, network, API, or timeout failure.

**data** `EmailStatusData`

The status payload when `success` is `true`.

**errorMessage** `string`

Human-readable description when `success` is `false`.

**errorCode** `string`

Machine-readable error code when `success` is `false`. Present only on `EmailStatusResult`, not on `Result`.

**statusCode** `number`

HTTP status code from the API response. Absent for client-side validation errors and network/timeout failures.

### EmailStatusData

**id** `string | number` *required*

Internal BosonMail identifier.

**uuid** `string`

UUID for the message. Defaults to `""` if absent in the API response.

**message\_id** `string`

The message identifier. Defaults to `""` if absent.

**status** `EmailSentStatus` *required*

Current email status in the BosonMail system.

**delivery\_status** `EmailSentStatus` *required*

Delivery status reported by the API.

**recipient** `string | string[]`

Recipient address or addresses. Defaults to `""` if absent.

**subject** `string`

Email subject. Defaults to `""` if absent.

**created\_at** `string`

ISO timestamp of when the email was created. Defaults to `""` if absent.

## Status values

The `EmailSentStatus` type is defined as:

```typescript theme={null}
type EmailSentStatus = "queued" | "sent" | "delivered" | "failed" | "bounced" | "rejected" | "deferred" | (string & {});
```

The type is open: the BosonMail backend may return values beyond the known list. Use the values the API returns rather than assuming every message follows the same progression. The exact meaning and transition order is not documented by BosonWare. The descriptions below are general email terms and should be confirmed with BosonWare.

| Status | General meaning (to be confirmed with BosonWare) |
| - | - |
| `queued` | The message has been accepted and is waiting to be processed. |
| `sent` | The message has left the BosonMail system and is in transit. |
| `delivered` | The receiving server accepted the message. Terminal status. |
| `failed` | Delivery could not be completed. Terminal status. |
| `bounced` | The receiving server rejected the message (for example, invalid address or mailbox full). Terminal status. |
| `rejected` | The message was rejected by BosonMail or the receiving server before delivery. Terminal status. |
| `deferred` | Delivery is temporarily delayed (for example, greylisting or rate limiting). Not terminal; may retry. |

> [!WARNING]
>
> The exact meaning of each status value and the transition order is not documented by BosonWare. Treat the descriptions above as general guidance. Confirm behavior with [support@bosonware.com](mailto:support@bosonware.com).

## Submission vs delivery

A successful `sendEmail` means the API accepted the message. The typical initial status is `"queued"`. Delivery to the recipient's inbox is a separate, asynchronous process that depends on the receiving server's availability, spam filters, and network conditions.

```mermaid theme={null}
sequenceDiagram
    participant App as Your application
    participant SDK as BosonMail SDK
    participant API as BosonMail API
    participant Mail as Recipient server

    App->>SDK: sendEmail(to, subject, body)
    SDK->>API: POST /emails/send
    API-->>SDK: { success: true, status: "queued" }
    SDK-->>App: Result { success, messageId, status: "queued" }

    Note over App: Later...

    App->>SDK: getEmailStatus(messageId)
    SDK->>API: GET /emails/:id/status
    API-->>SDK: { success: true, data: { status, delivery_status } }
    SDK-->>App: EmailStatusResult

    API->>Mail: SMTP delivery attempt
    Mail-->>API: Accept or reject
```

The diagram above is illustrative. Actual delivery flow may differ.

## Terminal statuses

The BosonMail README treats the following as terminal: `delivered`, `failed`, `bounced`, `rejected`. A polling loop should stop when it encounters any of these. `deferred` and `sent` are not terminal; the status may change on subsequent checks.

## Error results

### Client-side validation

```typescript theme={null}
{
  success: false,
  errorCode: "invalid_id",
  errorMessage: "'messageId' must be a non-empty string"
}
```

### API errors

When the API returns a non-2xx response or `success !== true`, the SDK extracts the error code and message from the response body:

```typescript theme={null}
{
  success: false,
  statusCode: 404,
  errorCode: "not_found",
  errorMessage: "Email could not be found"
}
```

### Incomplete response

If the API response lacks required fields (`id`, `status`, or `delivery_status` as strings), the SDK returns:

```typescript theme={null}
{
  success: false,
  statusCode: 200,
  errorCode: "invalid_response",
  errorMessage: "The API returned an incomplete email status response."
}
```

### Network or timeout

```typescript theme={null}
{
  success: false,
  errorCode: "request_failed",
  errorMessage: "Request timed out after 30000ms. The outcome may be unknown; check email status before retrying."
}
```

## Persist messageId for later lookup

Store the `messageId` from every successful `sendEmail` in your database or job queue so you can check status later without relying on in-memory state.

```typescript store-message-id.ts theme={null}
import BosonMailClient from "@bosonware-ent/bosonmail";

const client = new BosonMailClient({ apiKey: process.env.BOSONMAIL_API_KEY! });

const result = await client.sendEmail(
  "customer@example.com",
  "Order confirmation",
  { text: "Your order has been confirmed." }
);

if (result.success && result.messageId) {
  await db.emails.insert({
    messageId: result.messageId,
    recipient: "customer@example.com",
    subject: "Order confirmation",
    sentAt: new Date().toISOString()
  });
}
```

## Polling for updates

The SDK does not poll automatically. Implement polling in your application if you need to wait for a terminal status. A typical pattern checks every 5 seconds, up to 6 attempts (30 seconds total), and stops on terminal statuses.

```typescript poll-status.ts theme={null}
import BosonMailClient from "@bosonware-ent/bosonmail";
import type { EmailSentStatus } from "@bosonware-ent/bosonmail";

const client = new BosonMailClient({ apiKey: process.env.BOSONMAIL_API_KEY! });

const TERMINAL_STATUSES: EmailSentStatus[] = ["delivered", "failed", "bounced", "rejected"];

async function pollStatus(messageId: string, maxAttempts = 6, intervalMs = 5000) {
  for (let i = 0; i < maxAttempts; i++) {
    const result = await client.getEmailStatus(messageId);

    if (!result.success) {
      console.error("Status check failed:", result.errorMessage);
      return result;
    }

    const status = result.data!.status;
    console.log(`Attempt ${i + 1}: status=${status}`);

    if (TERMINAL_STATUSES.includes(status)) {
      return result;
    }

    if (i < maxAttempts - 1) {
      await new Promise(r => setTimeout(r, intervalMs));
    }
  }

  console.log("Max attempts reached without terminal status");
  return null;
}
```

For a complete guide, see [Monitoring delivery](https://docs.bosonware.com/guides/monitoring-delivery.md).

> [card] [Sending emails](https://docs.bosonware.com/sdk/sending-emails.md)
>
> Full sendEmail reference with parameters and validation rules.

> [card] [Error handling](https://docs.bosonware.com/sdk/error-handling.md)
>
> How to classify and respond to every kind of SDK error.

> [card] [Guides: Monitoring delivery](https://docs.bosonware.com/guides/monitoring-delivery.md)
>
> Practical guide for polling, webhooks, and delivery tracking.

> [card] [Client configuration](https://docs.bosonware.com/sdk/client-configuration.md)
>
> Timeout settings that affect status check requests.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.