# Create a copilot profile

`POST https://api.morevoice.ai/v1/copilot_profiles`

Returns the new `CopilotProfile`.

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

Operation ID: `copilot_profiles_create`.

## Parameters

### 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 |
| --- | --- | --- | --- |
| `alerts` | `object[]` | no | — |
| `coaching` | `object` | no | — |
| `coaching.monologue_seconds_max` | `number` | no | Continuous agent speech before "ask a question". |
| `coaching.silence_seconds_max` | `number` | no | Dead air before a nudge. |
| `coaching.talk_ratio_max` | `number` | no | Agent share of talk time above which to nudge (0–1). |
| `coaching.wpm_max` | `number` | no | — |
| `coaching.wpm_min` | `number` | no | — |
| `company` | `string` | no | Who the agent represents. |
| `compliance` | `object` | no | — |
| `compliance.forbidden_phrases` | `object[]` | no | — |
| `compliance.required_disclosures` | `object[]` | no | — |
| `fields` | `object[]` | no | Details the copilot picks out of the conversation. |
| `goal` | `string` | no | What the call should achieve. |
| `kb` | `object` | no | — |
| `kb.document_ids` | `string[]` | no | Knowledge-base documents the profile may use (empty: all). |
| `kb.links` | `object[]` | no | Reference links shown to the agent. |
| `kb.min_score` | `number` | no | Minimum confidence (0–1) to show a knowledge card unasked. |
| `language` | `string` | no | The calls' language (`he`, `en`, …). |
| `model` | `object` | no | — |
| `model.api` | `"chat" \| "responses"` | no | — |
| `model.deep_path` | `boolean` | no | false: the fast path only (no model calls). |
| `model.fallback_model` | `string` | no | — |
| `model.max_calls_per_minute` | `integer` | no | Model calls per minute per call. |
| `model.model` | `string` | no | — |
| `model.objection_similarity` | `number` | no | Meaning-based objection match threshold (cosine). |
| `model.priority` | `boolean` | no | Priority processing: steadier, lower latency, higher token price. |
| `model.speculative` | `boolean` | no | Start on stable interim text, before the utterance is final. |
| `model.temperature` | `number` | no | — |
| `name` | `string` | no | Default: the template's name. |
| `objections` | `object[]` | no | The objection library. |
| `product` | `string` | no | — |
| `qa_rubric` | `object[]` | no | The QA rubric this profile's calls are scored against (empty: the organisation's rubric). |
| `script` | `object` | no | — |
| `script.flow_id` | `string \| null` | no | An agent-script flow that drives the call branch by branch (null: the linear `stages`). |
| `script.version` | `"published" \| integer` | no | `published`, or a pinned version number. |
| `stages` | `object[]` | no | The call's stages, each with a checklist (used when no `script` flow is set). |
| `template_id` | `"sales-outbound" \| "customer-service"` | no | Start from a template (GET /v1/copilot_profiles/templates); the fields you send override it. |
| `tone` | `string` | no | How the agent should sound. |

Example:

```json
{
  "company": "Acme",
  "name": "Outbound sales",
  "product": "Acme Cloud PBX",
  "template_id": "sales-outbound"
}
```

## Responses

### 201 Created

The new profile. Returns `CopilotProfile`.

| Field | Type | Description |
| --- | --- | --- |
| `id` | `string` | The profile's ID. |
| `object` | `"copilot_profile"` | — |
| `livemode` | `boolean` | `true` in live mode, `false` in test mode. |
| `name` | `string` | — |
| `version` | `integer` | Goes up on every change. |
| `template_id` | `string \| null` | The template it was created from. |
| `goal` | `string` | What the call should achieve. |
| `tone` | `string` | How the agent should sound. |
| `company` | `string` | Who the agent represents. |
| `product` | `string` | — |
| `language` | `string` | The calls' language (`he`, `en`, …). |
| `stages` | `object[]` | The call's stages, each with a checklist (used when no `script` flow is set). |
| `objections` | `object[]` | The objection library. |
| `kb` | `object` | — |
| `kb.document_ids` | `string[]` | Knowledge-base documents the profile may use (empty: all). |
| `kb.links` | `object[]` | Reference links shown to the agent. |
| `kb.min_score` | `number` | Minimum confidence (0–1) to show a knowledge card unasked. |
| `fields` | `object[]` | Details the copilot picks out of the conversation. |
| `compliance` | `object` | — |
| `compliance.required_disclosures` | `object[]` | — |
| `compliance.forbidden_phrases` | `object[]` | — |
| `coaching` | `object` | — |
| `coaching.talk_ratio_max` | `number` | Agent share of talk time above which to nudge (0–1). |
| `coaching.monologue_seconds_max` | `number` | Continuous agent speech before "ask a question". |
| `coaching.silence_seconds_max` | `number` | Dead air before a nudge. |
| `coaching.wpm_max` | `number` | — |
| `coaching.wpm_min` | `number` | — |
| `alerts` | `object[]` | — |
| `qa_rubric` | `object[]` | The QA rubric this profile's calls are scored against (empty: the organisation's rubric). |
| `script` | `object` | — |
| `script.flow_id` | `string \| null` | An agent-script flow that drives the call branch by branch (null: the linear `stages`). |
| `script.version` | `"published" \| integer` | `published`, or a pinned version number. |
| `model` | `object` | — |
| `model.model` | `string` | — |
| `model.fallback_model` | `string` | — |
| `model.temperature` | `number` | — |
| `model.api` | `"chat" \| "responses"` | — |
| `model.priority` | `boolean` | Priority processing: steadier, lower latency, higher token price. |
| `model.max_calls_per_minute` | `integer` | Model calls per minute per call. |
| `model.speculative` | `boolean` | Start on stable interim text, before the utterance is final. |
| `model.deep_path` | `boolean` | false: the fast path only (no model calls). |
| `model.objection_similarity` | `number` | Meaning-based objection match threshold (cosine). |
| `created` | `string` | An ISO-8601 timestamp in UTC. |
| `updated` | `string` | An ISO-8601 timestamp in UTC. |

Example:

```json
{
  "alerts": [
    {
      "key": "escalation",
      "kind": "escalation",
      "label": "Asks for a manager",
      "message": "Acknowledge and offer a solution.",
      "notify_supervisor": true,
      "phrases": [
        "manager"
      ],
      "severity": "critical",
      "threshold": 0
    }
  ],
  "coaching": {
    "monologue_seconds_max": 40,
    "silence_seconds_max": 7,
    "talk_ratio_max": 0.65,
    "wpm_max": 175,
    "wpm_min": 0
  },
  "company": "Acme",
  "compliance": {
    "forbidden_phrases": [
      {
        "instead": "In most cases",
        "phrase": "guaranteed",
        "reason": "No guarantees",
        "severity": "warn"
      }
    ],
    "required_disclosures": []
  },
  "created": "2026-11-03T09:14:22.000Z",
  "fields": [
    {
      "hint": "",
      "key": "budget",
      "label": "Monthly budget",
      "options": [],
      "pattern": "",
      "required": false,
      "type": "money"
    }
  ],
  "goal": "Book a demo or a clear next step.",
  "id": "cop_8Ps2Ux5Zc7Eh0Jm3Or6Tw9",
  "kb": {
    "document_ids": [
      "kbd_6Nq0Sv3Xa5Cf8Hk1Mp4Rt7"
    ],
    "links": [],
    "min_score": 0.35
  },
  "language": "en",
  "livemode": true,
  "model": {
    "api": "chat",
    "deep_path": true,
    "fallback_model": "gpt-4.1-nano",
    "max_calls_per_minute": 12,
    "model": "gpt-4.1-mini",
    "objection_similarity": 0.72,
    "priority": true,
    "speculative": true,
    "temperature": 0.3
  },
  "name": "Outbound sales",
  "object": "copilot_profile",
  "objections": [
    {
      "examples": [
        "it costs too much"
      ],
      "follow_up": "What do you pay now?",
      "kb_query": "price list",
      "key": "price",
      "label": "Too expensive",
      "response": "Compare it with what downtime costs you today.",
      "triggers": [
        "too expensive"
      ]
    }
  ],
  "product": "Acme Cloud PBX",
  "qa_rubric": [
    {
      "description": "Asked open questions first.",
      "key": "discovery",
      "label": "Discovery",
      "weight": 60
    },
    {
      "description": "Agreed a dated next step.",
      "key": "close",
      "label": "Next step",
      "weight": 40
    }
  ],
  "script": {
    "flow_id": null,
    "version": "published"
  },
  "stages": [
    {
      "checklist": [
        {
          "ask": "",
          "key": "recorded",
          "label": "Say the call is recorded",
          "phrases": [
            "this call is recorded"
          ],
          "required": true
        }
      ],
      "goal": "Introduce yourself and ask for two minutes",
      "key": "opening",
      "label": "Opening"
    }
  ],
  "template_id": "sales-outbound",
  "tone": "Warm, confident, never pushy.",
  "updated": "2026-11-03T09:14:22.000Z",
  "version": 4
}
```

### 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`.

### 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 copilotProfile = await mv.copilotProfiles.create({
	company: "Acme",
	name: "Outbound sales",
	product: "Acme Cloud PBX",
	template_id: "sales-outbound",
});
console.log(copilotProfile);
```

**Python**

```python
from morevoice import MoreVoice

client = MoreVoice()  # MOREVOICE_API_KEY from the environment

copilot_profile = client.copilot_profiles.create({
    "company": "Acme",
    "name": "Outbound sales",
    "product": "Acme Cloud PBX",
    "template_id": "sales-outbound",
})
print(copilot_profile)
```

**cURL**

```sh
curl -X POST https://api.morevoice.ai/v1/copilot_profiles \
  -H "Authorization: Bearer $MOREVOICE_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "company": "Acme",
  "name": "Outbound sales",
  "product": "Acme Cloud PBX",
  "template_id": "sales-outbound"
}'
```
