Metadata-Version: 2.5
Name: sonovault
Version: 2.4.0
Summary: Python client for the SonoVault music metadata API: ISRC, ISWC, genre, BPM, key, labels, release dates, and cross-platform IDs for 93M+ tracks.
Project-URL: Homepage, https://sonovault.now
Project-URL: Documentation, https://sonovault.now/docs
Project-URL: Repository, https://github.com/rekordcloud/sonovault-python
Project-URL: Issues, https://github.com/rekordcloud/sonovault-python/issues
Author: Rekordcloud B.V.
License: MIT
License-File: LICENSE
Keywords: apple-music,audio-recognition,beatport,discogs,isrc,iswc,metadata,music,music-api,musicbrainz,spotify,tidal
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: requests>=2.25
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# sonovault

[![CI](https://github.com/rekordcloud/sonovault-python/actions/workflows/ci.yml/badge.svg)](https://github.com/rekordcloud/sonovault-python/actions/workflows/ci.yml)
[![PyPI](https://img.shields.io/pypi/v/sonovault)](https://pypi.org/project/sonovault/)

Python client for the **[SonoVault](https://sonovault.now)** music metadata API. 93M+ tracks with ISRC, ISWC, genre, BPM, musical key, record label, canonical release dates, and cross-platform IDs for Spotify, Apple Music, Tidal, Beatport, Discogs, and MusicBrainz. One call resolves them all.

- **One key, no OAuth.** A single `x-api-key` header, no approval queue.
- **Free tier.** 1,000 requests/month, no credit card: [get an API key](https://sonovault.now).
- **Docs.** Full API reference at [sonovault.now/docs](https://sonovault.now/docs).

## Install

```bash
pip install sonovault
```

Python 3.9+.

## Quickstart

```python
from sonovault import SonoVault

sv = SonoVault(api_key="YOUR_API_KEY")

# Find a track's ISRC from artist + title
page = sv.tracks.search(artist="Daft Punk", title="One More Time")
track = page["results"][0]
print(track["isrc"])   # "GBDUW0000053"
print(track["genre"], track["releases"][0]["label"]["name"])
print(track["bpm"], track["key_alphanumeric"])  # 123 "10B"

# An album's tracklist, in playing order
release = sv.releases.get(7)
for t in release["tracks"]:
    print(t["disc_number"], t["track_number"], t["title"])  # 1 1 One More Time

# One record groups every edition of an album, so pick the one you mean
for e in release["editions"]:
    print(e["id"], e["format"], e["release_date"], e["track_count"])  # 16216 cd 2001-03-12 14
deluxe = sv.releases.get(7, edition=16216)

# Resolve that ISRC to its ID on every platform
links = sv.tracks.links(isrc=track["isrc"])
for link in links["links"]:
    print(link["source"], link["url"])  # spotify https://open.spotify.com/track/...

# Recording to composition (ISWC), for royalty and publishing workflows
work = sv.tracks.iswc(isrc=track["isrc"])

# What a label released on one day (from_ / until are inclusive YYYY-MM-DD)
friday = sv.labels.releases(1, from_="2026-09-11", until="2026-09-11")
```

## Key and BPM

Every track (search, lookups, browse, resolve, release tracklists, stream events) carries its tempo and musical key. Key comes from OpenKeyScan and BPM from the Lexicon DJ beat detector (trusted by 100k+ DJs), both run by SonoVault on the audio.

```python
track = sv.tracks.by_isrc("GBDUW0000053")  # Daft Punk, One More Time

track["bpm"]               # 123 (full tempo, up to 2 decimals)
track["key_alphanumeric"]  # "10B" (1 to 12, A = minor, B = major)
track["key_musical"]       # "D"
track["key_open"]          # "3d" (Open Key notation)

# Every key we hold, one entry per source
for k in track["keys"]:
    print(k["source"], k["key_alphanumeric"])  # openkeyscan 10B
```

All of these are `None` (and `keys` is `[]`) when a track has not been analysed yet. Other audio features such as energy or danceability are not exposed.

## Bulk resolve

Resolve up to 100 lines in one request: track names, ISRCs, or platform IDs. Useful for enriching play logs and library exports.

```python
batch = sv.tracks.resolve(
    input_type="track_name",
    items=[
        {"artist": "Daft Punk", "title": "Harder, Better, Faster, Stronger"},
        {"artist": "Daft Punk", "title": "Around the World"},
    ],
)
for row in batch["results"]:
    print(row["status"], row["track"] and row["track"]["isrc"])
```

## Pagination

List endpoints return `{"results": [...], "next_cursor": ...}`. Pass the cursor back for the next page. `next_cursor` is `None` on the last page.

```python
from sonovault import paginate

for release in paginate(lambda cursor: sv.artists.releases(42, cursor=cursor)):
    print(release["title"])
```

Or walk the cursor yourself:

```python
cursor = None
while True:
    page = sv.artists.releases(42, cursor=cursor)
    # ...use page["results"]
    cursor = page.get("next_cursor")
    if not cursor:
        break
```

## Error handling

Non-2xx responses raise `SonoVaultError`:

```python
from sonovault import SonoVaultError

try:
    sv.tracks.browse(genre="House")  # paid-tier endpoint
except SonoVaultError as err:
    print(err.status, err.is_forbidden, err)
```

Rate-limited responses that carry a `Retry-After` header are retried automatically. The default is 2 retries, configurable with `max_retries`.


## Examples

Runnable scripts live in [`examples/`](examples/): find an ISRC, resolve cross-platform links, enrich a play log, follow live stream events over SSE, and verify webhook deliveries.

## API coverage

| Namespace | Methods |
|---|---|
| `sv.tracks` | `search`, `get`, `by_isrc`, `iswc`, `by_iswc`, `links`, `resolve`, `identify_audio`, `browse` |
| `sv.artists` | `search`, `get`, `releases` |
| `sv.labels` | `search`, `get`, `releases`, `artists` |
| `sv.releases` | `search`, `get`, `latest` |
| `sv.genres` | `list` |
| `sv.suggestions` | `submit`, `list` |
| `sv.streams` | `create`, `list`, `get`, `update`, `history`, `report`, `live`, `stop` |
| `sv.webhooks` | `create`, `list`, `get`, `update`, `delete`, `test`, `deliveries` |

Some endpoints (audio identify, browse, stream monitoring) need a paid tier. See [pricing](https://sonovault.now/pricing). Everything else works on the free tier.

## Related

- [SonoVault API docs](https://sonovault.now/docs). Full endpoint reference with examples in 8 languages.
- [sonovault-js](https://github.com/rekordcloud/sonovault-js). The TypeScript/Node client.
- [Free ISRC lookup](https://sonovault.now/isrc-lookup) and [ISWC lookup](https://sonovault.now/iswc-lookup). Browser tools built on the same API.

## License

MIT
