ProAssign API
Base path through the gateway: /api/identification/v1/proassigns. Every call needs a signed-in
profile (bearer); registering and the owner suggestion additionally require the acting
profile to hold a professional specialization (veterinarian, vet tech, practice, shelter/rescue,
breeder, groomer, trainer, carer, responder) — otherwise identification.professional_required
(403). Responses use the platform envelope { data, resultCode }. This page is the reference.
The service’s own OpenAPI document is for UPC platform staff only.
Concept
Section titled “Concept”A registration parks the identifier in status PRO_REGISTERED: recoverable at once (scans resolve
to the registering professional), owned by nobody. Ownership arrives one of three ways and always
ends as a normal claimed identifier (OwnershipGrant with reason PRO_ASSIGN):
| Method | Trigger |
|---|---|
KNOWN_OWNER | you supplied ownerProfileId at registration and that owner approved it (POST /proassigns/{id}/approve); with animalId the identifier is bound to that animal on approval. Since 2026-09-24 nothing is granted at registration |
CLAIM_CODE | the owner posts the printed identifier + the one-time code you were returned once |
CONTACT_MATCH | the owner signed up with a verified email / phone equal to what you captured; awaiting-me lists it, claim-by-contact claims it |
expiresInDays (default 365, max 1095) bounds the code only. Recovery resolution never stops.
Register
Section titled “Register”POST /proassigns → 201 ProAssignResultDto { proAssign, identifier, claimCode? }
{ "kind": "MICROCHIP", "rawCode": "985 141 000 123 456", "referenceNumber": "CLINIC-4471", "ownerName": "Jane Doe", "ownerPhone": "+1 555 010 2000", "ownerEmail": "jane@example.com", "ownerCountryCode": "CA", "isRecoveryContactable": true, "callName": "Bella", "speciesId": "…", "breedId": "…", "animalSexCode": "F", "appliedAtUtc": "2026-09-08T14:00:00Z", "implantedAtName": "Happy Paws Clinic", "expiresInDays": 365}kind:MICROCHIP(15-digit ISO or 9–10-digit legacy, elseidentification.invalid_identifier_format),VISUAL_TAG/RFID_TAG/NFC_TAG/QR_TAG,TATTOO,PASSPORT_NUMBER. A tag code pre-staged under another tag family is matched by code.- Owner: either
ownerProfileId(+ optionalownerAccountId; resolved from the profile when omitted, elseidentification.owner_account_unresolved), which addresses the registration to that owner to approve or decline (proAssign.awaitingOwnerApproval: true, identifier stillPRO_REGISTERED), or bothownerPhoneandownerEmail(identification.contact_required). - Animal: either
animalId(requiresownerProfileId, and must be that owner’s animal:identification.unauthorized403 when it is someone else’s, 404 when unknown, 503 when the animal service cannot answer), orcallName+speciesId(required) with the optionallocalName,registeredName,breedId,animalSexCode,colorText,dateOfBirth,descriptionText. - Whether the number is a United Pet Club chip or tag is decided by UPC from its own stock, never by
the request: an
isUpcIssuedyou send is ignored. When that check cannot be made the call answersidentification.dependency_unavailable(503); retry it. claimCodeis present only when no owner profile was named, and is never returned again. Conflicts:identification.duplicate_identity(already owned),identification.pro_assign_exists(open registration exists).
Approve or decline (the owner you named)
Section titled “Approve or decline (the owner you named)”POST /proassigns/{id}/approve{ animalId?, isPrimary?, skipAnimal? }— the owner you named takes the identifier (KNOWN_OWNER) and it is bound to the animal you named, to another of their own animals (animalId), or to none (skipAnimal). Only that owner (or platform staff) may call it (403 otherwise); an animal that is not theirs is refused.POST /proassigns/{id}/decline{ reason? }— the registration stays with you, unclaimed and recoverable to you;declinedAtUtcanddeclineReasonshow on it. Void it or re-issue a claim code for the client.
A declined, claimed or voided registration answers 409. While a registration waits for the owner you named, its claim code and a contact match do not take it.
Claim (owner)
Section titled “Claim (owner)”POST /proassigns/claim{ claimCode, code, kind?, ownerProfileId?, ownerAccountId?, animalId?, isPrimary? }— by printed identifier.POST /proassigns/{id}/claim— same body, by registration id.GET /proassigns/awaiting-me→ProAssignAwaitingDto[] { proAssign, matchedBy, registeredByDisplayName, registeredByHandle }—matchedByisNAMEDfor a registration addressed to the acting profile (approve or decline it), elseEMAIL/PHONE.POST /proassigns/{id}/claim-by-contact{ ownerProfileId?, ownerAccountId?, animalId?, isPrimary? }— re-verified server-side; 403 when no verified contact matches.
ownerProfileId defaults to the acting profile and must be it (another profile is 403),
ownerAccountId defaults to the token’s account. Wrong code → identification.invalid_credential
(400); five wrong codes lock the registration; past the window → identification.claim_expired
(409). With animalId — which must be the claimer’s own animal — the identifier is bound in the same
call and Identification.IdentifierAssigned.v1 is emitted (the Animal service mirrors it onto the
animal’s identification rows).
Manage (professional)
Section titled “Manage (professional)”GET /proassigns/mine?status=&includeClosed=&skip=&take=— your registrations (as registrant or as the registering organisation).GET /proassigns/{id};GET /proassigns/by-code/{code}?kind=&namespace=— client contact is redacted unless you registered it, your organisation did, you claimed it, or you are staff (contactRedacted: true).POST /proassigns/{id}/reissue-code→ newclaimCode, unlocked, window re-opened.POST /proassigns/{id}/void{ reason? }→ identifier returns toUNCLAIMED.POST /proassigns/owner-suggestions{ email?, phone? }→{ found, profileId, handle, displayName, matchedBy }— whether a member has verified that contact. Confirm with your client before registering against the suggested profile.
Related
Section titled “Related”- Breeding:
GET /api/breeding/v1/litters/lookup?code=&ownerProfileId=(bearer) — a litter by its code or a breeder’s newest litters, with offspring animal ids, so a professional can pick the right animal from a litter. - Animal:
GET /api/animal/v1/identifiers/{value}/resolveanswersANIMAL/NONEfor the registry’s own identification rows; professional pre-registrations are answered by/proassigns/by-code/{code}above. - Public lookup (
POST /api/identification/v1/lookup) resolves an unclaimed professional registration as aMATCHwithisProfessionallyRegistered: true; the finder relay reaches the registering practice.