# client.qa

> The qa methods of the morevoice Python SDK: Post-call QA scorecards and rubric.

Post-call QA scorecards and rubric. These methods are on `client.qa`, where `client` is a `MoreVoice` client (see [the Python SDK](https://docs.morevoice.ai/sdk/python/#connect)). On `AsyncMoreVoice` the same methods are awaited. Each one returns the response object and raises an exception when the API answers with an error.

## `override_scorecard_item()`

**Override a scorecard item.** Sets one rubric item's score (0–5, or null for not applicable) as a supervisor would, or removes the override with `clear: true`. The call's score and pass are recomputed; the change is in the scorecard's history.

```python
# client.qa
def override_scorecard_item(self, id: str, item_key: str, body: _m.ScorecardItemOverrideParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET) -> _m.Scorecard
```

`client.qa.override_scorecard_item()` · `await async_client.qa.override_scorecard_item()` · `PATCH /calls/{id}/scorecard/items/{item_key}` · [API reference](https://docs.morevoice.ai/api/operations/qa_override_scorecard_item/)

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `str` | yes | A call ID (`call_…`). |
| `item_key` | `str` | yes | The rubric item's key. |

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `clear` | `boolean` | no | true: remove the override (the model's score applies again). |
| `note` | `string` | no | Why (shown in the scorecard's history). |
| `score` | `number \| null` | no | The item's score, 0–5 (half points round), or null for not applicable. |

### Returns

`Scorecard`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | `string` | The scorecard's ID (one per call). |
| `object` | `"scorecard"` | Always `scorecard`. |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |
| `call_id` | `string` | A call ID (prefix `call_`). |
| `status` | `"pending" \| "running" \| "done" \| "error" \| "skipped"` | `skipped`: too short to score (`error` says why); `error`: scoring failed. |
| `error` | `string \| null` | — |
| `score` | `number \| null` | 0–100 after supervisor overrides (null: nothing applicable). |
| `model_score` | `number \| null` | 0–100 as the model scored it. |
| `passed` | `boolean \| null` | — |
| `critical_failed` | `string[]` | Keys of the critical items that failed the call. |
| `rubric_source` | `"default" \| "copilot_profile" \| null` | Scored against the organisation's rubric, or the call's copilot profile's. |
| `copilot_profile_id` | `string \| null` | `cop_…` ID. |
| `pass_threshold` | `number \| null` | — |
| `items` | `object[]` | One per rubric item. |
| `compliance` | `object \| null` | — |
| `disposition` | `"sale" \| "appointment" \| "callback_scheduled" \| "follow_up" \| "resolved" \| "unresolved" \| "not_interested" \| "escalated" \| … \| null` | — |
| `summary` | `string \| null` | — |
| `customer_sentiment` | `"positive" \| "neutral" \| "negative" \| "mixed" \| null` | — |
| `strengths` | `string[]` | — |
| `coaching` | `object[]` | — |
| `next_steps` | `string[]` | — |
| `objections` | `object[]` | — |
| `model` | `string \| null` | — |
| `created` | `string` | An ISO-8601 timestamp in UTC. |
| `updated` | `string` | An ISO-8601 timestamp in UTC. |

### Example

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

scorecard = client.qa.override_scorecard_item("call_7Hk2Lm9Qp", "item_key_123", {
    "note": "Also asked about the decision maker.",
    "score": 4,
})
print(scorecard)
```

## `retrieve_rubric()`

**Retrieve the QA rubric.** Returns the `QaRubric` object.

```python
# client.qa
def retrieve_rubric(self, *, more_voice_version: str | Unset = UNSET) -> _m.QaRubric
```

`client.qa.retrieve_rubric()` · `await async_client.qa.retrieve_rubric()` · `GET /qa/rubric` · [API reference](https://docs.morevoice.ai/api/operations/qa_retrieve_rubric/)

### Returns

`QaRubric`:

| Field | Type | Description |
| --- | --- | --- |
| `object` | `"qa_rubric"` | Always `qa_rubric`. |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |
| `name` | `string` | — |
| `pass_threshold` | `number` | A call passes at this score (0–100) or above, with no critical item failed. |
| `items` | `object[]` | — |
| `builtin` | `boolean` | true: the built-in rubric (you have not saved your own). |

### Example

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

qa_rubric = client.qa.retrieve_rubric()
print(qa_rubric)
```

## `retrieve_scorecard()`

**Retrieve a call's QA scorecard.** The call's post-call QA scorecard. Calls are scored automatically when the organisation's QA policy says so; 404 until one is.

```python
# client.qa
def retrieve_scorecard(self, id: str, *, more_voice_version: str | Unset = UNSET) -> _m.Scorecard
```

`client.qa.retrieve_scorecard()` · `await async_client.qa.retrieve_scorecard()` · `GET /calls/{id}/scorecard` · [API reference](https://docs.morevoice.ai/api/operations/qa_retrieve_scorecard/)

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `str` | yes | A call ID (`call_…`). |

### Returns

`Scorecard`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | `string` | The scorecard's ID (one per call). |
| `object` | `"scorecard"` | Always `scorecard`. |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |
| `call_id` | `string` | A call ID (prefix `call_`). |
| `status` | `"pending" \| "running" \| "done" \| "error" \| "skipped"` | `skipped`: too short to score (`error` says why); `error`: scoring failed. |
| `error` | `string \| null` | — |
| `score` | `number \| null` | 0–100 after supervisor overrides (null: nothing applicable). |
| `model_score` | `number \| null` | 0–100 as the model scored it. |
| `passed` | `boolean \| null` | — |
| `critical_failed` | `string[]` | Keys of the critical items that failed the call. |
| `rubric_source` | `"default" \| "copilot_profile" \| null` | Scored against the organisation's rubric, or the call's copilot profile's. |
| `copilot_profile_id` | `string \| null` | `cop_…` ID. |
| `pass_threshold` | `number \| null` | — |
| `items` | `object[]` | One per rubric item. |
| `compliance` | `object \| null` | — |
| `disposition` | `"sale" \| "appointment" \| "callback_scheduled" \| "follow_up" \| "resolved" \| "unresolved" \| "not_interested" \| "escalated" \| … \| null` | — |
| `summary` | `string \| null` | — |
| `customer_sentiment` | `"positive" \| "neutral" \| "negative" \| "mixed" \| null` | — |
| `strengths` | `string[]` | — |
| `coaching` | `object[]` | — |
| `next_steps` | `string[]` | — |
| `objections` | `object[]` | — |
| `model` | `string \| null` | — |
| `created` | `string` | An ISO-8601 timestamp in UTC. |
| `updated` | `string` | An ISO-8601 timestamp in UTC. |

### Example

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

scorecard = client.qa.retrieve_scorecard("call_7Hk2Lm9Qp")
print(scorecard)
```

## `run.scorecard()`

**Score a call.** Scores the call against its rubric now, even when it is too short for automatic scoring, and answers the scorecard (it can take a few seconds). A call that already has a finished scorecard is not scored again unless `force` is true. 409 while the call is in progress.

```python
# client.qa.run
def scorecard(self, id: str, body: _m.ScorecardRunParamsInput | Mapping[str, Any] | Unset = UNSET, *, more_voice_version: str | Unset = UNSET, idempotency_key: str | Unset = UNSET) -> _m.Scorecard
```

`client.qa.run.scorecard()` · `await async_client.qa.run.scorecard()` · `POST /calls/{id}/scorecard/run` · [API reference](https://docs.morevoice.ai/api/operations/qa_run_scorecard/)

### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | `str` | yes | A call ID (`call_…`). |

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `force` | `boolean` | no | Score again even when the call already has a finished scorecard (default false: it is returned as it is). |

### Returns

`Scorecard`:

| Field | Type | Description |
| --- | --- | --- |
| `id` | `string` | The scorecard's ID (one per call). |
| `object` | `"scorecard"` | Always `scorecard`. |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |
| `call_id` | `string` | A call ID (prefix `call_`). |
| `status` | `"pending" \| "running" \| "done" \| "error" \| "skipped"` | `skipped`: too short to score (`error` says why); `error`: scoring failed. |
| `error` | `string \| null` | — |
| `score` | `number \| null` | 0–100 after supervisor overrides (null: nothing applicable). |
| `model_score` | `number \| null` | 0–100 as the model scored it. |
| `passed` | `boolean \| null` | — |
| `critical_failed` | `string[]` | Keys of the critical items that failed the call. |
| `rubric_source` | `"default" \| "copilot_profile" \| null` | Scored against the organisation's rubric, or the call's copilot profile's. |
| `copilot_profile_id` | `string \| null` | `cop_…` ID. |
| `pass_threshold` | `number \| null` | — |
| `items` | `object[]` | One per rubric item. |
| `compliance` | `object \| null` | — |
| `disposition` | `"sale" \| "appointment" \| "callback_scheduled" \| "follow_up" \| "resolved" \| "unresolved" \| "not_interested" \| "escalated" \| … \| null` | — |
| `summary` | `string \| null` | — |
| `customer_sentiment` | `"positive" \| "neutral" \| "negative" \| "mixed" \| null` | — |
| `strengths` | `string[]` | — |
| `coaching` | `object[]` | — |
| `next_steps` | `string[]` | — |
| `objections` | `object[]` | — |
| `model` | `string \| null` | — |
| `created` | `string` | An ISO-8601 timestamp in UTC. |
| `updated` | `string` | An ISO-8601 timestamp in UTC. |

### Example

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

scorecard = client.qa.run.scorecard("call_7Hk2Lm9Qp", {
    "force": False,
})
print(scorecard)
```

## `update_rubric()`

**Replace the QA rubric.** Replaces the organisation's rubric. Weights are relative, on one 0–100 scale (only the ratios count). Calls scored from now on use it; existing scorecards keep the rubric they were scored with.

```python
# client.qa
def update_rubric(self, body: _m.QaRubricParamsInput | Mapping[str, Any], *, more_voice_version: str | Unset = UNSET) -> _m.QaRubric
```

`client.qa.update_rubric()` · `await async_client.qa.update_rubric()` · `PUT /qa/rubric` · [API reference](https://docs.morevoice.ai/api/operations/qa_update_rubric/)

### Request body

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `items` | `object[]` | yes | The items, in order; keys must be unique and at least one item needs a weight above 0. |
| `name` | `string` | no | Default: "Default QA rubric". |
| `pass_threshold` | `number` | no | Default 70. |

### Returns

`QaRubric`:

| Field | Type | Description |
| --- | --- | --- |
| `object` | `"qa_rubric"` | Always `qa_rubric`. |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |
| `name` | `string` | — |
| `pass_threshold` | `number` | A call passes at this score (0–100) or above, with no critical item failed. |
| `items` | `object[]` | — |
| `builtin` | `boolean` | true: the built-in rubric (you have not saved your own). |

### Example

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

qa_rubric = client.qa.update_rubric({
    "items": [
        {
            "key": "discovery",
            "label": "Discovery",
            "weight": 60,
        },
        {
            "key": "closing",
            "label": "Next step",
            "type": "boolean",
            "weight": 40,
        },
    ],
    "pass_threshold": 75,
})
print(qa_rubric)
```
