> For complete lifecycle-event payload schemas and examples, use the canonical overview: Session /api/sessions; Room lifecycle, members, and room playback /api/rooms; Session playback /api/playback; Recording /api/recording; DTMF /api/keypad-input; Messages /api/messages; WebSocket Session /api/web-socket. Use /api/event-delivery for transport behavior. Endpoint pages name relevant events, but these overviews are the canonical references.

# Stop recording room audio

POST https://api.telekesher.dev/api/v1/rooms/{room_id}/playback/record/stop

Stop the active room [Recording](/api/recording).

A `202 Accepted` response confirms that the stop request was accepted. It
does not mean the recording file is closed or final audio is available. The
flat response includes the request acknowledgement and the same Recording
identity.

Exactly one of these outcomes applies:

- If the room has an active Recording, the stop request is accepted.
- If the room has no active Recording, the response is
  `409 recording_not_active`; no recording command is sent and no event is
  emitted.

This operation does not support `Idempotency-Key`.

**Triggered webhook:**

- `recording.ended` is emitted immediately after the recording file is
  closed.
- It carries a fresh signed public URL for the same `recording_uuid`.
- A `media_url` request started at that boundary may briefly continue
  following the growing Recording until finalization completes.

See [Recording lifecycle events](/api/recording#lifecycle-events) for complete payload schemas and examples.

Reference: https://docs.vorbal.dev/api/room-playback/stop-recording

## Authentication

- `Authorization` header (bearer token, required) — Application auth. Send `Authorization: Bearer <app_uuid>:<api_key>` using any active key in the app's collection. See [Authentication](https://voice-platform.docs.buildwithfern.com/api/authentication) for details.

## Request

### Path parameters

- `room_id` (string, required) — Case-sensitive [room](/api/rooms) identifier.

### Headers

- `Operation-Id` (string, optional) — optional client-supplied lowercase RFC-4122 v4 UUID returned as operation_uuid; platform generates one when omitted; correlation metadata distinct from Idempotency-Key.

## Response

### 202

Room recording stop accepted

- `operation_uuid` (string, required)
- `status` (enum, required)
  - Allowed values: `in_progress`
- `recording_uuid` (string, required) — Stable identifier for this Recording.
- `expires_at` (datetime, required) — Exact expiry instant of media_url, derived from the URL's signed expiration.
- `media_url` (string, required) — Starts at byte zero and follows the growing Recording until EOF. After finalization, the same URL serves a finite, range-capable WAV. A boundary request may briefly wait for internal finalization. Validity defaults to 24 hours.
- `room_id` (string, optional) — Owning [Room](/api/rooms); mutually exclusive with `session_uuid`.
- `session_uuid` (string, optional) — Owning [Session](/api/sessions); mutually exclusive with `room_id`.

## Examples

**Response**

```json
{
  "operation_uuid": "550e8400-e29b-41d4-a716-446655440000",
  "status": "in_progress",
  "recording_uuid": "rec_11111111-2222-4333-8444-555555555555",
  "expires_at": "2026-08-03T12:00:00.000Z",
  "media_url": "https://recordings.example.com/c/signed-url-3",
  "room_id": "acW68-room-550e8400-e29b-41d4-a716-446655440000",
  "session_uuid": "acW68-f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
```

**SDK Code**

```python
import requests

url = "https://api.telekesher.dev/api/v1/rooms/room_id/playback/record/stop"

headers = {"Authorization": "Bearer <token>"}

response = requests.post(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.telekesher.dev/api/v1/rooms/room_id/playback/record/stop';
const options = {method: 'POST', headers: {Authorization: 'Bearer <token>'}};

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"
	"net/http"
	"io"
)

func main() {

	url := "https://api.telekesher.dev/api/v1/rooms/room_id/playback/record/stop"

	req, _ := http.NewRequest("POST", url, nil)

	req.Header.Add("Authorization", "Bearer <token>")

	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.telekesher.dev/api/v1/rooms/room_id/playback/record/stop")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.telekesher.dev/api/v1/rooms/room_id/playback/record/stop")
  .header("Authorization", "Bearer <token>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.telekesher.dev/api/v1/rooms/room_id/playback/record/stop', [
  'headers' => [
    'Authorization' => 'Bearer <token>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.telekesher.dev/api/v1/rooms/room_id/playback/record/stop");
var request = new RestRequest(Method.POST);
request.AddHeader("Authorization", "Bearer <token>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <token>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://api.telekesher.dev/api/v1/rooms/room_id/playback/record/stop")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers

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()
```