openapi: 3.2.0 info: title: AudD Music Recognition Streams API version: 1.4.4 description: 'The AudD music recognition API identifies songs from short audio clips (`api.audd.io/`), large audio/video files (`enterprise.audd.io/`), and real-time audio streams (callback or longpoll based on `api.audd.io/`). This OpenAPI document is the canonical contract for the API. Every official AudD SDK validates its parser against the fixtures shipped alongside this spec. Documentation: https://docs.audd.io Get an api_token: https://dashboard.audd.io Support: api@audd.io' contact: name: AudD API Support email: api@audd.io url: https://audd.io license: name: MIT identifier: MIT servers: - url: https://api.audd.io description: Standard recognition, streams and custom catalog endpoints. - url: https://enterprise.audd.io description: Enterprise large-file recognition endpoint. security: - api_token_form: [] - api_token_query: [] tags: - name: Streams paths: /setCallbackUrl/: post: operationId: setCallbackUrl summary: Configure where AudD POSTs stream-recognition callbacks tags: - Streams requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: true required: - api_token - url properties: api_token: type: string url: type: string format: uri description: 'Where AudD POSTs callbacks. Set to `https://audd.tech/empty/` if you only want longpoll. The URL itself can carry a `?return=apple_music,deezer` parameter to receive that metadata in callbacks. ' responses: '200': description: Callback URL set or rejected. content: application/json: schema: oneOf: - $ref: '#/components/schemas/StreamMutationSuccessResponse' - $ref: '#/components/schemas/ErrorResponse' examples: success: summary: Standard mutation-success response value: status: success result: null /getCallbackUrl/: post: operationId: getCallbackUrl summary: Get the configured callback URL tags: - Streams requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: true required: - api_token properties: api_token: type: string responses: '200': description: 'Returns the URL or — when no callback URL has ever been configured — error code 19 with message "Internal error". **The SDK uses this signal to short-circuit longpoll setup.** ' content: application/json: schema: oneOf: - $ref: '#/components/schemas/GetCallbackUrlSuccessResponse' - $ref: '#/components/schemas/ErrorResponse' examples: no_callback_configured: externalValue: https://raw.githubusercontent.com/AudDMusic/audd-openapi/63414c0a939be98c9ec6d9c2eb5c4c7b92b60a51/fixtures/error_19_no_callback_url.json /addStream/: post: operationId: addStream summary: Add a stream for live recognition tags: - Streams requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: true required: - api_token - url - radio_id properties: api_token: type: string url: type: string description: 'Stream URL — direct (DASH/Icecast/HLS/m3u/m3u8) or shortcut (`twitch:`, `youtube:`, `youtube-ch:`). ' radio_id: type: integer description: Caller-supplied identifier; must be unique per account. callbacks: type: string enum: - before description: 'Set to `before` to receive callbacks at song start. Default is callbacks at song end (with total play length). ' responses: '200': description: Stream added or rejected (e.g., content: application/json: schema: oneOf: - $ref: '#/components/schemas/StreamMutationSuccessResponse' - $ref: '#/components/schemas/ErrorResponse' examples: error_slots_exhausted: externalValue: https://raw.githubusercontent.com/AudDMusic/audd-openapi/63414c0a939be98c9ec6d9c2eb5c4c7b92b60a51/fixtures/error_902_stream_limit.json /getStreams/: post: operationId: getStreams summary: List configured streams tags: - Streams requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: true required: - api_token properties: api_token: type: string responses: '200': description: Returns the array of configured streams (may be empty). content: application/json: schema: oneOf: - $ref: '#/components/schemas/GetStreamsSuccessResponse' - $ref: '#/components/schemas/ErrorResponse' examples: empty: externalValue: https://raw.githubusercontent.com/AudDMusic/audd-openapi/63414c0a939be98c9ec6d9c2eb5c4c7b92b60a51/fixtures/getStreams_empty.json /setStreamUrl/: post: operationId: setStreamUrl summary: Update an existing stream's URL tags: - Streams requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: true required: - api_token - radio_id - url properties: api_token: type: string radio_id: type: integer url: type: string responses: '200': description: Stream URL updated or rejected. content: application/json: schema: oneOf: - $ref: '#/components/schemas/StreamMutationSuccessResponse' - $ref: '#/components/schemas/ErrorResponse' examples: success: summary: Standard mutation-success response value: status: success result: null /deleteStream/: post: operationId: deleteStream summary: Delete a stream tags: - Streams requestBody: required: true content: multipart/form-data: schema: type: object additionalProperties: true required: - api_token - radio_id properties: api_token: type: string radio_id: type: integer responses: '200': description: Stream deleted or rejected. content: application/json: schema: oneOf: - $ref: '#/components/schemas/StreamMutationSuccessResponse' - $ref: '#/components/schemas/ErrorResponse' examples: success: summary: Standard mutation-success response value: status: success result: null /longpoll/: get: operationId: longpoll summary: Long-poll for new recognition events on a category description: 'Long-polls for new recognition events. The category can be derived locally from the api_token + radio_id, or read from the `longpoll_category` field of `getStreams`. **Important DX caveat:** when no callback URL is configured for the account (which the server signals via error #19 from `getCallbackUrl`), longpoll silently returns timeout responses forever — events never fire. Every official SDK preflights `getCallbackUrl` and raises a descriptive error if no callback URL is set. The check is bypassable via a `skip_callback_check` flag.' tags: - Streams parameters: - in: query name: category required: true schema: type: string description: 9-char longpoll category — `longpoll_category` from `getStreams` or MD5(MD5(api_token)+str(radio_id))[:9]. - in: query name: timeout schema: type: integer default: 50 minimum: 1 maximum: 90 description: Seconds to wait for events before returning the timeout response. - in: query name: since_time schema: type: integer description: Server timestamp (ms) returned in the previous response — used to deduplicate events. responses: '200': description: 'Either a timeout response (no events) or an event response (one or more new recognitions/notifications). ' content: application/json: schema: $ref: '#/components/schemas/LongpollResponse' examples: timeout: externalValue: https://raw.githubusercontent.com/AudDMusic/audd-openapi/63414c0a939be98c9ec6d9c2eb5c4c7b92b60a51/fixtures/longpoll_no_events.json components: schemas: NapsterMetadata: type: object additionalProperties: true description: Mirror of the upstream Napster track payload. May be absent for some tracks. properties: type: type: string id: type: string index: type: integer disc: type: integer href: type: string format: uri playbackSeconds: type: integer isExplicit: type: boolean isStreamable: type: boolean isAvailableInHiRes: type: boolean name: type: string isrc: type: string shortcut: type: string blurbs: type: array items: type: string artistId: type: string artistName: type: string albumId: type: string albumName: type: string formats: type: array items: type: object additionalProperties: true previewURL: type: string format: uri contributors: type: object additionalProperties: true links: type: object additionalProperties: true LongpollEventResponse: type: object additionalProperties: true required: - timestamp description: 'Returned when one or more new recognition events fired during the wait. Carries the same per-event shape as a callback payload (either a `StreamCallbackResultBody` under `result`, or a notification block under `notification`) plus a `timestamp` to use as the next `since_time`. Tightening this oneOf during Phase 1 once a real fixture is captured. ' properties: result: $ref: '#/components/schemas/StreamCallbackResultBody' notification: type: object additionalProperties: true status: type: string timestamp: type: integer SpotifyMetadata: type: object additionalProperties: true description: Mirror of the upstream Spotify track payload. properties: album: type: object additionalProperties: true artists: type: array items: type: object additionalProperties: true available_markets: oneOf: - type: array items: type: string - type: 'null' disc_number: type: integer duration_ms: type: integer explicit: type: boolean external_ids: type: object additionalProperties: true external_urls: type: object additionalProperties: true href: type: string format: uri id: type: string is_local: type: boolean is_playable: type: boolean linked_from: oneOf: - type: object additionalProperties: true - type: 'null' name: type: string popularity: type: integer track_number: type: integer type: type: string uri: type: string LongpollTimeoutResponse: type: object additionalProperties: true required: - timeout - timestamp description: 'Returned when the longpoll wait elapsed without new events. The client should issue a new request using `timestamp` as the next `since_time`. ' properties: timeout: type: string const: no events before timeout timestamp: type: integer description: Server timestamp (ms) — pass as `since_time` on the next request. ErrorResponse: type: object additionalProperties: true required: - status - error properties: status: type: string const: error error: type: object required: - error_code - error_message additionalProperties: true properties: error_code: type: integer description: 'AudD-specific numeric error code. The SDK maps each code to a typed exception class (see audd-/docs/errors.md). The full set: 19, 20, 31337, 40, 50, 51, 100, 300, 400, 500, 600, 601, 602, 610, 611, 700, 701, 702, 900, 901, 902, 903, 904, 905, 906, 907, 1000. ' enum: - 19 - 20 - 31337 - 40 - 50 - 51 - 100 - 300 - 400 - 500 - 600 - 601 - 602 - 610 - 611 - 700 - 701 - 702 - 900 - 901 - 902 - 903 - 904 - 905 - 906 - 907 - 1000 error_message: type: string description: Human-readable, server-provided. Already includes any subscription-nudge appendix. request_params: type: object additionalProperties: true description: 'Server''s redacted echo of the request parameters. The api_token field is masked (e.g., "d***e"). Standard endpoint uses this field name; the enterprise endpoint uses `requested_params` (see below). ' requested_params: type: object additionalProperties: true description: 'Same as `request_params` but with this alternate name as returned by the enterprise endpoint. SDKs should normalize these into one field on the SDK-side error object. ' request_api_method: type: string description: 'Humanized echo of the API method (e.g., "Recognition", "Adding a stream stream", "Getting the URL for callbacks"). Informational only — not a programmatic discriminator. ' request_http_method: type: string enum: - GET - POST execution_time: type: string description: Wall-clock execution time on the server (enterprise endpoint only). result: type: object additionalProperties: true description: 'For most errors, omitted. For codes 19 and 31337, the server may populate a "branded" result with `artist`/`title` strings — the SDK surfaces these on the exception''s `branded_message` field and does NOT expose them as a recognition result. ' properties: artist: type: string title: type: string see api documentation: type: string format: uri contact us: type: string format: email GetStreamsSuccessResponse: type: object additionalProperties: true required: - status - result properties: status: type: string const: success result: type: array items: $ref: '#/components/schemas/Stream' DeezerMetadata: type: object additionalProperties: true description: Mirror of the upstream Deezer track payload. May be absent for some tracks. properties: id: type: integer readable: type: boolean title: type: string title_short: type: string title_version: type: string link: type: string format: uri duration: type: integer rank: type: integer explicit_lyrics: type: boolean explicit_content_lyrics: type: integer explicit_content_cover: type: integer preview: type: string format: uri md5_image: type: string artist: type: object additionalProperties: true album: type: object additionalProperties: true type: type: string MusicBrainzEntry: type: object additionalProperties: true description: 'Single MusicBrainz recording match. AudD returns an array of these because MusicBrainz''s matching often surfaces multiple candidates. ' required: - id properties: id: type: string format: uuid score: oneOf: - type: integer - type: string title: type: string length: type: integer disambiguation: type: string video: oneOf: - type: boolean - type: 'null' artist-credit: type: array items: type: object additionalProperties: true releases: type: array items: type: object additionalProperties: true isrcs: oneOf: - type: array items: type: string - type: 'null' tags: oneOf: - type: array items: type: object additionalProperties: true - type: 'null' GetCallbackUrlSuccessResponse: type: object additionalProperties: true required: - status - result properties: status: type: string const: success result: type: string format: uri description: The configured callback URL. StreamCallbackResultBody: type: object additionalProperties: true required: - radio_id - results description: 'Inner shape of the recognition-result callback variant — the value of the top-level `result` field. Holds the matched songs, the stream identifier, and per-event metadata. ' properties: radio_id: type: integer timestamp: type: string description: ISO-ish "YYYY-MM-DD HH:MM:SS" UTC. play_length: type: integer description: Seconds the song was played in the stream. Absent when callbacks=before. results: type: array items: type: object additionalProperties: true required: - artist - title - score properties: artist: type: string title: type: string album: type: string release_date: type: string label: type: string score: type: integer song_link: type: string format: uri apple_music: $ref: '#/components/schemas/AppleMusicMetadata' spotify: $ref: '#/components/schemas/SpotifyMetadata' deezer: $ref: '#/components/schemas/DeezerMetadata' napster: $ref: '#/components/schemas/NapsterMetadata' musicbrainz: type: array items: $ref: '#/components/schemas/MusicBrainzEntry' Stream: type: object additionalProperties: true required: - radio_id - url - stream_running properties: radio_id: type: integer description: Caller-supplied stream identifier. url: type: string description: Stream URL or shortcut (`twitch:`, `youtube:`, `youtube-ch:`). stream_running: type: boolean longpoll_category: type: string description: 'Pre-derived 9-character longpoll category for this stream. Equivalent to MD5(MD5(api_token) + str(radio_id))[:9]. Safe to share with clients (browser/widget) — no token leakage. ' LongpollResponse: anyOf: - $ref: '#/components/schemas/LongpollTimeoutResponse' - $ref: '#/components/schemas/LongpollEventResponse' description: 'Use `anyOf` rather than `oneOf` because both branches use `additionalProperties: true` and a timeout response (`timeout` + `timestamp`) trivially also satisfies the event-response branch (which only requires `timestamp`). SDKs disambiguate by presence of the `timeout` field. ' StreamMutationSuccessResponse: type: object additionalProperties: true required: - status description: Common shape returned by setCallbackUrl, addStream, setStreamUrl, deleteStream. properties: status: type: string const: success result: type: 'null' AppleMusicMetadata: type: object additionalProperties: true description: 'Mirror of the upstream Apple Music track payload. AudD passes it through verbatim, so SDK consumers can rely on additional fields appearing here as Apple ships them. ' properties: previews: type: array items: type: object additionalProperties: true properties: url: type: string format: uri artwork: type: object additionalProperties: true properties: width: type: integer height: type: integer url: type: string bgColor: type: string textColor1: type: string textColor2: type: string textColor3: type: string textColor4: type: string artistName: type: string url: type: string format: uri discNumber: type: integer genreNames: type: array items: type: string durationInMillis: type: integer releaseDate: type: string name: type: string isrc: type: string albumName: type: string playParams: type: object additionalProperties: true trackNumber: type: integer composerName: type: string securitySchemes: api_token_form: type: apiKey in: header name: api_token description: 'AudD authentication uses the `api_token` parameter sent either as a multipart/form-data field (POST) or as a query parameter (GET/POST). OpenAPI 3.1 has no first-class scheme for "auth in request body"; this entry documents the parameter for code generators that recognize it. ' api_token_query: type: apiKey in: query name: api_token description: api_token sent as a query parameter (works on every endpoint). agent_key: type: http scheme: bearer description: 'An agent key (agt_...) from the sign-up endpoint, sent only as Authorization: Bearer. How agents sign up and pay: https://audd.io/auth.md' x-service-info: categories: - music - audio docs: homepage: https://audd.io/ apiReference: https://docs.audd.io/ llms: https://audd.io/llms.txt