Partner Metadata API
Check an IPI
Does an IPI belong to the party you named? Answers while your user is still typing.
Check an IPI against the name you hold for a party, while the person is still in front of you.
This is the same registry check the Catalogue Ingest API runs when you send a work. Calling it from your own form moves the answer from a report you read afterwards to the moment your user can act on it.
The request#
GET /api/v1/registry/ipi-match?ipi=00123456790&first_name=Tobiah&last_name=Hollowmere
Authorization: Bearer trk_live_...
| Parameter | Required | Description |
|---|---|---|
ipi | Yes | The IPI Name Number. 9 to 11 digits. |
first_name | For a writer, with last_name | The party's legal first name. A company has none, so a publisher check omits it. |
last_name | Yes, unless you send full_name | The party's legal last name, or the registered company name. |
full_name | Instead of first_name and last_name | The party's whole legal name in one field, in any word order. |
role | No | writer (the default) or publisher. |
The name fields are separate on purpose. Send the legal name, never a stage name. A stage name and a
legal name usually have no words in common, so sending one produces a differs result that means
nothing. Keep the stage name in your own record and send it to Record as artist_name on the work.
Send one name form. Send full_name alone, or last_name with first_name. A request with both
forms gets a 400, because Record cannot tell which name you mean.
Use full_name when your record holds the name in one field. For a writer, the word order does not
matter, so Joellen Quillfeather and Quillfeather Joellen get the same answer. Registries often file the surname
first, and so do many naming traditions.
For a publisher, send the whole registered company name as full_name or as last_name, and omit
first_name. Do not split the company name across the two fields. The company rule compares word
for word and in order, so a split or an unexpected order reads as a different company.
Your key needs the registry:read scope.
The response#
{
"ipi": "00123456790",
"role": "writer",
"status": "agrees",
"registered_name": "TOBIAH EVERETT JR HOLLOWMERE",
"pro": "BMI",
"sources_checked": { "ipiqs": true }
}
sources_checked shows, for each registry, whether the check read it. The ipiqs key in
sources_checked names the CISAC (International Confederation of Societies of Authors and Composers)
IPI registry.
status | Meaning |
|---|---|
agrees | The registered name and the name you sent describe the same party. |
differs | The number is registered, to a name that does not match the one you sent. |
not_found | No registry holds this number. |
is_company | The registry files this number to a company, so no writer can hold it. |
is_person | The registry files this number to a person, so no publisher can hold it. |
invalid_ipi | Not a well-formed IPI, or its check digits fail. Record does no lookup. |
invalid_name | Record cannot compare the name you sent. It has no words, or the registry writes the party in a different script. |
not_checked | The registry did not answer. Unknown, never clear. |
registered_name is present on agrees and on is_company. Record withholds it on is_person and
differs. On agrees, the returned name can include words absent from the supplied name, because
the shared comparison permits partial matches.
suggested_name is present only on differs, and only when one word you sent already equals the
registered surname. With first_name and last_name, that word is last_name. With full_name,
it is any word. A given name does not count.
The comparison ignores case, accents and punctuation. When no word equals the surname, the response holds no name at all. A caller who guessed a number must not learn a stranger's legal name.
| You send | Registry holds | status | suggested_name |
|---|---|---|---|
full_name=Joellen Quillfeather | JO ELLEN MARIE QUILLFEATHER | differs | JO ELLEN MARIE QUILLFEATHER |
ZXQV Brambleton | ORLA PENHALLOW BRAMBLETON | differs | ORLA PENHALLOW BRAMBLETON |
full_name=Brambleton ZXQV | ORLA PENHALLOW BRAMBLETON | differs | ORLA PENHALLOW BRAMBLETON |
Amor Ferren | FERREN ALDO VANTRESS | differs | absent |
pro is present on agrees. Record fills it when exactly one society holds the party's performing
rights. Where no agreement of theirs carries performing rights, Record fills it when exactly one society
appears across all of them. More than one candidate leaves the field absent, because a guessed
affiliation is worse than none.
pro_candidates is present on agrees when two or more societies are on file. It lists every one of
them, with the societies that hold performing rights first. Show the list and let your user choose.
Do not preselect the first entry. The field is absent when only one society is on file.
Every judged outcome returns 200, including not_checked. Your form then has one code path. An
unreachable registry is normal while somebody is typing, and it is not an error.
How to use each answer#
agrees is a statement about the number, not about the person. Use registered_name to offer the
legal name: agreement does not mean the name is complete. Tobiah E agrees against
TOBIAH EVERETT JR HOLLOWMERE, because the initial matches the middle name, while the surname the
society files under is missing from what you sent. Use pro to fill the affiliation field.
differs is advisory. Never block a save on it. A real writer can spell their own name in a way
the comparison does not recognise. Jo'ellen Quillfeather matches JO ELLEN MARIE QUILLFEATHER and Joellen Quillfeather
does not, because the registry holds the given name as two words. Tell the user the number and the
name disagree, and ask them to check the number. Do not ask them to change their name to match
the registry: the usual cause is a borrowed or mistyped IPI.
When suggested_name is present, you can show it as the name the society files under. Let the user
accept it. Do not replace their entry without asking.
is_company means the number belongs to a company. It cannot be a writer's IPI under any
reading. If they administer through that company, the number belongs on a publisher row, not on the
writer.
is_person is the same finding from the other side, and you get it only with role=publisher.
The number belongs to a human being, so it cannot name a publisher. Move it to a writer row. This
answer carries no registered_name.
invalid_name is not a statement about the number. It has two causes:
- The name held nothing a comparison can use, such as a single punctuation mark. Record does no
lookup, and
sources_checked.ipiqsisfalse. Ask for the name again. - The registry writes the party in a different script from the name you sent.
山田 花子andYamada Hanakoshare no characters, and no rule can join two scripts from the names alone.sources_checked.ipiqsistrue. Send the name in the script the society uses, or check the number by another identifier, such as an ISWC (International Standard Musical Work Code).
Set role=publisher when you check a publisher's IPI. The name comparison changes with it. A company
has no given names to be lenient about. Its last word is a legal suffix, not a surname. So the two
kinds of party are judged by different rules.
not_checked must show as unchecked, never as cleared. Record could not reach the registry.
What this does not tell you#
It answers whether the name matches the number. It does not answer whether the party is the right
one. The registry holds 33 distinct people called JOHN SMITH, and John Smith agrees against every
one of them.
Do not label the result "verified" in your interface. Do not treat agrees as proof of identity.
Find an unknown IPI#
A writer who does not know their IPI can find it from a recording they wrote.
GET /api/v1/registry/ipi-find?isrc=USRC11700001&first_name=Kenneth&last_name=Wiggins
Authorization: Bearer trk_live_...
| Parameter | Required | Description |
|---|---|---|
isrc | Yes | An ISRC on a work that your catalogue delivered to Record. |
first_name | Yes | The writer's legal first name. |
last_name | Yes | The writer's legal last name. |
Record never returns an IPI from a name alone. Many people share one name, so a name alone gives your user a stranger's number. The ISRC must also be on your own catalogue. An ISRC that Record guessed during enrichment does not count.
Record returns an IPI only when all three checks pass:
- The registry links the recording to exactly one party whose name matches the name you sent.
- That party has exactly the words you sent, in any order. Part of a name is not enough.
- The CISAC registry agrees that the number belongs to a person with that name.
{
"isrc": "USRC11700001",
"status": "found",
"ipi": "00827411839",
"pro": "BMI"
}
status | Meaning |
|---|---|
found | One party on the recording has this name, and CISAC agrees. ipi holds the 11-digit number. |
not_found | No party on the recording has exactly this name. |
ambiguous | More than one number on the recording matches this name. Record returns none of them. |
unconfirmed | The recording names this party, but CISAC does not agree. |
not_in_catalogue | The ISRC is not on a work that your catalogue delivered. |
invalid_isrc | Not a well-formed ISRC. Record does no lookup. |
invalid_name | The name you sent has nothing that Record can compare. Record does no lookup. |
not_checked | A registry did not answer. Unknown, never clear. |
pro and pro_candidates follow the same rules as on ipi-match. Show the number to your user before you save it. Every answer except found means "ask your user", not "this writer has no
IPI".
Check the number first#
Two checks need no network, and reject most bad values on their own.
An IPI is 9 to 11 digits and nothing else.
const ipi = raw.replace(/[\s.\-]/g, '');
const wellFormed = /^\d{9,11}$/.test(ipi);
A value beginning with I, such as I-001234567-8, is an IPI Base Number. That is a different
identifier with a different check digit. Do not strip the letter and send the rest. Ask for the Name
Number, which is what every society files under.
An 11-digit IPI carries its own check digits, so a transposed pair fails arithmetic. Ten digits is an eleven with a dropped leading zero.
function ipiCheckDigitsValid(raw) {
const d = raw.replace(/\D/g, '');
if (!/^\d{10,11}$/.test(d)) return null; // 9 digits: cannot be checked, do not reject
const p = d.padStart(11, '0');
let sum = 0;
for (let i = 0; i < 9; i++) sum += (10 - i) * Number(p[i]);
let c = sum % 101;
if (c === 1) c = 0;
else if (c !== 0) c = 101 - c;
return c === Number(p.slice(9, 11));
}
Treat null as "cannot tell", never as a failure. A 9-digit value is a legitimate IPI that carries
no check digits, and rejecting it would turn away real writers.
These are the same rules that Record applies. So Record does not refuse on shape a value that your form accepts.
Rate limit#
120 requests a minute per key, for each of the two endpoints. That is set by what a form does, not by what the service can carry. A partner can agree a different limit with Record. See Rate limits. Debounce your field rather than calling on every keystroke.