Jak połączyć CRM z Heilo przez API
Prosta ścieżka integracji: Heilo wysyła dane rozmów do Twojego CRM-a, a niżej znajdziesz szczegóły dla programisty.
Szybki start: połącz CRM z Heilo
Najprostsza integracja polega na tym, że Heilo samo wysyła dane po każdej rozmowie do Twojego CRM-a.
Najważniejsze zdarzenie to call.completed. Oznacza: rozmowa jest gotowa, a CRM może zapisać kontakt, lead lub notatkę. Adresy REST /calls traktuj jako dodatek do sprawdzania lub odczytu danych.
- Przygotuj adres URL w CRM-ie, Zapierze, Make albo własnym systemie, na który Heilo ma wysyłać dane.
- W Heilo dodaj subskrypcję na zdarzenie call.completed. Opcjonalnie dodaj też call.outbound.attempted, jeśli chcesz śledzić próby połączeń wychodzących.
- Odbieraj call.completed i sprawdzaj podpis Heilo-Signature, żeby upewnić się, że wiadomość przyszła z Heilo.
- Nie twórz duplikatów: zapisuj event_id z nagłówka heilo-event-id. data.call_id oznacza konkretną rozmowę.
- W CRM-ie znajdź albo utwórz kontakt po numerze telefonu, potem dodaj lead, deal, aktywność albo notatkę z podsumowaniem i linkiem do nagrania.
Nie kodujesz? Przewodnik połączenia bez kodu (Zapier/Make) prowadzi krok po kroku.
Dostęp przez klucz API
Do publicznego API używasz klucza API. Wygeneruj go w karcie „Klucze API”, a programista wklei go w nagłówek Authorization:
Authorization: Bearer hk_live_AbC1MnPq...
W Heilo są trzy sposoby potwierdzania dostępu:
- Klucz API, np. hk_live_… — używany przez CRM, Zapier, Make albo własny skrypt.
- Sesja użytkownika w przeglądarce — używana tylko w panelu Heilo, nie w integracji API.
- Podpis HMAC — dodatkowe zabezpieczenie webhooków, czyli wiadomości wysyłanych z Heilo do Twojego adresu URL.
| Uprawnienie (scope) | Znaczenie |
|---|---|
| read.calls | Odczyt rozmów: GET /api/v1/calls, GET /api/v1/calls/:id |
| read.recordings | Wydanie linku do pliku audio rozmowy przez `GET /calls/{id}/recording-url`. Osobno od `read.calls`, bo audio to inna zgoda niż metadane — stary klucz go nie dostaje, trzeba utworzyć nowy z jawnym dostępem do nagrań. |
| write.calls, read.contacts, write.contacts, manage.webhooks, manage.api_keys | Zarezerwowane dla planowanych adresów API — nie zaznaczaj na zapas. |
Pole environment w odpowiedzi /me ma dziś zawsze wartość live. Klucze testowe są w planach.
Adres bazowy i wersja
Wszystkie publiczne adresy API zaczynają się od:
https://www.heilo.io/api/v1
Aktualna wersja
v1 · 2026-06-15
To nazwa wersji API, nie informacja o dzisiejszej dacie.
Status
Beta
Wersja API jest oznaczona datą. Drobne zmiany, takie jak nowe pola w odpowiedzi, nie powinny psuć istniejącej integracji.
Jeśli kiedyś zmienimy API w sposób wymagający zmian po Twojej stronie, wydamy nową główną wersję, np. v2, i utrzymamy starą wersję przez co najmniej 12 miesięcy.
Limity zapytań
Heilo ogranicza liczbę zapytań w ciągu godziny, osobno dla jednego klucza i całego konta. Limit resetuje się o pełnej godzinie UTC.
Na jeden klucz
1000 req/h
Na całe konto
5000 req/h
Po przekroczeniu limitu API zwraca 429 i informację, kiedy spróbować ponownie:
HTTP/1.1 429 Too Many Requests Retry-After: 1842 X-RateLimit-Limit: 1000 X-RateLimit-Remaining: 0 X-RateLimit-Reset: 2026-06-03T13:00:00Z
Błędy
Błędy mają stały format JSON. W automatyzacji zapisuj error.code, bo error.message jest opisem dla człowieka i może się zmienić.
{
"success": false,
"error": { "code": "RATE_LIMITED", "message": "Per-key rate limit 1000/h exceeded" },
"meta": { "timestamp": "2026-06-03T12:34:56Z" }
}| HTTP | code | Znaczenie |
|---|---|---|
| 400 | BAD_REQUEST | Niepoprawne parametry zapytania lub treści (ogólna walidacja) |
| 401 | UNAUTHORIZED | Brak lub niepoprawny klucz API |
| 402 | SUBSCRIPTION_INACTIVE | Subskrypcja nieaktywna — odnów płatność, aby znów włączyć klucz |
| 403 | FORBIDDEN | Klucz API nie ma potrzebnego uprawnienia |
| 404 | NOT_FOUND | Zasób nie istnieje lub znajduje się poza organizacją przypisaną do klucza API. |
| 422 | VALIDATION_ERROR | Reguła biznesowa odrzuciła żądanie (np. niepoprawny numer, limit) |
| 429 | RATE_LIMITED | Przekroczono limit zapytań |
| 500 | DATABASE_ERROR | Błąd serwera lub bazy — można spróbować ponownie później |
| 503 | MAINTENANCE | Publiczne API jest tymczasowo wyłączone |
Kod SUBSCRIPTION_INACTIVE występuje w dwóch sytuacjach: HTTP 402 — subskrypcja Heilo wygasła (płatność), oraz HTTP 409 — subskrypcja webhooka jest wstrzymana (np. przy akcji Test); wtedy najpierw kliknij „Ponów weryfikację”.
Te adresy służą głównie do sprawdzenia klucza i odczytu wybranych danych rozmów. Główna integracja CRM powinna opierać się na webhookach, czyli automatycznych powiadomieniach wysyłanych przez Heilo po rozmowie.
Sprawdza, czy klucz API działa. Zwraca identyfikator klucza, użytkownika, uprawnienia i limit zapytań.
Przydatne jako test połączenia: jeśli dostajesz odpowiedź 200, klucz i sieć działają.
curl https://www.heilo.io/api/v1/me \ -H "Authorization: Bearer hk_live_AbC1MnPq..."
{
"success": true,
"data": {
"api_key_id": "a1b2c3d4-5e6f-7081-92a3-b4c5d6e7f809",
"user_id": "5f4e3d2c-1a2b-4c3d-8e9f-0a1b2c3d4e5f",
"organization_id": "7a8b9c0d-1e2f-4a3b-9c8d-7e6f5a4b3c2d",
"scopes": ["read.calls", "manage.webhooks"],
"rate_limit_per_hour": 1000,
"environment": "live"
},
"meta": { "timestamp": "2026-06-03T12:34:56Z" }
}Te adresy pozwalają odczytać rozmowy. Klucz API musi mieć uprawnienie read.calls.
Lista rozmów organizacji. Stronicowanie (page/limit≤100), filtry: direction, status, zakres dat (dateFrom/dateTo). Zwraca has_more.
Parametry zapytania
| Parametr | Typ | Wartości |
|---|---|---|
| page | int | od 1 (domyślnie 1) |
| limit | int | 1–100 (domyślnie 20) |
| direction | enum | inbound | outbound |
| status | enum | new | to_call | contacted | qualified |
| dateFrom / dateTo | string | data YYYY-MM-DD lub ISO 8601, np. 2026-06-03T12:34:56Z |
| phone | string | numer klienta z rozmowy; spacje, myślniki i wiodący + są opcjonalne, np. 600 100 200 |
curl "https://www.heilo.io/api/v1/calls?limit=20&direction=inbound" \ -H "Authorization: Bearer hk_live_AbC1MnPq..."
{
"success": true,
"data": {
"items": [
{
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"direction": "inbound",
"caller_phone": "+48600100200",
"customer_phone_e164": "+48600100200",
"customer_phone_national": "600 100 200",
"company_phone_e164": "+48222630000",
"app_url": "https://www.heilo.io/calls/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"caller_name": "Jan Kowalski",
"duration": 87,
"crm_status": "new",
"review_status": null,
"outbound_lifecycle": null,
"transcript_processed": { "caller_name": "Jan Kowalski", "summary": "...", "service_needed": "...", "followup_email": null },
"created_at": "2026-06-03T12:34:56Z"
}
],
"has_more": false,
"page": 1,
"limit": 20
},
"meta": { "timestamp": "2026-06-03T12:34:56Z" }
}Jedna rozmowa po identyfikatorze. API zwróci 404, jeśli rozmowa nie należy do organizacji albo została usunięta.
curl https://www.heilo.io/api/v1/calls/<id> \ -H "Authorization: Bearer hk_live_AbC1MnPq..."
Świeży link do pliku audio rozmowy, ważny 15 minut. To pozwolenie na pobranie z terminem, a nie trwały odnośnik: zapisz `call_id` i poproś o link ponownie, bo adres wklejony w pole CRM-u przestanie działać w ciągu godziny. Link z webhooka `call.recording.ready` jest podpisany na siedem dni — ta trasa służy do sięgnięcia po audio później.
- 200 — link i moment, w którym przestaje działać.
- 409 `RECORDING_NOT_READY` — rozmowa jest Twoja, ale audio jeszcze nie dotarło. Zapytaj ponownie za chwilę.
- 409 `RECORDING_WITHHELD` — rozmowa jest w koszu albo zaplanowana do usunięcia. Obie te decyzje da się cofnąć, więc pytaj dalej, zamiast wykreślać nagranie u siebie.
- 410 `RECORDING_DELETED` — nagranie usunęła zamiatarka retencji i nie da się go odzyskać. Przestań pytać i przestań kolejkować.
- 410 `RECORDING_NOT_CAPTURED` — to połączenie wychodzące nigdy nie zostało nagrane i nagranie nigdy nie powstanie: bramka przechwytywania odmówiła nagrania przy jego rozpoczęciu, szło w trybie no_recording albo skończyło się bez rozmowy. Przestań pytać — nie ma powodu, by ponawiać. Połączenie przychodzące, którego nagrania odmówiono, dalej odpowiada 409, bo nagranie może jeszcze nadejść.
Odpowiedź jest podawana z nagłówkiem `Cache-Control: no-store`, bo ciało niesie poświadczenie. Uprawnienie jest sprawdzane ponownie przy pobraniu pliku, a nie tylko przy wydaniu linku, więc rozmowa usunięta w międzyczasie przestaje być dostępna natychmiast.
curl https://www.heilo.io/api/v1/calls/<id>/recording-url \ -H "Authorization: Bearer hk_live_AbC1MnPq..."
{
"success": true,
"data": {
"url": "https://www.heilo.io/api/v1/calls/<id>/recording.mp3?token=...&exp=...",
"expires_at": "2026-09-15T12:15:00.000Z"
}
}Lista rozmów i szczegół rozmowy nie zwracają plików nagrań. Link do nagrania dostajesz w webhooku, a po jego wygaśnięciu z `GET /calls/{id}/recording-url`. Nagrania mogą zostać usunięte zgodnie z retencją i RODO.
Co jest w REST, a co tylko w webhooku
Te dwa kanały nie niosą tego samego, a różnica decyduje o wyborze. REST jest trwały: rozmowę odczytasz z niego kiedykolwiek. Webhook jest bogatszy, ale przychodzi raz i część jego treści z czasem znika.
| Dane | REST | Webhook |
|---|---|---|
| Metadane rozmowy: kierunek, numery, czas trwania, data | jest | jest |
| Status w CRM i status przeglądu | jest | brak |
| Podsumowanie, imię dzwoniącego, potrzeba klienta | jest | jest |
| Pozostałe pola analizy: miasto, adres, ocena leada, preferowany termin, język | brak | jest |
| Zapis rozmowy słowo w słowo | brak | jest |
| Link do nagrania | jest, przez /calls/{id}/recording-url | jest, ważny 7 dni |
Stąd praktyczna zasada: pełną analizę bierz z webhooka w chwili, gdy przychodzi, bo REST nigdy jej nie niósł. Nagranie jest jedyną rzeczą, którą można teraz odzyskać później — poproś /calls/{id}/recording-url o świeży link ważny 15 minut, zamiast przechowywać ten siedmiodniowy z ładunku.
Specyfikacja i zapytanie na żywo
Te same trzy operacje, zapisane dla maszyn: OpenAPI 3.1. Zaimportuj je do Postmana albo Insomnii, albo wygeneruj klienta w swoim języku.
Specyfikacja i zapytanie na żywo
Wyślij stąd jedno zapytanie i sprawdź, czy klucz działa, zanim napiszesz choć linijkę kodu.
To wywołuje prawdziwe API Twoim prawdziwym kluczem i zwraca Twoje własne dane. Klucz zostaje w tej karcie przeglądarki — nigdzie go nie zapisujemy.
Webhooki: dane wysyłane do CRM-a
Heilo wysyła podpisane zdarzenia JSON na Twój endpoint. Subskrypcję utworzysz w karcie Subskrypcje webhooków. Aktywacja używa osobnego, niepodpisanego handshake webhook.subscription.verify, który nie może tworzyć rekordów biznesowych.
POST <your URL>
content-type: application/json
heilo-signature: t=1717423396,v1=4f3a...
heilo-event-id: 1bf3a5e2-...
heilo-event-type: call.completed
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-...",
"event_type": "call.completed",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-06-03T12:34:56Z",
"data": { /* see the setup guide for the full schema */ }
}Co się stanie, jeśli Twój adres nie odpowie:
- Błędy przejściowe uruchamiają maksymalnie 5 prób łącznie: po 2 min, 5 min, 30 min i 2 h, z niewielkim losowym przesunięciem późniejszych prób (jitter). Piąta nieudana próba kończy dostawę statusem dead-letter.
- Błędy trwałe (HTTP 401/403/422) od razu wstrzymują subskrypcję — bez ponawiania.
- 50 błędów przejściowych z rzędu albo 2 razy z rzędu HTTP 410 Gone (np. usunięty scenariusz w Make) także wstrzymują subskrypcję.
- Po poprawieniu adresu kliknij „Ponów weryfikację”, aby wznowić wysyłkę.
Gdy subskrypcja zostanie automatycznie wstrzymana, wysyłamy e-mail na adres właściciela konta. Zdarzenia z martwej kolejki możesz wysłać ponownie przyciskiem „Wyślij ponownie” w Historii wysyłek — po ponownej weryfikacji subskrypcji.
Odpowiedź 2xx potwierdza odbiór HTTP, nie zakończenie automatyzacji ani zapis w CRM. Dostawy mogą się powtarzać i przychodzić poza kolejnością. Heilo uzupełnia niedawne braki w ograniczonym oknie czasu; nie jest to odzyskiwanie całej historii. Sprawdzaj osobno historię dostaw i wynik w CRM.
Weryfikacja adresu webhooka
Niepodpisany handshake zawiera tylko event_type = webhook.subscription.verify oraz challenge. Odpowiedz wyłącznie w celu potwierdzenia endpointu; nie uruchamiaj zapisu biznesowego. Oba tryby używają tego samego żądania:
{
"event_type": "webhook.subscription.verify",
"challenge": "example-verification-token"
}Tryb prosty permissive (domyślnie)
Dowolna odpowiedź 2xx aktywuje subskrypcję, a treść odpowiedzi jest pomijana. To domyślny tryb dla odbiornika no-code.
Tryb zaawansowany strict (opcjonalnie)
Zwróć 2xx oraz JSON z dokładnie tą wartością challenge, którą otrzymałeś od Heilo:
{"challenge":"<echo of the challenge field from Heilo's POST>"}Wybierz tryb w formularzu tworzenia. Jego zmiana wymaga usunięcia i ponownego utworzenia subskrypcji. Trasy zarządzania subskrypcjami wymagają zalogowanej sesji i ochrony CSRF; nie są endpointami dostępnymi z kluczem API.
Możesz mieć maksymalnie 20 aktywnych subskrypcji na konto. Subskrypcję wstrzymujemy automatycznie po 50 błędach przejściowych z rzędu lub 2 razy z rzędu HTTP 410, a od razu przy HTTP 401/403/422.
Podpis bezpieczeństwa HMAC
Podpisane zdarzenia, w tym ręczny webhook.test, używają Heilo-Signature z HMAC-SHA256 liczonym z timestamp + kropka + oryginalne bajty żądania. Sprawdź podpis przed parsowaniem biznesowego JSON. Niepodpisany jest wyłącznie handshake potwierdzający endpoint.
signed_string = "<unix_timestamp>.<raw_request_body>" signature = HMAC-SHA256(signing_secret, signed_string).hex() header = "t=<unix_timestamp>,v1=<signature>"
import { createHmac, timingSafeEqual } from 'node:crypto';
// Pass the exact received Buffer (e.g. Express raw parser), never JSON.stringify(req.body).
// signingSecrets: every secret you currently trust, tried in constant time each.
// During a secret rotation pass [newSecret, oldSecret]; remove the old one once
// Heilo's grace window ends. Heilo itself always sends exactly ONE v1 signature —
// this list is what lets your receiver accept it under either secret while both
// are live, never a second signature to parse.
function verifyHeiloSignature(rawBody, header, signingSecrets) {
const match = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(header || '');
if (!match) return false;
const timestamp = Number(match[1]);
const now = Math.floor(Date.now() / 1000);
// Receiver policy: at most 10 minutes old or 5 minutes ahead (clock skew).
if (!Number.isSafeInteger(timestamp) || now - timestamp > 600 || timestamp - now > 300) return false;
// One string is accepted too. Empty entries are dropped: an HMAC key of ''
// is valid, so a blanked env var (OLD_SECRET=) would let anyone sign events.
const secrets = [].concat(signingSecrets).filter((s) => typeof s === 'string' && s.length > 0);
if (secrets.length === 0) return false;
const actual = Buffer.from(match[2], 'hex');
return secrets.some((signingSecret) => {
const expected = createHmac('sha256', signingSecret)
.update(match[1] + '.')
.update(rawBody)
.digest();
return actual.length === expected.length && timingSafeEqual(actual, expected);
});
}
function receiveHeiloWebhook(rawBody, signatureHeader, signingSecrets) {
if (!signatureHeader) {
// The ONLY unsigned exception confirms the endpoint; never enqueue it for CRM writes.
const probe = JSON.parse(rawBody.toString('utf8'));
if (probe && typeof probe === 'object' && !Array.isArray(probe)
&& Object.keys(probe).length === 2
&& probe.event_type === 'webhook.subscription.verify'
&& typeof probe.challenge === 'string') {
return { kind: 'verification', response: { challenge: probe.challenge } };
}
throw new Error('Missing Heilo-Signature');
}
if (!verifyHeiloSignature(rawBody, signatureHeader, signingSecrets)) throw new Error('Invalid Heilo-Signature');
return { kind: 'event', event: JSON.parse(rawBody.toString('utf8')) };
}
// HTTP adapter: limit body size; map verification to 200 JSON response.
// Signature errors -> 401 (pauses delivery; fix the secret, then Reverify). JSON errors -> 400.
// For kind=event: validate the envelope and chosen event_type, ignore webhook.test
// in business flows, then durably deduplicate/enqueue by event_id BEFORE returning 2xx.
// Enqueue failure: return 503. An HTTP acknowledgement is not proof of a CRM write.Przykłady akceptują podpisy starsze o maksymalnie 600 sekund (10 minut) i wyprzedzające zegar o 300 sekund (5 minut), zgodnie z obecnym weryfikatorem Heilo. Synchronizuj zegary serwerów. Kontrola czasu ogranicza okno ponownego użycia podpisu; nadal trzeba deduplikować po event_id.
Sekret podpisu pokazujemy tylko raz — przy utworzeniu subskrypcji. Zgubiłeś go albo podejrzewasz wyciek? Otwórz subskrypcję w Ustawienia → Integracje → Webhooki i wymień go tam — zobacz „Rotacja sekretu” poniżej. Nie trzeba usuwać subskrypcji i zakładać jej od nowa.
Rotacja sekretu
Heilo zawsze wysyła dokładnie jeden podpis v1, nigdy dwa naraz. Dlatego wymiana polega na kolejności: najpierw Twój odbiornik uczy się nowego sekretu, dopiero potem Heilo zaczyna nim podpisywać.
- Przygotuj nowy sekret w ustawieniach subskrypcji. Pokazujemy go raz, a on czeka na aktywację przez 24 godziny.
- Zainstaluj nowy sekret OBOK obecnego — Twój odbiornik musi akceptować podpis zrobiony którymkolwiek z nich.
- Opcjonalnie wyślij test podpisany nowym sekretem. Niesie nagłówek Heilo-Secret-Rotation-Id i zwykłe body webhook.test; odpowiedź 2xx nie dowodzi, że odbiornik sprawdził podpis — potwierdź to we własnym logu.
- Aktywuj rotację.
- Trzymaj stary sekret zainstalowany jeszcze przez 1 godzinę po aktywacji, potem go usuń.
Heilo nie zmienia niczego po stronie Twojego odbiornika. To Twój odbiornik musi w tym czasie przyjmować podpis zrobiony którymkolwiek z dwóch sekretów.
Tryb awaryjny: sekret wyciekł
Rotacja awaryjna od razu wstrzymuje wysyłkę. Zainstaluj WYŁĄCZNIE nowy sekret — stary uznaj za skompromitowany — potem aktywuj; nie ma okresu karencji. Wznów wysyłkę potem przyciskiem „Ponów weryfikację”. Dostawy, które czekały w kolejce w chwili wstrzymania, są pomijane; wyślij je ponownie z dziennika dostaw.
Sekret zaginął, ale nie wyciekł? Wystarczy zwykła wymiana — nie trzeba usuwać subskrypcji.
Zdarzenia, które może wysłać Heilo
Przy tworzeniu subskrypcji wybierasz, które zdarzenia chcesz odbierać. Każde zdarzenie ma unikalny identyfikator, dzięki czemu CRM może uniknąć duplikatów.
webhook.test jest wysyłany ręcznym przyciskiem Test i ma data._test = true. Użyj go do mapowania pól, a następnie wyklucz z obsługi biznesowej. Osobny handshake aktywacji to webhook.subscription.verify.
| nazwa techniczna | Opis |
|---|---|
| call.completed | Zakończona rozmowa, transkrypcja gotowa |
| call.outbound.attempted | Próba połączenia wychodzącego osiągnęła stan końcowy (rozmowa lub niepowodzenie) |
| call.recording.ready | Nagranie gotowe do pobrania |
| call.transcribed | Transkrypcja gotowa |
| call.failed | Rozmowa nieudana (zajęte / brak odpowiedzi / błąd) |
| call.outbound.lifecycle_repaired | Korekta statusu rozmowy wychodzącej |
| call.deletion_scheduled | Rozmowa zaplanowana do usunięcia (RODO) |
| call.recording.deleted | Nagranie usunięte (RODO) |
| call.followup_email.drafted | Draft maila follow-up gotowy |
| call.tracker.matched | Wzmianka o śledzonej frazie |
| contact.created | Nowy kontakt utworzony |
| contact.updated | Kontakt zaktualizowany |
Poniżej obiekt data każdego zdarzenia. Nazwy pól, typy i wartości słownikowe są częścią kontraktu API i nie zmieniają znaczenia w ramach v1; z czasem mogą dochodzić nowe, opcjonalne pola.
call.completed
Wysyłane po zakończeniu przetwarzania rozmowy. To główna wiadomość dla CRM-a: zawiera link do nagrania, podsumowanie i rozpoznane dane rozmówcy.
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.completed",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"direction": "inbound",
"caller_phone": "+447700900123",
"customer_phone_e164": "+447700900123",
"customer_phone_national": "07700 900123",
"company_phone_e164": "+48222630000",
"call_created_at": "2026-09-08T10:00:00Z",
"app_url": "https://www.heilo.io/calls/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"duration": 87,
"recording_url": "https://www.heilo.io/api/v1/calls/3fa85f64-5717-4562-b3fc-2c963f66afa6/recording.mp3?token=EXAMPLE&exp=1789466400",
"transcript_processed": {
"caller_name": "Alicja Testowa",
"counterparty_name": null,
"caller_location": "Warszawa, Mokotów",
"client_address": "ul. Przykładowa 10",
"client_city": "Warszawa",
"client_country": "Poland",
"service_needed": "Tynki gipsowe w mieszkaniu 65m²",
"services_match": true,
"preferred_date": "w przyszłym tygodniu",
"additional_details": "Klient wspomniał o terminie do końca czerwca. Druga rozmowa po wycenie.",
"lead_score": 7,
"summary": "Prośba o wycenę tynków gipsowych w mieszkaniu 65 m² na Mokotowie.",
"subject": "Wycena tynków — Warszawa, 65 m²",
"detected_language": "pl"
},
"transcript_original": "Proszę o ofertę w przyszłym tygodniu."
}
}| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| direction | 'inbound' | 'outbound' | Kierunek rozmowy. |
| caller_phone | string | null | Zapisany numer dzwoniącego; null, jeśli niedostępny w call.completed. |
| customer_phone_e164 | string | null | Numer klienta do dopasowania kontaktu w CRM; null, jeśli niedostępny w call.completed. |
| customer_phone_national | string | null | Ten sam numer klienta w formacie krajowym, gotowy do wklejenia w pole telefonu w CRM-ie; null, gdy zapisana wartość nie jest numerem — na przykład przy zastrzeżonym numerze. |
| company_phone_e164 | string | null | Numer, na który ta rozmowa przyszła albo z którego wyszła. Zwykle Twój numer w Heilo; przy przekierowaniu to Twój własny numer, który ją przekazał. Służy do kierowania notatek, gdy masz więcej niż jeden numer; null, gdy nie został zapisany. |
| call_created_at | string (ISO 8601) | null | Kiedy rozmowa została zapisana w Heilo (ISO 8601). To nie to samo co created_at koperty, które jest momentem wysyłki zdarzenia i przy naprawie może być późniejsze o dni. |
| app_url | string | null | Trwały odnośnik do rozmowy w Heilo. W odróżnieniu od recording_url nie wygasa, więc można go trzymać w rekordzie CRM-u. Otwarcie wymaga zalogowania do Heilo. |
| duration | number | Długość nagrania w sekundach. |
| recording_url | string | null | Stały link do nagrania; null, gdy nagranie nie było jeszcze zapisane w chwili przetwarzania. |
| transcript_processed | object | Przetworzona analiza rozmowy — patrz spis pól transcript_processed w tej sekcji. |
| transcript_original | string | null | Surowa, dosłowna transkrypcja; null, gdy niedostępna. |
Heilo może wysłać to samo zdarzenie więcej niż raz, dlatego CRM powinien sprawdzać event_id i nie tworzyć duplikatów. data.call_id łączy wszystkie zdarzenia dotyczące tej samej rozmowy.
call.outbound.attemptedWysyłane, gdy próba połączenia wychodzącego osiągnie stan końcowy — także nieudany. completed oznacza, że rozmowa się odbyła i zakończyła normalnie; nagranie i transkrypcja przyjdą osobnymi zdarzeniami.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| agent_user_id | string (uuid) | Identyfikator użytkownika Heilo, który dzwonił. |
| customer_phone | string | Wybierany numer klienta. |
| customer_phone_e164 | string | Numer klienta do dopasowania kontaktu w CRM; null, jeśli niedostępny w call.completed. |
| outbound_lifecycle | 'completed' | 'agent_no_answer' | 'customer_no_answer' | 'failed_to_initiate' | Stan końcowy, który wywołał zdarzenie; completed oznacza, że rozmowa się odbyła i zakończyła normalnie. |
| duration | number | null | Czas rozmowy w sekundach; null, gdy połączenie nie doszło do skutku przy nawiązywaniu albo czas nie jest jeszcze znany. |
| attempted_at | string (ISO 8601) | Moment wysłania zdarzenia (ISO 8601). |
| has_recording | boolean | true tylko wtedy, gdy outbound_lifecycle to completed i rozmowa nie była w trybie no_recording — nagranie przyjdzie wtedy jako call.recording.ready. |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.outbound.attempted",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"agent_user_id": "2ce127a0-c621-483d-b576-e68f69d95e84",
"customer_phone": "+447700900123",
"customer_phone_e164": "+447700900123",
"outbound_lifecycle": "completed",
"duration": 95,
"attempted_at": "2026-09-08T10:00:00Z",
"has_recording": true
}
}call.recording.readyWysyłane, gdy plik nagrania jest gotowy. Użyj, jeśli CRM ma pobierać lub archiwizować audio.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| recording_url | string | null | Stały link do nagrania; w rzadkich przypadkach null, gdy nie udało się wygenerować linku. |
| duration | number | null | Czas trwania w sekundach; null, gdy jeszcze nieznany. |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.recording.ready",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"recording_url": "https://www.heilo.io/api/v1/calls/3fa85f64-5717-4562-b3fc-2c963f66afa6/recording.mp3?token=EXAMPLE&exp=1789466400",
"duration": 87
}
}call.transcribedWysyłane w tym samym przebiegu co call.completed — zawiera wyłącznie transkrypcję, bez danych rozmowy i linku do nagrania.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| transcript_original | string | null | Surowa, dosłowna transkrypcja; null, gdy niedostępna. |
| transcript_processed | object | Przetworzona analiza rozmowy — patrz spis pól transcript_processed w tej sekcji. |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.transcribed",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"transcript_original": "Proszę o ofertę w przyszłym tygodniu.",
"transcript_processed": {
"caller_name": "Alicja Testowa",
"counterparty_name": null,
"caller_location": "Warszawa, Mokotów",
"client_address": "ul. Przykładowa 10",
"client_city": "Warszawa",
"client_country": "Poland",
"service_needed": "Tynki gipsowe w mieszkaniu 65m²",
"services_match": true,
"preferred_date": "w przyszłym tygodniu",
"additional_details": "Klient wspomniał o terminie do końca czerwca. Druga rozmowa po wycenie.",
"lead_score": 7,
"summary": "Prośba o wycenę tynków gipsowych w mieszkaniu 65 m² na Mokotowie.",
"subject": "Wycena tynków — Warszawa, 65 m²",
"detected_language": "pl"
}
}
}call.failedWysyłane, gdy połączenie wychodzące nie doszło do skutku (brak odpowiedzi, zajęte, błąd przy nawiązywaniu). Dotyczy tylko połączeń wychodzących. Zwykle nie warto tworzyć wtedy leada — wystarczy odnotować próbę kontaktu.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| outbound_lifecycle | 'agent_no_answer' | 'customer_no_answer' | 'failed_to_initiate' | Który etap połączenia wychodzącego się nie powiódł. |
| failure_reason | string | null | Techniczny kod przyczyny (np. customer_busy, agent_no_confirmation); może być null. |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.failed",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"outbound_lifecycle": "customer_no_answer",
"failure_reason": "customer_busy"
}
}call.outbound.lifecycle_repairedWysyłane, gdy Heilo koryguje wstecznie stan rozmowy wychodzącej (późny sygnał od operatora potwierdził, że rozmowa jednak się odbyła). Zaktualizuj stan rozmowy po swojej stronie.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| previous_lifecycle | 'agent_only' | Stan przed korektą; obecnie zawsze agent_only. |
| new_lifecycle | 'completed' | Stan po korekcie; obecnie zawsze completed. |
| repaired_at | string (ISO 8601) | Moment korekty (ISO 8601). |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.outbound.lifecycle_repaired",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"previous_lifecycle": "agent_only",
"new_lifecycle": "completed",
"repaired_at": "2026-09-08T10:00:00Z"
}
}call.deletion_scheduledRODO art. 17: rozmowa jest zaplanowana do usunięcia. CRM powinien przestać używać nagrania i przygotować się na usunięcie danych. Dostajesz informację o rozmowie tylko wtedy, gdy Heilo ma zapis, że jej treść mogła trafić na Twój adres. Samo zapisanie się na zdarzenia usunięcia nie czyni Cię odbiorcą — nie ma czego usuwać, jeśli nigdy nic nie dostałeś.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| pending_deletion_at | string (ISO 8601) | Kiedy dane zostaną trwale usunięte (ISO 8601). |
| reason | 'consent_not_asked' | 'consent_withdrawn' | 'retention_expired' | 'user_erasure' | Powód zaplanowania usunięcia. |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.deletion_scheduled",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"pending_deletion_at": "2026-09-09T10:00:00Z",
"reason": "user_erasure"
}
}call.recording.deletedRODO: nagranie zostało usunięte — recording_url zwraca 410. Usuń albo wyłącz link do nagrania po swojej stronie. Dostajesz informację o rozmowie tylko wtedy, gdy Heilo ma zapis, że jej treść mogła trafić na Twój adres, więc to nie jest komplet wszystkich usunięć w Twojej organizacji. Odpowiedź 2xx oznacza, że instrukcja dotarła, nigdy że kopia zniknęła.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| reason | string | null | Powód zapisany przy planowaniu usunięcia; może być null. |
| recording_sid | string | null | Identyfikator nagrania w Twilio; null, gdy nie dało się go ustalić. |
| deletion_kind | 'hard_deleted' | 'twilio_404' | hard_deleted = usunięte przez Heilo; twilio_404 = plik już wcześniej zniknął po stronie Twilio. |
| deleted_at | string (ISO 8601) | Moment usunięcia nagrania (ISO 8601). |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.recording.deleted",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"reason": "user_erasure",
"recording_sid": null,
"deletion_kind": "twilio_404",
"deleted_at": "2026-09-08T10:00:00Z"
}
}call.followup_email.draftedWysyłane po przetworzeniu rozmowy dwustronnej, gdy Heilo przygotowało szkic maila follow-up z jej ustaleń. Nie jest wysyłane dla poczty głosowej ani wtedy, gdy szkicu nie udało się przygotować. Heilo NIGDY nie wysyła tego maila do rozmówcy — szkic trafia do handlowca, który go przegląda i wysyła sam.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| subject | string | Temat maila, gotowy do wklejenia. |
| body | string | Treść maila zwykłym tekstem, BEZ podpisu — podpis dokłada handlowiec przy wysyłce. |
| language | string | Język szkicu: wykryty język rozmowy, a gdy nie udało się go wykryć — język konta ustawiony w Heilo (nie język numeru). |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.followup_email.drafted",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"subject": "Oferta po rozmowie",
"body": "Dzień dobry, przesyłam ustalenia naszej rozmowy.",
"language": "pl"
}
}call.tracker.matchedWysyłany, gdy co najmniej jeden skonfigurowany tracker słów kluczowych pasuje do przetworzonej transkrypcji. Dopasowanie zawiera znalezione terminy i fragmenty; brak fragmentu oznacza pustą tablicę.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| matches | object[] | Trackery dopasowane w tej rozmowie. |
| matches[].tracker_id | string (uuid) | Identyfikator skonfigurowanego trackera. |
| matches[].name | string | Nazwa trackera. |
| matches[].matched_terms | string[] | Dopasowane terminy. |
| matches[].excerpts | string[] | Fragmenty transkrypcji; tablica może być pusta. |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "call.tracker.matched",
"resource_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"matches": [
{
"tracker_id": "cd794362-6117-44d1-b487-c5e7e1ea9082",
"name": "Oferta",
"matched_terms": [
"ofertę"
],
"excerpts": [
"Proszę o ofertę w przyszłym tygodniu."
]
}
]
}
}contact.createdWysyłane po utworzeniu nowego kontaktu w Heilo. data.contact to pełny obraz nowego kontaktu; nie zawiera notatek ani tagów.
| Pole | Typ | Opis |
|---|---|---|
| contact | object | Pełny obraz nowego kontaktu (pola poniżej). |
| contact.id | string (uuid) | Identyfikator kontaktu w Heilo. |
| contact.phone | string | Numer telefonu kontaktu. |
| contact.first_name | string | null | null, jeśli nie podano. |
| contact.last_name | string | null | null, jeśli nie podano. |
| contact.email | string | null | null, jeśli nie podano. |
| contact.company | string | null | null, jeśli nie podano. |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "contact.created",
"resource_id": "86c68698-d54c-43e7-bbbc-328499b98d12",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"contact": {
"id": "86c68698-d54c-43e7-bbbc-328499b98d12",
"phone": "+447700900123",
"first_name": "Alicja",
"last_name": "Testowa",
"email": "alicja@example.com",
"company": null
}
}
}contact.updatedWysyłane po edycji kontaktu. W przeciwieństwie do contact.created to nie jest pełny obraz: data.diff zawiera tylko zmienione pola.
| Pole | Typ | Opis |
|---|---|---|
| contact_id | string (uuid) | Identyfikator zaktualizowanego kontaktu. |
| diff | object (partial) | Tylko zmienione pola — klucze nieobecne w diff nie były modyfikowane. |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "contact.updated",
"resource_id": "86c68698-d54c-43e7-bbbc-328499b98d12",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"contact_id": "86c68698-d54c-43e7-bbbc-328499b98d12",
"diff": {
"company": "Example",
"notes": "Oddzwonić",
"tags": [
"oferta"
]
}
}
}Możliwe klucze w diff: first_name, last_name, email, phone, company, notes, tags
webhook.testWysyłany wyłącznie po naciśnięciu Test przy subskrypcji. resource_id to ID subskrypcji, nie rozmowy. data zawiera syntetyczny payload call.completed i trzy znaczniki testowe opisane poniżej. Test nie potwierdza dostępności prawdziwego audio.
| Pole | Typ | Opis |
|---|---|---|
| call_id | string (uuid) | ID rozmowy w Heilo. Dla biznesowych zdarzeń rozmowy równe resource_id; w webhook.test jest to syntetyczne ID rozmowy. |
| direction | 'inbound' | 'outbound' | Kierunek rozmowy. |
| caller_phone | string | null | Zapisany numer dzwoniącego; null, jeśli niedostępny w call.completed. |
| customer_phone_e164 | string | null | Numer klienta do dopasowania kontaktu w CRM; null, jeśli niedostępny w call.completed. |
| customer_phone_national | string | null | Ten sam numer klienta w formacie krajowym, gotowy do wklejenia w pole telefonu w CRM-ie; null, gdy zapisana wartość nie jest numerem — na przykład przy zastrzeżonym numerze. |
| company_phone_e164 | string | null | Numer, na który ta rozmowa przyszła albo z którego wyszła. Zwykle Twój numer w Heilo; przy przekierowaniu to Twój własny numer, który ją przekazał. Służy do kierowania notatek, gdy masz więcej niż jeden numer; null, gdy nie został zapisany. |
| call_created_at | string (ISO 8601) | null | Kiedy rozmowa została zapisana w Heilo (ISO 8601). To nie to samo co created_at koperty, które jest momentem wysyłki zdarzenia i przy naprawie może być późniejsze o dni. |
| app_url | string | null | Trwały odnośnik do rozmowy w Heilo. W odróżnieniu od recording_url nie wygasa, więc można go trzymać w rekordzie CRM-u. Otwarcie wymaga zalogowania do Heilo. |
| duration | number | Długość nagrania w sekundach. |
| recording_url | string | null | Stały link do nagrania; null, gdy nagranie nie było jeszcze zapisane w chwili przetwarzania. |
| transcript_processed | object | Przetworzona analiza rozmowy — patrz spis pól transcript_processed w tej sekcji. |
| transcript_original | string | null | Surowa, dosłowna transkrypcja; null, gdy niedostępna. |
| _test | true | Zawsze true — odróżnia wiadomość testową od prawdziwych zdarzeń. |
| _message | string | Czytelna informacja, że to test. |
| _sent_at | string (ISO 8601) | Moment wysłania testu (ISO 8601). |
{
"api_version": "2026-06-15",
"event_id": "1bf3a5e2-4f82-4335-988e-4e044fa648d4",
"event_type": "webhook.test",
"resource_id": "c2d38cc8-bc1d-4336-91ea-51b8a549a882",
"created_at": "2026-09-08T10:00:00Z",
"data": {
"call_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"direction": "inbound",
"caller_phone": "+447700900123",
"customer_phone_e164": "+447700900123",
"customer_phone_national": "07700 900123",
"company_phone_e164": "+48222630000",
"call_created_at": "2026-09-08T10:00:00Z",
"app_url": "https://www.heilo.io/calls/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"duration": 87,
"recording_url": "https://www.heilo.io/api/v1/calls/3fa85f64-5717-4562-b3fc-2c963f66afa6/recording.mp3?token=EXAMPLE&exp=1789466400",
"transcript_processed": {
"caller_name": "Alicja Testowa",
"counterparty_name": null,
"caller_location": "Warszawa, Mokotów",
"client_address": "ul. Przykładowa 10",
"client_city": "Warszawa",
"client_country": "Poland",
"service_needed": "Tynki gipsowe w mieszkaniu 65m²",
"services_match": true,
"preferred_date": "w przyszłym tygodniu",
"additional_details": "Klient wspomniał o terminie do końca czerwca. Druga rozmowa po wycenie.",
"lead_score": 7,
"summary": "Prośba o wycenę tynków gipsowych w mieszkaniu 65 m² na Mokotowie.",
"subject": "Wycena tynków — Warszawa, 65 m²",
"detected_language": "pl"
},
"transcript_original": "Proszę o ofertę w przyszłym tygodniu.",
"_test": true,
"_message": "Synthetic webhook test; do not create CRM records.",
"_sent_at": "2026-09-08T10:00:00Z"
}
}transcript_processed — spis pól
Stabilny podzbiór pól, na którym możesz polegać przy mapowaniu do CRM-a. Każde pole jest opcjonalne — ma wartość null, gdy rozmowa nie zawierała tej informacji.
| Pole | Typ | Opis |
|---|---|---|
| caller_name | string | null | Imię i nazwisko rozmówcy, jeśli je podał. |
| summary | string | null | Krótkie podsumowanie rozmowy. |
| subject | string | null | Jednolinijkowy tytuł rozmowy (do 80 znaków). |
| service_needed | string | null | Czego dotyczyła prośba rozmówcy. |
| services_match | boolean | null | Czy prośba pasuje do usług, które oferujesz. |
| lead_score | number | null (1–10) | Ocena jakości leada od 1 do 10. |
| preferred_date | string | null | Termin wspomniany przez rozmówcę, jeśli padł. |
| client_city | string | null | Miasto, jeśli padło w rozmowie. |
| client_address | string | null | Adres, jeśli padł w rozmowie. |
| additional_details | string | null | Dodatkowy kontekst z rozmowy. |
Pola, które mogą się pojawić
| Pole | Typ | Opis |
|---|---|---|
| caller_location | string | null | Odniesienie geograficzne wykryte w rozmowie. |
| client_country | string | null | Kraj, jeśli padł w rozmowie. |
| counterparty_name | string | null | Nazwa drugiej strony — tylko rozmowy wychodzące i rozmowy, których Heilo cicho słucha (tryb słuchacza). |
| detected_language | string | Kod języka rozmowy (np. pl); klucz może w ogóle nie wystąpić. |
| proposal_items | object[] | null | Zaproponowane działania i decyzje wyciągnięte z rozmowy. |
Analiza może zawierać dodatkowe pola — traktuj nieznane pola jako opcjonalne i nie zakładaj ich obecności.
Planowane funkcje
Te adresy API planujemy dodać w kolejnych wydaniach. Kolejność zależy od potrzeb klientów.
- GET /contacts — lista kontaktów
- POST /contacts — tworzenie kontaktu (synchronizacja z CRM-a do Heilo)
- POST /calls — zainicjuj połączenie wychodzące z Twojego numeru Heilo; rozmowa jest nagrywana, transkrybowana i trafia do Twojego CRM-a jak każda inna
Brakuje konkretnego adresu API? Napisz na support@heilo.io i opisz, co chcesz zautomatyzować.
Planowane funkcje
Brakuje konkretnego adresu API? Napisz na support@heilo.io i opisz, co chcesz zautomatyzować.
Zarządzaj kluczami i webhookami w panelu
Po zalogowaniu wygenerujesz klucze API, dodasz subskrypcje webhooków i sprawdzisz historię wysyłek.