Методи 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-vueКомпозабли Vue.
- @animal-id/partner-angularСервіси Angular.
- @animal-id/partner-nestjsМодуль NestJS для серверних інтеграцій.
Автентифікація та підпис запиту
Базова URL-адреса: https://gw.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"]). Дивіться розділ «Розширення» кінцевої точки щодо її дозволених ключів; невідомі ключі → 422. |
Підписуйте та надсилайте точно ті самі байти тіла. Для 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 | Власник відхилив ваш запит на доступ — ви можете повторити запит після завершення терміну дії. |
Підтверджуйте будь-якою відповіддю 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
Почніть вводити — розділи відфільтруються за ключовими словами.
/v1/partner/dictionariesДовідники (багатомовні, з фільтрацією).▸Автентифікація: Публічна (підпис не потрібен). Кешується на CDN через ETag.
Поля запиту
| Поле | Обов. | Тип | Словник | Опис |
|---|---|---|---|---|
include | ні | string (csv) | — | Розділені комами ключі словників для повернення; порожнє → усі. Ключі: species, sex, sizes, lost_statuses, other_identifiers, procedure_types, countries, languages, cites. |
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": "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 | Стабільний ідентифікатор, що використовується як значення в кінцевих точках запису. Числовий для більшості словників (species, sex, …); для countries це доповнений нулями числовий код ISO 3166-1 у вигляді рядка (напр. "004", "804"); для languages це код ISO 639-1 (напр. "uk"). |
payload[].items[].names | Зіставляє локаль → локалізована назва. Локалі без перекладу повертаються до англійської. |
payload[].items[].alpha2 / alpha3 | Лише для countries: коди ISO 3166-1 alpha-2 / alpha-3 для зручного зіставлення. |
payload[].items[].native | Лише для languages: власна назва мови (ендонім), зручно для вибору мови. |
metadata.etag | Передайте назад у If-None-Match, щоб отримати 304, якщо змін немає. |
metadata.languages | Активні локалі, фактично присутні в цій збірці. |
Статуси відповіді
| Статус | Значення |
|---|---|
200 | OK — словники повернено. |
304 | Not Modified — ваш If-None-Match збігається; використовуйте кешовану копію. |
/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. |
consent | так | object | — | Блок згоди (незмінний аудит). |
consent.account_creation | так | bool | — | Має бути true — власник погодився на створення облікового запису. Час фіксації записується на стороні сервера. |
Тіло запиту (JSON)
{
"email": "jane@example.com",
"phone": "+380681234567",
"first_name": "Jane",
"last_name": "Doe",
"language": "uk",
"country": "804",
"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
}
}| Поле | Опис |
|---|---|
public_id | Стабільний публічний ідентифікатор власника — передайте його в POST /animals owners[].public_id (версія API >= 2026-07-04). |
user_gid | Застарілий числовий ідентифікатор власника (прикріплення власника у старих версіях API). |
has_account | Чи має власник уже придатний для використання обліковий запис. |
email | Email, що зберігається для цього власника (null, якщо невідомий). |
phone | Телефон, що зберігається для цього власника (null, якщо невідомий). |
display_hint | Замасковане відображуване ім'я (без персональних даних). |
Статуси відповіді
| Статус | Значення |
|---|---|
201 | Created (або знайдено наявного власника — ідемпотентно за 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 }
}| Поле | Опис |
|---|---|
public_id | Стабільний публічний ідентифікатор власника — передайте його в POST /animals owners[].public_id (версія API >= 2026-07-04). |
user_gid | Застарілий числовий ідентифікатор власника (прикріплення власника у старих версіях API). |
email | Email, що зберігається для цього власника (null, якщо невідомий). |
phone | Телефон, що зберігається для цього власника (null, якщо невідомий). |
Статуси відповіді
| Статус | Значення |
|---|---|
200 | Власника знайдено. |
404 | Немає власника з таким email_or_phone. |
422 | email_or_phone є обов'язковим. |
/v1/partner/animalsЗареєструвати тварину (за чипом).▸Автентифікація: HMAC. Ключ ветеринара/організації. · X-Eternity-Idempotency-Key обов'язково
Поля запиту
| Поле | Обов. | Тип | Словник | Опис |
|---|---|---|---|---|
species | так | int | species | Ідентифікатор словника 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[].consent.account_creation | умовно | bool | — | Вбудований режим: має бути true — власник погодився на створення облікового запису. Обов'язково лише при вбудованій реєстрації. |
breed | ні | string | — | Порода (вільний текст — без словника). |
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",
"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 | Помилка валідації: відсутні species/nickname/is_microchip; is_microchip=true без дійсного microchip; дублікат microchip (транспондер уже зареєстровано, поле "transponder"); або вбудований власник без email/phone чи без 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, "breed": "Labrador", "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 | Масив карток тварин — зазвичай одна, але значення може відповідати кільком. |
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",
"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 | Замасковане відображуване ім'я (без персональних даних). |
owners[].language | Бажана локаль. |
owners[].country_id | Доповнений нулями числовий код ISO 3166-1 у вигляді рядка (напр. "804"). |
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" } ] }Дозволи
Кожен об'єкт тварини містить об'єкт 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",
"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 | Замасковане відображуване ім'я (без персональних даних). |
owners[].language | Бажана локаль. |
owners[].country_id | Доповнений нулями числовий код ISO 3166-1 у вигляді рядка (напр. "804"). |
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 } ] }Дозволи
Кожен об'єкт тварини містить об'єкт 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",
"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 | Замасковане відображуване ім'я (без персональних даних). |
owners[].language | Бажана локаль. |
owners[].country_id | Доповнений нулями числовий код ISO 3166-1 у вигляді рядка (напр. "804"). |
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, "nickname": "Барсік", "microchip": "900263000123456", "deceased": false, "abilities": { "can_edit": 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",
"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 | Замасковане відображуване ім'я (без персональних даних). |
owners[].language | Бажана локаль. |
owners[].country_id | Доповнений нулями числовий код ISO 3166-1 у вигляді рядка (напр. "804"). |
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 | Створено новий запит доступу — власника сповіщено електронною поштою. |
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[] | The recorded procedures — same card as GET list/show. |
procedures[].id | Ідентифікатор запису процедури. |
procedures[].type | Numeric type id (procedure_types dictionary). |
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) і повторіть після погодження власником. |