# Sesiones de reproducción | Docs de AudioDN

> Endpoints de la API para crear sesiones de reproducción de audio seguras. Controla el acceso a pistas, colecciones y playlists con sesiones de reproducción con tiempo limitado y alcance definido.

Source: https://audiodeliverynetwork.com/es/docs/api/play-sessions/

---

# Sesiones de reproducción

Las sesiones de reproducción gestionan la reproducción de audio de colecciones, pistas o playlists.

El `player_color` resuelto de cada pista va acompañado de dos compañeros de solo lectura: `player_color_light` (ajustado para permanecer legible sobre un fondo claro) y `player_color_dark` (ajustado para un fondo oscuro), para que tu player pueda elegir el adecuado según su tema.

POST `/v1/play_session/:scope`

Crea una nueva sesión de reproducción para una colección o pista.

#### Parámetros

| Nombre | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `scope` | string | Obligatorio | "collection" o "track" (parámetro de ruta). "playlist" está reservado para una versión futura y actualmente devuelve 400. |
| `variants` | array of strings | Obligatorio | Lista no vacía de índices de variante para la sesión de reproducción (p. ej. \["hq", "lq"\]). |
| `collection_id` | uuid | Obligatorio | ID de la colección cuando el scope es "collection". Obligatorio salvo que la clave API tenga alcance a una colección. |
| `track_id` | uuid | Obligatorio | ID de la pista cuando el scope es "track". Obligatorio salvo que la clave API tenga alcance a una pista. |
| `is_downloadable` | boolean | Opcional | Solicita que las pistas de esta sesión sean descargables. Solo se respeta cuando la clave API también permite descargas (se configura por clave en el panel). El valor almacenado de la sesión es api\_key.is\_downloadable AND esta solicitud, así que una clave que prohíbe descargas siempre gana — el endpoint de descarga devolverá 403. |
| `expires_in` | number | Opcional | Duración de la sesión en segundos (predeterminado: 3600, mín: 60, máx: 86400) |

#### Ejemplo de solicitud

    

```
curl -X POST "https://api.audiodelivery.net/v1/play_session/collection" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "collection_id": "COLLECTION_ID",
  "variants": [
    "hq",
    "lq"
  ],
  "expires_in": 3600
}'
```

```
const payload = {
  "collection_id": "COLLECTION_ID",
  "variants": [
    "hq",
    "lq"
  ],
  "expires_in": 3600
};

const response = await fetch('https://api.audiodelivery.net/v1/play_session/collection', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(payload)
});

const data = await response.json();
```

```
import Foundation

func performRequest() async throws {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/play_session/collection")!)
    request.httpMethod = "POST"
    request.setValue("Bearer YOUR_API_KEY", forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    let bodyJSON = """
{
  "collection_id": "COLLECTION_ID",
  "variants": [
    "hq",
    "lq"
  ],
  "expires_in": 3600
}
"""
    request.httpBody = bodyJSON.data(using: .utf8)
    let (data, _) = try await URLSession.shared.data(for: request)
    let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
    // use json
}
```

```
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody

val client = OkHttpClient()

suspend fun performRequest(): String = withContext(Dispatchers.IO) {
    val body = """{
  "collection_id": "COLLECTION_ID",
  "variants": [
    "hq",
    "lq"
  ],
  "expires_in": 3600
}""".toRequestBody("application/json".toMediaType())
    val request = Request.Builder()
        .url("https://api.audiodelivery.net/v1/play_session/collection")
        .post(body)
        .addHeader("Authorization", "Bearer YOUR_API_KEY")
        .addHeader("Content-Type", "application/json")
        .build()
    val response = client.newCall(request).execute()
    response.body?.string() ?: error("Empty response body")
}
```

```
import 'dart:convert';
import 'package:http/http.dart' as http;

Future<Map<String, dynamic>> performRequest() async {
  final response = await http.post(
    Uri.parse("https://api.audiodelivery.net/v1/play_session/collection"),
    headers: {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
    },
    body: jsonEncode({
  "collection_id": "COLLECTION_ID",
  "variants": [
    "hq",
    "lq"
  ],
  "expires_in": 3600
}),
  );
  if (response.statusCode < 200 || response.statusCode >= 300) {
    throw Exception('Request failed: ${response.statusCode}');
  }
  return jsonDecode(response.body) as Map<String, dynamic>;
}
```

#### Respuesta

```
{
"ok": true,
"play_session_id": "uuid",
"play_session": {
  "id": "uuid",
  "creator_id": "uuid | null",
  "variants": ["string"],
  "is_downloadable": false,
  "expires_at": "string"
},
"tracks": [
  { "id": "uuid", "index": "string", "duration": 0, "order": 0, "player_title": "string | null", "player_subtitle": "string | null", "player_color": "string | null", "player_color_light": "string | null", "player_color_dark": "string | null" }
],
"first_track": {
  "track_id": "uuid",
  "cover_image": {
    "icon": { "type": "icon", "width": 80, "height": 80, "url": "string" },
    "small": { "type": "small", "width": 200, "height": 200, "url": "string" },
    "regular": { "type": "regular", "width": 400, "height": 400, "url": "string" }
  },
  "track": {
    "id": "uuid",
    "index": "string",
    "duration": 0,
    "player_title": "string | null",
    "player_subtitle": "string | null",
    "player_color": "string | null",
    "player_color_light": "string | null",
    "player_color_dark": "string | null",
    "theme": [],
    "file_name": "string",
    "info": {},
    "organization_index": "string | null",
    "order": 0,
    "metadata": {},
    "is_dark": false
  },
  "levels": { "levels": [ 0, 0.5, 1 ] },
  "variants": [
    { "path": "string", "url": "string", "variant": { "index": "string" } }
  ]
},
"expires_at": "string"
}
```

El campo `first_track` incluye los datos completos de reproducción de la primera pista (URLs de streaming firmadas, niveles de forma de onda, imagen de portada y variantes) para que tu player pueda renderizar de inmediato sin una segunda llamada a la API. Usa `GET /v1/play/:session_id/:track_id` para obtener pistas adicionales bajo demanda.

GET `/v1/play_session/:play_session_id`

Recupera detalles de una sesión de reproducción

#### Parámetros

| Nombre | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `play_session_id` | uuid | Obligatorio | El ID de la sesión de reproducción (parámetro de ruta) |

#### Ejemplo de solicitud

    

```
curl -X GET "https://api.audiodelivery.net/v1/play_session/SESSION_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

```
const response = await fetch('https://api.audiodelivery.net/v1/play_session/SESSION_ID', {
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
  }
});

const data = await response.json();
```

```
import Foundation

func performRequest() async throws {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/play_session/SESSION_ID")!)
    request.httpMethod = "GET"
    request.setValue("Bearer YOUR_API_KEY", forHTTPHeaderField: "Authorization")
    let (data, _) = try await URLSession.shared.data(for: request)
    let json = try JSONSerialization.jsonObject(with: data) as! [String: Any]
    // use json
}
```

```
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import okhttp3.*

val client = OkHttpClient()

suspend fun performRequest(): String = withContext(Dispatchers.IO) {
    val request = Request.Builder()
        .url("https://api.audiodelivery.net/v1/play_session/SESSION_ID")
        .addHeader("Authorization", "Bearer YOUR_API_KEY")
        .build()
    val response = client.newCall(request).execute()
    response.body?.string() ?: error("Empty response body")
}
```

```
import 'dart:convert';
import 'package:http/http.dart' as http;

Future<Map<String, dynamic>> performRequest() async {
  final response = await http.get(
    Uri.parse("https://api.audiodelivery.net/v1/play_session/SESSION_ID"),
    headers: {
      "Authorization": "Bearer YOUR_API_KEY",
    },
  );
  if (response.statusCode < 200 || response.statusCode >= 300) {
    throw Exception('Request failed: ${response.statusCode}');
  }
  return jsonDecode(response.body) as Map<String, dynamic>;
}
```

#### Respuesta

```
{
"ok": true,
"play_session_id": "uuid",
"play_session": {
  "id": "uuid",
  "creator_id": "uuid | null",
  "variants": ["string"],
  "is_downloadable": false,
  "expires_at": "string"
},
"tracks": [
  { "id": "uuid", "index": "string", "duration": 0, "order": 0, "player_title": "string | null", "player_subtitle": "string | null", "player_color": "string | null", "player_color_light": "string | null", "player_color_dark": "string | null" }
],
"first_track": {
  "track_id": "uuid",
  "cover_image": { "icon": {}, "small": {}, "regular": {} },
  "track": { "id": "uuid", "index": "string", "duration": 0, "player_title": "string | null", "player_subtitle": "string | null", "player_color": "string | null", "player_color_light": "string | null", "player_color_dark": "string | null", "theme": [], "file_name": "string", "info": {}, "organization_index": "string | null", "order": 0, "metadata": {}, "is_dark": false },
  "levels": { "levels": [] },
  "variants": [ { "path": "string", "url": "string", "variant": { "index": "string" } } ]
}
}
```

El campo `first_track` incluye los datos completos de reproducción de la primera pista para que tu player pueda renderizar de inmediato sin una segunda llamada a la API.

GET `/v1/play/:play_session_id/:play_track_id`

Recupera detalles de una pista concreta dentro de una sesión de reproducción. No se requiere autenticación: el ID de sesión actúa como token bearer.

#### Parámetros

| Nombre | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `play_session_id` | uuid | Obligatorio | El ID de la sesión de reproducción (parámetro de ruta) |
| `play_track_id` | uuid | Obligatorio | El ID de la pista dentro de la sesión (parámetro de ruta) |

#### Respuesta

```
{
"ok": true,
"play_session_id": "uuid",
"track_id": "uuid",
"play_session": {
  "id": "uuid",
  "variants": ["string"],
  "is_downloadable": false,
  "expires_at": "string"
},
"cover_image": {
  "icon": { "type": "icon", "width": 80, "height": 80, "url": "string" },
  "small": { "type": "small", "width": 200, "height": 200, "url": "string" },
  "regular": { "type": "regular", "width": 400, "height": 400, "url": "string" }
},
"track": {
  "id": "uuid",
  "index": "string",
  "duration": 0,
  "player_title": "string | null",
  "player_subtitle": "string | null",
  "player_color": "string | null",
  "player_color_light": "string | null",
  "player_color_dark": "string | null",
  "theme": [],
  "file_name": "string",
  "info": {},
  "organization_index": "string | null",
  "order": 0,
  "metadata": {},
  "is_dark": false
},
"levels": { "levels": [ 0, 0.5, 1 ] },
"variants": [
  { "path": "string", "url": "string", "variant": { "index": "string" } }
]
}
```

GET `/v1/play/:play_session_id/:play_track_id/:variant_index/download`

Descarga una variante concreta de una pista. Solo disponible cuando el is\_downloadable almacenado de la sesión es true (es decir, la clave API permite descargas y la sesión las solicitó); en caso contrario devuelve 403. No se requiere autenticación.

#### Parámetros

| Nombre | Tipo | Obligatorio | Descripción |
| --- | --- | --- | --- |
| `play_session_id` | uuid | Obligatorio | El ID de la sesión de reproducción (parámetro de ruta) |
| `play_track_id` | uuid | Obligatorio | El ID de la pista dentro de la sesión (parámetro de ruta) |
| `variant_index` | string | Obligatorio | El índice/identificador de la variante a descargar (parámetro de ruta) |

#### Respuesta

Devuelve una URL de descarga firmada de corta duración (30s). El cuerpo de la respuesta es JSON (no el archivo de audio); navega a `download.url` para obtener el archivo. La URL se sirve con `Content-Disposition: attachment` para que el navegador guarde el archivo en lugar de reproducirlo en línea. Si la sesión no es descargable, el endpoint devuelve `403` con un mensaje de error.

```
{
"ok": true,
"play_session_id": "uuid",
"track_id": "uuid",
"download": {
  "variant": "string",
  "url": "string"
}
}
```
