---
title: "Sent when a separation finishes and the stems are ready."
method: POST
path: "separation.completed"
---

# Sent when a separation finishes and the stems are ready.

`POST separation.completed` (webhook)

The instrumental and vocal tracks have been written to storage and the song is ready to download.

Delivered to every enabled endpoint subscribed to this event.

**Verify the signature.** Compute
`HMAC-SHA256(secret, timestamp + '.' + rawBody)` as hex and compare it
to the value in `x-vocaless-signature` (after the `v1=` prefix) using a
constant-time comparison. Reject a `x-vocaless-timestamp` far from your
own clock to prevent replay.

**Deduplicate on `x-vocaless-delivery`.** A delivery is retried up to 4
times (1m, 5m, 25m) until it gets a 2xx, and a worker that dies
mid-request may resend one that already arrived.

Download URLs are deliberately absent: they are short-lived, so call
`GET /songs/{id}` when you are ready to fetch the audio.

## Headers

- `x-vocaless-signature` string, required
- `x-vocaless-timestamp` string, required
- `x-vocaless-delivery` string, required

## Payload

- object
  - `id` string, uuid, required: Delivery id, same as the header.
  - `type` 'separation.completed', required
  - `created_at` string, date-time, required
  - `data` object, required
    - `song` WebhookSong, required
      - `duration_seconds` number, nullable, required
      - `id` string, required
      - `name` string, required
      - `status` 'error' | 'ready' | 'separating' | 'uploaded' | 'uploading', required

## Acknowledgement `2xx`

Any 2xx marks the delivery successful. Anything else is retried.

---

[API](https://skmtc.dev/vocaless/apis/vocaless-api.md) · [All operations](https://skmtc.dev/vocaless/apis/vocaless-api/llms.txt) · [OpenAPI document](https://skmtc.dev/vocaless/apis/vocaless-api/revisions/db15b6df3aa2?raw)
