# API Keys | AudioDN Docs

> Generate Client-Side Player and Client-Side Upload keys programmatically from your server.

Source: https://audiodeliverynetwork.com/docs/api/api-keys/

---

# API Keys

Create new API keys server-to-server using an existing **API Access** key. This lets you provision **Client-Side Player** and **Client-Side Upload** keys on demand — for example, minting a scoped player key per customer.

#### Inline Share & URL Signing keys are dashboard-only

**Inline Share** (see [Inline Share](/docs/api/share)) and **URL Signing** (see [Signing Keys](/docs/api/signing-keys)) keys are documented here for reference, but they **cannot be created or managed through the API**. They must be created from **Settings → API Keys** in the [AudioDN dashboard](https://account.audiodeliverynetwork.com), because they provision edge configuration (signing rules) that the API does not manage.

#### API Access keys are created in the dashboard

You must first create an **API Access** key from **Settings → API Keys** in the [AudioDN dashboard](https://account.audiodeliverynetwork.com). That key authenticates this endpoint. API Access keys themselves cannot be created via the API.

## Creatable Key Types

-   `player` — Client-Side Player key for playback
-   `uploader` — Client-Side Upload key for uploads

The `api` (API Access), `share` (Inline Share), and `signing` (URL Signing) types cannot be created here — they are managed only from the dashboard **Settings → API Keys** page.

## Expiry & Scope

Via the API, `expires_at` is **optional** for both key types — omit it to create a key that never expires by time. You can optionally limit a key to a specific `collection_id` (and further to a `track_id`). If your API Access key is itself scoped to a collection, the new key cannot be scoped outside it.

**Downloads:** a player key can optionally permit downloads. This is set from the dashboard when creating the key (the _Allow downloads_ toggle) and is not configurable through this API endpoint. The key's download permission is authoritative: the player `downloadable` attribute only _requests_ downloads, and a play session is downloadable only when the key allows it _and_ the request opts in.

POST `/v1/api_key`

Creates a new player or uploader API key

#### Parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `title` | string | Required | Name of the API key |
| `api_key_type_id` | string | Required | One of 'player' or 'uploader'. Share and signing keys are dashboard-only. |
| `collection_id` | uuid | Optional | Limit the key to a specific collection |
| `track_id` | uuid | Optional | Limit the key to a specific track (requires collection\_id) |
| `creator_id` | uuid | Optional | Limit the key to a specific creator |
| `variants` | array of strings | Optional | Optional. Limit a player key to specific variants. |
| `expires_at` | string | Optional | ISO 8601 expiration date/time. Optional; omit for a key that never expires by time. |

#### Example Request

    

```
curl -X POST "https://api.audiodelivery.net/v1/api_key" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"title": "Customer Player Key", "api_key_type_id": "player", "collection_id": "COLLECTION_ID"}'
```

```
const response = await fetch('https://api.audiodelivery.net/v1/api_key', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({"title": "Customer Player Key", "api_key_type_id": "player", "collection_id": "COLLECTION_ID"})
});

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

```
import Foundation

func performRequest() async throws {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/api_key")!)
    request.httpMethod = "POST"
    request.setValue("Bearer YOUR_API_KEY", forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    let body = {"title": "Customer Player Key", "api_key_type_id": "player", "collection_id": "COLLECTION_ID"}
    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 = """{"title": "Customer Player Key", "api_key_type_id": "player", "collection_id": "COLLECTION_ID"}""".toRequestBody("application/json".toMediaType())
    val request = Request.Builder()
        .url("https://api.audiodelivery.net/v1/api_key")
        .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/api_key'),
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
    },
    body: jsonEncode({"title": "Customer Player Key", "api_key_type_id": "player", "collection_id": "COLLECTION_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,
  "api_request_id": "uuid",
  "api_key": "string"
}
```

#### Shown once

The full `api_key` is returned only in this response and is never stored in plaintext. Save it securely — it cannot be retrieved again.
