Skip to content

Commit f857ee2

Browse files
author
AudD
committed
Initial release v1.4.0
0 parents  commit f857ee2

26 files changed

Lines changed: 2660 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
spec-validate:
11+
name: OpenAPI spec validation
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-python@v5
16+
with:
17+
python-version: '3.12'
18+
cache: pip
19+
cache-dependency-path: requirements-dev.txt
20+
- name: Install
21+
run: pip install -r requirements-dev.txt
22+
- name: Validate openapi.yaml structure
23+
run: |
24+
python -c "
25+
import yaml, openapi_spec_validator as v
26+
v.validate(yaml.safe_load(open('openapi.yaml')))
27+
print('openapi.yaml: structurally valid')
28+
"
29+
- name: Validate fixtures against spec schemas
30+
run: python tests/validate.py
31+
32+
redocly-lint:
33+
name: Redocly lint
34+
runs-on: ubuntu-latest
35+
steps:
36+
- uses: actions/checkout@v4
37+
- uses: actions/setup-node@v4
38+
with:
39+
node-version: '20'
40+
- name: Install redocly
41+
run: npm install -g @redocly/cli@1
42+
- name: Lint
43+
run: redocly lint openapi.yaml

.github/workflows/dispatch.yml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Dispatch to SDKs
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'openapi.yaml'
8+
- 'fixtures/**'
9+
10+
permissions: {}
11+
12+
jobs:
13+
fan-out:
14+
name: Trigger contract tests across SDK repos
15+
runs-on: ubuntu-latest
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
sdk:
20+
- audd-python
21+
- audd-node
22+
- audd-java
23+
- audd-kotlin
24+
- audd-swift
25+
- audd-dotnet
26+
- audd-ruby
27+
- audd-php
28+
- audd-rust
29+
- audd-go
30+
steps:
31+
- name: Generate GitHub App token
32+
id: app-token
33+
uses: actions/create-github-app-token@v1
34+
with:
35+
app-id: ${{ secrets.SDK_DISPATCH_APP_ID }}
36+
private-key: ${{ secrets.SDK_DISPATCH_APP_PRIVATE_KEY }}
37+
owner: AudDMusic
38+
repositories: ${{ matrix.sdk }}
39+
40+
- name: Fire repository_dispatch
41+
env:
42+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
43+
SDK_REPO: ${{ matrix.sdk }}
44+
TRIGGER_SHA: ${{ github.sha }}
45+
TRIGGER_RUN_ID: ${{ github.run_id }}
46+
run: |
47+
gh api \
48+
--method POST \
49+
-H "Accept: application/vnd.github+json" \
50+
"/repos/AudDMusic/$SDK_REPO/dispatches" \
51+
-f event_type=openapi-updated \
52+
-f "client_payload[trigger_sha]=$TRIGGER_SHA" \
53+
-f "client_payload[trigger_run_id]=$TRIGGER_RUN_ID"
54+
echo "dispatched openapi-updated to AudDMusic/$SDK_REPO"

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
__pycache__/
2+
*.py[cod]
3+
.venv/
4+
venv/
5+
.pytest_cache/
6+
.mypy_cache/
7+
.ruff_cache/
8+
*.egg-info/
9+
.env
10+
.DS_Store
11+
fixtures/raw/*.json

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 AudD (https://audd.io)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# audd-openapi
2+
3+
[![CI](https://github.com/AudDMusic/audd-openapi/actions/workflows/ci.yml/badge.svg)](https://github.com/AudDMusic/audd-openapi/actions/workflows/ci.yml)
4+
5+
The canonical OpenAPI 3.1 specification for the [AudD](https://audd.io) music recognition API.
6+
7+
This repository is the source of truth that all official AudD SDKs build their typed models against. Third parties can also use this spec to generate their own clients.
8+
9+
| File | Purpose |
10+
|---|---|
11+
| [`openapi.yaml`](./openapi.yaml) | OpenAPI 3.1 spec covering every public AudD endpoint |
12+
| [`fixtures/`](./fixtures/) | Real captured API responses, PII scrubbed — used by every SDK's contract tests |
13+
| [`tests/validate.py`](./tests/validate.py) | Validates each fixture against its schema in `openapi.yaml` |
14+
| [`tests/capture_fixtures.py`](./tests/capture_fixtures.py) | Re-capture fixtures from the live API (requires an api_token) |
15+
16+
## What's covered
17+
18+
- **Standard recognition**`POST/GET https://api.audd.io/`
19+
- **Enterprise recognition**`POST https://enterprise.audd.io/` (hours- to days-long files)
20+
- **Stream management**`setCallbackUrl`, `getCallbackUrl`, `addStream`, `getStreams`, `setStreamUrl`, `deleteStream`
21+
- **Longpoll**`GET /longpoll/`
22+
- **Custom catalog upload**`POST /upload/` (special access required)
23+
- **Lyrics search**`POST /findLyrics/`
24+
25+
The WebSocket recognition variant is intentionally not modeled — AudD recommends the HTTP endpoints for all use cases.
26+
27+
## Validate locally
28+
29+
```bash
30+
python -m venv .venv
31+
source .venv/bin/activate
32+
pip install -r requirements-dev.txt
33+
python tests/validate.py
34+
```
35+
36+
To re-capture fixtures from the live API:
37+
38+
```bash
39+
AUDD_TEST_TOKEN_STD=... AUDD_TEST_TOKEN_ENTERPRISE=... \
40+
python tests/capture_fixtures.py
41+
python tests/scrub_fixtures.py
42+
```
43+
44+
## Generate a client
45+
46+
This spec is hand-written and validates against real fixtures. You can use it with any OpenAPI-compatible code generator. Note that AudD's official SDKs are hand-written rather than generated — to maximize idiomatic feel in each language — but they validate against this same spec.
47+
48+
## Contract drift detection
49+
50+
When this repo lands a change to `openapi.yaml` or `fixtures/`, a workflow fires `repository_dispatch` events at every `audd-<lang>` SDK repo to re-run their contract tests against the new spec. Each SDK also runs the same tests on a nightly cron as a safety net.
51+
52+
## License
53+
54+
MIT — see [LICENSE](./LICENSE).
55+
56+
## Support
57+
58+
- Documentation: https://docs.audd.io
59+
- Tokens: https://dashboard.audd.io
60+
- Email: api@audd.io

SECURITY.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Security Policy
2+
3+
To report a vulnerability, please email **api@audd.io**. We aim to respond within 2 business days.
4+
5+
Do not open public GitHub issues for security reports.
6+
7+
This repository contains specification documents and fixtures only — no production code, secrets, or services. Vulnerability reports for the AudD API itself should also be sent to api@audd.io.

fixtures/README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Fixtures
2+
3+
Real captured AudD API responses, used as the source of truth for SDK contract tests in every `audd-<lang>` repo.
4+
5+
| File | Source | Endpoint | Notes |
6+
|---|---|---|---|
7+
| `recognize_basic.json` | live capture | `POST api.audd.io/` | Standard recognition without metadata |
8+
| `recognize_with_metadata.json` | live capture | `POST api.audd.io/` | Standard recognition with `return=apple_music,spotify,deezer,napster,musicbrainz` |
9+
| `recognize_custom_match.json` | synthesized from design spec | `POST api.audd.io/` | Custom-catalog match shape (only `timecode` + `audio_id`) — can't easily capture live without enterprise custom-catalog access |
10+
| `enterprise_with_isrc_upc.json` | live capture (enterprise token, `limit=1`) | `POST enterprise.audd.io/` | Enterprise success with ISRC and UPC fields |
11+
| `error_900_invalid_token.json` | live capture | `POST api.audd.io/` | Invalid api_token |
12+
| `error_700_no_file.json` | live capture | `POST api.audd.io/` | No file or url sent |
13+
| `error_19_no_callback_url.json` | live capture | `POST api.audd.io/getCallbackUrl/` | The "no callback URL configured" signal — server returns code 19 (catch-all "Internal error") |
14+
| `error_902_stream_limit.json` | live capture | `POST api.audd.io/addStream/` | Stream slots exhausted on subscription |
15+
| `error_904_enterprise_unauthorized.json` | live capture | `POST enterprise.audd.io/` | Standard token denied at enterprise endpoint |
16+
| `getStreams_empty.json` | live capture | `POST api.audd.io/getStreams/` | Empty stream list |
17+
| `longpoll_no_events.json` | live capture | `GET api.audd.io/longpoll/` | Longpoll timeout response (no new events) |
18+
| `streams_callback_with_result.json` | from docs.audd.io/streams.md | callback POSTed by AudD to user webhook | Recognition-result variant of the callback payload |
19+
| `streams_callback_with_notification.json` | from docs.audd.io/streams.md | callback POSTed by AudD to user webhook | Notification variant (stream connectivity) |
20+
21+
Synthesized fixtures match the documented response shapes 1:1; they're called out explicitly so reviewers know which were captured live.
22+
23+
To re-capture: see `tests/capture_fixtures.py`. **Always pass `limit=1` for enterprise endpoint calls.**
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"status": "success",
3+
"result": [
4+
{
5+
"songs": [
6+
{
7+
"score": 81,
8+
"artist": "Tears For Fears",
9+
"title": "Everybody Wants To Rule The World",
10+
"album": "Songs From The Big Chair",
11+
"release_date": "2014-11-10",
12+
"label": "UMC (Universal Music Catalogue)",
13+
"timecode": "00:57",
14+
"isrc": "GBUM71403885",
15+
"upc": "00602547037169",
16+
"song_link": "https://lis.tn/NbkVb"
17+
}
18+
],
19+
"offset": "00:00"
20+
}
21+
],
22+
"execution_time": "159.226763ms"
23+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"status": "error",
3+
"error": {
4+
"error_code": 19,
5+
"error_message": "Getting the URL for callbacks failed: Internal error."
6+
},
7+
"request_params": {
8+
"api_token": "d***e"
9+
},
10+
"request_api_method": "getCallbackUrl",
11+
"request_http_method": "POST",
12+
"see api documentation": "https://docs.audd.io",
13+
"contact us": "api@audd.io"
14+
}

fixtures/error_700_no_file.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"status": "error",
3+
"error": {
4+
"error_code": 700,
5+
"error_message": "Recognition failed: you haven't sent a file via POST or a file URL in the `url` parameter. If you sent the request by POST, please check the protocol you're using: the URL should start with https:// (http:// requests get redirected to https and we don't receive any data from you) and that your Content-Type header equals to `multipart/form-data`."
6+
},
7+
"request_params": {
8+
"api_token": "d***e"
9+
},
10+
"request_api_method": "recognize",
11+
"request_http_method": "POST",
12+
"see api documentation": "https://docs.audd.io",
13+
"contact us": "api@audd.io"
14+
}

0 commit comments

Comments
 (0)