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=00827411839&first_name=Kenneth&last_name=Wiggins
Authorization: Bearer trk_live_...
| Parameter | Required | Description |
|---|---|---|
ipi | Yes | The IPI Name Number. 9 to 11 digits. |
first_name | For a writer | The party's legal first name. A company has none, so a publisher check omits it. |
last_name | Yes | The party's legal last name, or the registered company name. |
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 us as artist_name on the work.
For a publisher, send the whole registered company name as last_name and omit first_name. Do not
split the company name across the two fields. The company rule compares word for word, so a split we
do not expect reads as a different company.
Your key needs the registry:read scope.
The response#
{
"ipi": "00827411839",
"role": "writer",
"status": "agrees",
"registered_name": "KENNETH TYRONE JR WIGGINS",
"pro": "BMI",
"sources_checked": { "ipiqs": true }
}
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. We performed no lookup. |
invalid_name | The name you sent has nothing we can compare. We performed no lookup. |
not_checked | The registry did not answer. Unknown, never clear. |
registered_name is present on agrees and on is_company. We withhold names 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.
pro is present on agrees. We fill it when exactly one society holds the party's performing
rights. Where no agreement of theirs carries performing rights, we fill 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.
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 green light on the number, not on the person. Use registered_name to offer the
legal name: agreement does not mean the name is complete. Kenneth T agrees against
KENNETH TYRONE JR WIGGINS, because the initial confirms 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
our comparison does not recognise. Ky'saun James matches KY SAUN MALIK JAMES and Kysaun James
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.
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 means the field held nothing a comparison can use, such as a single punctuation
mark. Ask for the name again. It is not a statement about the number.
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. We 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.
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 we apply, so a value your form accepts will not be refused by us on shape.
Rate limit#
120 requests a minute per key. That is set by what a form does, not by what the service can carry. Debounce your field rather than calling on every keystroke.