# Score a call

`POST https://api.morevoice.ai/v1/calls/{id}/scorecard/run`

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.

Authenticate with a secret API key: `Authorization: Bearer $MOREVOICE_API_KEY`.

Operation ID: `qa_run_scorecard`.

## Parameters

### Path parameters

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

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `MoreVoice-Version` | `string` | no | The API version to use for this request. Defaults to the version the API key is pinned to. |
| `Idempotency-Key` | `string` | no | A unique key (for example a UUID) that makes this request safe to retry: for 24 hours, a retry with the same key and parameters returns the first response instead of acting twice. |

## Request body

Optional, `application/json`.

| 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). |

Example:

```json
{
  "force": false
}
```

## Responses

### 200 OK

OK Returns `Scorecard`.

| Field | Type | Description |
| --- | --- | --- |
| `id` | `string` | The scorecard's ID (one per call). |
| `object` | `"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` | — |
| `compliance.verdict` | `"pass" \| "warn" \| "fail"` | — |
| `compliance.issues` | `object[]` | — |
| `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:

```json
{
  "call_id": "call_5Fh7Jk9Lm1Np3Qr5St7Vx9",
  "coaching": [
    {
      "better": "Who else decides on this?",
      "tip": "Confirm the budget owner"
    }
  ],
  "compliance": {
    "issues": [],
    "verdict": "pass"
  },
  "copilot_profile_id": null,
  "created": "2026-11-03T09:16:40.000Z",
  "critical_failed": [],
  "customer_sentiment": "positive",
  "disposition": "appointment",
  "error": null,
  "id": "qa_5Fh7Jk9Lm1Np3Qr5St7Vx9",
  "items": [
    {
      "critical": false,
      "evidence": [
        {
          "line": 7,
          "offset_ms": 41200,
          "quote": "What do you pay today?",
          "speaker": "agent"
        }
      ],
      "key": "discovery",
      "label": "Discovery",
      "model_score": 3,
      "override": {
        "at": "2026-11-03T10:02:00.000Z",
        "by": "Dana Levi",
        "note": "Also asked about the decision maker.",
        "score": 4
      },
      "reasoning": "Asked about the current provider and the budget before the offer.",
      "score": 4,
      "weight": 40
    }
  ],
  "livemode": true,
  "model": "gpt-4.1",
  "model_score": 77.5,
  "next_steps": [
    "Send the demo invite"
  ],
  "object": "scorecard",
  "objections": [
    {
      "agent_response": "Compared it with today's costs.",
      "handled": true,
      "text": "It sounds expensive"
    }
  ],
  "pass_threshold": 70,
  "passed": true,
  "rubric_source": "default",
  "score": 82.5,
  "status": "done",
  "strengths": [
    "Clear opening"
  ],
  "summary": "The customer agreed to a demo on Monday.",
  "updated": "2026-11-03T10:02:00.000Z"
}
```

### 400 Bad Request

The request is invalid: a parameter is missing, malformed or unknown, or the version header is unknown. Returns `ErrorEnvelope`.

### 401 Unauthorized

No valid API key was sent. Returns `ErrorEnvelope`.

### 403 Forbidden

The key may not do this (a missing scope, a plan limit, or a compliance block). Returns `ErrorEnvelope`.

### 404 Not Found

No object with this ID exists in this organisation and mode. Returns `ErrorEnvelope`.

### 409 Conflict

The request conflicts with the object's state, or the Idempotency-Key was reused with other parameters. Returns `ErrorEnvelope`.

### 429 Too Many Requests

Too many requests, or no call capacity right now. Retry after the Retry-After delay. Returns `ErrorEnvelope`.

### 500 Internal Server Error

Something went wrong on MoreVoice's side. Retry with the same Idempotency-Key. Returns `ErrorEnvelope`.

## Code samples

**TypeScript**

```ts
import MoreVoice from "@morevoice/sdk";

const mv = new MoreVoice(); // MOREVOICE_API_KEY from the environment

const scorecard = await mv.qa.run.scorecard("call_7Hk2Lm9Qp", {
	force: false,
});
console.log(scorecard);
```

**Python**

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

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

**cURL**

```sh
curl -X POST https://api.morevoice.ai/v1/calls/call_7Hk2Lm9Qp/scorecard/run \
  -H "Authorization: Bearer $MOREVOICE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "force": false
}'
```
