API та інтеграції

Один ключ. Говорить звідусіль.

REST API, сумісний з OpenAI SDK, вебхуки з підписом HMAC і MCP-сервер. Модулі для n8n, Make і Zapier та потік у телефонію — у роботі.

POST /v1/audio/speechstream: trueMCP · 4 toolswebhooks · 3 eventsSIP · WSS
REST API

Змініть baseURL — решта коду лишається.

Ендпоінти дзеркалять OpenAI: audio.speech.create працює без змін. Ключ hm_live_…, моделі homin-neo-1, homin-pro-1, homin-live-1. Символи рахуються так, як їх отримає провайдер: літери, пробіли, розділові знаки й кожен знак наголосу U+0301 — і ваш, і доданий словником, а пауза — довжиною тегу <break>. Списане приходить у заголовку x-homin-credits.

# один запит — готовий mp3
curl https://homin.ua/v1/audio/speech \
  -H "Authorization: Bearer $HOMIN_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"homin-pro-1","voice":"solomiia",
       "input":"Стари́й за́мок стоїть над Дніпро́м, а на дверя́х — іржавий замо́к і загу́блені ключі́."}' \
  --output hello.mp3

Довідник ендпоінтів

https://homin.ua/v1
POST/audio/speech scope: write
текст → mp3 потоком · format: mp3_44100_128 або mp3_22050_32 · рекомендовано до 5 000 символів · наголос U+0301
POST/generations/quote scope: read
{ voice, input } → { chars, credits, upTo? } — стільки спише синтез; upTo — стеля, якщо модель наголосів додасть свої знаки · сам кошторис нічого не списує
GET/audio/file/{id}.mp3
збережений файл · готове посилання — у заголовку x-homin-audio-url, діє добу
GET/voices
голоси: id, ім’я, модель, мови, семпл · без ключа
POST/stress/check
{ text } → текст із наголосами й омографи з варіантами · без ключа
GET/usage scope: read
кредити, тариф, витрати за місяць, бюджет ключа
GET/usage/daily scope: read
витрати по днях · days до 90
GET/generations scope: read
історія генерацій · limit до 200, cursor, q, status · /generations/{id} — одна
DELETE/generations/{id} scope: delete
видаляє генерацію
GET/keys scope: keys
ключі простору · POST — випуск, PATCH і DELETE /keys/{id} · право keys типово вимкнене
Помилки синтезу (POST /audio/speech) — JSON з кодом у полі error і зазвичай з поясненням у detail; коди — у таблиці нижче.

Коди помилок

POST /audio/speech
HTTPКодЩо означає
400input_requiredнемає тексту в input
400inputтекст довший за 20 000 символів
400rejectedнемає тексту для озвучення — наприклад, лише наголоси чи паузи
400voice_requiredне вказано voice
400format_unsupportedformat не mp3_44100_128 і не mp3_22050_32
400model_unknownневідома модель
400model_not_supportedмодель не озвучує цей голос
400model_not_allowedключ не має доступу до цієї моделі
400quota_exceededбракує кредитів або вичерпано бюджет ключа
401key_revokedключ недійсний, відкликаний або прострочений
401rejectedу запиті немає ключа
402provider_rejectedпровайдер синтезу відхилив запит через ліміт свого тарифу
402margin_floorжоден провайдер не озвучить цей запит у межах мінімальної маржі платформи — спробуйте інший голос чи модель
403insufficient_scopeключу бракує права «синтез»
403workspace_suspendedпростір призупинено — зверніться в підтримку
403provider_not_allowedголоси ElevenLabs доступні лише в студії
404rejectedголос не знайдено
413payload_too_largeтіло запиту більше за 128 КБ
422voice_unavailableголос зараз недоступний у провайдера синтезу
422text_too_longтекст задовгий для моделі синтезу
429rate_limitedз однієї адреси понад 600 запитів за хвилину чи 4 синтези одночасно — повторіть після Retry-After
429provider_busyпровайдер синтезу перевантажений — повторіть за хвилину
502provider_authпровайдер синтезу не прийняв ключ платформи
502provider_rejectedпровайдер синтезу відхилив запит
502upstream_failedсинтез не вдався — повторіть запит
503provider_unavailableнемає провайдера, який зараз озвучить цей голос
503provider_quotaу провайдера синтезу вичерпано ліміт платформи
504control_timeoutшлюз не дочекався відповіді сервера HOMIN — повторіть запит

Ліміти та гарантії

FreeProBusinessEnterprise
Запитів / хв на ключ—120600за договором
Символів / добу—500 0005 000 000без ліміту
Паралельних потоків Live1 (демо)—50500+
Відповідь API (p95)—< 150 мс< 150 мс< 100 мс
SLA——99,9 %99,95 %
MCP

Один рядок у конфігу — і асистент говорить українською.

ChatGPT, Claude, Claude Code, Cursor — будь-який клієнт MCP підключається за адресою і сам викликає інструменти HOMIN.

# Customize → Connectors → «Add custom connector»: вставте адресу й увійдіть
https://homin.ua/mcp
tts_speakтекст → аудіо
stress_checkнаголоси
voices_listголоси
usage_getбаланс

Як це виглядає в асистенті

Ви: «Озвуч цей абзац голосом Остапа і збережи mp3»
→ stress_check({ text: "…" }) · 1 омограф
Claude: «У слові „замок” два наголоси. Це будівля чи на дверях?»
Ви: «Будівля»
→ tts_speak({ voice: "ostap", input: "…за́мок…" })
▶abzats.mp3 · 0:42 · 14 кредитів
Claude: «Готово. Залишилось 12 466 кредитів.»
Асистент сам перевіряє наголоси перед озвученням — так працює stress_check у парі з tts_speak.
Автоматизації

n8n, Make, Zapier і вебхуки.

Шаблони сценаріїв: від таблиці до аудіо в каналі. Готових модулів поки немає — підключайте через HTTP-запит до API і вебхуки.

ШаблонGoogle Sheets → HOMIN → Telegram

Google Sheetsновий рядок
HOMINtts_speak · Соломія
Telegramголосове в канал
n8nMakeZapier

ШаблонRSS → дайджест новин голосом

RSSнові статті
HOMINNeo · Верес
Spotify / Driveепізод щоранку
n8nMake

ШаблонCRM → персональний голосовий дзвінок

HubSpotнова угода
HOMIN LiveБогдан
Twilioдзвінок клієнту
ZapierMake

ВебхукиПодії генерацій і бюджету, підпис HMAC, до 3 повторів

generation.completedgeneration.failedbudget.threshold
POST https://your.app/hooks/homin
X-HOMIN-Event: generation.completed
X-HOMIN-Signature: sha256=9f86d081…
X-HOMIN-Timestamp: 1760270402
X-HOMIN-Delivery: clx…
{ "id": "evt_3f9a1c0b7d2e4f6a8b1c2d3e",
  "type": "generation.completed", "created": 1760270400,
  "data": { "id": "clw9k2m4x0001", "voice": "solomiia",
    "model": "pro", "chars": 640, "credits": 13, "seconds": 41.2,
    "url": "https://homin.ua/audio/file/clw9k2m4x0001.mp3?exp=…&sig=…" } }
Документація вебхуків
Вебхуки

Події на ваш сервер — з підписом і повторами.

HOMIN надсилає POST із JSON на вашу HTTPS-адресу, коли генерація готова чи не вдалася або ключ доходить порогу бюджету. Вебхуки належать простору, а керують ними в кабінеті власник і адміністратори з доступом до ключів.

Події та підпис

HMAC-SHA256
ПодіяКолиdata
generation.completedаудіо готовеid, voice (slug), model (neo|pro|live), chars, credits, seconds|null, url|null
generation.failedсинтез не вдався або генерацію закритоid, error
budget.thresholdключ дійшов 80 % бюджету, вичерпав його або запит не вмістився в залишокscope (key), key {id, name}, threshold (80|100), level (warning|exhausted), spent, budget, remaining
webhook.testтест із кабінетуendpoint

Тіло — JSON { id, type, created, data }; id події однаковий для всіх ендпойнтів і повторів, created — Unix-секунди.

X-HOMIN-Event— тип події
X-HOMIN-Signature— sha256=HMAC(секрет, timestamp.body)
X-HOMIN-Timestamp— час підпису цієї спроби, Unix-секунди; розходиться з вашим годинником більш ніж на 5 хв — відхиляйте
X-HOMIN-Delivery— id доставки, один для всіх спроб, — для звірки з журналом у кабінеті
# 1. перевірити підпис: body.json — сире тіло запиту, TS — X-HOMIN-Timestamp
printf '%s.' "$TS" | cat - body.json \
  | openssl dgst -sha256 -hmac "$HOMIN_WEBHOOK_SECRET" | awk '{print "sha256=" $NF}'
# має збігтися з X-HOMIN-Signature

# 2. надіслати на свій приймач підписаний тест
TS=$(date +%s)
BODY='{"id":"evt_test_local","type":"webhook.test","created":'"$TS"',"data":{"endpoint":"local"}}'
SIG=$(printf '%s.%s' "$TS" "$BODY" | openssl dgst -sha256 -hmac "$HOMIN_WEBHOOK_SECRET" | awk '{print $NF}')
curl -sS https://your.app/hooks/homin \
  -H 'Content-Type: application/json' \
  -H 'User-Agent: HOMIN-Webhooks/1.0' \
  -H 'X-HOMIN-Event: webhook.test' \
  -H 'X-HOMIN-Delivery: test_local' \
  -H "X-HOMIN-Timestamp: $TS" \
  -H "X-HOMIN-Signature: sha256=$SIG" \
  --data-binary "$BODY"

Коди збоїв і пороги бюджету

generation.failed— error — лише публічний код:
provider_rejectedprovider_busyprovider_quotaprovider_authprovider_unavailablevoice_unavailabletext_too_longstream_failedgateway_timeoutupstream_failedmargin_floorstorage_failedclosed_by_staffgeneration_failed

Значення — як у «Коди помилок» вище; stream_failed — потік обірвався, storage_failed — аудіо не збереглося, gateway_timeout — шлюз не прозвітував вчасно, closed_by_staff — генерацію закрила підтримка, generation_failed — усе інше.

budget.threshold
  • warning (80 %) і exhausted (100 %) приходять по одному разу на кожне значення бюджету; поріг фіксується в момент резерву кредитів.
  • Якщо один запит перетнув обидва пороги, приходить лише exhausted.
  • exhausted приходить і на перший запит, що не вмістився в залишок, коли вже витрачено щонайменше 80 %; сам запит отримує quota_exceeded.
  • Знову пороги спрацюють лише після зміни бюджету ключа; повернення кредитів за невдалі генерації їх не скидає.
  • spent, budget і remaining — у кредитах; ключі без бюджету й генерації в студії подій не дають.

Доставка й повтори

  • Доставка at-least-once: дедуплікуйте за id у тілі — він підписаний, на відміну від X-HOMIN-Delivery; 2xx відповідайте одразу, а обробку робіть асинхронно.
  • Успіх — відповідь 2xx за 10 с; 3xx, 4xx, 5xx, таймаут чи помилка мережі — невдача. Редиректів не виконуємо, тіло відповіді не читаємо.
  • Невдалу спробу повторюємо через 1 хв, 10 хв і 1 год (±20 %) — разом до 4 спроб із тим самим id і X-HOMIN-Delivery.
  • Невдалу доставку можна повторити з журналу в кабінеті: одна спроба з тим самим id і свіжим url, поки тіло доставки зберігається (7 днів).
  • Після 20 остаточно невдалих доставок поспіль вебхук вимикається, а власникам простору приходить лист; події за час вимкнення не зберігаються.
  • Вебхук, привʼязаний до ключа, вимикається разом із відкликанням ключа.
  • Порядок доставок не гарантовано — орієнтуйтеся на created.
  • З одного простору одночасно йде не більше 2 доставок, решта чекає в черзі: повільний приймач затримує насамперед ваші ж події.
  • Тест із кабінету надсилає webhook.test із тим самим підписом, одразу й без повторів. На невідомі типи подій відповідайте 2xx.

Посилання url підписується заново для кожної спроби й діє 24 години. Свіже беріть з поля audioUrl у GET /generations/{id} — від тієї ж бази, що REST API, з ключем із правом «читання». audioUrl — відносний шлях: додайте до нього адресу сайту.

Керуйте вебхуками в кабінеті: Ключі й інтеграції → Вебхуки. Секрет показується один раз, а після перевипуску старий перестає діяти одразу.Відкрити кабінет

Як підключити

1
Додайте вебхукКабінет → Ключі й інтеграції → Вебхуки → «Додати». Потрібні роль owner або admin із доступом до ключів і підтверджена пошта; до 10 вебхуків на простір.
2
Вкажіть адресуЛише https, до 2048 символів, без логіна й пароля. Адреса має бути публічною: приватні й внутрішні адреси, зокрема через DNS, відхиляються з url_private — і при збереженні, і перед кожною доставкою.
3
Оберіть події та ключgeneration.completed, generation.failed, budget.threshold — останній лише для ключів із бюджетом. Ключ необовʼязковий: з ним приходять лише події цього ключа, без нього — усі події простору.
4
Збережіть секретСекрет whsec_… показуємо один раз: одразу збережіть його на приймачі, наприклад у HOMIN_WEBHOOK_SECRET. Загубили — «Новий секрет», і старий одразу перестане діяти.
5
Натисніть «Тест»Прийде webhook.test із підписом, а кабінет покаже код відповіді. Далі кожну доставку видно в «Журналі».
data.id у generation.completed — той самий id генерації, що приходить у заголовку x-homin-generation відповіді 200 на запит синтезу; GET /generations/{id} від бази REST API віддає її статус і свіже посилання на аудіо. У generation.failed id збігається із цим заголовком, лише якщо збій стався вже після початку відповіді 200; коли синтез одразу відповів помилкою, id генерації у відповіді немає.

Якщо не приходять

1
Натисніть «Тест»Кабінет одразу покаже код відповіді приймача або причину збою. Тест іде без черги й повторів і в журнал не потрапляє.
2
Відкрийте «Журнал»Усі доставки від нових до старих: статус, код, спроби й час наступної спроби. Під подією — id доставки, той самий, що в X-HOMIN-Delivery.
3
Виправте й повторітьНевдалу доставку повторіть кнопкою «Повторити» в журналі: вебхук має бути ввімкнено, а тіло доставки зберігається 7 днів.

Код у журналі

http_3xx–5xx— приймач відповів не 2xx — у журналі видно сам код. 401 найчастіше означає інший секрет або тіло, змінене до перевірки підпису; 3xx — редирект, його не виконуємо.
timeout— приймач не відповів вчасно — 10 с на всю спробу. Відповідайте 2xx одразу, а обробку виносьте поза запит.
send_failed— зʼєднання не вдалося — приймач відмовив чи обірвав його або має недійсний TLS-сертифікат.
dns_failed— домен не розвʼязується — немає записів A чи AAAA або DNS не відповів вчасно.
url_private— адреса в приватному діапазоні — домен веде в приватну чи внутрішню мережу. Приймач має бути доступний з інтернету.
secret_undecryptable— секрет не розшифровується на нашому боці — натисніть «Новий секрет» і оновіть його на приймачі.
endpoint_disabled— вебхук вимкнули, поки доставка чекала в черзі, — увімкніть його й повторіть доставку.
ops_cancelled— доставку скасувала підтримка під час аварійної зупинки — повторіть її кнопкою «Повторити» в журналі.

Чому вебхук вимкнувся

too_many_failures— 20 остаточно невдалих доставок поспіль; власникам простору приходить лист. Виправте приймач і перевірте його «Тестом».
key_revoked— ключ, до якого привʼязано вебхук, відкликано: у «Змінити» оберіть інший ключ або всі події простору й збережіть.
Увімкнути вебхук знову можна перемикачем «Увімкнено» в його рядку: лічильник невдач обнулиться, а події за час вимкнення не повертаються.
Телефонія та агенти

Потік у дзвінок — без проміжних файлів.

HOMIN Live віддає аудіо потоком у Twilio, SIP/Asterisk, LiveKit і Pipecat. Перша фраза за ~300 мс.

<!-- TwiML: з'єднати дзвінок із HOMIN Live -->
<Response>
  <Connect>
    <Stream url="wss://live.homin.ua/twilio">
      <Parameter name="voice" value="bohdan"/>
      <Parameter name="agent" value="agent_support"/>
    </Stream>
  </Connect>
</Response>

Як працює Live

1
Клієнт говоритьASR стрімить текст, агент готує відповідь ще до кінця фрази
2
HOMIN відповідає потокомперший чанк аудіо ≈ 300 мс, далі — без пауз
3
Передача людиніза правилом або на запит — із коротким переказом розмови
~300 мсдо першої фрази
12кредитів / хв
50потоків у Business
Кабінет розробника

Ключ — за хвилину. Перше аудіо — за три.

Відкрити ключі й аналітикуЗареєструватися безкоштовноКлюч показується один раз · SHA-256 · бюджети й ліміти на кожен ключ
Відчуй звучання мови