# Upload Sessions | AudioDN Docs

> API endpoints for creating secure upload sessions. Enable time-limited, authenticated audio file uploads to collections.

Source: https://audiodeliverynetwork.com/docs/api/upload-sessions/

---

# Upload Sessions

Upload sessions enable batch uploading of multiple tracks to a collection.

The resolved `player_color` is accompanied by two read-only companions, `player_color_light` and `player_color_dark`, adjusted to stay legible on light and dark backgrounds respectively.

POST `/v1/upload_session`

Creates a new upload session for batch uploading tracks. Returns an upload\_session\_id only — create a track in the session (below) to get a per-track upload URL.

#### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `collection_id` | uuid | Optional | ID of the collection. Required unless the API key is scoped to a collection. |
| `creator_id` | uuid | Optional | ID of the creator |
| `organization_index` | string | Optional | Organization index |
| `metadata` | object | Optional | Additional metadata |
| `expires_in` | number | Optional | Session duration in seconds (default: 3600, min: 60, max: 86400) |

#### Example Request

    

```
curl -X POST "https://api.audiodelivery.net/v1/upload_session" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"collection_id": "COLLECTION_ID", "expires_in": 7200}'
```

```
const response = await fetch('https://api.audiodelivery.net/v1/upload_session', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({"collection_id": "COLLECTION_ID", "expires_in": 7200})
});

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

```
import Foundation

func performRequest() async throws {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/upload_session")!)
    request.httpMethod = "POST"
    request.setValue("Bearer YOUR_API_KEY", forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    let body = {"collection_id": "COLLECTION_ID", "expires_in": 7200}
    request.httpBody = try JSONSerialization.data(withJSONObject: body)
    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", "expires_in": 7200}""".toRequestBody("application/json".toMediaType())
    val request = Request.Builder()
        .url("https://api.audiodelivery.net/v1/upload_session")
        .post(body)
        .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.post(
    Uri.parse('https://api.audiodelivery.net/v1/upload_session'),
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: jsonEncode({"collection_id": "COLLECTION_ID", "expires_in": 7200}),
  );
  if (response.statusCode < 200 || response.statusCode >= 300) {
    throw Exception('Request failed: ${response.statusCode}');
  }
  return jsonDecode(response.body) as Map<String, dynamic>;
}
```

#### Response

```
{
  "ok": true,
  "upload_session_id": "uuid",
  "upload_session": {
    "id": "uuid",
    "creator_id": "uuid | null",
    "collection_id": "uuid",
    "organization_index": "string | null",
    "metadata": {},
    "expires_at": "string"
  },
  "player_color": "string | null",
  "player_color_light": "string | null",
  "player_color_dark": "string | null",
  "expires_at": "string"
}
```

GET `/v1/upload_session/:upload_session_id`

Retrieves details about an upload session. No authentication required — the session ID acts as the credential.

#### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `upload_session_id` | uuid | Required | The ID of the upload session (path parameter) |

#### Example Request

    

```
curl -X GET "https://api.audiodelivery.net/v1/upload_session/SESSION_ID"
```

```
const response = await fetch('https://api.audiodelivery.net/v1/upload_session/SESSION_ID');

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

```
import Foundation

func performRequest() async throws {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/upload_session/SESSION_ID")!)
    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/upload_session/SESSION_ID")
        .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/upload_session/SESSION_ID'));
  if (response.statusCode < 200 || response.statusCode >= 300) {
    throw Exception('Request failed: ${response.statusCode}');
  }
  return jsonDecode(response.body) as Map<String, dynamic>;
}
```

#### Response

```
{
  "ok": true,
  "upload_session_id": "uuid",
  "upload_session": {
    "id": "uuid",
    "creator_id": "uuid | null",
    "collection_id": "uuid",
    "organization_index": "string | null",
    "metadata": {},
    "expires_at": "string"
  },
  "player_color": "string | null",
  "player_color_light": "string | null",
  "player_color_dark": "string | null",
  "expires_at": "string"
}
```

POST `/v1/upload/:upload_session_id/track`

Creates a new track within an upload session and returns its per-track upload URL. Call this once per file. No authentication required — the session ID acts as the credential.

#### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `upload_session_id` | uuid | Required | The ID of the upload session (path parameter) |
| `file_name` | string | Required | Original filename of the track |
| `organization_index` | string | Optional | Organization index |
| `metadata` | object | Optional | Additional metadata |

#### Example Request

    

```
curl -X POST "https://api.audiodelivery.net/v1/upload/SESSION_ID/track" \
  -H "Content-Type: application/json" \
  -d '{"file_name": "track-1.mp3"}'
```

```
const response = await fetch('https://api.audiodelivery.net/v1/upload/SESSION_ID/track', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({"file_name": "track-1.mp3"})
});

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

```
import Foundation

func performRequest() async throws {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/upload/SESSION_ID/track")!)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    let body = {"file_name": "track-1.mp3"}
    request.httpBody = try JSONSerialization.data(withJSONObject: body)
    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 = """{"file_name": "track-1.mp3"}""".toRequestBody("application/json".toMediaType())
    val request = Request.Builder()
        .url("https://api.audiodelivery.net/v1/upload/SESSION_ID/track")
        .post(body)
        .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/upload/SESSION_ID/track'),
    headers: {
      'Content-Type': 'application/json',
    },
    body: jsonEncode({"file_name": "track-1.mp3"}),
  );
  if (response.statusCode < 200 || response.statusCode >= 300) {
    throw Exception('Request failed: ${response.statusCode}');
  }
  return jsonDecode(response.body) as Map<String, dynamic>;
}
```

#### Response

```
{
  "ok": true,
  "api_request_id": "uuid",
  "upload_session_id": "uuid",
  "track_id": "uuid",
  "track": {
    "id": "uuid",
    "index": "string",
    "path": "string",
    "upload_url": "string"
  },
  "upload_session": {
    "id": "uuid",
    "creator_id": "uuid | null",
    "collection_id": "uuid",
    "organization_index": "string | null",
    "metadata": {},
    "expires_at": "string"
  },
  "track_upload": {
    "method": "PUT",
    "upload_url": "string",
    "ttl": 0,
    "expires_at": "string"
  },
  "track_cover_upload": {
    "method": "POST",
    "upload_url": "string",
    "ttl": 0,
    "expires_at": "string"
  }
}
```
