# Send Test Email

POST /api/v2/projects/{projectId}/emails/send-test

Sends a one-off preview of a campaign message to specific contacts, rendered with their data so personalisation can be checked before the real send. Note the unusual shape: the campaign, message, and project are passed in the request body rather than looked up by ID, so this can preview unsaved edits. Test sends do not touch campaign status or stats, but they do consume balance and respect sender blocking.

## Request

- projectId: string, path, required — ID of the project sending the test.
- campaign: object, required — The campaign to preview. Passed in full rather than by ID so unsaved changes can be tested.
  - createdAt: string, required
  - id: string, required
  - name: string, required
  - projectId: string, required
  - status: DRAFT | SCHEDULED | SENDING | SENT | PAUSED | CANCELLED, required
  - updatedAt: string, required
  - abTestConfig: object
    - variable: SUBJECT | FROM_NAME | CONTENT | SEND_TIME, required — What differs across variants: subject, from name, content, or send time.
    - samplePaginationEnd: integer — Send cursor at the end of the sample phase. Set by the runtime.
    - samplePercent: number, default 20 — Percent of the audience that receives the sample variants.
    - sendTimeDelayHours: number, default 2 — Delay between sample sends when variable is SEND_TIME.
    - sendTimeDelayUnit: HOURS | MINUTES, default HOURS — Unit for sendTimeDelayHours.
    - status: AWAITING_SAMPLE | AWAITING_WINNER | ROLLED_OUT, default AWAITING_SAMPLE — A/B test phase. Omit on create; the runtime advances this.
    - winnerMessageId: string — Winning message id. Set by the runtime after the test resolves.
    - winnerMetric: OPEN_RATE | CLICK_RATE, default OPEN_RATE — Metric used to pick the winning variant.
    - winnerRolloutAt: string — ISO timestamp when the winner was rolled out to the rest of the list.
    - winnerSelectedAt: string — ISO timestamp when the winner was selected.
    - winnerWaitHours: number, default 4 — How long to wait after the sample before picking 
…

## Response

- 200: Successful response
  - message: string, required
  - success: boolean, required
- 400: Invalid input data
- 401: Authorization not provided
- 403: Insufficient access
- 500: Internal server error
