Методы API
Документация Partner API
Этот справочник описывает, как ваша интеграция взаимодействует с Animal-ID от имени организации: аутентификация, обязательные заголовки и основные эндпоинты MVP (владельцы, животные, процедуры, фото, словари).
SDK и клиентские библиотеки
Официальные open-source SDK, инкапсулирующие подпись запросов и эндпоинты ниже — подключите их вместо ручной подписи запросов.
PHP · Composer
Серверный PHP SDK: HMAC-подпись запросов и типизированные клиенты для каждого эндпоинта.
composer require animal-id/aid-partner-sdk
JavaScript · npm
Пакеты для фреймворков (Node и браузер), построенные на общем ядре.
npm i @animal-id/partner-core
- @animal-id/partner-coreНезависимое от фреймворка ядро: подпись + типизированный клиент.
- @animal-id/partner-reactХуки и хелперы React.
- @animal-id/partner-vueComposables для Vue.
- @animal-id/partner-angularСервисы для Angular.
- @animal-id/partner-nestjsМодуль NestJS для серверных интеграций.
Аутентификация и подпись запроса
Базовый URL: https://gw-dev.animal-id.net · все пути имеют префикс /v1/partner.
Каждый подписанный запрос содержит четыре заголовка. Подпись — это HMAC-SHA256 (hex) канонической строки, ключом для которого служит ваш приватный ключ:
stringToSign = METHOD + "\n" + path[?query] + "\n" + sha256_hex(rawBody) + "\n" + timestamp signature = hex( hmac_sha256(stringToSign, privateKey) )
| Заголовок | Значение |
|---|---|
X-Eternity-App-Id | Идентификатор вашего приложения. |
X-Eternity-Public-Key | Ваш публичный ключ. |
X-Eternity-Timestamp | Unix-секунды; должны находиться в пределах ±300s от времени сервера. |
X-Eternity-Signature | Вычисленный выше HMAC-SHA256 в hex. |
X-Eternity-Idempotency-Key | UUID, обязателен для каждого POST/PATCH/DELETE. Повторы возвращают первый ответ; тот же ключ + другое тело → 409. |
X-Eternity-Animal-ID-Version | Необязательная версия даты (YYYY-MM-DD). По умолчанию — версия, зафиксированная при выдаче вашего приложения; начиная с 2026-07-04, регистрация животного привязывает существующих владельцев по public_id вместо user_gid. |
X-Eternity-Expand | Необязательно. JSON-массив ключей расширения для встраивания дополнительных данных на поддерживаемых эндпоинтах (например, ["owners"]). Смотрите раздел «Expansion» эндпоинта для допустимых ключей; неизвестные ключи → 422. |
X-Eternity-Lang-Code | Необязательный. Код языка (uk, en, ru, de, es) для названий, которые возвращает API — например species_name и breed_name в карточке животного и названия в справочниках. Если не передан, используется язык региона по умолчанию. |
Подписывайте и отправляйте точно те же байты тела. Для GET/DELETE тело пустое (его sha256 — это хеш пустой строки). path включает строку запроса, если она присутствует. Для загрузок multipart/form-data (фотографии) необработанное тело также не является частью подписи — подписывайте с sha256 пустого тела.
Каждый успешный ответ оборачивает результаты в массив payload. Эндпоинты создания/получения одного ресурса возвращают массив из одного элемента (например, { "payload": [ { … } ] }); приведённые ниже примеры по эндпоинтам для краткости показывают один объект.
APP_ID="aid_app_xxx"; PUBLIC_KEY="pk_xxx"; PRIVATE_KEY="sk_xxx"
METHOD="POST"
PATH_Q="/v1/partner/owners" # path (+ "?query" if any), exactly as sent
BODY='{"email":"jane@example.com","consent":{"account_creation":true}}'
TS=$(date +%s)
BODY_HASH=$(printf '%s' "$BODY" | openssl dgst -sha256 | awk '{print $2}')
STRING_TO_SIGN=$(printf '%s\n%s\n%s\n%s' "$METHOD" "$PATH_Q" "$BODY_HASH" "$TS")
SIG=$(printf '%s' "$STRING_TO_SIGN" | openssl dgst -sha256 -hmac "$PRIVATE_KEY" | awk '{print $2}')
curl -X "$METHOD" "https://gw.animal-id.net$PATH_Q" \
-H "X-Eternity-App-Id: $APP_ID" \
-H "X-Eternity-Public-Key: $PUBLIC_KEY" \
-H "X-Eternity-Timestamp: $TS" \
-H "X-Eternity-Signature: $SIG" \
-H "X-Eternity-Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d "$BODY"const crypto = require('crypto');
function sign({ method, pathQ, body = '', privateKey }) {
const ts = Math.floor(Date.now() / 1000).toString();
const bodyHash = crypto.createHash('sha256').update(body).digest('hex');
const stringToSign = [method, pathQ, bodyHash, ts].join('\n');
const signature = crypto.createHmac('sha256', privateKey).update(stringToSign).digest('hex');
return { ts, signature };
}
const body = JSON.stringify({ email: 'jane@example.com' });
const { ts, signature } = sign({ method: 'POST', pathQ: '/v1/partner/owners', body, privateKey: 'sk_xxx' });
await fetch('https://gw.animal-id.net/v1/partner/owners', {
method: 'POST',
headers: {
'X-Eternity-App-Id': 'aid_app_xxx',
'X-Eternity-Public-Key': 'pk_xxx',
'X-Eternity-Timestamp': ts,
'X-Eternity-Signature': signature,
'X-Eternity-Idempotency-Key': crypto.randomUUID(),
'Content-Type': 'application/json',
},
body, // sign and send the SAME bytes
});import hashlib, hmac, time, json, uuid, requests
def sign(method, path_q, body, private_key):
ts = str(int(time.time()))
body_hash = hashlib.sha256(body.encode()).hexdigest()
string_to_sign = "\n".join([method, path_q, body_hash, ts])
signature = hmac.new(private_key.encode(), string_to_sign.encode(), hashlib.sha256).hexdigest()
return ts, signature
body = json.dumps({"email": "jane@example.com"}, separators=(",", ":"))
ts, signature = sign("POST", "/v1/partner/owners", body, "sk_xxx")
requests.post(
"https://gw.animal-id.net/v1/partner/owners",
data=body, # send the SAME bytes you signed
headers={
"X-Eternity-App-Id": "aid_app_xxx",
"X-Eternity-Public-Key": "pk_xxx",
"X-Eternity-Timestamp": ts,
"X-Eternity-Signature": signature,
"X-Eternity-Idempotency-Key": str(uuid.uuid4()),
"Content-Type": "application/json",
},
)<?php
function signRequest(string $method, string $pathQ, string $body, string $privateKey): array {
$ts = (string) time();
$bodyHash = hash('sha256', $body);
$stringToSign = implode("\n", [$method, $pathQ, $bodyHash, $ts]);
$signature = hash_hmac('sha256', $stringToSign, $privateKey);
return [$ts, $signature];
}
$body = json_encode(['email' => 'jane@example.com']);
[$ts, $signature] = signRequest('POST', '/v1/partner/owners', $body, 'sk_xxx');
$ch = curl_init('https://gw.animal-id.net/v1/partner/owners');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body, // send the SAME bytes you signed
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"X-Eternity-App-Id: aid_app_xxx",
"X-Eternity-Public-Key: pk_xxx",
"X-Eternity-Timestamp: $ts",
"X-Eternity-Signature: $signature",
'X-Eternity-Idempotency-Key: ' . bin2hex(random_bytes(16)),
'Content-Type: application/json',
],
]);
$response = curl_exec($ch);Вебхуки
Получайте отложенные события — например, когда владелец одобряет запрос ветеринара на доступ — в виде подписанных POST-запросов на ваш сервер. Укажите URL и найдите секрет подписи на вкладке API-ключей.
Подписанная доставка вебхукаПодпись и тело вебхука▸Мы отправляем POST для каждого события на указанный вами URL вебхука, подписанный вашим отдельным секретом вебхука (показывается один раз при генерации). Проверьте подпись, прежде чем доверять доставке: пересчитайте HMAC по каноничной строке и сравните за постоянное время:
canonical = "POST" + "\n" + path[?query] + "\n" + sha256_hex(rawBody) + "\n" + timestamp signature = hex( hmac_sha256(canonical, webhookSecret) )
| Заголовок | Значение |
|---|---|
X-Eternity-Webhook-Id | Уникальный идентификатор доставки (UUID); неизменен при повторных отправках того же события. |
X-Eternity-Webhook-Event | Ключ события, напр. animal_access.approved. |
X-Eternity-Webhook-Timestamp | Unix-секунды, когда доставка была подписана; отклоняйте доставки с расходящимся временем. |
X-Eternity-Webhook-Signature | HMAC-SHA256 (hex) каноничной строки, ключом является ваш секрет вебхука (не приватный ключ API). |
Тело доставки (JSON)
{
"id": "5f1c0b8e-3a2d-4c7b-9b1a-2e6f0d4c8a91",
"event": "animal_access.approved",
"occurred_at": "2026-06-24T09:15:00+00:00",
"result": {
"animal_id": "8xK3pQzVnB7rL2qF",
"requester_user_gid": 90231,
"status": "granted",
"requested_at": "2026-06-23T09:00:00+00:00",
"expires_at": "2026-06-30T09:00:00+00:00",
"retry_after_seconds": 0,
"decided_at": "2026-06-24T09:15:00+00:00"
}
}| Поле | Описание |
|---|---|
id | Уникальный идентификатор события (совпадает с заголовком X-Eternity-Webhook-Id). |
event | Ключ события, напр. animal_access.approved. |
occurred_at | Когда произошло событие (ISO 8601). |
result | Решение о доступе. Повторяет GET /v1/partner/animals/{id}/access-request и добавляет animal_id, requester_user_gid и decided_at. |
События
| Ключ | Значение |
|---|---|
animal_access.approved | Владелец одобрил ваш ожидающий запрос на доступ — теперь вы можете редактировать животное. |
animal_access.denied | Владелец отклонил ваш запрос на доступ — вы можете запросить снова после истечения срока. |
consent.approved | Человек, у которого вы просили, разрешил — можете пользоваться разрешением, пока оно не закончится. |
consent.denied | Человек, у которого вы просили, отклонил запрос. Ничего не предоставлено. |
consent.revoked | Выданное вам разрешение отозвано. Если это был переданный ключ, он сразу перестаёт работать. |
consent.expired | Никто не ответил вовремя, и запрос потерял силу. Это не отказ — можете спросить снова. |
Тело события о согласии
События о согласии доставляются вашему приложению-платформе, а не организации: когда врач разрешает вам держать ключ, действующий от его имени, никакая клиника в этом не участвует.
{
"id": "282824f1-b65e-40f4-86d1-62a2bac566df",
"event": "consent.revoked",
"occurred_at": "2026-08-26T19:45:00+00:00",
"result": {
"consent_id": "qeHSuvlSZHAWpacF",
"kind": "key_handover",
"status": "revoked",
"doctor_id": "c71ORqKq81fRoTcm",
"clinic_id": null,
"decided_at": "2026-08-26T19:45:00+00:00"
}
}| Поле | Описание |
|---|---|
consent_id | Запрос, к которому относится это решение, — тот же идентификатор, что вернул вызов провижининга. |
kind | key_handover (ключ, действующий от имени врача) или clinic_membership (добавление врача в клинику). |
status | approved, denied, revoked или expired. |
doctor_id | Публичный идентификатор врача — для передачи ключа. Иначе null; также null, если аккаунт с тех пор удалён. |
clinic_id | Публичный идентификатор клиники — для членства в клинике. Иначе null. |
decided_at | Когда наступило это состояние (ISO 8601). Для истечения это крайний срок, а не момент, когда мы это заметили. |
Обрабатывайте consent.revoked. Разрешение можно отозвать в любой момент, и переданный ключ перестаёт работать в ту же секунду — без этого события вы узнаете об этом только когда упадёт следующий вызов.
Подтверждайте любым ответом 2xx. Статус, отличный от 2xx, или таймаут записывается как неудачная доставка, которую вы можете отправить повторно из журнала доставок вебхуков в кабинете.
const crypto = require('crypto');
// Express: mount with a raw-body parser so you verify the EXACT bytes received.
// app.post('/animal-id/webhook', express.raw({ type: 'application/json' }), handler)
function verify(req, webhookSecret) {
const ts = req.header('X-Eternity-Webhook-Timestamp');
const sig = req.header('X-Eternity-Webhook-Signature');
const path = req.originalUrl; // path (+ ?query) exactly as received
const raw = req.body; // Buffer of the raw request body
const bodyHash = crypto.createHash('sha256').update(raw).digest('hex');
const canonical = ['POST', path, bodyHash, ts].join('\n');
const expected = crypto.createHmac('sha256', webhookSecret).update(canonical).digest('hex');
return sig && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
}<?php
// Verify a webhook delivery from Animal ID before trusting it.
function verifyWebhook(string $rawBody, string $path, string $webhookSecret): bool {
$ts = $_SERVER['HTTP_X_ETERNITY_WEBHOOK_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_ETERNITY_WEBHOOK_SIGNATURE'] ?? '';
$canonical = implode("\n", ['POST', $path, hash('sha256', $rawBody), $ts]);
$expected = hash_hmac('sha256', $canonical, $webhookSecret);
return $sig !== '' && hash_equals($expected, $sig);
}
$rawBody = file_get_contents('php://input'); // verify the EXACT bytes received
if (!verifyWebhook($rawBody, $_SERVER['REQUEST_URI'], getenv('AID_WEBHOOK_SECRET'))) {
http_response_code(401);
exit;
}
$event = json_decode($rawBody, true); // ['id' => …, 'event' => …, 'result' => …]
http_response_code(204); // acknowledge with any 2xxМетоды API
Начните вводить — разделы отфильтруются по ключевым словам.
Platform API — заведение
Создание клиник и врачей и запросы разрешения у людей, которое нельзя взять самому. Именно отсюда начинается интеграция: сначала заводите аккаунты, затем получаете ключи, которыми с ними будете работать.
- Подписывается ключом платформы, который выдаётся вам один раз при заведении партнёрского аккаунта. В X-Eternity-App-Id отправляйте uuid приложения платформы.
- До данных животных он не достаёт никогда. Ключ платформы на пути /v1/partner/ вернёт 401 — это работает разделение, а не ошибка настройки.
/v1/platform/organizationsНайти уже существующую клинику, прежде чем создавать новую.▸Авторизация: HMAC with your PLATFORM key.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
query | да | string | — | Фрагмент названия или адреса, минимум 2 символа. |
limit | нет | int | — | Максимум результатов, до 50 (по умолчанию 20). |
Пример ответа
{
"payload": [
{
"public_id": "TGo1Gwe2ppRkUFO1",
"org_name": "Лапа",
"full_address": "Україна, Київ, вул. Прикладна, 1",
"status": 3,
"linked": false
}
]
}| Поле | Описание |
|---|---|
public_id | Передайте его в эндпоинт ниже, чтобы завести сюда врача. |
status | Статус модерации. Заведённая вами клиника остаётся вне публичного каталога, пока её не заберёт директор. |
linked | true, если эту клинику завели именно вы. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | Совпадения (пустой список, если ничего не найдено). |
422 | Ошибка валидации (query отсутствует или короче 2 символов). |
/v1/platform/organizationsСоздать клинику или найти уже созданную по вашему идентификатору.▸Авторизация: HMAC with your PLATFORM key. Issued separately from clinic keys; it never reaches animal data.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
external_org_id | да | string | — | Ваш собственный идентификатор этой клиники. Повторный вызов с тем же значением вернёт уже созданную клинику, а не создаст вторую — передавайте стабильное значение. |
name | да | string | — | Clinic name. |
director_public_id | да | string | — | Врач, который займёт место директора, — по его public_id (из POST /owners или из эндпоинта ниже). Клиника не может существовать без директора, и один врач может директорствовать только в одной клинике; если названный человек уже директорствует, ответ будет 409. |
email | нет | string | — | Contact email. |
phone | нет | string | — | Contact phone (E.164). |
website | нет | string | — | Website. |
address | нет | string | — | Full address. |
country_id | нет | int | countries | Country dictionary id. |
description | нет | string | — | Free-text description. |
lat | нет | number | — | Latitude. |
lng | нет | number | — | Longitude. |
Тело запроса (JSON)
{
"external_org_id": "crm-clinic-118",
"name": "Лапа",
"director_public_id": "V1StGXR8Z5jd",
"email": "clinic@example.com",
"phone": "+380441234567"
}Пример ответа
{
"payload": {
"public_id": "yAvgJrSYehJo9JXh",
"name": "Лапа",
"status": 2,
"created": true
}
}| Поле | Описание |
|---|---|
public_id | Стабильный публичный идентификатор клиники — передайте его в эндпоинт ниже. |
created | true, если клинику создал именно этот вызов; false, если возвращена уже существующая. |
status | Статус модерации. Заведённая клиника остаётся вне публичного каталога, пока её не заберёт директор. |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Clinic created. |
200 | Клиника для этого external_org_id уже существовала — возвращена та же самая. |
409 | Указанный директор уже руководит другой клиникой. Укажите другого врача. |
422 | Ошибка валидации (отсутствуют external_org_id, name или director_public_id). |
/v1/platform/organizations/{clinic_public_id}/membersЗавести врача в клинику и получить его ключи.▸Авторизация: HMAC with your PLATFORM key.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
email | условно | string | — | Email врача. Нужен либо email, либо телефон. |
phone | условно | string | — | Телефон врача (E.164). Нужен либо email, либо телефон. |
first_name | нет | string | — | Имя. |
last_name | нет | string | — | Фамилия. |
language | нет | string | languages | Предпочитаемая локаль. |
clinic_name | нет | string | — | Подпись, отображаемая на выданных учётных данных. |
external_doctor_id | нет | string | — | Ваш собственный идентификатор этого врача. То же поле и те же правила, что и external_owner_id: пишется один раз, не перезаписывается и виден только вам. |
consent | да | object | — | Блок согласия (неизменяемый аудит). |
consent.account_creation | да | bool | — | Должно быть true. Ключи, которые вы получаете, действуют от имени этого человека, поэтому его согласие обязательно. |
Тело запроса (JSON)
{
"email": "doctor@example.com",
"first_name": "Ihor",
"last_name": "Melnyk",
"language": "uk",
"external_doctor_id": "crm-doc-4471",
"consent": { "account_creation": true }
}Пример ответа
{
"payload": {
"public_id": "LSG9w6B2rwAiPoJD",
"app_id": "4833d2e5-1a97-4572-ac5d-a03c7614e0d7",
"public_key": "94af0494...",
"private_key": "b208c6e0...",
"created": true
}
}| Поле | Описание |
|---|---|
app_id | App-Id, которым этот врач подписывает вызовы плоскости данных (X-Eternity-App-Id). |
public_key | Публичная половина пары ключей врача. |
private_key | Приватная половина. Показывается в этом ответе и больше никогда — сохраните её до закрытия соединения. |
public_id | Стабильный публичный идентификатор врача — используйте его везде, где называется владелец или директор. |
created | true, если аккаунт создал именно этот вызов; false, если у врача уже был аккаунт и он найден. |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Врач заведён; учётные данные возвращены. |
409 | У этого врача уже есть ключ для этой клиники, либо клинику создавали не вы и её директор вас не одобрил — сначала поднимите запрос clinic_membership. |
422 | Ошибка валидации (нет email/телефона или не принят consent.account_creation). |
/v1/platform/organizations/{clinic_public_id}/members/{doctor_public_id}/credentialsПолучить ключи, действующие от имени врача, который на это согласился.▸Авторизация: HMAC with your PLATFORM key.
Пример ответа
{
"payload": {
"public_id": "LSG9w6B2rwAiPoJD",
"app_id": "dcd4895e-550e-424a-9c5d-5206cbce2956",
"public_key": "11fff5d1...",
"private_key": "00604b9b...",
"created": false
}
}| Поле | Описание |
|---|---|
private_key | Показывается один раз и больше никогда. Ключ принадлежит вам и отделён от собственного ключа врача — когда он отзовёт согласие, ваш перестанет работать, а его нет. |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Ключи выданы. |
409 | Врач не согласился на передачу, либо с этой клиникой вы работать не можете. В сообщении сказано, что именно. |
/v1/platform/consentsЗапросить разрешение у врача или клиники.▸Авторизация: HMAC with your PLATFORM key.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
kind | да | string | — | key_handover — держать ключи, действующие от имени этого врача; разрешить это может только сам врач. clinic_membership — завести врача в клинику, которую вы не создавали; решает её директор. |
doctor_public_id | да | string | — | Врач, которого касается запрос. |
clinic_public_id | условно | string | — | Обязательно для clinic_membership: клиника, директора которой вы спрашиваете. |
Тело запроса (JSON)
{
"kind": "clinic_membership",
"doctor_public_id": "LSG9w6B2rwAiPoJD",
"clinic_public_id": "jJlmHf0sgxMT3Gni"
}Пример ответа
{
"payload": {
"public_id": "5G5rBYl0hQvpJuCZ",
"kind": "clinic_membership",
"status": "pending",
"expires_at": 1788973565,
"decided_at": null
}
}| Поле | Описание |
|---|---|
public_id | По нему опрашивайте статус. |
status | pending, пока человек не ответит, затем approved или denied. |
expires_at | Unix-секунды. Запрос без ответа закрывается сам, и одобрение перестаёт действовать в тот же момент — разрешение не бессрочное. |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Запрос создан, либо возвращён уже существующий — повторное обращение не создаёт второй. |
409 | Некому это решать (например, клиника без директора). |
422 | Ошибка валидации (неизвестный kind или отсутствует clinic_public_id для clinic_membership). |
/v1/platform/consents/{public_id}Проверить, на каком этапе запрос разрешения.▸Авторизация: HMAC with your PLATFORM key.
Пример ответа
{
"payload": {
"public_id": "5G5rBYl0hQvpJuCZ",
"kind": "clinic_membership",
"status": "approved",
"expires_at": 1788973565,
"decided_at": 1787763211
}
}Статусы ответа
| Статус | Значение |
|---|---|
200 | Текущее состояние. |
404 | Такого запроса нет или он принадлежит другому партнёру. |
Partner API — данные
Животные, владельцы, процедуры и фото — повседневная поверхность. Каждая запись здесь фиксируется от имени врача, чьим ключом она подписана.
- Подписывается ключом врача, который возвращается один раз — когда вы заводите врача в клинику или получаете его учётные данные после согласия. В X-Eternity-App-Id отправляйте uuid приложения этого врача.
- Завести ничего не может и перестаёт работать в тот момент, когда врач отзывает разрешение. Справочники не требуют подписи вообще.
/v1/partner/dictionariesСправочники (многоязычные, с фильтрацией).▸Авторизация: Публичный (подпись не требуется). Кэшируется в CDN через ETag.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
include | нет | string (csv) | — | Ключи справочников через запятую; пустое значение — все. Ключи: species, pet_species_featured, sex, sizes, lost_statuses, other_identifiers, procedure_types, countries, languages, cites. `pet_species_featured` — канонический список популярных видов с public_id в формате UUID; передавайте его код в POST /animals как species_public_id. |
q | нет | string | — | Фильтровать записи по локализованному названию на любом активном языке. |
lang | нет | string | languages | Проецировать названия в одну локаль (uk, en, ru, de, es). По умолчанию: все активные. |
Пример ответа
{
"payload": [
{
"key": "species",
"items": [
{ "code": 3, "names": { "uk": "Собаки", "en": "Dogs", "ru": "Собаки", "de": "Dogs" } },
{ "code": 4, "names": { "uk": "Коти", "en": "Cats" } }
]
},
{
"key": "pet_species_featured",
"items": [
{ "code": "1b289672-0a74-48d2-9600-7104bedacd8c", "names": { "uk": "Собака", "en": "Dog" } },
{ "code": "b0dd3c3a-4d35-4479-91f9-616ae072c400", "names": { "uk": "Домашні коти", "en": "Domestic cats" } }
]
},
{
"key": "countries",
"items": [
{ "code": "804", "alpha2": "UA", "alpha3": "UKR",
"names": { "uk": "Україна", "en": "Ukraine", "ru": "Украина", "de": "Ukraine", "es": "Ukraine" } }
]
},
{
"key": "languages",
"items": [
{ "code": "uk", "native": "Українська",
"names": { "uk": "Українська", "en": "Ukrainian", "ru": "Украинский", "de": "Ukrainian", "es": "Ukrainian" } }
]
}
],
"metadata": { "etag": "W/\"dict-…\"", "generated_at": "2026-05-30T08:00:00+00:00", "languages": ["uk","en","ru","de","es"] },
"links": [],
"message": null
}| Поле | Описание |
|---|---|
payload[].key | Ключ словаря. |
payload[].items[].code | Стабильный id, используемый как значение в эндпоинтах записи. Числовой для большинства справочников (species, sex, …); для pet_species_featured это канонический public_id вида (UUID) → передавайте его как species_public_id в POST /animals; для countries это дополненный нулями числовой код ISO 3166-1 в виде строки (напр. "004", "804"); для languages это код ISO 639-1 (напр. "uk"). |
payload[].items[].names | Сопоставление локаль → локализованное название. Локали без перевода откатываются на английский. |
payload[].items[].alpha2 / alpha3 | Только страны: коды ISO 3166-1 alpha-2 / alpha-3 для удобного сопоставления. |
payload[].items[].native | Только языки: собственное название языка (эндоним), удобно для выбора языка. |
metadata.etag | Передайте обратно в If-None-Match, чтобы получить 304 при отсутствии изменений. |
metadata.languages | Активные локали, реально присутствующие в этой сборке. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK — словари возвращены. |
304 | Not Modified — ваш If-None-Match совпадает; используйте кэшированную копию. |
/v1/partner/dictionaries/speciesПоиск видов животных (канонический, по public_id).▸Авторизация: Public (no signature required).
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
q | нет | string | — | Поисковый запрос по виду (любой таксономический ранг, подстрока и устойчивость к опечаткам). Не передавайте, чтобы посмотреть лучшие совпадения. Дополняет справочник pet_species_featured, где только популярные виды. |
Пример ответа
{
"payload": [
{ "public_id": "1b289672-0a74-48d2-9600-7104bedacd8c", "name": "Dog", "rank": "species", "has_breeds": true },
{ "public_id": "9cd7d2a1-4e45-4922-8f9e-fb84c61ca6ae", "name": "Cats", "rank": "genus", "has_breeds": false }
]
}| Поле | Описание |
|---|---|
payload[].public_id | public_id вида — передайте его как species_public_id в POST /animals или в /dictionaries/species/{species_public_id}/breeds. |
payload[].name | Локализованное название вида (язык запроса, фолбэк — английский). |
payload[].rank | Таксономический ранг (вид, род, семейство, …). |
payload[].has_breeds | Есть ли у этого вида список пород. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK — matching species. |
/v1/partner/dictionaries/species/{species_public_id}/breedsПороды для вида (канонические, по public_id).▸Авторизация: Public (no signature required).
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
species_public_id | да | string | — | Сегмент пути: public_id вида (UUID). Найти его можно через pet_species_featured или /dictionaries/species. |
q | нет | string | — | Необязательный фильтр по названию породы (подстрока, устойчив к опечаткам). |
Пример ответа
{
"payload": [
{ "public_id": "6bb37956-d7fb-426d-8045-9d2fb854ee43", "name": "Belgian Shepherd Dog", "kind": "purebred" },
{ "public_id": "d1f2a0c8-7b3e-4a1d-9c22-0f5e6b7a8c90", "name": "Mixed breed", "kind": "mixed" }
]
}| Поле | Описание |
|---|---|
payload[].public_id | Канонический public_id породы — передайте его как breed_public_id в POST /animals. |
payload[].name | Локализованное название породы (язык запроса, фолбэк — английский). |
payload[].kind | purebred | mixed | unknown | crossbreed | variety. mixed/unknown/crossbreed — специальные служебные варианты. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK — породы этого вида (пустой список, если пород нет). |
404 | species_public_id не является корректным UUID (маршрут не совпал). |
/v1/partner/ownersСоздать (или найти) владельца; возвращает глобальный ID пользователя.▸Авторизация: HMAC. Любой партнёрский ключ. · X-Eternity-Idempotency-Key обязательно
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
email | условно | string | — | Email владельца. Требуется один из email/phone — именно так с владельцем позже связываются/аутентифицируют его. |
phone | условно | string | — | Телефон владельца (E.164). Требуется один из email/phone. |
first_name | нет | string | — | Имя. |
last_name | нет | string | — | Фамилия. |
language | нет | string | languages | Предпочитаемая локаль. |
country | нет | string | countries | Дополненный нулями числовой код ISO 3166-1 в виде строки (например, "804") — соответствует коду из словаря countries. |
external_owner_id | нет | string | — | Ваш собственный идентификатор этого человека. Сохраняется один раз, при первом контакте, и никогда не перезаписывается — передавайте его, чтобы обе стороны могли сверить одного и того же человека позже. Максимум 128 символов. |
consent | да | object | — | Блок согласия (неизменяемый аудит). |
consent.account_creation | да | bool | — | Должно быть true — владелец согласился на создание учётной записи. Время фиксации записывается на стороне сервера. |
Тело запроса (JSON)
{
"email": "jane@example.com",
"phone": "+380681234567",
"first_name": "Jane",
"last_name": "Doe",
"language": "uk",
"country": "804",
"external_owner_id": "crm-4471",
"consent": {
"account_creation": true
}
}Пример ответа
{
"payload": {
"user_gid": 90231,
"public_id": "V1StGXR8Z5jd",
"has_account": true,
"email": "jane@example.com",
"phone": null,
"display_hint": "Ол*** К.",
"language": "uk",
"country_id": 804,
"external_owner_id": "crm-4471"
}
}| Поле | Описание |
|---|---|
public_id | Стабильный публичный идентификатор владельца — передайте его в POST /animals owners[].public_id (версия API >= 2026-07-04). |
user_gid | Устаревший числовой идентификатор владельца (привязка владельца в старых версиях API). |
has_account | Есть ли у владельца уже работающая учётная запись. |
email | Email, имеющийся в записи для этого владельца (null, если неизвестен). |
phone | Телефон, имеющийся в записи для этого владельца (null, если неизвестен). |
display_hint | Маскированное отображаемое имя (без PII). |
external_owner_id | Идентификатор, который ВЫ передали нам для этого человека, или null, если не передавали. Ограничен вашей интеграцией — вы никогда не видите, как того же человека называет другой партнёр. |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Создан (или сопоставлен существующий владелец — идемпотентно по email/phone). |
409 | X-Eternity-Idempotency-Key повторно использован с другим телом или ещё обрабатывается. |
422 | Ошибка валидации (отсутствует email/phone или consent.account_creation не принят). |
/v1/partner/owners/searchНайти владельца по точному email или телефону.▸Авторизация: HMAC. Любой партнёрский ключ.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
email_or_phone | да | string | — | Точный email или телефон (одно поле; email определяется по формату). |
Пример ответа
{
"payload": { "user_gid": 90231, "public_id": "V1StGXR8Z5jd", "has_account": true, "email": "jane@example.com", "phone": null, "display_hint": "Ол*** К.", "language": "uk", "country_id": 804, "external_owner_id": "crm-4471" }
}| Поле | Описание |
|---|---|
public_id | Стабильный публичный идентификатор владельца — передайте его в POST /animals owners[].public_id (версия API >= 2026-07-04). |
user_gid | Устаревший числовой идентификатор владельца (привязка владельца в старых версиях API). |
email | Email, имеющийся в записи для этого владельца (null, если неизвестен). |
phone | Телефон, имеющийся в записи для этого владельца (null, если неизвестен). |
external_owner_id | Идентификатор, который ВЫ передали нам для этого человека, или null, если не передавали. Ограничен вашей интеграцией — вы никогда не видите, как того же человека называет другой партнёр. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | Владелец найден. |
404 | Нет владельца с таким email_or_phone. |
422 | Требуется email_or_phone. |
/v1/partner/animalsЗарегистрировать животное (по чипу).▸Авторизация: HMAC. Ключ ветеринара/организации. · X-Eternity-Idempotency-Key обязательно
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
species | условно | int | species | Устаревший id вида из справочника. Нужен ровно один из species / species_public_id. |
species_public_id | условно | string | pet_species_featured | Канонический public_id вида (UUID) из справочника pet_species_featured. Нужен ровно один из species / species_public_id; если передан — имеет приоритет над species. |
is_microchip | да | bool | — | Чипировано ли животное. true → microchip обязателен; false → microchip игнорируется, и реестр присваивает временный номер WC. |
microchip | условно | string | — | Микрочип (транспондер). Требуется только когда is_microchip = true. |
nickname | да | string | — | Кличка животного. |
qr_tag | нет | string | — | Серийный номер QR-паспорта для привязки при регистрации. |
owners | нет | array | — | Владельцы; первый становится main_owner, остальные — owners (с устранением дубликатов). Каждая запись либо привязывает существующего владельца, ЛИБО регистрирует нового на месте. |
owners[].public_id | условно | string | — | Режим привязки (версия API >= 2026-07-04): public_id существующего владельца из POST/GET owners. Пропустите, чтобы зарегистрировать встроенно. |
owners[].user_gid | условно | int | — | Режим привязки (версии API до 2026-07-04): устаревший числовой идентификатор владельца. Пропустите, чтобы зарегистрировать встроенно. |
owners[].email | условно | string | — | Встроенный режим: email владельца. Требуется одно из email/phone, когда нет public_id/user_gid (upsert — без дубликатов). |
owners[].phone | условно | string | — | Режим на месте: телефон владельца (E.164). |
owners[].first_name | нет | string | — | Режим на месте: имя. |
owners[].last_name | нет | string | — | Режим на месте: фамилия. |
owners[].language | нет | string | languages | Режим на месте: предпочитаемая локаль. |
owners[].country | нет | string | countries | Режим на месте: дополненный нулями числовой код ISO 3166-1 в виде строки (например, "804") — соответствует коду из словаря countries. |
owners[].external_owner_id | нет | string | — | Inline-режим: ваш собственный идентификатор этого человека — то же поле и те же правила, что и в POST /owners. |
owners[].consent.account_creation | условно | bool | — | Режим на месте: должно быть true — владелец согласился на создание учётной записи. Требуется только при регистрации на месте. |
breed | нет | string | — | Порода (свободный текст). Используется, только если breed_public_id отсутствует. |
breed_public_id | нет | string | — | Канонический public_id породы (UUID) из GET /breeds?species_public_id=. Должен принадлежать этому виду; если передан — имеет приоритет над текстовой породой. |
color | нет | string | — | Окрас (свободный текст — без словаря). |
gender_id | нет | int | sex | Идентификатор из словаря gender. |
dob | нет | date | — | Дата рождения (ISO 8601). |
microchip_date | нет | date | — | Когда был имплантирован чип (ISO 8601). |
sterilization | нет | bool | — | Флаг стерилизации. |
size | нет | int | sizes | Идентификатор из словаря size. |
identifiers | нет | array | — | Дополнительные идентификаторы помимо microchip/qr. |
identifiers[].type | да | int | other_identifiers | Идентификатор типа из словаря other_identifiers (tattoo, ring, …). |
identifiers[].value | да | string | — | Значение идентификатора. |
identifiers[].added_at | нет | date | — | Когда идентификатор был присвоен (ISO 8601). |
Тело запроса (JSON)
{
"species": 3,
"is_microchip": true,
"microchip": "900263000123456",
"nickname": "Барсік",
"qr_tag": null,
"gender_id": 1,
"breed": "Labrador",
"color": "black",
"dob": "2022-03-01T00:00:00+00:00",
"microchip_date": "2022-11-20T00:00:00+00:00",
"sterilization": true,
"size": 2,
"owners": [
{ "public_id": "V1StGXR8Z5jd" },
{
"email": "jane@example.com",
"phone": "+380681234567",
"first_name": "Jane",
"last_name": "Doe",
"external_owner_id": "crm-4471",
"consent": { "account_creation": true }
}
],
"identifiers": [
{ "type": 3, "value": "TAT-001", "added_at": "2026-05-01T00:00:00+00:00" }
]
}Пример ответа
{ "payload": { "id": "8xK3pQzVnB7rL2qF" } }| Поле | Описание |
|---|---|
id | Неугадываемый публичный идентификатор животного (NanoID). Используйте его во всех последующих вызовах по животному. |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Животное зарегистрировано. |
409 | Конфликт X-Eternity-Idempotency-Key (тот же ключ, другое тело). |
422 | Ошибка валидации: нет nickname/is_microchip либо ни species, ни species_public_id; неизвестный species_public_id/breed_public_id или breed_public_id, не принадлежащий этому виду; is_microchip=true без корректного микрочипа; дубль микрочипа (такой транспондер уже зарегистрирован, поле "transponder"); либо встроенный владелец без email/телефона или без consent.account_creation. |
/v1/partner/animals/by-identifier/{type}/{value}Поиск по конкретному типу идентификатора. Всегда массив.▸Авторизация: HMAC. Любой партнёрский ключ.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
type | да | path enum | — | microchip или qr_tag. |
value | да | path string | — | Значение идентификатора для поиска. |
Пример ответа
{
"payload": [
{ "id": "8xK3pQzVnB7rL2qF", "species": 3,
"species_public_id": "d49c523a-d7ff-41b4-9ab6-0d1d2ce20939", "species_name": "Собака",
"breed": "Labrador", "breed_public_id": null, "breed_name": null,
"color": "black", "gender_id": 1,
"nickname": "Барсік", "microchip": "900263000123456", "qr_tag": null,
"dob": "2022-03-01", "register_date": "2026-05-30", "sterilization_status": true,
"lost_status": null, "deceased": false, "died_at": null, "status": 1,
"abilities": { "can_edit": true } }
]
}| Поле | Описание |
|---|---|
payload | Массив карточек животных — обычно одна, но значение может разрешиться в несколько. |
species_public_id | Канонический public_id вида — тот же ключ, который вы передаёте обратно как species_public_id в POST /animals. |
species_name | Название вида на языке запроса (фолбэк — английский, затем латинское название). |
breed_public_id | Канонический public_id породы или null, если у животного только текстовая порода. |
breed_name | Каноническое название породы на языке запроса; null, когда breed_public_id пуст — тогда читайте `breed`. |
microchip / qr_tag | Активные идентификаторы. |
lost_status | "active", когда заявлено об утере, иначе null. |
deceased | True, как только зафиксирована эвтаназия/смерть. |
Возможности
Каждый объект животного содержит объект abilities, описывающий, что аутентифицированный пользователь-партнёр может делать с этим животным. Это первый флаг доступа; со временем будут добавлены и другие.
| Поле | Описание |
|---|---|
abilities.can_edit | Может ли аутентифицированный пользователь-партнёр редактировать это животное — обновлять его данные, добавлять процедуры и управлять фотографиями. True, когда пользователь зарегистрировал животное, имеет к нему любое отношение (animal_user_relation) или является активным участником организации, в реестре которой оно числится (org_animals). |
Расширение (X-Eternity-Expand)
Необязательный заголовок, содержащий JSON-массив ключей расширения (например, ["owners"]). Каждый запрошенный ключ встраивает дополнительное поле в каждый объект животного в ответе; опустите заголовок, чтобы получить обычную карточку. Неизвестные ключи отклоняются с 422.
| Ключ | Добавляет | Описание |
|---|---|---|
owners | owners[] | Владельцы животного — основной владелец плюс любые совладельцы — каждый с контактными данными и флагом is_main_owner. Доступно только в этом партнёрском интерфейсе. |
"owners": [
{
"user_gid": 90231,
"public_id": "V1StGXR8Z5jd",
"has_account": true,
"email": "jane@example.com",
"phone": "+380681234567",
"display_hint": "Ja*** D.",
"language": "uk",
"country_id": "804",
"external_owner_id": "crm-4471",
"is_main_owner": true
}
]| Поле | Описание |
|---|---|
owners[].public_id | Стабильный публичный идентификатор владельца — передайте его в POST /animals owners[].public_id (версия API >= 2026-07-04). |
owners[].user_gid | Устаревший числовой идентификатор владельца (привязка владельца в старых версиях API). |
owners[].has_account | Есть ли у владельца уже работающая учётная запись. |
owners[].email | Email, имеющийся в записи для этого владельца (null, если неизвестен). |
owners[].phone | Телефон, имеющийся в записи для этого владельца (null, если неизвестен). |
owners[].display_hint | Маскированное отображаемое имя (без PII). |
owners[].language | Предпочитаемая локаль. |
owners[].country_id | Дополненный нулями числовой код ISO 3166-1 в виде строки (например, "804"). |
owners[].external_owner_id | Идентификатор, который ВЫ передали нам для этого человека, или null, если не передавали. Ограничен вашей интеграцией — вы никогда не видите, как того же человека называет другой партнёр. |
owners[].is_main_owner | true для основного владельца (animal_user_relation типа main_owner); false для совладельцев. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK — массив (возможно, пустой). |
/v1/partner/animals/by-identifier/{value}Поиск по всем типам идентификаторов сразу. Всегда массив.▸Авторизация: HMAC. Любой партнёрский ключ.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
value | да | path string | — | Значение идентификатора; поиск ведётся по microchip и qr_tag. |
Пример ответа
{ "payload": [ { "id": "8xK3pQzVnB7rL2qF", "nickname": "Барсік", "microchip": "900263000123456",
"species": 3, "species_public_id": "d49c523a-d7ff-41b4-9ab6-0d1d2ce20939",
"species_name": "Собака", "breed": "Labrador",
"breed_public_id": null, "breed_name": null } ] }| Поле | Описание |
|---|---|
species_public_id / breed_public_id | Канонические ключи — те же, что принимает POST /animals. breed_public_id пуст, пока у животного только текстовая порода. |
species_name / breed_name | Названия на языке запроса (фолбэк — английский, затем латинское/каноническое название). |
Возможности
Каждый объект животного содержит объект abilities, описывающий, что аутентифицированный пользователь-партнёр может делать с этим животным. Это первый флаг доступа; со временем будут добавлены и другие.
| Поле | Описание |
|---|---|
abilities.can_edit | Может ли аутентифицированный пользователь-партнёр редактировать это животное — обновлять его данные, добавлять процедуры и управлять фотографиями. True, когда пользователь зарегистрировал животное, имеет к нему любое отношение (animal_user_relation) или является активным участником организации, в реестре которой оно числится (org_animals). |
Расширение (X-Eternity-Expand)
Необязательный заголовок, содержащий JSON-массив ключей расширения (например, ["owners"]). Каждый запрошенный ключ встраивает дополнительное поле в каждый объект животного в ответе; опустите заголовок, чтобы получить обычную карточку. Неизвестные ключи отклоняются с 422.
| Ключ | Добавляет | Описание |
|---|---|---|
owners | owners[] | Владельцы животного — основной владелец плюс любые совладельцы — каждый с контактными данными и флагом is_main_owner. Доступно только в этом партнёрском интерфейсе. |
"owners": [
{
"user_gid": 90231,
"public_id": "V1StGXR8Z5jd",
"has_account": true,
"email": "jane@example.com",
"phone": "+380681234567",
"display_hint": "Ja*** D.",
"language": "uk",
"country_id": "804",
"external_owner_id": "crm-4471",
"is_main_owner": true
}
]| Поле | Описание |
|---|---|
owners[].public_id | Стабильный публичный идентификатор владельца — передайте его в POST /animals owners[].public_id (версия API >= 2026-07-04). |
owners[].user_gid | Устаревший числовой идентификатор владельца (привязка владельца в старых версиях API). |
owners[].has_account | Есть ли у владельца уже работающая учётная запись. |
owners[].email | Email, имеющийся в записи для этого владельца (null, если неизвестен). |
owners[].phone | Телефон, имеющийся в записи для этого владельца (null, если неизвестен). |
owners[].display_hint | Маскированное отображаемое имя (без PII). |
owners[].language | Предпочитаемая локаль. |
owners[].country_id | Дополненный нулями числовой код ISO 3166-1 в виде строки (например, "804"). |
owners[].external_owner_id | Идентификатор, который ВЫ передали нам для этого человека, или null, если не передавали. Ограничен вашей интеграцией — вы никогда не видите, как того же человека называет другой партнёр. |
owners[].is_main_owner | true для основного владельца (animal_user_relation типа main_owner); false для совладельцев. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK — массив (возможно, пустой). |
/v1/partner/animals/by-ownerПоиск животных по контакту владельца. Всегда массив.▸Авторизация: HMAC. Любой партнёрский ключ.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
email_or_phone | да | string | — | Точный email или телефон владельца (одно поле; email определяется по формату). Телефон сначала разрешается до владельца. |
Пример ответа
{ "payload": [ { "id": "8xK3pQzVnB7rL2qF", "nickname": "Барсік", "species": 3,
"species_public_id": "d49c523a-d7ff-41b4-9ab6-0d1d2ce20939",
"species_name": "Собака", "breed": "Labrador",
"breed_public_id": null, "breed_name": null } ] }| Поле | Описание |
|---|---|
species_public_id / breed_public_id | Канонические ключи — те же, что принимает POST /animals. breed_public_id пуст, пока у животного только текстовая порода. |
species_name / breed_name | Названия на языке запроса (фолбэк — английский, затем латинское/каноническое название). |
Возможности
Каждый объект животного содержит объект abilities, описывающий, что аутентифицированный пользователь-партнёр может делать с этим животным. Это первый флаг доступа; со временем будут добавлены и другие.
| Поле | Описание |
|---|---|
abilities.can_edit | Может ли аутентифицированный пользователь-партнёр редактировать это животное — обновлять его данные, добавлять процедуры и управлять фотографиями. True, когда пользователь зарегистрировал животное, имеет к нему любое отношение (animal_user_relation) или является активным участником организации, в реестре которой оно числится (org_animals). |
Расширение (X-Eternity-Expand)
Необязательный заголовок, содержащий JSON-массив ключей расширения (например, ["owners"]). Каждый запрошенный ключ встраивает дополнительное поле в каждый объект животного в ответе; опустите заголовок, чтобы получить обычную карточку. Неизвестные ключи отклоняются с 422.
| Ключ | Добавляет | Описание |
|---|---|---|
owners | owners[] | Владельцы животного — основной владелец плюс любые совладельцы — каждый с контактными данными и флагом is_main_owner. Доступно только в этом партнёрском интерфейсе. |
"owners": [
{
"user_gid": 90231,
"public_id": "V1StGXR8Z5jd",
"has_account": true,
"email": "jane@example.com",
"phone": "+380681234567",
"display_hint": "Ja*** D.",
"language": "uk",
"country_id": "804",
"external_owner_id": "crm-4471",
"is_main_owner": true
}
]| Поле | Описание |
|---|---|
owners[].public_id | Стабильный публичный идентификатор владельца — передайте его в POST /animals owners[].public_id (версия API >= 2026-07-04). |
owners[].user_gid | Устаревший числовой идентификатор владельца (привязка владельца в старых версиях API). |
owners[].has_account | Есть ли у владельца уже работающая учётная запись. |
owners[].email | Email, имеющийся в записи для этого владельца (null, если неизвестен). |
owners[].phone | Телефон, имеющийся в записи для этого владельца (null, если неизвестен). |
owners[].display_hint | Маскированное отображаемое имя (без PII). |
owners[].language | Предпочитаемая локаль. |
owners[].country_id | Дополненный нулями числовой код ISO 3166-1 в виде строки (например, "804"). |
owners[].external_owner_id | Идентификатор, который ВЫ передали нам для этого человека, или null, если не передавали. Ограничен вашей интеграцией — вы никогда не видите, как того же человека называет другой партнёр. |
owners[].is_main_owner | true для основного владельца (animal_user_relation типа main_owner); false для совладельцев. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK — массив (пустой, если у владельца нет email в записи при поиске только по телефону). |
422 | Требуется email_or_phone. |
/v1/partner/animals/{id}Полная карточка животного.▸Авторизация: HMAC. Любой партнёрский ключ.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
id | да | path string | — | Публичный идентификатор животного (NanoID). |
Пример ответа
{ "payload": { "id": "8xK3pQzVnB7rL2qF", "species": 3,
"species_public_id": "d49c523a-d7ff-41b4-9ab6-0d1d2ce20939", "species_name": "Собака",
"breed": "Labrador", "breed_public_id": null, "breed_name": null,
"nickname": "Барсік", "microchip": "900263000123456", "deceased": false,
"abilities": { "can_edit": true } } }| Поле | Описание |
|---|---|
species_public_id | Канонический public_id вида — тот же ключ, который вы передаёте обратно как species_public_id в POST /animals. |
species_name | Название вида на языке запроса (фолбэк — английский, затем латинское название). |
breed_public_id | Канонический public_id породы или null, если у животного только текстовая порода. |
breed_name | Каноническое название породы на языке запроса; null, когда breed_public_id пуст — тогда читайте `breed`. |
Возможности
Каждый объект животного содержит объект abilities, описывающий, что аутентифицированный пользователь-партнёр может делать с этим животным. Это первый флаг доступа; со временем будут добавлены и другие.
| Поле | Описание |
|---|---|
abilities.can_edit | Может ли аутентифицированный пользователь-партнёр редактировать это животное — обновлять его данные, добавлять процедуры и управлять фотографиями. True, когда пользователь зарегистрировал животное, имеет к нему любое отношение (animal_user_relation) или является активным участником организации, в реестре которой оно числится (org_animals). |
Расширение (X-Eternity-Expand)
Необязательный заголовок, содержащий JSON-массив ключей расширения (например, ["owners"]). Каждый запрошенный ключ встраивает дополнительное поле в каждый объект животного в ответе; опустите заголовок, чтобы получить обычную карточку. Неизвестные ключи отклоняются с 422.
| Ключ | Добавляет | Описание |
|---|---|---|
owners | owners[] | Владельцы животного — основной владелец плюс любые совладельцы — каждый с контактными данными и флагом is_main_owner. Доступно только в этом партнёрском интерфейсе. |
"owners": [
{
"user_gid": 90231,
"public_id": "V1StGXR8Z5jd",
"has_account": true,
"email": "jane@example.com",
"phone": "+380681234567",
"display_hint": "Ja*** D.",
"language": "uk",
"country_id": "804",
"external_owner_id": "crm-4471",
"is_main_owner": true
}
]| Поле | Описание |
|---|---|
owners[].public_id | Стабильный публичный идентификатор владельца — передайте его в POST /animals owners[].public_id (версия API >= 2026-07-04). |
owners[].user_gid | Устаревший числовой идентификатор владельца (привязка владельца в старых версиях API). |
owners[].has_account | Есть ли у владельца уже работающая учётная запись. |
owners[].email | Email, имеющийся в записи для этого владельца (null, если неизвестен). |
owners[].phone | Телефон, имеющийся в записи для этого владельца (null, если неизвестен). |
owners[].display_hint | Маскированное отображаемое имя (без PII). |
owners[].language | Предпочитаемая локаль. |
owners[].country_id | Дополненный нулями числовой код ISO 3166-1 в виде строки (например, "804"). |
owners[].external_owner_id | Идентификатор, который ВЫ передали нам для этого человека, или null, если не передавали. Ограничен вашей интеграцией — вы никогда не видите, как того же человека называет другой партнёр. |
owners[].is_main_owner | true для основного владельца (animal_user_relation типа main_owner); false для совладельцев. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK. |
404 | Животное не найдено. |
/v1/partner/animals/{id}Обновить изменяемые поля / отметить как умершее.▸Авторизация: HMAC. Владелец ИЛИ ветеринар с активным отношением к животному. · X-Eternity-Idempotency-Key обязательно
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
nickname | нет | string | — | Новая кличка. |
color | нет | string | — | Новый окрас (свободный текст — без словаря). |
sterilization_status | нет | bool | — | Установить флаг стерилизации. |
deceased | нет | bool | — | true → пометить животное умершим. |
Тело запроса (JSON)
{
"nickname": "Барсік",
"color": "black",
"sterilization_status": true,
"deceased": false
}Пример ответа
204 No Content
Статусы ответа
| Статус | Значение |
|---|---|
204 | Обновлено. |
403 | Нет доступа к этому животному — запросите его (POST /v1/partner/animals/{id}/access-request) и повторите после одобрения владельцем. |
409 | Конфликт X-Eternity-Idempotency-Key. |
422 | Ошибка валидации. |
/v1/partner/animals/{id}/access-requestПопросить владельца животного предоставить вам доступ.▸Авторизация: HMAC. Ключ ветеринара/организации. · X-Eternity-Idempotency-Key обязательно
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
id | да | path string | — | Публичный идентификатор животного (NanoID). |
Пример ответа
{
"payload": {
"status": "pending",
"requested_at": "2026-06-23T09:00:00+00:00",
"expires_at": "2026-06-30T09:00:00+00:00",
"retry_after_seconds": 604800
}
}| Поле | Описание |
|---|---|
status | "granted" — у вас уже есть доступ, запрос не создавался; "pending" — ожидается решение владельца; "denied" — владелец отказал (можно пересмотреть до истечения срока). |
requested_at | Когда был создан запрос (null при status="granted"). |
expires_at | Когда запрос истекает и вы можете запросить снова (null при status="granted"). |
retry_after_seconds | Секунды до того, как вы сможете снова запросить то же животное (0 после истечения; null при status="granted"). |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Создан новый запрос на доступ — владелец уведомлён по email. |
200 | Новый запрос не создан: у вас уже есть доступ (status "granted") или активный запрос уже существует (status "pending"/"denied") — подождите retry_after_seconds перед повторным запросом. |
404 | Животное не найдено. |
/v1/partner/animals/{id}/access-requestПроверить, одобрен ли ваш запрос на доступ.▸Авторизация: HMAC. Ключ ветеринара/организации.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
id | да | path string | — | Публичный идентификатор животного (NanoID). |
Пример ответа
{
"payload": {
"status": "granted",
"requested_at": "2026-06-23T09:00:00+00:00",
"expires_at": "2026-06-30T09:00:00+00:00",
"retry_after_seconds": 0
}
}| Поле | Описание |
|---|---|
status | "granted" — доступ одобрен и активен; "pending" — ожидается решение владельца; "denied" — отклонён; "none" — нет активного запроса. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK. |
404 | Животное не найдено. |
/v1/partner/animals/{id}/proceduresЗапись процедур; открывает приём. Один объект или массив.▸Авторизация: HMAC. Ключ ветеринара/организации с доступом к животному. · X-Eternity-Idempotency-Key обязательно
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
(body) | да | object | array | — | Один объект процедуры или их массив (≤100). |
type | да | int | procedure_types | Идентификатор каталога процедур: 10 вакцинация, 20 вакцинация от бешенства, 30 идентификация транспондером, 40 идентификация токеном, 50 дегельминтизация, 60 стерилизация, 70 эвтаназия / удостоверение смерти. |
occurred_at | да | datetime | — | Когда выполнено (ISO 8601). |
summary | нет | string | — | Заметка в свободной форме. |
revaccination_date | нет | date | — | Переопределить дату следующей вакцинации (вакцинации). |
type_specific_payload | нет | object | — | Поля по типу — валидируются на стороне сервера: 10/20 → {vaccine_name*, batch_number*}; 30 → {transponder_number* — 15 digits}; 40 → {token_number*}; 50 → {drug*, batch_number?, dose?}; 60 → {method?, anesthesia_type?}; 70 → {reason*, death_date*}. Для типа 30: если у животного уже есть микрочип, он сохраняется — новый номер записывается как дополнительный идентификатор (other_identifiers тип 11) вместо замены чипа. |
Тело запроса (JSON)
[
{
"type": 10,
"occurred_at": "2026-05-30T08:00:00+00:00",
"summary": "Annual shot",
"revaccination_date": "2027-05-30",
"type_specific_payload": {
"vaccine_name": "Nobivac",
"batch_number": "A123"
}
},
{
"type": 30,
"occurred_at": "2026-05-30T08:05:00+00:00",
"type_specific_payload": {
"transponder_number": "900263000123456"
}
}
]Пример ответа
{
"payload": {
"appointment_id": 7741,
"procedures": [
{ "id": 99001, "animal_id": "8xK3pQzVnB7rL2qF", "visit_id": 7741, "type": 10,
"occurred_at": "2026-05-30T08:00:00+00:00", "summary": "Annual shot", "revaccination_date": "2027-05-30",
"type_specific_payload": { "vaccine_name": "Nobivac", "batch_number": "A123" } }
]
}
}| Поле | Описание |
|---|---|
appointment_id | Визит, открытый/использованный для этой партии. |
procedures[] | Записанные процедуры — та же карточка, что и в GET списка/карточки. |
procedures[].id | Идентификатор записи процедуры. |
procedures[].type | Числовой id типа (справочник procedure_types). |
procedures[].type_specific_payload | Сохранённые данные, специфичные для типа. |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Записано; визит открыт. |
403 | Нет доступа к этому животному — запросите его (POST /v1/partner/animals/{id}/access-request) и повторите после одобрения владельцем. |
404 | Животное не найдено. |
409 | Конфликт X-Eternity-Idempotency-Key. |
422 | Неподдерживаемый тип, отсутствует occurred_at или отсутствуют поля, специфичные для типа. |
/v1/partner/animals/{id}/proceduresСписок процедур животного. Всегда массив.▸Авторизация: HMAC. Ключ ветеринара/организации.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
type | нет | int | procedure_types | Фильтровать по идентификатору каталога процедур. |
since | нет | datetime | — | Только в эту дату или после неё. |
until | нет | datetime | — | Только в эту дату или до неё. |
Пример ответа
{
"payload": [
{ "id": 99001, "animal_id": "8xK3pQzVnB7rL2qF", "visit_id": 7741, "type": 10,
"occurred_at": "2026-05-30T08:00:00+00:00", "summary": null, "revaccination_date": "2027-05-30",
"type_specific_payload": { "vaccine_name": "Nobivac", "batch_number": "A123" } }
]
}| Поле | Описание |
|---|---|
type | Идентификатор каталога процедур (словарь procedure_types). |
visit_id | Приём, под которым была записана процедура. |
type_specific_payload | Поля по типу. |
Статусы ответа
| Статус | Значение |
|---|---|
200 | OK — массив (возможно, пустой). |
404 | Животное не найдено. |
/v1/partner/procedures/{id}Одна процедура.▸Авторизация: HMAC. Ключ ветеринара/организации.
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
id | да | path int | — | Идентификатор записи процедуры. |
Пример ответа
{
"payload": {
"id": 99001, "animal_id": "8xK3pQzVnB7rL2qF", "visit_id": 7741, "type": 10,
"occurred_at": "2026-05-30T08:00:00+00:00", "summary": null, "revaccination_date": "2027-05-30",
"type_specific_payload": { "vaccine_name": "Nobivac", "batch_number": "A123" }
}
}Статусы ответа
| Статус | Значение |
|---|---|
200 | OK. |
404 | Процедура не найдена. |
/v1/partner/animals/{id}/photosЗагрузить фото (multipart). Владелец или ветеринар со связью.▸Авторизация: HMAC + multipart/form-data. Владелец ИЛИ ветеринар с отношением. · X-Eternity-Idempotency-Key обязательно
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
file | да | file | — | Файл изображения. Максимум 8 MB на фото (config partner.photos.max_single_mb). |
kind | нет | enum | — | avatar | gallery | nose_print. avatar устанавливает главное фото. По умолчанию gallery. |
Пример ответа
{ "payload": { "id": 33015 } }| Поле | Описание |
|---|---|
id | Идентификатор нового фото. |
Статусы ответа
| Статус | Значение |
|---|---|
201 | Загружено. |
403 | Нет доступа к этому животному — запросите его (POST /v1/partner/animals/{id}/access-request) и повторите после одобрения владельцем. |
422 | Недопустимый файл или больше 8 MB (уменьшите размер / понизьте качество). |
413 | Весь запрос превышает 15 MB. |
/v1/partner/animals/{id}/photos/{photoId}Мягкое удаление фото.▸Авторизация: HMAC. Владелец ИЛИ ветеринар с отношением. · X-Eternity-Idempotency-Key обязательно
Поля запроса
| Поле | Обяз. | Тип | Словарь | Описание |
|---|---|---|---|---|
id | да | path string | — | Публичный идентификатор животного (NanoID). |
photoId | да | path int | — | Идентификатор фото. |
Пример ответа
204 No Content
Статусы ответа
| Статус | Значение |
|---|---|
204 | Удалено. |
403 | Нет доступа к этому животному — запросите его (POST /v1/partner/animals/{id}/access-request) и повторите после одобрения владельцем. |