---
title: Response Schema
description: Shape of job objects, summaries, signals, and audio quality.
type: doc
icon: braces
sidebar:
  label: Response Schema
  order: 2
  icon: braces
search:
  tags: [results]
---
The Amplifier API produces two response shapes:

- **Model jobs** (`POST /v2/models/{model_name}/analyze`) — multi-sign result with a `summary` wrapper, a `signals[]` array, `audio_quality`, and `extended_metrics`. See [Model API](/reference/models).
- **Sign jobs** (`POST /v2/signs/{sign_name}/analyze`) — single-signal result with a singular `signal` object and `audio_quality`. See [Sign API](/reference/signs).

Both endpoints return the full job object immediately (`job_id`, `status: queued`, `result: null`). Retrieve the completed result with `GET /v2/jobs/{job_id}`, or receive it via webhook.

When a request fails, the API returns a JSON object with `code`, `message`, and `status` — see [Errors](/reference/errors).

For workflow and display rules, see [Interpreting Results](/guides/interpreting-results).

## Model response

Analyze submit and `GET /v2/jobs/{job_id}` share the same job envelope. At submit time `status` is `queued` and `result` is `null`. The table below is the canonical field list.

### Job response

`GET /v2/jobs/{job_id}` returns the job status and, when complete, the full analysis result.

| Field | Type | Description |
|---|---|---|
| `job_id` | string | Unique job identifier. |
| `status` | string | Job status: `queued`, `running`, `done`, `failed`, or `timed-out`. See [Enumerations](/reference/enumerations#job-status). |
| `created_at` | string | ISO 8601; fractional seconds and timezone designator vary. See [Timestamps](#timestamps). |
| `completed_at` | string or null | ISO 8601; null while `queued` or `running`. Semantics for `done` versus `failed` and `timed-out`: [Timestamps](#timestamps) and [Job status: failed](#job-status-failed). |
| `job_type` | string | `"model"` or `"sign"`. |
| `api_version` | string | `"v2"`. |
| `audio_content_type` | string | MIME type of the submitted audio. |
| `audio_size_bytes` | integer | Size in bytes of the submitted audio as accepted and processed for this job. |
| `audio_duration_seconds` | number | Duration of the submitted audio in seconds. |
| `audio_sample_rate` | integer or null | Sample rate in Hz. |
| `model_name` | string or null | Named model (e.g. `"pulse"`) when this is a model job; otherwise `null`. |
| `sign_name` | string or null | Named sign (e.g. `"stress"`) when this is a sign job; otherwise `null`. |
| `result` | object or null | Full analysis when `status` is `done`. When `failed` or `timed-out`, typically `null`. See [Job status: failed](#job-status-failed). |

Both `model_name` and `sign_name` may appear on the same object. Treat the unused discriminator as `null`; do not require it to be omitted.

> **Note**
> `status` is one of `queued`, `running`, `done`, `failed`, or `timed-out`. Nullable fields — `completed_at`, `result`, `audio_sample_rate`, and the unused discriminator — may be `null`.

`result` contains:

| Field | Type | Description |
|---|---|---|
| `summary` | object | Aggregated result across all signals. |
| `signals` | array | Per-sign results, one entry per sign in the model bundle. |
| `audio_quality` | object | Recording quality scores and detected issue codes. |
| `extended_metrics` | array | Per-metric wellness scores for the model. Empty array when no metrics are configured. |

```json
{
  "job_id": "189bce4a-52cb-4e60-8586-cef89e719109",
  "status": "done",
  "created_at": "2026-02-22T09:14:00Z",
  "completed_at": "2026-02-22T09:14:03Z",
  "job_type": "model",
  "api_version": "v2",
  "model_name": "pulse",
  "sign_name": null,
  "audio_content_type": "audio/wav",
  "audio_size_bytes": 876032,
  "audio_duration_seconds": 27.4,
  "result": {
    "summary": { ... },
    "signals": [ ... ],
    "audio_quality": { ... },
    "extended_metrics": [ ... ]
  }
}
```

### Timestamps

**Type:** `created_at` and `completed_at` are ISO 8601 datetimes; RFC 3339–compatible parsing is recommended.

**Variability:** The API may return:

- A timezone designator: `Z` (UTC) or numeric offset `±hh:mm`, or omit the designator in some responses.
- Fractional seconds at variable precision (milliseconds, microseconds, and so on).

**UTC:** Values with a `Z` suffix are UTC. When no offset appears, treat the timestamp as UTC.

**Client guidance:** Use a standard ISO 8601-compatible datetime parser. Prefer parsing over string comparison, and allow for a varying number of fractional digits.

Both of these forms are valid.

With `Z`, no fractional seconds:

```json
"created_at": "2026-02-22T09:14:00Z",
"completed_at": "2026-02-22T09:14:03Z"
```

With fractional seconds, no `Z`:

```json
"created_at": "2026-03-28T01:05:35.943000",
"completed_at": "2026-03-28T01:05:38.120500"
```

### Job status: failed

This section covers both terminal outcomes that end without a result: `failed` and `timed-out`.

When `status` is `"failed"` or `"timed-out"`, processing ended without a result. For a valid `job_id` on your account, `GET /v2/jobs/{job_id}` still returns `200 OK` with a job object — these outcomes are expressed in `status`, not via a 4xx HTTP code.

Poll until `status` is `done`, `failed`, or `timed-out`, then branch:

- **`done`:** `result` contains the full analysis.
- **`failed`:** `result` is typically `null`; `completed_at` may also be `null`. For the failure reason, check your operational logs or contact support — the job object does not include a structured error code.
- **`timed-out`:** processing did not complete in time; `result` and `completed_at` are `null`. Submit a new job to retry.

`404 Not Found` applies when the job is unknown or belongs to a different account — see [Jobs API](/reference/jobs).

### summary object

`result.summary` is the primary object for routing decisions. Read it first.

| Field | Type | Description |
|---|---|---|
| `overall_level` | string | Highest level across all signals: `none`, `low`, `consider`, `moderate`, `elevated`, or `inconclusive`. See [Signal levels](/guides/interpreting-results#signal-levels). |
| `recommended_action` | string | Highest-priority action: `none`, `monitor`, `consider`, `review`, `escalate`, or `inconclusive`. See [Recommended action logic](/guides/interpreting-results#recommended-action-logic). |
| `flagged_count` | integer | Count of signals where `flagged: true`. |
| `primary_signals` | string[] | Top 1–3 `name` values by score, descending (matches `signals[].name`). |
| `description` | object | Narrative `summary` plus `vocal_features`. See [description object](#description-object). |

`overall_level` reflects the highest `level` value across all signals in the bundle. `recommended_action` is derived from the full distribution of signal levels — not from `overall_level` alone. See [Recommended action logic](/guides/interpreting-results#recommended-action-logic) for the derivation.

```json
{
  "overall_level": "elevated",
  "recommended_action": "escalate",
  "flagged_count": 3,
  "primary_signals": ["stress", "anxiety", "fatigue"],
  "description": {
    "summary": "Voice patterns suggest elevated indicators for stress and anxiety...",
    "vocal_features": [ ... ]
  }
}
```

### signals array

`signals` contains one entry per sign in the model bundle.

| Field | Type | Description |
|---|---|---|
| `name` | string | External sign name. See [Sign Catalog](/catalogs/signs). |
| `label` | string | Human-readable model name. |
| `score` | number | Raw confidence score, 0.0–1.0. Keep for internal use; use `level` for display. For the score-to-level mapping, see [Signal levels](/guides/interpreting-results#signal-levels). |
| `level` | string | Quantized level: `none`, `low`, `consider`, `moderate`, `elevated`, or `inconclusive`. |
| `flagged` | boolean | `true` when level is `consider`, `moderate`, or `elevated`. |

```json
[
  {"name": "stress", "label": "Stress", "score": 0.81, "level": "elevated", "flagged": true},
  {"name": "anxiety", "label": "Anxiety", "score": 0.71, "level": "elevated", "flagged": true},
  {"name": "fatigue", "label": "Fatigue", "score": 0.54, "level": "consider", "flagged": true}
]
```

For display rules and field usage guidance, see [Display guidelines](/guides/interpreting-results#display-guidelines).

### description object

`description` is nested inside `summary`. It contains a machine-generated plain-text summary and a structured array of annotated vocal feature values.

| Field | Type | Description |
|---|---|---|
| `summary` | string | LLM-generated plain-text description of the acoustic findings. Not a diagnostic assessment. |
| `vocal_features` | array | Annotated acoustic feature values that informed the summary. See [vocal_features array](#vocal_features-array). |

Surface `description` in care-staff interfaces. For the full display rules, see [Display guidelines](/guides/interpreting-results#display-guidelines).

### vocal_features array

Each entry in `vocal_features` describes a single acoustic measurement extracted from the recording.

| Field | Type | Description |
|---|---|---|
| `feature` | string | Canonical feature identifier (e.g. `speech_rate`, `voice_shimmer`, `pitch_mean`). See [Speech feature IDs](/reference/enumerations#speech-feature-ids). |
| `label` | string | Human-readable feature name (e.g. `"Speech Rate"`, `"Voice Shimmer"`, `"Average Pitch"`). |
| `value` | number | Measured value for this recording. |
| `unit` | string | Unit of measurement (e.g. `"dB"`, `"syllables/s"`, `"Hz"`). |
| `value_interpretation` | string | Interpretation relative to reference range: `"within range"`, `"slightly elevated"`, `"high"`, `"reduced"`, or `"low"`. |

```json
{
  "summary": "Voice patterns suggest elevated stress and fatigue indicators...",
  "vocal_features": [
    {
      "feature": "speech_rate",
      "label": "Speech Rate",
      "value": 3.2,
      "unit": "syllables/s",
      "value_interpretation": "reduced"
    },
    {
      "feature": "voice_shimmer",
      "label": "Voice Shimmer",
      "value": 0.041,
      "unit": "dB",
      "value_interpretation": "slightly elevated"
    }
  ]
}
```

### audio_quality object

`audio_quality` scores the recording and lists issue codes. Use them to keep the result or re-record. File metadata is on the job: `audio_size_bytes`, `audio_duration_seconds`, `audio_content_type`.

| Field | Type | Description |
|---|---|---|
| `issues` | string[] | Detected quality issue codes. Empty array means no issues. See [Audio quality issue codes](/guides/audio-requirements#audio-quality-issue-codes) for the full list and recommended actions. |
| `voice_percentage` | number or null | Percentage of the recording containing active speech (0–100). A value of `0` means no speech was detected; `100` means the full recording contains active speech. Values below 30 typically correspond to an `insufficient_speech` issue. |
| `audio_clarity` | number or null | Background noise quality score (0–100), derived from SI-SDR (Scale-Invariant Signal-to-Distortion Ratio). Higher values indicate a clearer recording with less background noise. Values below 50 typically correspond to a `high_background_noise` issue. |

`issues`, `voice_percentage`, and `audio_clarity` are coherent: when a score is below its threshold, the corresponding issue code will typically be present in `issues`.

```json
{
  "issues": [],
  "voice_percentage": 82.4,
  "audio_clarity": 74.1
}
```

Example with quality issues detected:

```json
{
  "issues": ["high_background_noise", "insufficient_speech"],
  "voice_percentage": 21.3,
  "audio_clarity": 38.6
}
```

When `issues` is non-empty, signals may still be returned. Use the issue codes to decide whether to act on the result or re-record — see [Audio quality issue codes](/guides/audio-requirements#audio-quality-issue-codes) for the recommended action for each code.

### extended_metrics array

`extended_metrics` contains wellness metric scores derived from the voice recording. The set of metrics returned depends on the model. For metric definitions, see [Extended Metrics](/catalogs/extended-metrics).

| Field | Type | Description |
|---|---|---|
| `metric_id` | string | Canonical metric identifier (e.g. `anxious-mood`, `vad-valence`). See [Extended metric IDs](/reference/enumerations#extended-metric-ids). |
| `label` | string | Human-readable metric name (e.g. `"Anxious Mood"`, `"Emotional Valence"`). |
| `score_mean` | number | Mean score, 0.0–1.0. |
| `score_std` | number | Standard deviation of the score, 0.0–1.0. |
| `low_anchor` | string | Verbal anchor describing the state at score ≈ 0 (e.g. `"tranquil"`). |
| `high_anchor` | string | Verbal anchor describing the state at score ≈ 1 (e.g. `"panicked"`). |

```json
[
  {
    "metric_id": "anxious-mood",
    "label": "Anxious Mood",
    "score_mean": 0.72,
    "score_std": 0.08,
    "low_anchor": "tranquil",
    "high_anchor": "panicked"
  },
  {
    "metric_id": "vad-valence",
    "label": "Emotional Valence",
    "score_mean": 0.38,
    "score_std": 0.05,
    "low_anchor": "negative",
    "high_anchor": "positive"
  }
]
```

## Sign response

`POST /v2/signs/{sign_name}/analyze` returns the same job object envelope (see [Job response](#job-response) above), but with `job_type: "sign"`, a non-null `sign_name`, `model_name` typically `null`, and a structurally different `result` interior.

The `result` object uses a singular `signal` object instead of `summary` plus `signals[]`:

```json
{
  "job_id": "4a8f12c9-e7b2-4d3a-9f1c-8b6d2e5a7c0f",
  "status": "done",
  "job_type": "sign",
  "api_version": "v2",
  "model_name": null,
  "sign_name": "stress",
  "result": {
    "signal": { ... },
    "audio_quality": { ... }
  }
}
```

### signal object

`signal` is a single object, not an array, containing the full result for the requested sign. Where the model response places `description` and `recommended_action` on the `summary` wrapper, the sign response places them directly on `signal`.

| Field | Type | Description |
|---|---|---|
| `name` | string | External sign name. See [Sign Catalog](/catalogs/signs). |
| `label` | string | Human-readable sign name. |
| `score` | number | Raw confidence score, 0.0–1.0. Keep for internal use; use `level` for display. For the score-to-level mapping, see [Signal levels](/guides/interpreting-results#signal-levels). |
| `level` | string | Quantized level: `none`, `low`, `consider`, `moderate`, `elevated`, or `inconclusive`. |
| `flagged` | boolean | `true` when level is `consider`, `moderate`, or `elevated`. |
| `recommended_action` | string | Action for this sign: `none`, `monitor`, `consider`, `review`, `escalate`, or `inconclusive`. |
| `description` | object | Narrative `summary` plus `vocal_features`. Same schema as the [description object](#description-object). |

`recommended_action` is derived from this sign's `level` alone — not aggregated across a bundle. See [Recommended action logic](/guides/interpreting-results#recommended-action-logic).

`description` contains an LLM-generated plain-text summary of the acoustic findings and a structured `vocal_features` array. The same display rules apply: surface it in care-staff interfaces. On the inconclusive path, `summary` contains a standard inconclusive message and `vocal_features` is empty.

```json
{
  "name": "stress",
  "label": "Stress",
  "score": 0.81,
  "level": "elevated",
  "flagged": true,
  "recommended_action": "escalate",
  "description": {
    "summary": "Voice patterns suggest elevated stress indicators...",
    "vocal_features": [
      {
        "feature": "speech_rate",
        "label": "Speech Rate",
        "value": 3.2,
        "unit": "syllables/s",
        "value_interpretation": "reduced"
      }
    ]
  }
}
```

Use `job_type` to select the correct result parser:

| `job_type` | Result shape |
|---|---|
| `model` | `summary` plus `signals[]` (model bundle) |
| `sign` | singular `signal` object |

For display rules, see [Display guidelines](/guides/interpreting-results#display-guidelines).
