## Start a sequence test

**post** `/v1/sequences/{id}/tests`

Tries the sequence on one contact without sending anything: the contact is enrolled in a test, its steps run back to back with waits skipped, and each message is composed from the contact’s real data and kept as a draft. Use it to check what a step, a template variable or its fallback produces before publishing.

Tests the open draft when there is one or the sequence has never been published, otherwise the published version; `target` in the response says which. Send `expectedVersion` to test exactly the draft you last read. The test continues after the response, so the request returns right away with status `RUNNING`.

Returns 400 `invalid_configuration` with `invalidContacts` naming a contact that does not exist or lacks what a step needs (an email address, a LinkedIn URL or a phone number), or with `issues` when the draft cannot run, 400 `permissions_not_granted` when the draft has agent steps whose permissions are not granted (grant them in Lightfield), 400 `no_selectable_sender` when a channel has no available sender, 409 when `expectedVersion` is not the open draft’s `version`; retrieve the draft and retry, and 429 when a test limit is reached, with a message naming it: the workspace already has 10 tests running (retry once one is `COMPLETED` or `FAILED`), or it started more than 5 tests a minute (retry after `Retry-After` seconds). See <u>[Sequence errors](/using-the-api/errors/#sequence-errors)</u>.

Each call creates a test enrollment and drafts, and agent steps use model credits.

**[Required scope](/using-the-api/scopes/):** `sequences:update`

**[Rate limit category](/using-the-api/rate-limits/):** Write

### Path Parameters

- `id: string`

  Unique identifier of the sequence.

### Body Parameters

- `contactId: string`

  ID of the contact to test the sequence on. The test composes each message from this contact’s real data and sends nothing.

- `expectedVersion: optional string`

  The open draft’s `version` as last read. When sent, the test runs exactly that draft, and is refused with 409 if the draft has changed or none is open. Omit it to test whatever is open now.

### Returns

- `SequenceStartTestResponse object { id, contactId, status, target }`

  - `id: string`

    ID of the test, an enrollment ID. Use it to read the result.

  - `contactId: string`

    ID of the contact being tested.

  - `status: "RUNNING"`

    Always `RUNNING`: the test continues after the response.

    - `"RUNNING"`

  - `target: "DRAFT" or "PUBLISHED"`

    Which version is being tested: the open `DRAFT` when there is one or the sequence was never published, otherwise the `PUBLISHED` version.

    - `"DRAFT"`

    - `"PUBLISHED"`

### Example

```http
curl https://api.lightfield.app/v1/sequences/$ID/tests \
    -H 'Content-Type: application/json' \
    -H 'Lightfield-Version: 2026-03-01' \
    -H "Authorization: Bearer $API_KEY" \
    -d '{
          "contactId": "x"
        }'
```

#### Response

```json
{
  "id": "id",
  "contactId": "contactId",
  "status": "RUNNING",
  "target": "DRAFT"
}
```
