# Send newsletter test email

Send a newsletter preview to your own email address, with its normal layout, merge fields and unsubscribe footer. Does not send to the selected audience or publish the newsletter.

POST https://api.brigg.app/v1/operations/newsletters.SendNewsletterTestEmail

## Access & visibility

Allow `newsletters.SendNewsletterTestEmail` on your API key.

**Acting member required.** Send `Brigg-Act-As` with an [approved member account ID](https://developer.brigg.app/authentication#member-delegation). The key supplies permissions; the member selects whose data is used.

The selected member must be active and approved by the credential. This selects whose private data is used; the credential supplies permissions. Private ownership and project boundaries still apply.

[Set up authentication](https://developer.brigg.app/authentication) · [Choose permissions](https://developer.brigg.app/permissions)

## Request fields

Send a JSON object with the following fields. Required fields must be included; omit optional fields you do not need.
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `newsletter_id` | string | Yes | Read the issue and use its newsletter_id when available. This is the content identity, not the issue or schedule ID. [newsletters.GetNewsletterIssue](https://developer.brigg.app/reference/newsletters/GetNewsletterIssue). At least 1 character. |
| `subject` | string or null | No | Subject override for this test only, trimmed before use. Omit, null or blank uses the saved campaign subject, then a subject derived from the content. It does not update the saved draft. |
| `preview_text` | string or null | No | Inbox preview line for this test only. Omit or null uses the saved draft's preview text; an empty string explicitly removes it from this test. It does not update the saved draft. |

## Send a preview without changing the campaign

Read [Get newsletter issue](https://developer.brigg.app/reference/newsletters/GetNewsletterIssue) and retain its newsletter_id once prepared. The test uses the acting member's current draft when present, otherwise the published content. The member must be allowed to act on this newsletter, not merely know its ID.

The test is addressed only to the acting member, personalizes merge fields with that member's contact details, and prefixes the subject with a preview label in the newsletter's language. It does not save your overrides, publish the newsletter, create a campaign send or mail subscribers.

A successful response means accepted for sending, not delivered. Inspect the actual email's layout, links, merge values and footer before a person sends the campaign in Brigg. The test recipient's existing unsubscribe preference still applies. After a lost response, retry with the original idempotency key instead of creating another preview.

## Response

Returns **200 OK** with a JSON body.
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `ok` | boolean | Yes | True when the test message was accepted for sending. It does not confirm mailbox delivery or that a person read it. |
| `message_id` | string | Yes | Identifier for this outgoing test message. Keep it for troubleshooting. It is not a newsletter, issue or Brigg inbox-message ID; this operation provides no delivery-status polling endpoint. |
| `to` | string | Yes | Email address belonging to the approved acting member. There is no recipient override; member delegation selects whose own preview is sent. |

## Errors & retries

Set `BRIGG_REQUEST_ID` once for each logical action. The samples send it as `Idempotency-Key`. Reuse the same value and body on retries, including after a timeout; a missing response does not prove the action failed.

For rate limits, follow the server’s retry guidance and back off. See [HTTP errors](https://developer.brigg.app/http#errors) and [safe retries and limits](https://developer.brigg.app/reliability).

| HTTP status | Code | What to do |
| --- | --- | --- |
| 400 | `invalid_json` | Send a JSON object with Content-Type: application/json. |
| 400 | `invalid_input` | Check the request fields and types. Supply a stable Idempotency-Key containing 1–200 characters. |
| 401 | `invalid_key` | The workspace API key is missing, invalid or revoked. |
| 403 | `forbidden` | Check the key’s operation and resource grants. Supply Brigg-Act-As with a member authorized by the key’s delegation grant. The selected member must be active and approved by the credential. This selects whose private data is used; the credential supplies permissions. Private ownership and project boundaries still apply. |
| 404 | `not_found` | The requested operation or resource is not available to this credential. |
| 429 | `rate_limited` | Wait for Retry-After before retrying. Reuse the original Idempotency-Key. |
| 400 | `no_email` | The acting member has no email address for the preview. Complete that member's account setup in Brigg. |
| 409 | `not_built` | The selected newsletter has no prepared email content. Finish preparing and reviewing it in Brigg first. |
| 409 | `images_not_hosted` | Newsletter images are not ready for email delivery. Finish preparing the newsletter's images in Brigg before retrying. |
| 422 | `suppressed` | This member's email address is suppressed or unsubscribed for this workspace. No preview was sent; respect the existing preference. |

## Next steps

- [Get newsletter issue](https://developer.brigg.app/reference/newsletters/GetNewsletterIssue)
- [Save newsletter draft](https://developer.brigg.app/reference/newsletters/SaveNewsletterDraft)

[Download OpenAPI](https://developer.brigg.app/openapi.json) · [Versioning & retirement](https://developer.brigg.app/versioning)

## Examples

### Preview the saved draft

The preview goes to Jamie, the approved acting member. No subscriber receives it.
#### cURL


```sh
curl 'https://api.brigg.app/v1/operations/newsletters.SendNewsletterTestEmail' \
  -H "Authorization: Bearer $BRIGG_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Brigg-Act-As: $BRIGG_ACT_AS" \
  -H "Idempotency-Key: $BRIGG_REQUEST_ID" \
  --data-raw '{
  "newsletter_id": "c_newsletter_autumn"
}'
```

#### TypeScript


```typescript
const actAs = process.env.BRIGG_ACT_AS;
if (!actAs) throw new Error("Set BRIGG_ACT_AS to an approved member account ID.");

const requestId = process.env.BRIGG_REQUEST_ID;
if (!requestId) throw new Error("Set BRIGG_REQUEST_ID once per action and reuse it on retries.");

const response = await fetch("https://api.brigg.app/v1/operations/newsletters.SendNewsletterTestEmail", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BRIGG_API_KEY}`,
    "Content-Type": "application/json",
    "Brigg-Act-As": actAs,
    "Idempotency-Key": requestId, // Create once per action; reuse on retries.
  },
  body: JSON.stringify({
    "newsletter_id": "c_newsletter_autumn"
  }),
});
const result = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${result.error} — ${result.message}`);
console.log(result);
```

#### Python


```python
import json
import os
from urllib.request import Request, urlopen
from urllib.error import HTTPError

request_id = os.environ["BRIGG_REQUEST_ID"]  # Reuse for retries of this action.
payload = {
  "newsletter_id": "c_newsletter_autumn"
}
request = Request(
    "https://api.brigg.app/v1/operations/newsletters.SendNewsletterTestEmail",
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {os.environ['BRIGG_API_KEY']}",
        "Content-Type": "application/json",
        "Brigg-Act-As": os.environ["BRIGG_ACT_AS"],
        "Idempotency-Key": request_id,  # Create once per action; reuse on retries.
    },
    method="POST",
)
try:
    with urlopen(request) as response:
        print(json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))
    raise
```

#### Response example


```json
{
  "ok": true,
  "message_id": "msg_preview_autumn",
  "to": "jamie@example.com"
}
```

### Test a subject with no preheader

These overrides affect this message only. Empty preview_text clears the inbox preview line.
#### cURL


```sh
curl 'https://api.brigg.app/v1/operations/newsletters.SendNewsletterTestEmail' \
  -H "Authorization: Bearer $BRIGG_API_KEY" \
  -H 'Content-Type: application/json' \
  -H "Brigg-Act-As: $BRIGG_ACT_AS" \
  -H "Idempotency-Key: $BRIGG_REQUEST_ID" \
  --data-raw '{
  "newsletter_id": "c_newsletter_autumn",
  "subject": "Your autumn project update",
  "preview_text": ""
}'
```

#### TypeScript


```typescript
const actAs = process.env.BRIGG_ACT_AS;
if (!actAs) throw new Error("Set BRIGG_ACT_AS to an approved member account ID.");

const requestId = process.env.BRIGG_REQUEST_ID;
if (!requestId) throw new Error("Set BRIGG_REQUEST_ID once per action and reuse it on retries.");

const response = await fetch("https://api.brigg.app/v1/operations/newsletters.SendNewsletterTestEmail", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.BRIGG_API_KEY}`,
    "Content-Type": "application/json",
    "Brigg-Act-As": actAs,
    "Idempotency-Key": requestId, // Create once per action; reuse on retries.
  },
  body: JSON.stringify({
    "newsletter_id": "c_newsletter_autumn",
    "subject": "Your autumn project update",
    "preview_text": ""
  }),
});
const result = await response.json();
if (!response.ok) throw new Error(`${response.status}: ${result.error} — ${result.message}`);
console.log(result);
```

#### Python


```python
import json
import os
from urllib.request import Request, urlopen
from urllib.error import HTTPError

request_id = os.environ["BRIGG_REQUEST_ID"]  # Reuse for retries of this action.
payload = {
  "newsletter_id": "c_newsletter_autumn",
  "subject": "Your autumn project update",
  "preview_text": ""
}
request = Request(
    "https://api.brigg.app/v1/operations/newsletters.SendNewsletterTestEmail",
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {os.environ['BRIGG_API_KEY']}",
        "Content-Type": "application/json",
        "Brigg-Act-As": os.environ["BRIGG_ACT_AS"],
        "Idempotency-Key": request_id,  # Create once per action; reuse on retries.
    },
    method="POST",
)
try:
    with urlopen(request) as response:
        print(json.load(response))
except HTTPError as error:
    print(error.code, json.load(error))
    raise
```

#### Response example


```json
{
  "ok": true,
  "message_id": "msg_preview_autumn",
  "to": "jamie@example.com"
}
```

## JSON schemas


```json-schema-request
{
  "type": "object",
  "properties": {
    "newsletter_id": {
      "type": "string",
      "minLength": 1,
      "description": "Read the issue and use its newsletter_id when available. This is the content identity, not the issue or schedule ID. [newsletters.GetNewsletterIssue](https://developer.brigg.app/reference/newsletters/GetNewsletterIssue)."
    },
    "subject": {
      "type": [
        "string",
        "null"
      ],
      "description": "Subject override for this test only, trimmed before use. Omit, null or blank uses the saved campaign subject, then a subject derived from the content. It does not update the saved draft."
    },
    "preview_text": {
      "type": [
        "string",
        "null"
      ],
      "description": "Inbox preview line for this test only. Omit or null uses the saved draft's preview text; an empty string explicitly removes it from this test. It does not update the saved draft."
    }
  },
  "required": [
    "newsletter_id"
  ],
  "additionalProperties": false,
  "examples": [
    {
      "newsletter_id": "c_newsletter_autumn"
    }
  ]
}
```


```json-schema-response
{
  "type": "object",
  "properties": {
    "ok": {
      "type": "boolean",
      "description": "True when the test message was accepted for sending. It does not confirm mailbox delivery or that a person read it."
    },
    "message_id": {
      "type": "string",
      "description": "Identifier for this outgoing test message. Keep it for troubleshooting. It is not a newsletter, issue or Brigg inbox-message ID; this operation provides no delivery-status polling endpoint."
    },
    "to": {
      "type": "string",
      "description": "Email address belonging to the approved acting member. There is no recipient override; member delegation selects whose own preview is sent."
    }
  },
  "required": [
    "ok",
    "message_id",
    "to"
  ],
  "additionalProperties": false,
  "examples": [
    {
      "ok": true,
      "message_id": "msg_preview_autumn",
      "to": "jamie@example.com"
    }
  ]
}
```

