> ## Documentation Index
> Fetch the complete documentation index at: https://f4c7a9e2d8b1-docs.tenzo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Meeting notes API

> Create Meeting Copilot notes through the Public API and control post-meeting actions.

## Creating Notes via the Public API

If you record and transcribe meetings elsewhere, you can hand a finished transcript to Tenzo via the `POST /api/v1/meeting-copilot-note` endpoint and have it build a Meeting Copilot note — optionally running the same post-meeting pipeline the in-app bot uses when a meeting ends. The full request/response contract lives under the **Meeting Copilot** tag in the [Tenzo Public API reference](https://api.tenzo.ai/v1/tenzo-api-documentation#tag/Meeting-Copilot).

Authenticate with a Bearer API key (it starts with `tenzo_pk_`) — see [API & Webhook Configuration](/settings/api-webhook-config#generating-an-api-key) to generate one. The note template, job, and candidate you reference are all scoped to the organization the key belongs to.

To prevent duplicate notes when retrying requests (e.g. after network timeouts), include an `Idempotency-Key: <unique-id>` header (up to 256 characters). Successful responses are cached for 24 hours; subsequent requests with the same key return the cached note response immediately without creating duplicates.

<Note>
  Meeting Copilot must be enabled for your organization before this endpoint will accept requests. If it isn't, every call returns `403 Meeting notes are not enabled for this organization`, even with a valid API key — contact your Tenzo representative to have it turned on.
</Note>

<Warning>
  By default (`run_post_meeting_actions: true`) the post-meeting pipeline runs **in the background and has side effects**: it generates the note content and summary, can send a summary email, write back to your ATS, create a Tenzo Job, and fire your `note.finalized` webhook. The request returns as soon as the note and transcript are saved — poll `GET /api/v1/meeting-copilot-note` for the generated summary and sections. To persist the note and transcript without triggering any of that, send `run_post_meeting_actions: false`.
</Warning>

### Request Body

| Field | Type | Required | Default | Description |
| - | - | - | - | - |
| `meeting_type` | enum | Yes | — | One of `interview`, `intake`, `sales`, `staffing_discovery`, or `other`. Controls which post-meeting output is generated. |
| `transcript` | array | Yes | — | The meeting transcript, in order. At least one entry is required. Each entry is a [transcript line](#transcript-line). |
| `note_template_id` | string | No | `null` | A note template (preset) id whose sections, context, and redaction rules shape the note. Its type must match `meeting_type` (returns `400` on mismatch). Returns `404` if it does not exist in your org. |
| `name` | string | No | `"Untitled Note"` | Display name for the created note. Max 500 characters. |
| `candidate_email` | string | No | `null` | Best-effort email used to link an existing candidate in your org to the note. If no candidate matches, the note is still created but left unlinked (`candidate_id` is `null`) — it does not 404. Ignored for `intake` and `staffing_discovery` meetings, which are not about a specific candidate. |
| `summary_email` | string | No | `null` | Recipient for the generated summary email. No summary email is sent when omitted. |
| `job_id` | string | No | `null` | Tenzo job id to link the note to. Returns `404` if it does not exist in your org. |
| `ats_writes` | boolean | No | `null` | Controls only ATS job creation/updates for intake notes and extracted candidate-field writes for interview notes. Omit to inherit the template's defaults (enabled unless the template says otherwise). Does not control Tenzo screen creation without an ATS. |
| `intake_field_overrides` | array | No | `null` | Intake only: ATS job field ids to sync, overriding the template's default selection for this note. An empty array syncs no fields. |
| `company_remote_id` | string | No | `null` | Intake only: ATS-native company / client corporation id (e.g. Bullhorn `ClientCorporation` ID). Pre-populates the ATS Sync company entity picker, unlocking automated job creation. |
| `contact_remote_id` | string | No | `null` | Intake only: ATS-native contact / hiring manager id (e.g. Bullhorn `ClientContact` ID). Pre-populates the ATS Sync hiring manager entity picker. |
| `remote_ats_job_id` | string | No | `null` | ATS-native job id to link the note to. |
| `description_draft` | string | No | `null` | Intake only: free-text job-description draft used to seed clarifying questions when no job is linked. |
| `run_post_meeting_actions` | boolean | No | `true` | When `true`, schedule the post-meeting pipeline in the background after creating the note (see the warning above). Set to `false` to only persist the note and its transcript. |

#### Relationship between `run_post_meeting_actions` and `ats_writes`

* **`run_post_meeting_actions`** gates the *entire* post-meeting pipeline (summary generation, structured note questions, emails, webhooks, ATS writes, and Tenzo screen creation). When set to `false`, none of the background processing executes.
* **`ats_writes`** is a fine-grained sub-toggle *within* that pipeline. When `run_post_meeting_actions: true`, `ats_writes` determines whether the pipeline performs write-backs to your ATS (creating/updating a job or writing candidate fields). If `run_post_meeting_actions: false`, `ats_writes` has no effect because the pipeline is bypassed entirely.
* **Without an ATS**, automatic Tenzo screen creation follows the note template's [Create Tenzo screen](/templates/meeting-copilot#create-tenzo-screen-intake-templates-without-an-ats) setting. This endpoint does not offer a per-note override for that setting; `ats_writes: false` does not disable it.

<Note>
  Only `note_template_id` and `job_id` return `404` when they don't exist in your org. `candidate_email` is best-effort: a non-matching email never fails the request, it just leaves the note unlinked.
</Note>

#### Transcript line

Each entry in `transcript` describes one spoken line:

| Field | Type | Required | Default | Description |
| - | - | - | - | - |
| `role` | enum / string | Yes | — | Speaker role: `host` (or case-insensitive `"Host"`, `"interviewer"`, `"organizer"`, `"recruiter"`) or `attendee` (or `"Attendee"`, `"candidate"`, `"interviewee"`, `"guest"`). |
| `content` | string | Yes | — | What the speaker said on this line. 1–20,000 characters. |
| `speaker_email` | string | No | `null` | The speaker's email, if known. Also accepts `email` or `speakerEmail`. |
| `start_ts` | integer | No | `0` | Start time in **seconds**, relative to meeting start. Also accepts `startTime`, `start_time`, or `startTs`. Float values are rounded to integer seconds. |
| `end_ts` | integer | No | `0` | End time in **seconds**, relative to meeting start. Also accepts `endTime`, `end_time`, or `endTs`. Float values are rounded to integer seconds. |

**Transcript size limits** — a request exceeding any of these is rejected with `422`: at most **5000 lines**, **20,000 characters** per line, and **800,000 UTF-8 bytes** of transcript text in total.

### Response

The response returns immediately after the note is created; the summary and structured sections are produced by the background pipeline and read separately via `GET /api/v1/meeting-copilot-note`.

| Field | Type | Description |
| - | - | - |
| `success` | boolean | Whether the note was created. |
| `note_id` | string | Tenzo internal id of the created note. Use it with `GET /api/v1/meeting-copilot-note` to read the generated summary and sections. |
| `candidate_id` | string \| null | Linked candidate id, if one was resolved from `candidate_email`; `null` when no candidate matched. |
| `message` | string | Always `"Meeting Copilot note created successfully"`. |

### Errors

| Status | Meaning |
| - | - |
| `400` | The template's type doesn't match `meeting_type`, `intake_field_overrides`, `company_remote_id`, or `contact_remote_id` was sent for a non-intake meeting, or your organization has reached its note limit. |
| `403` | Meeting Copilot is not enabled for your organization. |
| `404` | The referenced `note_template_id` or `job_id` doesn't exist in your org. |
| `422` | The request body failed validation, including the transcript size limits above. |
| `503` | The transcript couldn't be saved. The partially created note is deleted, so the request is safe to retry. |

### Example

Create an interview note from a transcript, link it to a candidate and job, and schedule the full post-meeting pipeline:

```bash theme={null}
curl -X POST https://api.tenzo.ai/api/v1/meeting-copilot-note \
  -H "Authorization: Bearer tenzo_pk_..." \
  -H "Idempotency-Key: 7b5a8e32-4d1a-4e6f-96a8-202609070001" \
  -H "Content-Type: application/json" \
  -d '{
    "meeting_type": "interview",
    "name": "Backend Engineer — Phone Screen",
    "note_template_id": "tmpl_abc123",
    "candidate_email": "candidate@example.com",
    "summary_email": "recruiter@example.com",
    "job_id": "job_xyz789",
    "run_post_meeting_actions": true,
    "transcript": [
      {
        "role": "host",
        "content": "Thanks for making time today — tell me about your recent work.",
        "speaker_email": "recruiter@example.com",
        "start_ts": 0,
        "end_ts": 4
      },
      {
        "role": "attendee",
        "content": "Sure. I have led API design on a platform team for the last three years.",
        "speaker_email": "candidate@example.com",
        "start_ts": 4,
        "end_ts": 11
      }
    ]
  }'
```

Example response:

```json theme={null}
{
  "success": true,
  "note_id": "note_5f8c21",
  "candidate_id": "cand_9d4b60",
  "message": "Meeting Copilot note created successfully"
}
```

Fetch the generated summary and sections with `GET /api/v1/meeting-copilot-note?tenzo_id=note_5f8c21` once processing completes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.