# AI models

Use a MailSlurp model ID to choose the evaluator for email and SMS matching, assertions, and structured extraction. Set `aiOptions.model` on your request, or omit it to use the default, `BALANCED_V1`.

## Supported model IDs

Use one of these public MailSlurp IDs in `aiOptions.model`:

| Model ID | Selection guidance |
| --- | --- |
| <code class="whitespace-nowrap">BALANCED_V1</code> | Default for message matching, assertions, and extraction when model selection is omitted. |
| <code class="whitespace-nowrap">FLASH_LATEST</code> | Moving alias. Its implementation can change; evaluate your test cases when comparing results over time. |
| <code class="whitespace-nowrap">QUALITY_V1</code> | Versioned model ID. Check the model catalog for availability before selecting it. |

A model ID in the schema is a valid selector, but availability depends on the models enabled in the API environment you call. Check the model catalog before selecting a different model. An unavailable model produces an error; it does not silently switch to another model.

## Check available models

Call `GET /ai/models` with your API key to discover the enabled models. This command prints only their MailSlurp IDs:

```bash
curl --fail --silent --show-error \
  'https://api.mailslurp.com/ai/models' \
  -H "x-api-key: $MAILSLURP_API_KEY" \
  | jq -r '.[].model'
```

The catalog also reports `supportedMessageTypes`, `movingAlias`, and `tokenMultiplier`. Use those fields when checking whether a model supports your message type and how it consumes your AI allowance. Read current values from the catalog rather than assuming that every model has the same multiplier.

With a current JavaScript SDK, use `aiController.getAIMessageModels()` and the public model enum:

```typescript
import { MailSlurp, AIMessageAIOptionsModelEnum } from 'mailslurp-client';

const mailslurp = new MailSlurp({ apiKey: process.env.MAILSLURP_API_KEY! });
const model = AIMessageAIOptionsModelEnum.BALANCED_V1;
const available = await mailslurp.aiController.getAIMessageModels();
const enabledIds: string[] = available.map((item) => item.model);
if (!enabledIds.includes(model)) {
  throw new Error(`The requested MailSlurp model is unavailable: ${model}`);
}
const aiOptions = { model };
```

Use `aiOptions` in the operation's request options. If your installed SDK does not export `AIMessageAIOptionsModelEnum` or `getAIMessageModels`, update `mailslurp-client` or call the REST endpoint directly.

## Select a model for extraction

This request extracts an OTP from an existing email. Replace `EMAIL_ID` with the email's resource ID; for SMS, set `message.type` to `SMS` and supply the SMS resource ID.

```json
{
  "message": {
    "type": "EMAIL",
    "id": "EMAIL_ID"
  },
  "extractionPreset": "OTP_CODE",
  "aiOptions": {
    "model": "BALANCED_V1",
    "maxTokens": 8000,
    "maxOutputTokens": 2048
  }
}
```

Send it to `POST /ai/messages/extract`. Model selection uses the same top-level `aiOptions` on the message wait, assertion, and expectation operations. For an AI condition added to an existing email or SMS wait, configure `ai.aiOptions` in the wait's match or condition options instead. On `/ai/messages/wait`, keep the evaluator settings in the top-level `aiOptions`; do not supply conflicting settings in `match.aiOptions`.

See the [AI workflow documentation](/docs/ai/) for complete requests, extraction schemas, evidence, and failure handling, and [wait conditions](/docs/wait-for/) for adding a semantic match to an existing wait.

## Choose and compare models in tests

Start with the default model and a representative set of messages from your application. Include missing codes, ambiguous content, localized templates, and messages that should not match. Compare the returned status and evidence as well as the extracted value.

For repeatable test configuration, set the model ID explicitly. `FLASH_LATEST` is a moving alias, so its implementation can change over time. A versioned ID makes your selection explicit, but AI output still needs assertions and source evidence; identical inputs are not a guarantee of identical output.

Keep token limits and timeout handling in place when changing models. Treat `INCONCLUSIVE` as an outcome to handle, and avoid retrying with different models until a test happens to pass. For an OTP, check `successful`, the code's expected format, and its extraction evidence before entering it in a browser.

Model selection here applies to the message-testing APIs. For saved transformer workflows and their request options, see [AI transformers](/docs/ai-transformers/) and [invoking transformers](/docs/ai-invocation/).
