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

# All-day sessions

> Submit one long-form recording — get back N scored conversations. Boundary detection + per-segment V5 analysis in a single API call.

Submit one HTTPS URL of any length recording. We detect every sales conversation inside, score each one with the standard six-pillar V5 analysis, and return a clean rollup. Works for anything from a 1-minute single pitch up to a 12-hour workday.

**What you send:** one HTTPS URL.

**What you get back:** N first-class [`Analysis`](/api-reference/analyses/fetch-an-analysis) rows with `parent_session_id` set, where N is the number of distinct conversations we detected. Could be 0, 1, or 100. Every existing analysis tool you've already integrated (`get_analysis`, webhooks, dashboards) Just Works on the children.

***

## When to use it

| You have                                               | You want                 | Use this                                                                       |
| ------------------------------------------------------ | ------------------------ | ------------------------------------------------------------------------------ |
| One recording, you know it's a single call             | One score, lowest cost   | [`POST /v1/analyses`](/api-reference/analyses/submit-a-recording-for-analysis) |
| One recording, you don't know if it's one call or many | Auto-detect + score each | **`POST /v1/all-day-sessions`** ← you are here                                 |
| One recording with multiple known calls inside         | N scores, one per call   | **`POST /v1/all-day-sessions`**                                                |
| N separate URLs you already split                      | N scores                 | Loop `POST /v1/analyses`                                                       |

All-day is the right call any time the partner can't pre-split the audio. It's a superset of `/v1/analyses` (one call → 1 analysis result) with the boundary-detection layer added. Slightly more expensive because of the boundary detection step, but you save the Deepgram cost of any extra slicing pass.

### Possible result counts

* **0 conversations** — recording contained no sales conversation (pure internal/team meeting, music, silence). Session completes with `segments_detected: 0`. No charges for V5 analysis since none ran.
* **1 conversation** — recording was a single continuous call. You get one analysis spanning roughly the full recording.
* **N conversations** — typical all-day case. One analysis per detected conversation, scored in parallel (max 5 concurrent).

***

## The 60-second mental model

```
You POST one URL ────► Server transcribes (Deepgram, ONCE)
                              │
                              ▼
                     Gemini detects conversation boundaries
                              │
                              ▼
                     For each segment with confidence ≥ 0.8:
                       └─► V5 analysis on sliced transcript
                              │
                              ▼
                     Returns: parent session + N child Analyses

Webhooks fire:
  • all_day_session.processing_started  (worker picked it up — "Parlay has it")
  • all_day_session.detected            (segments visible, before analyses run)
  • analysis.completed                  (existing event, fires per segment)
  • all_day_session.completed           (everything terminal — rollup ready)
```

**Audio storage:** we never re-host your file. The response carries `start_seconds`/`end_seconds` offsets — your UI uses HTTP Range requests on **your** original URL to play any segment.

***

## Submit a session

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.goparlay.io/v1/all-day-sessions \
    -H "Authorization: Bearer pk_live_YOUR_KEY" \
    -H "Idempotency-Key: $(uuidgen)" \
    -H "Content-Type: application/json" \
    -d '{
      "recording_url": "https://your-bucket.s3.amazonaws.com/2026-05-06-rep1.mp3?...",
      "org_id": "acme-corp",
      "rep_id": "alex-smith"
    }'
  ```

  ```ts TypeScript theme={null}
  const res = await fetch("https://api.goparlay.io/v1/all-day-sessions", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${PARLAY_KEY}`,
      "Idempotency-Key": crypto.randomUUID(),
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      recording_url: "https://your-bucket.s3.amazonaws.com/2026-05-06-rep1.mp3?...",
      org_id: "acme-corp",
      rep_id: "alex-smith",
    }),
  });
  const { id } = await res.json();
  ```

  ```python Python theme={null}
  import os, uuid, requests

  resp = requests.post(
      "https://api.goparlay.io/v1/all-day-sessions",
      headers={
          "Authorization": f"Bearer {os.environ['PARLAY_KEY']}",
          "Idempotency-Key": str(uuid.uuid4()),
          "Content-Type": "application/json",
      },
      json={
          "recording_url": "https://your-bucket.s3.amazonaws.com/2026-05-06-rep1.mp3?...",
          "org_id": "acme-corp",
          "rep_id": "alex-smith",
      },
  )
  session = resp.json()
  ```
</CodeGroup>

You get back a 202:

```json theme={null}
{
  "id": "f33705f0-5360-4434-8548-c280066da7e7",
  "status": "queued",
  "created_at": "2026-05-07T00:50:34.607922+00:00"
}
```

The session moves through statuses asynchronously: `queued → transcribing → detecting → analyzing → completed`.

***

## Production keys only

Sandbox keys (`pk_sandbox_…`) cannot submit all-day sessions — they reject with `invalid_recording_url`. The reason: an all-day call burns real Deepgram + Gemini credits proportional to audio length, and sandbox is supposed to be free. Test with a single short recording via [`POST /v1/analyses`](/api-reference/analyses/submit-a-recording-for-analysis) using `mock://*` fixtures during development; switch to a `pk_live_…` key for real audio.

***

## Wait for results

You have three patterns. Pick whichever matches your existing setup.

### Pattern 1 — webhooks (recommended)

Register a webhook for the events you care about. Most partners already have `analysis.completed` wired in for standalone analyses — that handler runs unchanged for each segment, since segments are first-class Analyses with `parent_session_id` set.

```bash theme={null}
curl -X POST https://api.goparlay.io/v1/webhooks \
  -H "Authorization: Bearer pk_live_YOUR_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/parlay-webhook",
    "enabled_events": [
      "all_day_session.processing_started",
      "all_day_session.detected",
      "all_day_session.completed",
      "all_day_session.failed",
      "analysis.completed"
    ]
  }'
```

| Event                                | When it fires                                               | Use it for                                                                                                                               |
| ------------------------------------ | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `all_day_session.processing_started` | Worker picks the session up off the queue                   | "Parlay has it" reassurance on backed-up days — fires before transcription starts so even an 8-hour file doesn't sit in `queued` silence |
| `all_day_session.detected`           | Boundaries found, before per-segment analysis starts        | Show the partner "we found 5 calls" while analyses are still processing                                                                  |
| `analysis.completed`                 | Each segment finishes (existing event, fires N times)       | Existing per-call coaching workflows                                                                                                     |
| `all_day_session.completed`          | All segments terminal                                       | Rollup view ("Alex's Tuesday at a glance")                                                                                               |
| `all_day_session.failed`             | Unrecoverable error (no speech, transcription failed, etc.) | Surface a partner-friendly error + offer retry                                                                                           |

### Pattern 2 — poll the session

```bash theme={null}
curl https://api.goparlay.io/v1/all-day-sessions/$SESSION_ID \
  -H "Authorization: Bearer pk_live_YOUR_KEY"
```

Poll every 5–10 seconds until `status === "completed"`. Typical end-to-end latency is **1.5 minutes for a 24-minute recording**, **5–10 minutes for a full 8-hour day** with 5 segments.

### Pattern 3 — wait inline (the MCP tool does this for you)

If you're calling from an AI agent, the [`submit_all_day_recording`](https://docs.goparlay.io/mcp/tool-catalog) MCP tool waits up to 10 minutes for completion and returns the full session inline.

***

## What you get back

Once `status === "completed"`, the session response carries every detected segment plus their `analysis_id` forward-links:

```json theme={null}
{
  "id": "f33705f0-5360-4434-8548-c280066da7e7",
  "status": "completed",
  "duration_seconds": 1437,
  "segments_detected": 1,
  "segments_analyzed": 1,
  "segments_pending_review": 0,
  "segments_skipped": 0,
  "segments": [
    {
      "id": "21452f64-714e-4e59-a806-d8871e27ad36",
      "start_seconds": 0,
      "end_seconds": 1437,
      "confidence": 0.95,
      "customer_name": "Jackson",
      "is_sales_conversation": true,
      "detected_outcome": "ongoing",
      "summary": "James (rep) conducts a group product training and Q&A session for prospects Jackson, Keri, John, and Charles, focusing on search functionality, data export, and post-sale support, with discussions about the trial ending and signing an agreement.",
      "status": "analyzed",
      "analysis_id": "83171c80-6333-465b-b759-a67508909425",
      "analysis_url": "/v1/analyses/83171c80-6333-465b-b759-a67508909425",
      "created_at": "2026-05-07T00:51:20.391105+00:00",
      "analyzed_at": "2026-05-07T00:52:01.123Z"
    }
  ],
  "options": {},
  "metadata": {},
  "callback_url": null,
  "error": null,
  "created_at": "2026-05-07T00:50:34.607922+00:00",
  "started_at": "2026-05-07T00:50:34.700Z",
  "completed_at": "2026-05-07T00:52:01.487Z",
  "partner_org_id": "...",
  "partner_rep_id": "..."
}
```

Drill into any segment via `GET /v1/analyses/:analysis_id` to get the full canonical 6-pillar analysis (clarity, influence, objection, discovery, delivery, close + feedback\_v5 + action\_plan\_v5). The shape is **identical to a standalone analysis** — same fields, same KPIs, same nesting. The only difference is `parent_session_id` is set.

***

## Playing back a segment in your UI

This is the part that surprises new partners. **You don't ask Parlay for the segment audio — we don't host it.**

You already have the original recording on your bucket. The session response gives you `start_seconds` and `end_seconds`, plus a ready-to-paste `playback` block on every segment that bundles both the browser snippet and an ffmpeg one-liner:

```json theme={null}
{
  "playback": {
    "recording_url": "https://your-bucket.s3.amazonaws.com/2026-05-06-rep1.mp3?...",
    "start_seconds": 1820,
    "end_seconds": 4100,
    "browser_seek_js": "const audio = document.querySelector('audio'); audio.currentTime = 1820; audio.play(); audio.addEventListener('timeupdate', () => { if (audio.currentTime >= 4100) audio.pause(); });",
    "ffmpeg_extract": "ffmpeg -ss 1820 -to 4100 -i \"https://your-bucket.s3.amazonaws.com/...\" -c copy segment.mp3"
  }
}
```

**Browser playback** — drop the `browser_seek_js` snippet into any page that has an `<audio>` element pointing at the original URL. Modern browsers issue HTTP Range requests automatically — only the relevant byte range downloads. Same behavior Spotify and Twitch use. No new file, no Parlay-hosted URL, no second download.

**Offline export** — the `ffmpeg_extract` command uses `-c copy` (stream-copy, no re-encoding) so it runs instantly and preserves the original quality. Pipe it into a script if you want to archive every conversation as a separate file:

```bash theme={null}
# Archive every analyzed segment from a session as segment-0.mp3, segment-1.mp3, ...
curl -s https://api.goparlay.io/v1/all-day-sessions/$ID \
  -H "Authorization: Bearer $KEY" \
  | jq -r '.segments[].playback.ffmpeg_extract' \
  | awk '{print $0 " segment-" NR-1 ".mp3"}' \
  | sh
```

**Pre-signed URL expiry** — if your S3/GCS pre-signed URL has expired by the time the user clicks play (typical TTL: 1 hour), your backend mints a fresh one on demand. The `recording_url` echoed back in the `playback` block is the same URL you submitted, so you can swap it for a freshly-signed one if needed.

***

## Backend requirements

The two playback patterns above (browser HTTP Range, server-side ffmpeg) have very different runtime needs. Worth knowing before you wire this into your stack.

### HTTP Range playback (browser)

Works in any frontend with no special backend. Modern browsers issue Range requests automatically against an `<audio>` or `<video>` element. The byte fetching happens between the browser and your bucket. Parlay is not in the path. No timeout limits, no ffmpeg binary needed, no server-side compute.

This is the easiest pattern and covers most use cases.

### Server-side ffmpeg extraction

The `ffmpeg_extract` recipe in the `playback` block is a shell command. Running it requires:

* The `ffmpeg` binary on the machine executing the command
* Enough wall-clock time for the slice to copy (usually under 5 seconds for `-c copy` stream-copy, but depends on file size and source bucket latency)
* Filesystem write access
* Outbound network access to the audio URL

Many serverless and edge runtimes can't satisfy all four. A quick reference:

| Runtime                            | `ffmpeg` available?                                    | Typical wall-clock cap              | Notes                           |
| ---------------------------------- | ------------------------------------------------------ | ----------------------------------- | ------------------------------- |
| Cloud Run / Render / Fly / Railway | No by default, easy to add via Dockerfile              | Minutes to hours                    | Long-running OK                 |
| AWS Lambda                         | No by default, needs a layer or custom container image | 15 min hard cap                     | Custom layer is well-documented |
| Vercel Functions (Node)            | No, no easy way to add                                 | 10s Hobby, 60s Pro, 300s Enterprise | Not a good fit for ffmpeg       |
| Vercel Edge Functions              | No                                                     | 25s streaming, 30s total            | Not a good fit                  |
| Cloudflare Workers                 | No, native binaries unsupported                        | 30s CPU                             | Not a good fit                  |
| Supabase Edge Functions (Deno)     | No, WASM-only environment                              | 150s                                | Possible via ffmpeg.wasm, slow  |
| Next.js API routes (Vercel)        | Same as Vercel Functions                               | Same as above                       | Same caveats                    |

If you're on a runtime in the bottom half of that table and you want to extract slices, you have a few options:

* Skip extraction entirely. Use browser HTTP Range for playback. Many partners don't need server-side slicing at all.
* Run the ffmpeg work elsewhere. Push a job to a queue (SQS, Cloud Tasks, Cloudflare Queues, Supabase pg\_cron) and pick it up from a long-running worker.
* Trigger ffmpeg from a container service. Cloud Run and Render both have generous free tiers and run unmodified Dockerfiles with ffmpeg pre-installed.

### Webhook handlers specifically

The `all_day_session.*` and `analysis.completed` webhook events arrive at whatever URL you registered. Your handler should return a 2xx response in a few seconds. If your handler is on a runtime with a short execution window (Vercel default 10s, Cloudflare Workers 30s CPU), running ffmpeg synchronously inside the handler will either time out or drop the response. The pattern that works in every runtime: acknowledge the webhook immediately, push the heavy work onto a queue or worker. The [webhooks guide](/guides/webhooks#best-practices) has more on this.

### What we host vs what you host

To be explicit about the boundary:

| Thing                                          | Hosted by |
| ---------------------------------------------- | --------- |
| The audio file                                 | You       |
| Transcription, boundary detection, V5 analysis | Parlay    |
| Slice extraction (ffmpeg, byte range)          | You       |
| The analysis records and segment metadata      | Parlay    |
| Webhook delivery + signing                     | Parlay    |
| Webhook receiver                               | You       |

We never re-host audio. The `playback` block is a convenience set of recipes that operate on your URL. How and where you run them is up to you.

***

## Confidence + auto-analyze threshold

Each detected segment carries a confidence score from 0.0 to 1.0. The default behavior:

| Confidence | Default action                                    | Status         |
| ---------- | ------------------------------------------------- | -------------- |
| ≥ 0.8      | Auto-analyze with V5                              | `analyzed`     |
| 0.5 – 0.8  | Skip auto-analysis, surface for human review      | `needs_review` |
| `< 0.5`    | Skip entirely (probably not a sales conversation) | `skipped`      |

You can tune the threshold or turn auto-analysis off entirely:

```json theme={null}
{
  "recording_url": "...",
  "org_id": "acme",
  "rep_id": "alex",
  "options": {
    "min_confidence": 0.7,
    "auto_analyze": true
  }
}
```

Setting `auto_analyze: false` returns the detected segments without running V5 — useful when you want to filter or review before paying for analysis.

***

## Resolving playbooks per segment

Per-segment analyses run through the standard playbook resolver, which means **per-rep playbooks just work**.

If you've created a rep-level playbook for `alex-smith` (via [`POST /v1/orgs/:org_id/playbooks`](/api-reference/playbooks/create-a-playbook-org-level-or-per-rep-override) with `rep_id` set), every segment in this session uses Alex's playbook automatically. No extra config needed at the session level.

The full resolution order at analysis time:

1. `options.playbook_content` (request literal)
2. `options.playbook_id` (explicit id)
3. Active rep playbook for `rep_id`
4. Active org playbook for `org_id`
5. None (default scoring)

***

## Pricing model

Two billable events per session, both itemized on your usage report:

| Event                   | Trigger                             | Approximate cost           |
| ----------------------- | ----------------------------------- | -------------------------- |
| `all_day_transcription` | One Deepgram call on the full input | \~\$0.30 per hour of audio |
| `all_day_detection`     | Single-shot Gemini boundary call    | \~\$0.05 per session       |
| `analysis` (existing)   | One per analyzed segment            | \~\$0.06 per segment       |

**Worked example** — 8-hour day with 5 segments:

* Deepgram: \~\$2.40
* Boundary detection: \~\$0.05
* 5 × analysis: \~\$0.30
* **Total: \~\$2.75**

Compare to processing 5 separate recordings via `/v1/analyses` — same five analyses, but you'd pay Deepgram five times instead of once. **For an 8-hour day, all-day sessions are roughly 4× cheaper than the equivalent N standalone analyses.**

***

## Limits + edge cases

| Limit                              | Value                                                                                                                                   |
| ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| Audio length supported             | **1 minute to 12 hours**. Anything beyond 12 hours is best-effort and may hit Gemini boundary-detection ceilings around 15K utterances. |
| Min length                         | No hard minimum, but a recording shorter than \~30 seconds usually has no usable speech and will fail at the Deepgram step.             |
| Max segments per session           | No hard cap. 0, 1, or N are all valid. Typical days produce 5–15.                                                                       |
| Concurrent V5 analyses per session | 5                                                                                                                                       |
| Audio formats                      | MP3, WAV, M4A, AAC, OGG, FLAC, OPUS, WEBM, MP4                                                                                          |
| URL must be                        | HTTPS, no auth headers required, byte-range-fetchable                                                                                   |

If your URL requires authentication (e.g., S3 bucket policy denies public reads), use a **pre-signed URL** — that's what S3 and GCS pre-signed URLs are for, and Parlay handles them transparently.

***

## Submitting via MCP

For AI-agent workflows, the [`@goparlay/mcp-server`](/mcp/installation) package exposes four conversational tools:

```
submit_all_day_recording({
  recording_url: "https://your-bucket/full-day.mp3",
  org_id: "acme",
  rep_id: "alex",
})
// → returns the parent session + every detected segment with analysis_ids,
//   waits up to 10 minutes for completion

get_all_day_session({ session_id: "..." })
list_all_day_sessions({ rep_id: "alex" })
archive_all_day_session({ session_id: "..." })
```

The killer demo:

> *"My rep recorded their whole Tuesday — here's the URL. Tell me what happened and which calls need follow-up."*
>
> The AI calls `submit_all_day_recording`, gets the segments, summarizes each (Acme won, Beta Corp ongoing, Charlie skipped low-signal, Delta pricing pushback), and surfaces just the high-signal ones for review. One prompt, one URL, the rep's whole day analyzed.

***

## What we deliberately do NOT do

* **No second transcription.** We Deepgram the full file ONCE; per-segment analyses run on the sliced text. You don't pay Deepgram per segment.
* **No re-hosted audio.** No `segment_audio_url` field exists. Use HTTP Range requests on your original URL to play.
* **No human-review UI.** Segments below the confidence threshold are surfaced via `needs_review` status — what your dashboard does with them is up to you.
* **No automatic merge across multi-day recordings.** One session per recording; if a rep records two 4-hour days separately, that's two sessions.

***

## See also

* [`POST /v1/all-day-sessions` API reference](/api-reference/all-day-sessions/submit-a-long-form-recording-for-boundary-detection-per-segment-analysis)
* [Webhooks guide](/guides/webhooks) — handling `all_day_session.*` events
* [Playbooks guide](/api-reference/playbooks/create-a-playbook-org-level-or-per-rep-override) — per-rep playbooks for personalized scoring
* [`@goparlay/mcp-server`](/mcp/installation) — AI-native client install
