API Reference

The AudioLib API allows you to fetch random audio tracks from curated libraries. It follows REST conventions and returns JSON responses.

API base URL

http://api.audiolib.ai

Quick Start

Get a playable audio URL in one request.

cURL

bash
curl -X POST http://api.audiolib.ai/v1/audio \
  -H "Authorization: Bearer alp_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"library":"audio.focus"}'

JavaScript

javascript
const res = await fetch('http://api.audiolib.ai/v1/audio', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer alp_your_api_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ library: 'audio.focus' }),
})

const json = await res.json()
if (json.code !== 0) throw new Error(json.msg || 'Audio request failed')

const { url, quota } = json.data
console.log('Remaining quota:', quota.remaining_quota)
new Audio(url).play()

DSH Plugin

dsh-plugin-audiolib turns AudioLib into an ambient soundtrack for DeepSeek Harness, driven by the agent's own session events: a turn opens and music plays, every turn closes and the room goes quiet. A track is never interrupted by a state change — the state you are in when a track ends decides what plays next.

Install

DSH manages profile plugins with pnpm, so enable it first. If you installed DSH with npx @deepseek-ai/dsh web, the CLI lives inside the profile and plain dsh is not on your PATH — reach it through npx instead.

bash
corepack enable pnpm
npx @deepseek-ai/dsh plugin --profile web add dsh-plugin-audiolib

corepack ships with Node, so this adds no third-party global install, and corepack disable pnpm reverses it. Already have dsh on your PATH some other way? dsh plugin --profile web add dsh-plugin-audiolib works the same.

Add your API key

Restart the harness, then open Settings → Plugins → Plugin configuration and paste your key into the AudioLib soundtrack card. It goes to the DSH credential store (~/.dsh/.credentials.yaml, mode 600), never into a config file, and takes effect on the next track without a restart. The environment works too, if you prefer it:

bash
export AUDIOLIB_API_KEY=alp_your_api_key

Generate keys from your dashboard — the free tier is 300 requests/month.

Install a streaming player

Tracks stream: playback starts on the first buffered bytes, the way an AudioLib URL is meant to be consumed. That needs a player that reads a URL — mpv or ffplay, whichever is on PATH.

bash
brew install mpv        # macOS
apt install mpv         # Linux

Without one, the plugin falls back to macOS's built-in afplay, which only reads local files. It then downloads each track ahead of the moment it is needed — a working fallback, but it spends several megabytes per track and stalls when switching libraries mid-session.

Configure

Override the plugin row in your profile's cordis.patch.yml:

yaml
- id: audiolib
  name: dsh-plugin-audiolib
  config:
    workingLibrary: audio.focus
    idleLibrary: audio.ambient
FieldDefaultMeaning
apiKeyRefAUDIOLIB_API_KEYName of the credential holding the key — a reference, never the key itself
baseUrlhttp://api.audiolib.ai/v1/audioAudio endpoint
ambienttrueLet session events drive the soundtrack
workingLibraryaudio.focusPlays while a turn is open; '' for silence
idleLibrary''Plays once every turn has closed; '' for silence
exposeToolstrueGive the model music_play / music_stop / music_status
playerCommand[]Player argv; empty auto-selects. {url} declares a streaming player, {file} a file-only one
requestTimeoutMs15000AudioLib request deadline

Any library id the API accepts works — see the library catalog for the full list.

Note: The card's library pickers are read-only for now — DSH serves only built-in plugins' settings sections to the browser. Set the libraries in cordis.patch.yml until that lifts. The key control is unaffected.

Tools

With exposeTools on, the model can score its own work:

ToolBehaviour
music_play(library)Takes effect at the next seam; starts immediately when nothing is playing.
music_stop()Stops now and stays silent until music_play is called again.
music_status()Reports the playing track plus plan, remaining calls, and rate limit. Costs no API call — every audio response carries a quota snapshot.

These are ordinary registrations on ctx.tools, so Code Mode can call them as await tools.music_play({ library }) too. An explicit choice lasts as long as the work does: when the last open turn closes, the soundtrack returns to idleLibrary.

Authentication

All API requests require a Bearer token in the Authorization header. Generate API keys from your dashboard.

http
Authorization: Bearer alp_your_api_key_here

Key format: API keys begin with alp_ followed by 32 random characters. Keys are shown only once upon creation. Store them securely.

Endpoints

MethodEndpointDescription
POST/v1/audioFetch a random audio track from a library

Request Format

Send a JSON body with the library field set to a library's standard name.

FieldTypeRequiredDescription
librarystringYesThe standard name of the library (e.g. "audio.ambient")
json
{
  "library": "audio.ambient"
}

Response Format

Success responses use a standard envelope. Audio fields are in data.

json
{
  "code": 0,
  "data": {
    "title": "Deep Space Drift",
    "url": "https://cdn.example.com/audio/track.m4a",
    "duration_sec": 240,
    "quota": {
      "plan_name": "Free",
      "total_quota": 300,
      "used_quota": 7,
      "remaining_quota": 293,
      "is_unlimited": false,
      "rate_per_minute": 60,
      "period_end": 1782864000
    }
  },
  "msg": "ok"
}

Quota fields

Successful audio responses include the current quota snapshot in data.quota. Use it to show remaining usage or rate-limit information in your product.

FieldTypeDescription
quota.plan_namestringCurrent plan display name.
quota.total_quotanumberTotal audio calls available in the current period.
quota.used_quotanumberAudio calls already used in the current period.
quota.remaining_quotanumberAudio calls still available in the current period.
quota.is_unlimitedbooleanWhether the active plan has unlimited audio calls.
quota.rate_per_minutenumberMaximum audio API calls allowed per minute.
quota.period_endnumberUnix timestamp in seconds when the current quota period ends.

Error Codes

HTTP StatusError CodeDescription
401MISSING_AUTHAuthorization header is missing or malformed
401INVALID_KEY_FORMATAPI key does not match expected format (alp_...)
401INVALID_KEYAPI key is invalid, inactive, or revoked
400INVALID_JSONRequest body is not valid JSON
400MISSING_LIBRARYThe library field is missing from the request body
404LIBRARY_NOT_FOUNDNo library found with the given name
404NO_AUDIO_ITEMSThe library has no active audio items
429QUOTA_EXCEEDEDThe current quota period has no remaining successful audio API calls
503PRESIGN_FAILEDTemporary URL could not be generated (storage/signing error)
500INTERNAL_ERRORAn unexpected server error occurred
json
{
  "error": "Library 'audio.unknown' not found",
  "code": "LIBRARY_NOT_FOUND"
}

Examples

cURL

bash
curl -X POST http://api.audiolib.ai/v1/audio \
  -H "Authorization: Bearer alp_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{"library":"audio.sleep"}'

JavaScript (fetch)

javascript
const response = await fetch('http://api.audiolib.ai/v1/audio', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer alp_your_api_key',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ library: 'audio.focus' }),
})

const json = await response.json()
if (json.code !== 0) throw new Error(json.msg || 'Audio request failed')

console.log(json.data.url) // Play this URL
console.log(json.data.quota.remaining_quota) // Show remaining quota

Python (requests)

python
import requests

response = requests.post(
    'http://api.audiolib.ai/v1/audio',
    headers={'Authorization': 'Bearer alp_your_api_key'},
    json={'library': 'audio.ambient'}
)

data = response.json()
if data['code'] != 0:
    raise RuntimeError(data.get('msg', 'Audio request failed'))

print(data['data']['url'])
print(data['data']['quota']['remaining_quota'])