> This page is for Audio Decisions.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://dev.hume.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://dev.hume.ai/_mcp/server.

# Create decision

POST https://api.cloud.hume.ai/v0/decisions/file
Content-Type: multipart/form-data

Asks questions about one audio file and returns an answer to each, with the `run_id` of the model run that produced them. Each answer estimates how human raters would respond, so you choose the thresholds for acting on it.

All the questions in a request are answered in one model inference, so an answer can change when other questions are added, removed or reordered. To compare answers across recordings, send the same questions in the same order. To evaluate several files, send one request per file.

Reference: https://dev.hume.ai/audio-decisions/reference/decisions/create

## Authentication

- `X-Hume-Api-Key` header (required) — API Key authentication via header

## Request

### Body (multipart/form-data)

This endpoint expects a multipart form containing a file.

- `request` (DecisionsRequest, required)
- `file` (file, required) — The audio file, MP3 or WAV, in a part named `file`.

## Response

### 200

The answer to each question, keyed by question ID, and the `run_id` of the model run that produced the answers.

- `run_id` (string, required) — Identifies this request's run. Pass it to the run endpoints to look the run up. A run can take a moment to appear, and under heavy load may not be recorded.
- `answers` (map from string to Answer, required) — The answer to each question, keyed by question ID.
- `received` (Received, required) — What the model received for a decisions request, which is what the request is billed.

## Errors

### 400 Bad Request Error

Something in the request needs correcting. `code` says which.

- `type` ("error", required) — The type of the object. Always `error`.
- `code` (enum, required) — What went wrong, grouped by the HTTP status it is returned with. **`400 Bad Request`**: something in the request needs correcting. - `message_invalid`: the request body is malformed or does not match the schema outside a question, for example because a decisions request has no `request` part, or no `file` part or more than one, or an input tokens request has no `audio_duration_ms`. - `question_invalid`: a question is invalid, including when it does not match the schema, for example because it has duplicate option names or fewer than two options. - `audio_decode_failed`: the audio file could not be decoded. - `audio_format_unsupported`: the audio file is not MP3 or WAV. - `audio_too_short`: the audio is shorter than 5 seconds, or `audio_duration_ms` is under 5000. - `audio_too_long`: the audio is longer than 5 minutes, or `audio_duration_ms` is over 300000. - `invalid_request`: a query parameter has a value the endpoint does not accept, or `cursor` is not one the endpoint issued. List runs only. **`402 Payment Required`** - `payment_required`: the organization has no payment method on file, or has an unpaid invoice. **`403 Forbidden`** - `forbidden`: the credential does not grant access to this API, or the organization is not permitted to use it. **`404 Not Found`** - `not_found`: no run with this ID exists in your organization. **`413 Content Too Large`** - `payload_too_large`: the request body is larger than 25,000,000 bytes: for a decisions request, its `request` and `file` parts together. **`415 Unsupported Media Type`** - `unsupported_media_type`: the request body is not `multipart/form-data` for a decisions request, or not `application/json` for an input tokens request. **`500 Internal Server Error`** - `internal_error`: an unexpected error occurred on the server. Retry the request; if it keeps failing, contact support, quoting the `request_id`. **`503 Service Unavailable`** - `server_busy`: the service is at capacity. Retry after the number of seconds in the `Retry-After` header.
  - Allowed values: `message_invalid`, `question_invalid`, `audio_decode_failed`, `audio_format_unsupported`, `audio_too_short`, `audio_too_long`, `invalid_request`, `payment_required`, `forbidden`, `not_found`, `payload_too_large`, `unsupported_media_type`, `internal_error`, `server_busy`
- `message` (string, required) — A description of the problem for a person. Its wording may change, so switch on `code`.
- `request_id` (string, required) — The ID of the request that failed. Quote it when contacting support.
- `param` (string, optional) — Where the error was found: a JSON Pointer into the `request` part or the input tokens body, or the name of a part or header. For a field that is missing, unknown or of the wrong type, it can name an enclosing object, such as the question, instead of the field. Omitted when the error has no narrower location than the whole request.

### 401 Unauthorized Error

The request carried no valid credential. Check the API key you sent.

- `message` (string, required) — A description of the problem for a person.
- `request_id` (string, optional) — The ID of the request. A `401` carries it only when an API key was rejected, and a `429` never does.

### 402 Payment Required Error

The organization has no payment method on file, or has an unpaid invoice. An admin can update its payment method in the Hume Cloud portal.

- `type` ("error", required) — The type of the object. Always `error`.
- `code` (enum, required) — What went wrong, grouped by the HTTP status it is returned with. **`400 Bad Request`**: something in the request needs correcting. - `message_invalid`: the request body is malformed or does not match the schema outside a question, for example because a decisions request has no `request` part, or no `file` part or more than one, or an input tokens request has no `audio_duration_ms`. - `question_invalid`: a question is invalid, including when it does not match the schema, for example because it has duplicate option names or fewer than two options. - `audio_decode_failed`: the audio file could not be decoded. - `audio_format_unsupported`: the audio file is not MP3 or WAV. - `audio_too_short`: the audio is shorter than 5 seconds, or `audio_duration_ms` is under 5000. - `audio_too_long`: the audio is longer than 5 minutes, or `audio_duration_ms` is over 300000. - `invalid_request`: a query parameter has a value the endpoint does not accept, or `cursor` is not one the endpoint issued. List runs only. **`402 Payment Required`** - `payment_required`: the organization has no payment method on file, or has an unpaid invoice. **`403 Forbidden`** - `forbidden`: the credential does not grant access to this API, or the organization is not permitted to use it. **`404 Not Found`** - `not_found`: no run with this ID exists in your organization. **`413 Content Too Large`** - `payload_too_large`: the request body is larger than 25,000,000 bytes: for a decisions request, its `request` and `file` parts together. **`415 Unsupported Media Type`** - `unsupported_media_type`: the request body is not `multipart/form-data` for a decisions request, or not `application/json` for an input tokens request. **`500 Internal Server Error`** - `internal_error`: an unexpected error occurred on the server. Retry the request; if it keeps failing, contact support, quoting the `request_id`. **`503 Service Unavailable`** - `server_busy`: the service is at capacity. Retry after the number of seconds in the `Retry-After` header.
  - Allowed values: `message_invalid`, `question_invalid`, `audio_decode_failed`, `audio_format_unsupported`, `audio_too_short`, `audio_too_long`, `invalid_request`, `payment_required`, `forbidden`, `not_found`, `payload_too_large`, `unsupported_media_type`, `internal_error`, `server_busy`
- `message` (string, required) — A description of the problem for a person. Its wording may change, so switch on `code`.
- `request_id` (string, required) — The ID of the request that failed. Quote it when contacting support.
- `param` (string, optional) — Where the error was found: a JSON Pointer into the `request` part or the input tokens body, or the name of a part or header. For a field that is missing, unknown or of the wrong type, it can name an enclosing object, such as the question, instead of the field. Omitted when the error has no narrower location than the whole request.

### 403 Forbidden Error

The credential does not grant access to this API, or the organization is not permitted to use it. Contact support to request access.

- `type` ("error", required) — The type of the object. Always `error`.
- `code` (enum, required) — What went wrong, grouped by the HTTP status it is returned with. **`400 Bad Request`**: something in the request needs correcting. - `message_invalid`: the request body is malformed or does not match the schema outside a question, for example because a decisions request has no `request` part, or no `file` part or more than one, or an input tokens request has no `audio_duration_ms`. - `question_invalid`: a question is invalid, including when it does not match the schema, for example because it has duplicate option names or fewer than two options. - `audio_decode_failed`: the audio file could not be decoded. - `audio_format_unsupported`: the audio file is not MP3 or WAV. - `audio_too_short`: the audio is shorter than 5 seconds, or `audio_duration_ms` is under 5000. - `audio_too_long`: the audio is longer than 5 minutes, or `audio_duration_ms` is over 300000. - `invalid_request`: a query parameter has a value the endpoint does not accept, or `cursor` is not one the endpoint issued. List runs only. **`402 Payment Required`** - `payment_required`: the organization has no payment method on file, or has an unpaid invoice. **`403 Forbidden`** - `forbidden`: the credential does not grant access to this API, or the organization is not permitted to use it. **`404 Not Found`** - `not_found`: no run with this ID exists in your organization. **`413 Content Too Large`** - `payload_too_large`: the request body is larger than 25,000,000 bytes: for a decisions request, its `request` and `file` parts together. **`415 Unsupported Media Type`** - `unsupported_media_type`: the request body is not `multipart/form-data` for a decisions request, or not `application/json` for an input tokens request. **`500 Internal Server Error`** - `internal_error`: an unexpected error occurred on the server. Retry the request; if it keeps failing, contact support, quoting the `request_id`. **`503 Service Unavailable`** - `server_busy`: the service is at capacity. Retry after the number of seconds in the `Retry-After` header.
  - Allowed values: `message_invalid`, `question_invalid`, `audio_decode_failed`, `audio_format_unsupported`, `audio_too_short`, `audio_too_long`, `invalid_request`, `payment_required`, `forbidden`, `not_found`, `payload_too_large`, `unsupported_media_type`, `internal_error`, `server_busy`
- `message` (string, required) — A description of the problem for a person. Its wording may change, so switch on `code`.
- `request_id` (string, required) — The ID of the request that failed. Quote it when contacting support.
- `param` (string, optional) — Where the error was found: a JSON Pointer into the `request` part or the input tokens body, or the name of a part or header. For a field that is missing, unknown or of the wrong type, it can name an enclosing object, such as the question, instead of the field. Omitted when the error has no narrower location than the whole request.

### 413 Content Too Large Error

The request body, `request` and `file` parts together, is larger than 25,000,000 bytes.

- `type` ("error", required) — The type of the object. Always `error`.
- `code` (enum, required) — What went wrong, grouped by the HTTP status it is returned with. **`400 Bad Request`**: something in the request needs correcting. - `message_invalid`: the request body is malformed or does not match the schema outside a question, for example because a decisions request has no `request` part, or no `file` part or more than one, or an input tokens request has no `audio_duration_ms`. - `question_invalid`: a question is invalid, including when it does not match the schema, for example because it has duplicate option names or fewer than two options. - `audio_decode_failed`: the audio file could not be decoded. - `audio_format_unsupported`: the audio file is not MP3 or WAV. - `audio_too_short`: the audio is shorter than 5 seconds, or `audio_duration_ms` is under 5000. - `audio_too_long`: the audio is longer than 5 minutes, or `audio_duration_ms` is over 300000. - `invalid_request`: a query parameter has a value the endpoint does not accept, or `cursor` is not one the endpoint issued. List runs only. **`402 Payment Required`** - `payment_required`: the organization has no payment method on file, or has an unpaid invoice. **`403 Forbidden`** - `forbidden`: the credential does not grant access to this API, or the organization is not permitted to use it. **`404 Not Found`** - `not_found`: no run with this ID exists in your organization. **`413 Content Too Large`** - `payload_too_large`: the request body is larger than 25,000,000 bytes: for a decisions request, its `request` and `file` parts together. **`415 Unsupported Media Type`** - `unsupported_media_type`: the request body is not `multipart/form-data` for a decisions request, or not `application/json` for an input tokens request. **`500 Internal Server Error`** - `internal_error`: an unexpected error occurred on the server. Retry the request; if it keeps failing, contact support, quoting the `request_id`. **`503 Service Unavailable`** - `server_busy`: the service is at capacity. Retry after the number of seconds in the `Retry-After` header.
  - Allowed values: `message_invalid`, `question_invalid`, `audio_decode_failed`, `audio_format_unsupported`, `audio_too_short`, `audio_too_long`, `invalid_request`, `payment_required`, `forbidden`, `not_found`, `payload_too_large`, `unsupported_media_type`, `internal_error`, `server_busy`
- `message` (string, required) — A description of the problem for a person. Its wording may change, so switch on `code`.
- `request_id` (string, required) — The ID of the request that failed. Quote it when contacting support.
- `param` (string, optional) — Where the error was found: a JSON Pointer into the `request` part or the input tokens body, or the name of a part or header. For a field that is missing, unknown or of the wrong type, it can name an enclosing object, such as the question, instead of the field. Omitted when the error has no narrower location than the whole request.

### 415 Unsupported Media Type Error

The request body is not `multipart/form-data`.

- `type` ("error", required) — The type of the object. Always `error`.
- `code` (enum, required) — What went wrong, grouped by the HTTP status it is returned with. **`400 Bad Request`**: something in the request needs correcting. - `message_invalid`: the request body is malformed or does not match the schema outside a question, for example because a decisions request has no `request` part, or no `file` part or more than one, or an input tokens request has no `audio_duration_ms`. - `question_invalid`: a question is invalid, including when it does not match the schema, for example because it has duplicate option names or fewer than two options. - `audio_decode_failed`: the audio file could not be decoded. - `audio_format_unsupported`: the audio file is not MP3 or WAV. - `audio_too_short`: the audio is shorter than 5 seconds, or `audio_duration_ms` is under 5000. - `audio_too_long`: the audio is longer than 5 minutes, or `audio_duration_ms` is over 300000. - `invalid_request`: a query parameter has a value the endpoint does not accept, or `cursor` is not one the endpoint issued. List runs only. **`402 Payment Required`** - `payment_required`: the organization has no payment method on file, or has an unpaid invoice. **`403 Forbidden`** - `forbidden`: the credential does not grant access to this API, or the organization is not permitted to use it. **`404 Not Found`** - `not_found`: no run with this ID exists in your organization. **`413 Content Too Large`** - `payload_too_large`: the request body is larger than 25,000,000 bytes: for a decisions request, its `request` and `file` parts together. **`415 Unsupported Media Type`** - `unsupported_media_type`: the request body is not `multipart/form-data` for a decisions request, or not `application/json` for an input tokens request. **`500 Internal Server Error`** - `internal_error`: an unexpected error occurred on the server. Retry the request; if it keeps failing, contact support, quoting the `request_id`. **`503 Service Unavailable`** - `server_busy`: the service is at capacity. Retry after the number of seconds in the `Retry-After` header.
  - Allowed values: `message_invalid`, `question_invalid`, `audio_decode_failed`, `audio_format_unsupported`, `audio_too_short`, `audio_too_long`, `invalid_request`, `payment_required`, `forbidden`, `not_found`, `payload_too_large`, `unsupported_media_type`, `internal_error`, `server_busy`
- `message` (string, required) — A description of the problem for a person. Its wording may change, so switch on `code`.
- `request_id` (string, required) — The ID of the request that failed. Quote it when contacting support.
- `param` (string, optional) — Where the error was found: a JSON Pointer into the `request` part or the input tokens body, or the name of a part or header. For a field that is missing, unknown or of the wrong type, it can name an enclosing object, such as the question, instead of the field. Omitted when the error has no narrower location than the whole request.

### 429 Too Many Requests Error

The request exceeds a rate limit for the account. Hume's API gateway answers it before the request reaches the service, so its body has no `code`. Retry after the number of seconds in the `Retry-After` header.

- `message` (string, required) — A description of the problem for a person.
- `request_id` (string, optional) — The ID of the request. A `401` carries it only when an API key was rejected, and a `429` never does.

### 500 Internal Server Error

An unexpected error occurred on the server. Retry the request, and if it keeps failing, contact support with the `request_id`.

- `type` ("error", required) — The type of the object. Always `error`.
- `code` (enum, required) — What went wrong, grouped by the HTTP status it is returned with. **`400 Bad Request`**: something in the request needs correcting. - `message_invalid`: the request body is malformed or does not match the schema outside a question, for example because a decisions request has no `request` part, or no `file` part or more than one, or an input tokens request has no `audio_duration_ms`. - `question_invalid`: a question is invalid, including when it does not match the schema, for example because it has duplicate option names or fewer than two options. - `audio_decode_failed`: the audio file could not be decoded. - `audio_format_unsupported`: the audio file is not MP3 or WAV. - `audio_too_short`: the audio is shorter than 5 seconds, or `audio_duration_ms` is under 5000. - `audio_too_long`: the audio is longer than 5 minutes, or `audio_duration_ms` is over 300000. - `invalid_request`: a query parameter has a value the endpoint does not accept, or `cursor` is not one the endpoint issued. List runs only. **`402 Payment Required`** - `payment_required`: the organization has no payment method on file, or has an unpaid invoice. **`403 Forbidden`** - `forbidden`: the credential does not grant access to this API, or the organization is not permitted to use it. **`404 Not Found`** - `not_found`: no run with this ID exists in your organization. **`413 Content Too Large`** - `payload_too_large`: the request body is larger than 25,000,000 bytes: for a decisions request, its `request` and `file` parts together. **`415 Unsupported Media Type`** - `unsupported_media_type`: the request body is not `multipart/form-data` for a decisions request, or not `application/json` for an input tokens request. **`500 Internal Server Error`** - `internal_error`: an unexpected error occurred on the server. Retry the request; if it keeps failing, contact support, quoting the `request_id`. **`503 Service Unavailable`** - `server_busy`: the service is at capacity. Retry after the number of seconds in the `Retry-After` header.
  - Allowed values: `message_invalid`, `question_invalid`, `audio_decode_failed`, `audio_format_unsupported`, `audio_too_short`, `audio_too_long`, `invalid_request`, `payment_required`, `forbidden`, `not_found`, `payload_too_large`, `unsupported_media_type`, `internal_error`, `server_busy`
- `message` (string, required) — A description of the problem for a person. Its wording may change, so switch on `code`.
- `request_id` (string, required) — The ID of the request that failed. Quote it when contacting support.
- `param` (string, optional) — Where the error was found: a JSON Pointer into the `request` part or the input tokens body, or the name of a part or header. For a field that is missing, unknown or of the wrong type, it can name an enclosing object, such as the question, instead of the field. Omitted when the error has no narrower location than the whole request.

### 503 Service Unavailable Error

The service is at capacity. Retry after the number of seconds in the `Retry-After` header.

- `type` ("error", required) — The type of the object. Always `error`.
- `code` (enum, required) — What went wrong, grouped by the HTTP status it is returned with. **`400 Bad Request`**: something in the request needs correcting. - `message_invalid`: the request body is malformed or does not match the schema outside a question, for example because a decisions request has no `request` part, or no `file` part or more than one, or an input tokens request has no `audio_duration_ms`. - `question_invalid`: a question is invalid, including when it does not match the schema, for example because it has duplicate option names or fewer than two options. - `audio_decode_failed`: the audio file could not be decoded. - `audio_format_unsupported`: the audio file is not MP3 or WAV. - `audio_too_short`: the audio is shorter than 5 seconds, or `audio_duration_ms` is under 5000. - `audio_too_long`: the audio is longer than 5 minutes, or `audio_duration_ms` is over 300000. - `invalid_request`: a query parameter has a value the endpoint does not accept, or `cursor` is not one the endpoint issued. List runs only. **`402 Payment Required`** - `payment_required`: the organization has no payment method on file, or has an unpaid invoice. **`403 Forbidden`** - `forbidden`: the credential does not grant access to this API, or the organization is not permitted to use it. **`404 Not Found`** - `not_found`: no run with this ID exists in your organization. **`413 Content Too Large`** - `payload_too_large`: the request body is larger than 25,000,000 bytes: for a decisions request, its `request` and `file` parts together. **`415 Unsupported Media Type`** - `unsupported_media_type`: the request body is not `multipart/form-data` for a decisions request, or not `application/json` for an input tokens request. **`500 Internal Server Error`** - `internal_error`: an unexpected error occurred on the server. Retry the request; if it keeps failing, contact support, quoting the `request_id`. **`503 Service Unavailable`** - `server_busy`: the service is at capacity. Retry after the number of seconds in the `Retry-After` header.
  - Allowed values: `message_invalid`, `question_invalid`, `audio_decode_failed`, `audio_format_unsupported`, `audio_too_short`, `audio_too_long`, `invalid_request`, `payment_required`, `forbidden`, `not_found`, `payload_too_large`, `unsupported_media_type`, `internal_error`, `server_busy`
- `message` (string, required) — A description of the problem for a person. Its wording may change, so switch on `code`.
- `request_id` (string, required) — The ID of the request that failed. Quote it when contacting support.
- `param` (string, optional) — Where the error was found: a JSON Pointer into the `request` part or the input tokens body, or the name of a part or header. For a field that is missing, unknown or of the wrong type, it can name an enclosing object, such as the question, instead of the field. Omitted when the error has no narrower location than the whole request.

## Types

### Answer

The answer to one question. `type` names the question's primitive and determines the answer's fields. Treat an unrecognized `type` as unknown rather than as an error.

- `type`: `noul` (noul answer)
  - `noul` (double, required) — The estimated share of human raters who would answer yes, from 0 to 1. A value near 0.5 means raters would split, not that the model is unsure.
- `type`: `choice` (choice answer)
  - `choice` (string, required) — The name of the option with the highest probability.
  - `confidence` (double, required) — How much human raters would agree, from 0 when every option is equally likely to 1 when all probability is on one option.
  - `probabilities` (map from string to double, required) — The probability of each option, keyed by option name. Each estimates the share of human raters who would choose the option, and together they sum to 1, within rounding.
- `type`: `score` (score answer)
  - `confidence` (double, required) — How much human raters would agree, from 0 when the probabilities are at least as spread out as a uniform distribution to 1 when all probability is on one level.
  - `legend` (map from string to string, required) — The text of each level, as given in the question's `criteria`, keyed by level index like `probabilities`, so a score can be read without relying on the key order of a JSON object.
  - `probabilities` (map from string to double, required) — The probability of each level, keyed by level index as a string. Each estimates the share of human raters who would choose the level, and together they sum to 1, within rounding.
  - `score` (double, required) — The probability-weighted mean of the level indices, from 0 to the index of the highest level.
- `type`: `span` (span answer)
  - `spans` (list of Span, required) — The spans where the described event may occur, in order of `audio_start_ms`. Overlapping candidates are merged. An empty array means the event was not found.

### Received

What the model received for a decisions request, which is what the request is billed.

- `input_tokens` (integer, required) — The input tokens this request is billed. `POST /v0/decisions/file/input_tokens` estimates them before a request is sent.

### Span

A span where the described event may occur.

- `audio_start_ms` (integer, required) — Where the span begins, in milliseconds from the start of the audio file.
- `audio_end_ms` (integer, required) — Where the span ends, in milliseconds from the start of the audio file.
- `probability` (double, required) — The probability that the event occurs in the span.

## Examples

### Voice agent QA

**Request**

```json
{
  "file": "<file: <file1>>",
  "request": {
    "questions": {
      "agent_glitches": {
        "type": "span",
        "instructions": "Where does the agent glitch, slur or sound robotic?"
      },
      "agent_naturalness": {
        "type": "score",
        "criteria": [
          "Not at all",
          "2",
          "3",
          "4",
          "Extremely"
        ],
        "instructions": "How natural does the agent sound?"
      },
      "agent_tone": {
        "type": "choice",
        "criteria": [
          {
            "name": "warm",
            "description": "Warm and friendly toward the caller"
          },
          {
            "name": "neutral",
            "description": "Polite but impersonal"
          },
          {
            "name": "curt",
            "description": "Short or dismissive with the caller"
          }
        ],
        "instructions": "Which best describes the tone of the agent?"
      },
      "talks_over_caller": {
        "type": "noul",
        "instructions": "Does the agent talk over the caller?"
      }
    },
    "context": "A simulated test call in which a voice AI agent helps a caller reschedule an appointment. Both voices are synthetic, and the agent speaks first."
  }
}
```

**Response**

```json
{
  "run_id": "019a1f3c-7d2e-7b41-9c58-2e6f4a1d8b03",
  "answers": {
    "agent_glitches": {
      "type": "span",
      "spans": [
        {
          "audio_start_ms": 38120,
          "audio_end_ms": 38940,
          "probability": 0.7734
        },
        {
          "audio_start_ms": 97510,
          "audio_end_ms": 98260,
          "probability": 0.5182
        }
      ]
    },
    "agent_naturalness": {
      "type": "score",
      "confidence": 0.4229,
      "legend": {
        "0": "Not at all",
        "1": "2",
        "2": "3",
        "3": "4",
        "4": "Extremely"
      },
      "probabilities": {
        "0": 0.0218,
        "1": 0.0874,
        "2": 0.2463,
        "3": 0.4385,
        "4": 0.206
      },
      "score": 2.7195
    },
    "agent_tone": {
      "type": "choice",
      "choice": "warm",
      "confidence": 0.3072,
      "probabilities": {
        "curt": 0.0693,
        "neutral": 0.3926,
        "warm": 0.5381
      }
    },
    "talks_over_caller": {
      "type": "noul",
      "noul": 0.1274
    }
  },
  "received": {
    "input_tokens": 11683
  }
}
```

**SDK Code**

```python Voice agent QA
from hume_audio_decisions import (
    Criterion,
    DecisionsClient,
    DecisionsRequest,
    Question_Choice,
    Question_Noul,
    Question_Score,
    Question_Span,
)

client = DecisionsClient(
    api_key="YOUR_API_KEY_HERE",
)

with open("test_call.wav", "rb") as audio:
    client.decisions.create(
        file=("test_call.wav", audio, "audio/wav"),
        request=DecisionsRequest(
            context="A simulated test call in which a voice AI agent helps a caller reschedule an appointment. Both voices are synthetic, and the agent speaks first.",
            questions={
                "talks_over_caller": Question_Noul(
                    instructions="Does the agent talk over the caller?",
                ),
                "agent_tone": Question_Choice(
                    instructions="Which best describes the tone of the agent?",
                    criteria=[
                        Criterion(
                            name="warm",
                            description="Warm and friendly toward the caller",
                        ),
                        Criterion(
                            name="neutral",
                            description="Polite but impersonal",
                        ),
                        Criterion(
                            name="curt",
                            description="Short or dismissive with the caller",
                        ),
                    ],
                ),
                "agent_naturalness": Question_Score(
                    instructions="How natural does the agent sound?",
                    criteria=["Not at all", "2", "3", "4", "Extremely"],
                ),
                "agent_glitches": Question_Span(
                    instructions="Where does the agent glitch, slur or sound robotic?",
                ),
            },
        ),
    )
```

```typescript Voice agent QA
import { DecisionsClient } from "@humeai/audio-decisions";

async function main() {
    const client = new DecisionsClient({
        apiKey: "YOUR_API_KEY_HERE",
    });
    await client.decisions.create({
        file: {
            path: "test_call.wav",
            contentType: "audio/wav",
        },
        request: {
            context: "A simulated test call in which a voice AI agent helps a caller reschedule an appointment. Both voices are synthetic, and the agent speaks first.",
            questions: {
                talks_over_caller: {
                    type: "noul",
                    instructions: "Does the agent talk over the caller?",
                },
                agent_tone: {
                    type: "choice",
                    instructions: "Which best describes the tone of the agent?",
                    criteria: [
                        {
                            name: "warm",
                            description: "Warm and friendly toward the caller",
                        },
                        {
                            name: "neutral",
                            description: "Polite but impersonal",
                        },
                        {
                            name: "curt",
                            description: "Short or dismissive with the caller",
                        },
                    ],
                },
                agent_naturalness: {
                    type: "score",
                    instructions: "How natural does the agent sound?",
                    criteria: ["Not at all", "2", "3", "4", "Extremely"],
                },
                agent_glitches: {
                    type: "span",
                    instructions: "Where does the agent glitch, slur or sound robotic?",
                },
            },
        },
    });
}
main();
```

### TTS prompt adherence (noul)

**Request**

```json
{
  "file": "<file: <file1>>",
  "request": {
    "questions": {
      "whispered": {
        "type": "noul",
        "instructions": "Is the voice whispering?"
      }
    },
    "context": "Speech generated by an instruction-following text-to-speech model. The prompt asked for a whispered read."
  }
}
```

**Response**

```json
{
  "run_id": "019a1f41-2b6c-7e05-8a3d-71c9e0b54f26",
  "answers": {
    "whispered": {
      "type": "noul",
      "noul": 0.9312
    }
  },
  "received": {
    "input_tokens": 556
  }
}
```

**SDK Code**

```python TTS prompt adherence (noul)
from hume_audio_decisions import DecisionsClient, DecisionsRequest, Question_Noul

client = DecisionsClient(
    api_key="YOUR_API_KEY_HERE",
)

with open("whisper.wav", "rb") as audio:
    client.decisions.create(
        file=("whisper.wav", audio, "audio/wav"),
        request=DecisionsRequest(
            context="Speech generated by an instruction-following text-to-speech model. The prompt asked for a whispered read.",
            questions={
                "whispered": Question_Noul(
                    instructions="Is the voice whispering?",
                ),
            },
        ),
    )
```

```typescript TTS prompt adherence (noul)
import { DecisionsClient } from "@humeai/audio-decisions";

async function main() {
    const client = new DecisionsClient({
        apiKey: "YOUR_API_KEY_HERE",
    });
    await client.decisions.create({
        file: {
            path: "whisper.wav",
            contentType: "audio/wav",
        },
        request: {
            context: "Speech generated by an instruction-following text-to-speech model. The prompt asked for a whispered read.",
            questions: {
                whispered: {
                    type: "noul",
                    instructions: "Is the voice whispering?",
                },
            },
        },
    });
}
main();
```

### Speech emotion labeling (choice)

**Request**

```json
{
  "file": "<file: <file1>>",
  "request": {
    "questions": {
      "emotion": {
        "type": "choice",
        "criteria": [
          {
            "name": "happiness",
            "description": "Happiness or amusement"
          },
          {
            "name": "sadness",
            "description": "Sadness or grief"
          },
          {
            "name": "anger",
            "description": "Anger, whether shouted or held back"
          },
          {
            "name": "fear",
            "description": "Fear or anxiety"
          },
          {
            "name": "neutral",
            "description": "No clear emotion"
          }
        ],
        "instructions": "Which emotion does the speaker convey?"
      }
    },
    "context": "A clip from a licensed corpus of scripted speech by consenting voice actors, being labeled to train an expressive text-to-speech model."
  }
}
```

**Response**

```json
{
  "run_id": "019a1f45-c918-7a72-b6e4-0d3f8a2c7e91",
  "answers": {
    "emotion": {
      "type": "choice",
      "choice": "sadness",
      "confidence": 0.642,
      "probabilities": {
        "anger": 0.0587,
        "fear": 0.1243,
        "happiness": 0.0412,
        "neutral": 0.0622,
        "sadness": 0.7136
      }
    }
  },
  "received": {
    "input_tokens": 525
  }
}
```

**SDK Code**

```python Speech emotion labeling (choice)
from hume_audio_decisions import (
    Criterion,
    DecisionsClient,
    DecisionsRequest,
    Question_Choice,
)

client = DecisionsClient(
    api_key="YOUR_API_KEY_HERE",
)

with open("clip.wav", "rb") as audio:
    client.decisions.create(
        file=("clip.wav", audio, "audio/wav"),
        request=DecisionsRequest(
            context="A clip from a licensed corpus of scripted speech by consenting voice actors, being labeled to train an expressive text-to-speech model.",
            questions={
                "emotion": Question_Choice(
                    instructions="Which emotion does the speaker convey?",
                    criteria=[
                        Criterion(
                            name="happiness",
                            description="Happiness or amusement",
                        ),
                        Criterion(
                            name="sadness",
                            description="Sadness or grief",
                        ),
                        Criterion(
                            name="anger",
                            description="Anger, whether shouted or held back",
                        ),
                        Criterion(
                            name="fear",
                            description="Fear or anxiety",
                        ),
                        Criterion(
                            name="neutral",
                            description="No clear emotion",
                        ),
                    ],
                ),
            },
        ),
    )
```

```typescript Speech emotion labeling (choice)
import { DecisionsClient } from "@humeai/audio-decisions";

async function main() {
    const client = new DecisionsClient({
        apiKey: "YOUR_API_KEY_HERE",
    });
    await client.decisions.create({
        file: {
            path: "clip.wav",
            contentType: "audio/wav",
        },
        request: {
            context: "A clip from a licensed corpus of scripted speech by consenting voice actors, being labeled to train an expressive text-to-speech model.",
            questions: {
                emotion: {
                    type: "choice",
                    instructions: "Which emotion does the speaker convey?",
                    criteria: [
                        {
                            name: "happiness",
                            description: "Happiness or amusement",
                        },
                        {
                            name: "sadness",
                            description: "Sadness or grief",
                        },
                        {
                            name: "anger",
                            description: "Anger, whether shouted or held back",
                        },
                        {
                            name: "fear",
                            description: "Fear or anxiety",
                        },
                        {
                            name: "neutral",
                            description: "No clear emotion",
                        },
                    ],
                },
            },
        },
    });
}
main();
```

### TTS naturalness benchmark (score)

**Request**

```json
{
  "file": "<file: <file1>>",
  "request": {
    "questions": {
      "naturalness": {
        "type": "score",
        "criteria": [
          "Not at all",
          "2",
          "3",
          "4",
          "Extremely"
        ],
        "instructions": "How natural does the voice sound?"
      }
    },
    "context": "Output from a text-to-speech model under evaluation, reading a product announcement."
  }
}
```

**Response**

```json
{
  "run_id": "019a1f4a-5e03-7d1b-a2f7-9b4c6e1d3a58",
  "answers": {
    "naturalness": {
      "type": "score",
      "confidence": 0.4503,
      "legend": {
        "0": "Not at all",
        "1": "2",
        "2": "3",
        "3": "4",
        "4": "Extremely"
      },
      "probabilities": {
        "0": 0.0186,
        "1": 0.0642,
        "2": 0.1873,
        "3": 0.4417,
        "4": 0.2882
      },
      "score": 2.9167
    }
  },
  "received": {
    "input_tokens": 725
  }
}
```

**SDK Code**

```python TTS naturalness benchmark (score)
from hume_audio_decisions import DecisionsClient, DecisionsRequest, Question_Score

client = DecisionsClient(
    api_key="YOUR_API_KEY_HERE",
)

with open("voice.wav", "rb") as audio:
    client.decisions.create(
        file=("voice.wav", audio, "audio/wav"),
        request=DecisionsRequest(
            context="Output from a text-to-speech model under evaluation, reading a product announcement.",
            questions={
                "naturalness": Question_Score(
                    instructions="How natural does the voice sound?",
                    criteria=["Not at all", "2", "3", "4", "Extremely"],
                ),
            },
        ),
    )
```

```typescript TTS naturalness benchmark (score)
import { DecisionsClient } from "@humeai/audio-decisions";

async function main() {
    const client = new DecisionsClient({
        apiKey: "YOUR_API_KEY_HERE",
    });
    await client.decisions.create({
        file: {
            path: "voice.wav",
            contentType: "audio/wav",
        },
        request: {
            context: "Output from a text-to-speech model under evaluation, reading a product announcement.",
            questions: {
                naturalness: {
                    type: "score",
                    instructions: "How natural does the voice sound?",
                    criteria: ["Not at all", "2", "3", "4", "Extremely"],
                },
            },
        },
    });
}
main();
```

### Vocal burst annotation (span)

**Request**

```json
{
  "file": "<file: <file1>>",
  "request": {
    "questions": {
      "vocal_bursts": {
        "type": "span",
        "instructions": "Where does the speaker laugh, sigh, gasp or make another vocal burst?"
      }
    },
    "context": "A clip from a licensed corpus of scripted speech by consenting voice actors, being labeled to train an expressive text-to-speech model."
  }
}
```

**Response**

```json
{
  "run_id": "019a1f4e-8f71-7c26-9d0a-4e5b2f7c1b64",
  "answers": {
    "vocal_bursts": {
      "type": "span",
      "spans": [
        {
          "audio_start_ms": 9840,
          "audio_end_ms": 10630,
          "probability": 0.9127
        },
        {
          "audio_start_ms": 27450,
          "audio_end_ms": 28390,
          "probability": 0.8364
        },
        {
          "audio_start_ms": 41020,
          "audio_end_ms": 41380,
          "probability": 0.3518
        }
      ]
    }
  },
  "received": {
    "input_tokens": 3821
  }
}
```

**SDK Code**

```python Vocal burst annotation (span)
from hume_audio_decisions import DecisionsClient, DecisionsRequest, Question_Span

client = DecisionsClient(
    api_key="YOUR_API_KEY_HERE",
)

with open("clip.wav", "rb") as audio:
    client.decisions.create(
        file=("clip.wav", audio, "audio/wav"),
        request=DecisionsRequest(
            context="A clip from a licensed corpus of scripted speech by consenting voice actors, being labeled to train an expressive text-to-speech model.",
            questions={
                "vocal_bursts": Question_Span(
                    instructions="Where does the speaker laugh, sigh, gasp or make another vocal burst?",
                ),
            },
        ),
    )
```

```typescript Vocal burst annotation (span)
import { DecisionsClient } from "@humeai/audio-decisions";

async function main() {
    const client = new DecisionsClient({
        apiKey: "YOUR_API_KEY_HERE",
    });
    await client.decisions.create({
        file: {
            path: "clip.wav",
            contentType: "audio/wav",
        },
        request: {
            context: "A clip from a licensed corpus of scripted speech by consenting voice actors, being labeled to train an expressive text-to-speech model.",
            questions: {
                vocal_bursts: {
                    type: "span",
                    instructions: "Where does the speaker laugh, sigh, gasp or make another vocal burst?",
                },
            },
        },
    });
}
main();
```