> For the documentation index, fetch https://sync.so/docs/llms.txt. Append .md to a page URL for Markdown. Documentation-search MCP: https://sync.so/docs/_mcp/server. # Edit dialogue and preview the result as audio POST https://api.sync.so/v2/dialogue-edits Content-Type: application/json Applies word-level edits to a transcript from `POST /v2/transcriptions` and synthesizes preview audio for the same window: only the edited spans are re-spoken in a voice cloned from the source, everything else stays the original recording. Poll `GET /v2/dialogue-edits/{id}` until `status` is `COMPLETED`, `COMPLETED_PARTIAL` or `FAILED`; a completed or partially completed job carries `previewAudioUrl`, the retimed `resultTranscript` and the edited regions as `resultSlots`. Edits that cannot be applied to the transcript are refused with a 400 before a job exists. An API-key request is admitted only for the whole video (leave startMs and endMs unset) and only when the organization's rollout enables segment lipsync and section expansion: a partial window is refused with errorCode `dialogue_edit_unsupported` (422), a rollout without both flags with `dialogue_edit_retime_required` (422), and a rollout that cannot be evaluated with `generation_infra_service_unavailable` (503; retry with backoff). Studio sessions may select a window. Normal billing, planning, duration and rate limits still apply. Reference: https://sync.so/docs/api-reference/api/dialogue-edits-api/create ## Authentication - `x-api-key` header (required) — API Key authentication via header ## Servers - `https://api.sync.so` (Default, default) - `https://dev-api.sync.so` (dev) - `http://localhost:3001` (local) ## Request ### Body (application/json) This endpoint expects a CreateDialogueEditDto. - `transcript` (Transcript, required) — The transcript the edits refer to, as returned by GET /v2/transcriptions/\{id}. Edits name words by their id in this transcript. Word timings are in milliseconds from the start of the source video. - `edits` (list of DialogueEditOperation, required) — The edits to apply: change replaces one word (wordId, replacement), remove cuts a contiguous run of words (wordIds). Between 1 and 100 edits per job. - `sourceVideoUrl` (string, required) — URL of the source video the transcript was made from, hosted in sync. storage (upload it via POST /v2/assets/upload first). - `startMs` (integer, optional) — Start of the edited window, in milliseconds from the start of the source. Use the same window the transcript was made for. Defaults to 0. An API-key request must leave startMs and endMs unset; the edit then covers the whole video. - `endMs` (integer, optional) — End of the edited window, in milliseconds from the start of the source. Omit to run to the end. The window cannot exceed 10 minutes. An API-key request must leave startMs and endMs unset to edit the whole video. - `voiceId` (string, optional) — Opaque voice id returned as voiceId by an earlier dialogue-edit job of the same source. Reusing it skips cloning the voice again. Omit on the first job for a source. Ids your organization has not used before are ignored. - `projectId` (string, optional) — Optional id of a project in your organization to file the job under. - `rerunOfJobId` (string, optional) — Id of the completed dialogue-edit job this request revises, when regenerating a preview after adjusting the edits. Informational lineage only; unknown ids are ignored. ## Response ### 201 Dialogue edit job created successfully - `id` (string, required) — Job id. Poll GET /v2/dialogue-edits/\{id} with it. - `status` (enum, required) — Job status. COMPLETED, COMPLETED_PARTIAL and FAILED are terminal. COMPLETED_PARTIAL means the preview is playable but shipped without something that was requested; treat it as completed. - Allowed values: `PENDING`, `PROCESSING`, `COMPLETED`, `COMPLETED_PARTIAL`, `FAILED` - `sourceVideoUrl` (string, required) — The source video the job was created from. - `sourceStartMs` (integer, required) — Start of the edited window, in source milliseconds. - `edits` (list of DialogueEditOperation, required) — The edits that were applied, exactly as submitted. - `segmentLipsyncEnabled` (boolean, required) — Whether the preview was cut for per-region lipsync (true) or for re-lipsyncing the whole window (false). Decided when the job is created and fixed for its lifetime. For jobs created with an API key, the rollout is evaluated against the organization's members. - `sectionExpansionEnabled` (boolean, required) — Whether the preview was made under the section-expansion policy. Decided when the job is created and fixed for its lifetime. For jobs created with an API key, the rollout is evaluated against the organization's members. - `createdAt` (datetime, required) — When the job was created. - `sourceEndMs` (integer, optional) — End of the edited window, in source milliseconds. Null when the job runs to the end of the source. - `previewAudioUrl` (string, optional) — Hosted WAV of the edited audio for the whole window: the original recording with only the edited spans re-synthesized. Null until the job completes. - `previewAssetId` (string, optional) — Asset id of the registered preview after completion, when available. Null or absent before completion or for an unregistered preview. To lipsync the edit, pass the job id as `dialogueEdit: { id }` on `POST /v2/generate`. - `previewDurationMs` (integer, optional) — Length of the preview audio in milliseconds. Differs from the window length by however much the edits grew or shrank it. Null until the job completes. - `sourceTranscript` (Transcript, optional) — The transcript the edits were made against, exactly as submitted. Returned in every status. - `resultTranscript` (Transcript, optional) — The transcript as it reads after the edits, with every word timed against the preview audio. Null until the job completes. - `resultSlots` (list of DialogueEditResultSlot, optional) — The edited regions in order, each located on the preview timeline (outputStartMs, outputDurationMs) and in the source video (sourceStartMs, sourceDurationMs). Everything between two slots is untouched source. Null until the job completes. - `voiceId` (string, optional) — Opaque id of the voice cloned from the source and used for synthesis. Pass it as voiceId on the next dialogue-edit job of the same source to skip cloning. Null until the voice exists. - `error` (DialogueEditError, optional) — Why the job failed. Null unless status is FAILED. - `startedAt` (datetime, optional) — When the job started processing. Null until it starts. - `finishedAt` (datetime, optional) — When the job reached a terminal status. Null until it finishes. ## Errors ### 400 Bad Request Error Bad Request - Invalid input or unsupported model - `message` (GenerationErrorMessage, required) — A message describing the error. - `statusCode` (double, required) — The type of error that occurred. - `errorCode` (string, optional) — Stable, machine-readable error code (e.g. project_not_found, voice_not_found, concurrency_limit_reached). Branch your error handling on this, not on the message text. The full catalog of codes with messages and suggested fixes is served unauthenticated at GET /v2/errors. - `suggestion` (string, optional) — A suggested fix an agent can act on. - `field` (string, optional) — The request field the error refers to, when the failure is tied to a specific field (e.g. projectId, voiceId, input[].assetId). - `docsUrl` (string, optional) — Link to the documentation page for the failing operation. - `requestId` (string, optional) — Present on unexpected 500 responses. Include it when contacting support so the failing request can be located directly. - `generationId` (string, optional) — Original generation ID when available for an uncertain keyed submission. Poll this ID; do not create another action to bypass IDEMPOTENCY_OUTCOME_UNKNOWN. - `dialogueEditSection` (DialogueEditRetimeFailureSection, optional) — For dialogue_edit_removal_too_large: the section to change, when it can be identified. Create a new dialogue edit preview before submitting again. ### 401 Unauthorized Error Unauthorized - Invalid or missing authentication - `message` (GenerationErrorMessage, required) — A message describing the error. - `statusCode` (double, required) — The type of error that occurred. - `errorCode` (string, optional) — Stable, machine-readable error code (e.g. project_not_found, voice_not_found, concurrency_limit_reached). Branch your error handling on this, not on the message text. The full catalog of codes with messages and suggested fixes is served unauthenticated at GET /v2/errors. - `suggestion` (string, optional) — A suggested fix an agent can act on. - `field` (string, optional) — The request field the error refers to, when the failure is tied to a specific field (e.g. projectId, voiceId, input[].assetId). - `docsUrl` (string, optional) — Link to the documentation page for the failing operation. - `requestId` (string, optional) — Present on unexpected 500 responses. Include it when contacting support so the failing request can be located directly. - `generationId` (string, optional) — Original generation ID when available for an uncertain keyed submission. Poll this ID; do not create another action to bypass IDEMPOTENCY_OUTCOME_UNKNOWN. - `dialogueEditSection` (DialogueEditRetimeFailureSection, optional) — For dialogue_edit_removal_too_large: the section to change, when it can be identified. Create a new dialogue edit preview before submitting again. ### 402 Payment Required Error Payment Required - Feature requires higher plan - `message` (GenerationErrorMessage, required) — A message describing the error. - `statusCode` (double, required) — The type of error that occurred. - `errorCode` (string, optional) — Stable, machine-readable error code (e.g. project_not_found, voice_not_found, concurrency_limit_reached). Branch your error handling on this, not on the message text. The full catalog of codes with messages and suggested fixes is served unauthenticated at GET /v2/errors. - `suggestion` (string, optional) — A suggested fix an agent can act on. - `field` (string, optional) — The request field the error refers to, when the failure is tied to a specific field (e.g. projectId, voiceId, input[].assetId). - `docsUrl` (string, optional) — Link to the documentation page for the failing operation. - `requestId` (string, optional) — Present on unexpected 500 responses. Include it when contacting support so the failing request can be located directly. - `generationId` (string, optional) — Original generation ID when available for an uncertain keyed submission. Poll this ID; do not create another action to bypass IDEMPOTENCY_OUTCOME_UNKNOWN. - `dialogueEditSection` (DialogueEditRetimeFailureSection, optional) — For dialogue_edit_removal_too_large: the section to change, when it can be identified. Create a new dialogue edit preview before submitting again. ### 422 Unprocessable Entity Error Unprocessable Entity - The requested generation is not downloadable (generation_not_downloadable), or submit-time validation failed (e.g. inaccessible media, invalid segments, a projectId/voiceId/assetId that does not resolve in your organization, or a file exceeding the plan size limit). The body carries a stable errorCode and, where applicable, the failing field. - `message` (GenerationErrorMessage, required) — A message describing the error. - `statusCode` (double, required) — The type of error that occurred. - `errorCode` (string, optional) — Stable, machine-readable error code (e.g. project_not_found, voice_not_found, concurrency_limit_reached). Branch your error handling on this, not on the message text. The full catalog of codes with messages and suggested fixes is served unauthenticated at GET /v2/errors. - `suggestion` (string, optional) — A suggested fix an agent can act on. - `field` (string, optional) — The request field the error refers to, when the failure is tied to a specific field (e.g. projectId, voiceId, input[].assetId). - `docsUrl` (string, optional) — Link to the documentation page for the failing operation. - `requestId` (string, optional) — Present on unexpected 500 responses. Include it when contacting support so the failing request can be located directly. - `generationId` (string, optional) — Original generation ID when available for an uncertain keyed submission. Poll this ID; do not create another action to bypass IDEMPOTENCY_OUTCOME_UNKNOWN. - `dialogueEditSection` (DialogueEditRetimeFailureSection, optional) — For dialogue_edit_removal_too_large: the section to change, when it can be identified. Create a new dialogue edit preview before submitting again. ### 429 Too Many Requests Error Too Many Requests - Batch concurrency limit reached - `statusCode` (double, required) — The HTTP status code (429). - `message` (GenerationErrorMessage, required) — A human-readable description of the error. - `errorCode` (string, optional) — Machine-readable error code (`concurrency_limit_reached`). - `activeBatches` (double, optional) — The number of batches you currently have in progress. - `concurrencyLimit` (double, optional) — The maximum number of concurrent batches allowed on your plan. - `retryAfterSeconds` (double, optional) — Suggested number of seconds to wait before retrying. Mirrors the `Retry-After` header. ### 500 Internal Server Error Internal Server Error - An unexpected failure on our side. The body carries errorCode internal_error and a requestId; include the requestId when contacting support. - `message` (GenerationErrorMessage, required) — A message describing the error. - `statusCode` (double, required) — The type of error that occurred. - `errorCode` (string, optional) — Stable, machine-readable error code (e.g. project_not_found, voice_not_found, concurrency_limit_reached). Branch your error handling on this, not on the message text. The full catalog of codes with messages and suggested fixes is served unauthenticated at GET /v2/errors. - `suggestion` (string, optional) — A suggested fix an agent can act on. - `field` (string, optional) — The request field the error refers to, when the failure is tied to a specific field (e.g. projectId, voiceId, input[].assetId). - `docsUrl` (string, optional) — Link to the documentation page for the failing operation. - `requestId` (string, optional) — Present on unexpected 500 responses. Include it when contacting support so the failing request can be located directly. - `generationId` (string, optional) — Original generation ID when available for an uncertain keyed submission. Poll this ID; do not create another action to bypass IDEMPOTENCY_OUTCOME_UNKNOWN. - `dialogueEditSection` (DialogueEditRetimeFailureSection, optional) — For dialogue_edit_removal_too_large: the section to change, when it can be identified. Create a new dialogue edit preview before submitting again. ### 503 Service Unavailable Error Service Unavailable - A sync. labs service or provider dependency is temporarily unavailable. The body carries a stable errorCode such as elevenlabs_service_unavailable or controller_dependency_error. Keyed generation creates may return IDEMPOTENCY_OUTCOME_UNKNOWN when acceptance needs reconciliation, or IDEMPOTENCY_UNAVAILABLE when new keyed admission is disabled. Preserve the same key and payload; do not bypass protection. generation_admission_paused means new generation requests are paused for maintenance; generation_admission_unavailable means the API can't confirm it is accepting them. Retry after Retry-After. - `message` (GenerationErrorMessage, required) — A message describing the error. - `statusCode` (double, required) — The type of error that occurred. - `errorCode` (string, optional) — Stable, machine-readable error code (e.g. project_not_found, voice_not_found, concurrency_limit_reached). Branch your error handling on this, not on the message text. The full catalog of codes with messages and suggested fixes is served unauthenticated at GET /v2/errors. - `suggestion` (string, optional) — A suggested fix an agent can act on. - `field` (string, optional) — The request field the error refers to, when the failure is tied to a specific field (e.g. projectId, voiceId, input[].assetId). - `docsUrl` (string, optional) — Link to the documentation page for the failing operation. - `requestId` (string, optional) — Present on unexpected 500 responses. Include it when contacting support so the failing request can be located directly. - `generationId` (string, optional) — Original generation ID when available for an uncertain keyed submission. Poll this ID; do not create another action to bypass IDEMPOTENCY_OUTCOME_UNKNOWN. - `dialogueEditSection` (DialogueEditRetimeFailureSection, optional) — For dialogue_edit_removal_too_large: the section to change, when it can be identified. Create a new dialogue edit preview before submitting again. ## Types ### Transcript A word-level transcript. Word timings are in milliseconds from the start of the source video. - `segments` (list of TranscriptSegment, required) — The transcript segments, in order. - `speakerCount` (integer, required) — The number of distinct speakers detected. ### DialogueEditOperation A single edit: change replaces one word, remove cuts a contiguous run of words. - `kind`: `change` - `replacement` (string, required) — The text to speak in place of the word. - `wordId` (string, required) — The id of the word to replace, from the submitted transcript. - `kind`: `remove` - `wordIds` (list of string, required) — The ids of the words to cut, from the submitted transcript. ### DialogueEditResultSlot An edited region, located on the preview timeline and in the source video. Everything between two slots is untouched source. - `kind` (enum, required) — The kind of edit this region represents. - Allowed values: `change`, `removal`, `silence` - `outputStartMs` (integer, required) — Start of the region on the preview timeline, in milliseconds. - `outputDurationMs` (integer, required) — Length of the region on the preview timeline, in milliseconds; 0 for a pure cut. - `sourceStartMs` (integer, optional) — Start of the region in the source video, in absolute milliseconds. - `sourceDurationMs` (integer, optional) — Length of the region in the source video, in milliseconds. ### DialogueEditError Why a dialogue edit job failed. Present only when status is FAILED. - `code` (enum, required) — Machine-readable failure code. EDIT_TOO_LONG, SOURCE_TOO_LONG, VOICE_SAMPLE_TOO_SHORT and PLAN_FAILED describe the request and will not succeed on retry. - Allowed values: `EXTRACTION_FAILED`, `VOICE_CLONE_FAILED`, `VOICE_SAMPLE_TOO_SHORT`, `SYNTHESIS_FAILED`, `EDIT_TOO_LONG`, `SOURCE_TOO_LONG`, `PLAN_FAILED`, `TIMEOUT`, `UNKNOWN` - `message` (string, required) — Human-readable summary of the failure. - `spanText` (string, optional) — For EDIT_TOO_LONG: the replacement text that does not fit the time its span has to occupy. Shorten it and resubmit. ### GenerationErrorMessage A message describing the error. ### DialogueEditRetimeFailureSection The dialogue-edit section that removes too much speech to stay in sync. - `slotIndex` (integer, required) — Zero-based index of the section in the preview's `resultSlots`. - `sourceStartMs` (integer, optional) — Start of the section in the source video, in absolute milliseconds. - `sourceDurationMs` (integer, optional) — Length of the section in the source video, in milliseconds. ### TranscriptSegment A run of words attributed to one speaker turn. - `id` (string, required) — The segment id. - `words` (list of TranscriptWord, required) — The words in the segment, in order. ### TranscriptWord A single transcribed word with its timing in the source. - `id` (string, required) — The word id. Dialogue edits name words by this id. - `text` (string, required) — The transcribed text of the word. - `startMs` (integer, required) — Start of the word, in milliseconds from the start of the source. - `endMs` (integer, required) — End of the word, in milliseconds from the start of the source. ## Examples **Request** ```json { "transcript": { "segments": [ { "id": "seg_1", "words": [ { "id": "w_1", "text": "The", "startMs": 120, "endMs": 260 }, { "id": "w_2", "text": "quarterly", "startMs": 260, "endMs": 820 }, { "id": "w_3", "text": "results", "startMs": 820, "endMs": 1240 } ] } ], "speakerCount": 1 }, "edits": [ { "kind": "change", "replacement": "annual", "wordId": "w_2" } ], "sourceVideoUrl": "https://assets.sync.so/docs/example-video.mp4" } ``` **Response** ```json { "id": "7644754c-bdfc-4d51-a78f-e0cb0cbbd40f", "status": "PENDING", "sourceVideoUrl": "https://assets.sync.so/docs/example-video.mp4", "sourceStartMs": 0, "edits": [ { "kind": "change", "replacement": "annual", "wordId": "w_2" } ], "segmentLipsyncEnabled": false, "sectionExpansionEnabled": false, "createdAt": "2024-01-15T09:31:00Z", "sourceEndMs": 30000 } ``` **SDK Code** ```python import requests url = "https://api.sync.so/v2/dialogue-edits" payload = { "transcript": { "segments": [ { "id": "seg_1", "words": [ { "id": "w_1", "text": "The", "startMs": 120, "endMs": 260 }, { "id": "w_2", "text": "quarterly", "startMs": 260, "endMs": 820 }, { "id": "w_3", "text": "results", "startMs": 820, "endMs": 1240 } ] } ], "speakerCount": 1 }, "edits": [ { "kind": "change", "replacement": "annual", "wordId": "w_2" } ], "sourceVideoUrl": "https://assets.sync.so/docs/example-video.mp4" } headers = { "x-api-key": "", "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) print(response.json()) ``` ```javascript const url = 'https://api.sync.so/v2/dialogue-edits'; const options = { method: 'POST', headers: {'x-api-key': '', 'Content-Type': 'application/json'}, body: '{"transcript":{"segments":[{"id":"seg_1","words":[{"id":"w_1","text":"The","startMs":120,"endMs":260},{"id":"w_2","text":"quarterly","startMs":260,"endMs":820},{"id":"w_3","text":"results","startMs":820,"endMs":1240}]}],"speakerCount":1},"edits":[{"kind":"change","replacement":"annual","wordId":"w_2"}],"sourceVideoUrl":"https://assets.sync.so/docs/example-video.mp4"}' }; try { const response = await fetch(url, options); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } ``` ```go package main import ( "fmt" "strings" "net/http" "io" ) func main() { url := "https://api.sync.so/v2/dialogue-edits" payload := strings.NewReader("{\n \"transcript\": {\n \"segments\": [\n {\n \"id\": \"seg_1\",\n \"words\": [\n {\n \"id\": \"w_1\",\n \"text\": \"The\",\n \"startMs\": 120,\n \"endMs\": 260\n },\n {\n \"id\": \"w_2\",\n \"text\": \"quarterly\",\n \"startMs\": 260,\n \"endMs\": 820\n },\n {\n \"id\": \"w_3\",\n \"text\": \"results\",\n \"startMs\": 820,\n \"endMs\": 1240\n }\n ]\n }\n ],\n \"speakerCount\": 1\n },\n \"edits\": [\n {\n \"kind\": \"change\",\n \"replacement\": \"annual\",\n \"wordId\": \"w_2\"\n }\n ],\n \"sourceVideoUrl\": \"https://assets.sync.so/docs/example-video.mp4\"\n}") req, _ := http.NewRequest("POST", url, payload) req.Header.Add("x-api-key", "") req.Header.Add("Content-Type", "application/json") res, _ := http.DefaultClient.Do(req) defer res.Body.Close() body, _ := io.ReadAll(res.Body) fmt.Println(res) fmt.Println(string(body)) } ``` ```ruby require 'uri' require 'net/http' url = URI("https://api.sync.so/v2/dialogue-edits") http = Net::HTTP.new(url.host, url.port) http.use_ssl = true request = Net::HTTP::Post.new(url) request["x-api-key"] = '' request["Content-Type"] = 'application/json' request.body = "{\n \"transcript\": {\n \"segments\": [\n {\n \"id\": \"seg_1\",\n \"words\": [\n {\n \"id\": \"w_1\",\n \"text\": \"The\",\n \"startMs\": 120,\n \"endMs\": 260\n },\n {\n \"id\": \"w_2\",\n \"text\": \"quarterly\",\n \"startMs\": 260,\n \"endMs\": 820\n },\n {\n \"id\": \"w_3\",\n \"text\": \"results\",\n \"startMs\": 820,\n \"endMs\": 1240\n }\n ]\n }\n ],\n \"speakerCount\": 1\n },\n \"edits\": [\n {\n \"kind\": \"change\",\n \"replacement\": \"annual\",\n \"wordId\": \"w_2\"\n }\n ],\n \"sourceVideoUrl\": \"https://assets.sync.so/docs/example-video.mp4\"\n}" response = http.request(request) puts response.read_body ``` ```java import com.mashape.unirest.http.HttpResponse; import com.mashape.unirest.http.Unirest; HttpResponse response = Unirest.post("https://api.sync.so/v2/dialogue-edits") .header("x-api-key", "") .header("Content-Type", "application/json") .body("{\n \"transcript\": {\n \"segments\": [\n {\n \"id\": \"seg_1\",\n \"words\": [\n {\n \"id\": \"w_1\",\n \"text\": \"The\",\n \"startMs\": 120,\n \"endMs\": 260\n },\n {\n \"id\": \"w_2\",\n \"text\": \"quarterly\",\n \"startMs\": 260,\n \"endMs\": 820\n },\n {\n \"id\": \"w_3\",\n \"text\": \"results\",\n \"startMs\": 820,\n \"endMs\": 1240\n }\n ]\n }\n ],\n \"speakerCount\": 1\n },\n \"edits\": [\n {\n \"kind\": \"change\",\n \"replacement\": \"annual\",\n \"wordId\": \"w_2\"\n }\n ],\n \"sourceVideoUrl\": \"https://assets.sync.so/docs/example-video.mp4\"\n}") .asString(); ``` ```php request('POST', 'https://api.sync.so/v2/dialogue-edits', [ 'body' => '{ "transcript": { "segments": [ { "id": "seg_1", "words": [ { "id": "w_1", "text": "The", "startMs": 120, "endMs": 260 }, { "id": "w_2", "text": "quarterly", "startMs": 260, "endMs": 820 }, { "id": "w_3", "text": "results", "startMs": 820, "endMs": 1240 } ] } ], "speakerCount": 1 }, "edits": [ { "kind": "change", "replacement": "annual", "wordId": "w_2" } ], "sourceVideoUrl": "https://assets.sync.so/docs/example-video.mp4" }', 'headers' => [ 'Content-Type' => 'application/json', 'x-api-key' => '', ], ]); echo $response->getBody(); ``` ```csharp using RestSharp; var client = new RestClient("https://api.sync.so/v2/dialogue-edits"); var request = new RestRequest(Method.POST); request.AddHeader("x-api-key", ""); request.AddHeader("Content-Type", "application/json"); request.AddParameter("application/json", "{\n \"transcript\": {\n \"segments\": [\n {\n \"id\": \"seg_1\",\n \"words\": [\n {\n \"id\": \"w_1\",\n \"text\": \"The\",\n \"startMs\": 120,\n \"endMs\": 260\n },\n {\n \"id\": \"w_2\",\n \"text\": \"quarterly\",\n \"startMs\": 260,\n \"endMs\": 820\n },\n {\n \"id\": \"w_3\",\n \"text\": \"results\",\n \"startMs\": 820,\n \"endMs\": 1240\n }\n ]\n }\n ],\n \"speakerCount\": 1\n },\n \"edits\": [\n {\n \"kind\": \"change\",\n \"replacement\": \"annual\",\n \"wordId\": \"w_2\"\n }\n ],\n \"sourceVideoUrl\": \"https://assets.sync.so/docs/example-video.mp4\"\n}", ParameterType.RequestBody); IRestResponse response = client.Execute(request); ``` ```swift import Foundation let headers = [ "x-api-key": "", "Content-Type": "application/json" ] let parameters = [ "transcript": [ "segments": [ [ "id": "seg_1", "words": [ [ "id": "w_1", "text": "The", "startMs": 120, "endMs": 260 ], [ "id": "w_2", "text": "quarterly", "startMs": 260, "endMs": 820 ], [ "id": "w_3", "text": "results", "startMs": 820, "endMs": 1240 ] ] ] ], "speakerCount": 1 ], "edits": [ [ "kind": "change", "replacement": "annual", "wordId": "w_2" ] ], "sourceVideoUrl": "https://assets.sync.so/docs/example-video.mp4" ] as [String : Any] let postData = JSONSerialization.data(withJSONObject: parameters, options: []) let request = NSMutableURLRequest(url: NSURL(string: "https://api.sync.so/v2/dialogue-edits")! as URL, cachePolicy: .useProtocolCachePolicy, timeoutInterval: 10.0) request.httpMethod = "POST" request.allHTTPHeaderFields = headers request.httpBody = postData as Data let session = URLSession.shared let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in if (error != nil) { print(error as Any) } else { let httpResponse = response as? HTTPURLResponse print(httpResponse) } }) dataTask.resume() ```