BMI APIrepertoire.bmi.com ↗
Search BMI's Songview database for writers/composers and retrieve their full catalog: BMI Work IDs, co-writers, performers, IPI numbers, and affiliations.
What is the BMI API?
The BMI Repertoire API exposes 2 endpoints that cover BMI's public Songview catalog, letting you search for any registered writer or composer by name and pull their complete catalog of musical works. The search_writers endpoint returns IPI numbers, PRO affiliations, and the opaque identifiers you need to call get_catalog, which returns paginated work records including BMI Work IDs, co-writers, performers, and reconciliation status for catalogs of any size.
curl -X GET 'https://api.parse.bot/scraper/fc797f45-3476-4cf2-ac70-2392382c3a89/search_writers?name=Ed+Sheeran&page=1&search_type=all' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace repertoire-bmi-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: BMI Songview SDK — bounded, re-runnable; every call capped."""
from parse_apis.BMI_Songview_API import BmiSongview, SearchType, ParseError
client = BmiSongview()
# Search for writers by name — limit caps total items fetched.
for writer in client.writers.search(name="Ed Sheeran", search_type=SearchType.ALL, limit=3):
print(writer.writer_name, writer.affiliation, writer.ipi_number)
# Drill-down: take ONE writer with .first(), then walk their works.
writer = client.writers.search(name="Ed Sheeran", limit=1).first()
if writer:
for work in writer.works.list(search_text="Ed Sheeran", limit=3):
print(work.title, work.bmi_work_id, work.iswc)
for pub in work.publishers:
print(" Publisher:", pub.name, pub.affiliation, pub.ipi_number)
for wd in work.writer_details:
print(" Writer:", wd.name, wd.affiliation, wd.ipi_number)
# Typed errors: wrap the fallible call, catch the specific class.
try:
for w in client.writers.search(name="Taylor Swift", limit=2):
print(w.writer_name, w.ipi_number)
except ParseError as e:
print(f"error: {e}")
print("exercised: writers.search / works.list")
Search for writers/composers by name in the BMI Songview database. Returns matching writers with their IPI numbers, affiliations, and opaque identifiers needed to fetch their full catalog via get_catalog.
| Param | Type | Description |
|---|---|---|
| namerequired | string | Writer or composer name to search for (e.g. 'Ed Sheeran', 'Taylor Swift'). |
| page | integer | Page number of search results. |
| search_type | string | Which catalog scope to search in. |
{
"type": "object",
"fields": {
"page": "current page number",
"total": "total number of matching writers",
"writers": "array of matching writer records"
},
"sample": {
"data": {
"page": 1,
"total": 2,
"writers": [
{
"cae": "YO0HedHMatLb45JzS23DVw%3d%3d",
"writer_id": "Ak4jiB8Q6zj%2bHuOb%2fYcyrg%3d%3d",
"ipi_number": null,
"affiliation": "NS",
"part_id_sub": "YO0HedHMatLb45JzS23DVw%3d%3d",
"writer_name": "SHEERAN ED",
"title_sample": "TICKET IN THE RAIN"
},
{
"cae": "a5SF%2bFhc4aql1sWCF7Ttng%3d%3d",
"writer_id": "AtDsYllmwKEqNriQVP074w%3d%3d",
"ipi_number": "583552527",
"affiliation": "PRS",
"part_id_sub": "YO0HedHMatLb45JzS23DVw%3d%3d",
"writer_name": "SHEERAN ED",
"title_sample": "THURSDAY FEAT H E R"
}
]
},
"status": "success"
}
}About the BMI API
Searching for Writers
The search_writers endpoint accepts a name string (required) and returns a paginated list of matching writer records. Each record includes the writer's IPI number, their performing rights organization affiliation, and three opaque identifiers — writer_id, cae, and part_id_sub — that are required inputs for get_catalog. The total field tells you how many writers matched, which is useful when a common name returns multiple results across affiliated and unaffiliated catalogs.
Retrieving a Writer's Catalog
Once you have the identifiers from search_writers, pass writer_id, cae, and part_id_sub to get_catalog. The page_size parameter accepts exactly three values — 20, 50, or 100 — and total_pages lets you iterate through the full catalog programmatically. Each work record in the works array carries a BMI Work ID, the work title, reconciliation status, any co-writers credited, and associated performers. The response header also surfaces ipi_number, affiliation, and writer_name for confirmation that you're looking at the right catalog.
Coverage and Identifiers
The catalog reflects BMI's public Songview database, which covers works registered with BMI. The IPI number returned by both endpoints is the internationally recognized Interested Party Information number used across PROs worldwide. Co-writer records within each work allow you to trace collaborative relationships. The search_type parameter on both endpoints scopes which portion of the catalog is queried, and search_text on get_catalog lets you pass the original query string through for context when building multi-step lookup flows.
The BMI API is a managed, monitored endpoint for repertoire.bmi.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when repertoire.bmi.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official repertoire.bmi.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Verify BMI Work IDs and IPI numbers for music licensing due diligence
- Map co-writing relationships for a given composer using the co-writers field in get_catalog
- Cross-reference a writer's PRO affiliation when clearing rights across multiple organizations
- Build a songwriter discography page using paginated get_catalog results and total_works
- Identify all performers associated with a specific writer's catalog
- Check reconciliation status of works to flag unmatched or disputed registrations
- Resolve writer name variants to canonical entries via IPI number from search_writers
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does BMI offer an official public developer API for Songview?+
What does get_catalog return for each musical work?+
works array includes the work title, BMI Work ID, reconciliation status, a list of co-writers, and associated performers. The response envelope also returns total_works, total_pages, ipi_number, affiliation, and writer_name for the writer whose catalog you requested.Does the API return royalty payment data or performance history?+
Are ASCAP or SESAC works included in the results?+
affiliation field reflects what BMI's Songview reports for that IPI. You can fork this API on Parse and revise it to add endpoints targeting other PRO catalogs.What happens when a writer name matches multiple entries in search_writers?+
total field in the search response tells you how many records matched, and results are paginated using the page parameter. Each record carries a distinct writer_id, cae, and ipi_number, so you can disambiguate between writers who share a name before calling get_catalog.