Sign inGet Started

Tworzenie połączenia głosowego

Warning: Voice sequences are in preview. Steps, entry data, and the sequence definition format can change in ways that break existing sequences and API requests.

Użyj POST /v1/voice/calls, aby zadzwonić pod numer telefonu i uruchomić opublikowaną sekwencję lub definicję sekwencji wysłaną w żądaniu, gdy odbiorca odbierze. Żądanie wykonuje prawdziwe połączenie; obowiązują zwykłe opłaty za połączenia.

Podgląd CLI i MCP: Te interfejsy wymagają zgodnego klienta. Sprawdź, czy Twój serwer MCP udostępnia voice_calls_create, lub uruchom bird voice --help, aby wyświetlić polecenia w swoim CLI. Sprawdź dostępność nowszych wersji za pomocą bird update --check i zobacz Instalacja CLI. Jeśli narzędzie lub polecenie jest niedostępne, użyj API HTTP lub SDK.

W podglądzie CLI i MCP przygotowują to samo połączenie do przejrzenia i uruchomienia w przeglądarce przez osobę. Agent otrzymuje zarejestrowany wynik akceptacji po uruchomieniu żądania przez osobę.

Zanim zaczniesz

Przygotuj te zasoby w tym samym obszarze roboczym:

  • Sekwencja do uruchomienia: włączona, niezarchiwizowana sekwencja z aktywną publikacją zbudowana w dashboardzie lub kompletna definicja wysłana w żądaniu.
  • Klucz API do żądań HTTP albo login OAuth do CLI i MCP, z obydwoma uprawnieniami voice_management:write i voice:write.
  • Numer dzwoniący, który obszar roboczy może prezentować, na przykład własny lub zweryfikowany identyfikator dzwoniącego, oraz włączony kraj docelowy. Wybieraj numer z kraju odbiorcy: niektóre sieci komórkowe odrzucają połączenie prezentujące zagraniczny identyfikator dzwoniącego.
  • Odbiorca, którego kontrolujesz, do pierwszego połączenia.

Obiekt sequence przyjmuje dokładnie jedno z sequence.id lub sequence.definition. Oba wymagają też entry_node_id, kroku Start call, od którego rozpoczyna się połączenie, oraz trigger_data, obiektu zgodnego ze schematem danych danego wejścia. Użyj {}, gdy wejście przyjmuje puste dane. Dokumentacja Create Call opisuje limity żądań i opcjonalny czas dzwonienia.

Wywołanie sekwencji zbudowanej w dashboardzie

Użyj sequence.id, aby uruchomić sekwencję, którą zbudowałeś i opublikowałeś w dashboardzie. Create Call zawsze uruchamia aktywną publikację.

  1. Otwórz sekwencję w Sequences.
  2. W sekcji How to run this sequence wybierz More details obok Create a call.
  3. Jeśli sekwencja ma kilka wpisów, wybierz Call trigger, od którego chcesz rozpocząć.
  4. Skopiuj żądanie. Zawiera ono identyfikator sekwencji i identyfikator wpisu.

Zapisz ciało żądania jako call.json, zastępując przykładowe numery swoimi:

Przykład kodu
{
  "from": "+12025550100",
  "to": "+12025550101",
  "sequence": {
    "id": "YOUR_SEQUENCE_ID",
    "entry_node_id": "YOUR_ENTRY_NODE_ID",
    "trigger_data": {}
  }
}

Wypełnij trigger_data polami zadeklarowanymi przez wpis, w tym zagnieżdżonymi obiektami i tablicami. Create Call nie akceptuje wersji historycznych, szkiców ani trybu testowego. Aby przetestować zapisany szkic, użyj kontrolek Place a call w dashboardzie.

Uruchomienie sekwencji inline

Użyj sequence.definition, aby wysłać kompletną sekwencję wraz z połączeniem. Bird uruchamia ją jednorazowo i nie zapisuje, więc połączenie nie ma identyfikatora sekwencji. Definicja inline sprawdza się w przepływach generowanych przez aplikację dla każdego połączenia.

Definicja inline musi przejść te same kontrole co publikowanie sekwencji. Jej przebieg może wykonać co najwyżej 16 poleceń, wliczając podpowiedzi gather; połączenie wymagające 17. kończy się błędem śledzenia call_limit. Dokumentacja węzłów wymienia każdy krok, którego możesz użyć, wraz z jego polami i wynikami. Aby zacząć od działającego przepływu, zbuduj go i opublikuj w dashboardzie, otwórz sekwencję i wybierz Copy JSON w sekcji Definition JSON pod Published version.

Ten call.json prosi odbiorcę o naciśnięcie 1, aby usłyszeć godziny otwarcia, lub 2, aby usłyszeć wskazówki dojazdu. Cisza i każdy inny klawisz kończą uruchomienie z własnymi przyczynami zakończenia:

Przykład kodu
{
  "from": "+12025550100",
  "to": "+12025550101",
  "sequence": {
    "entry_node_id": "start",
    "trigger_data": {},
    "definition": {
      "schema_version": 1,
      "expression_environment": "bird.cel.v1",
      "nodes": [
        {
          "id": "start",
          "type": "trigger.start_call",
          "type_version": 1,
          "config": {},
          "input": {},
          "connections": { "event": { "node_id": "menu", "port": "input" } }
        },
        {
          "id": "menu",
          "type": "voice.gather",
          "type_version": 1,
          "config": {},
          "input": {
            "prompts": [
              {
                "type": "say",
                "text": "Press 1 for opening hours, or 2 for directions.",
                "language": "en"
              }
            ],
            "max_digits": 1,
            "timeout_seconds": 5,
            "inter_digit_timeout_seconds": 2,
            "finish_on_key": "#",
            "private": false,
            "matches": { "hours": "1", "directions": "2" }
          },
          "connections": {
            "hours": { "node_id": "hours", "port": "input" },
            "directions": { "node_id": "directions", "port": "input" },
            "timeout": { "node_id": "no_input", "port": "input" },
            "fallback": { "node_id": "other_input", "port": "input" }
          }
        },
        {
          "id": "hours",
          "type": "voice.say",
          "type_version": 1,
          "config": {},
          "input": { "text": "We are open Monday through Friday, nine to five.", "language": "en" },
          "connections": { "next": { "node_id": "done", "port": "input" } }
        },
        {
          "id": "directions",
          "type": "voice.say",
          "type_version": 1,
          "config": {},
          "input": {
            "text": "Find directions on your appointment confirmation.",
            "language": "en"
          },
          "connections": { "next": { "node_id": "done", "port": "input" } }
        },
        {
          "id": "done",
          "type": "logic.exit",
          "type_version": 1,
          "config": { "status": "succeeded", "reason": "information_played" },
          "input": { "output": {} }
        },
        {
          "id": "no_input",
          "type": "logic.exit",
          "type_version": 1,
          "config": { "status": "succeeded", "reason": "no_input" },
          "input": { "output": {} }
        },
        {
          "id": "other_input",
          "type": "logic.exit",
          "type_version": 1,
          "config": { "status": "succeeded", "reason": "unrecognized_input" },
          "input": { "output": {} }
        }
      ]
    }
  }
}

Pole connections każdego węzła mapuje wynik na następny węzeł. Pole matches menu nazywa jego opcje, a connections używa tych samych nazw obok wbudowanych wyników timeout i fallback.

Personalizacja sekwencji inline

Zadeklaruj pola, które wysyłasz, w data_schema wpisu, a następnie odczytuj je jako trigger.data.<field> w wartości $expr. To połączenie wita odbiorcę po imieniu i potwierdza lub oznacza jego wizytę:

Przykład kodu
{
  "from": "+12025550100",
  "to": "+12025550101",
  "sequence": {
    "entry_node_id": "start",
    "trigger_data": {
      "appointment_id": "apt_2048",
      "customer_name": "Sam",
      "appointment_time": "Tuesday at 10 AM"
    },
    "definition": {
      "schema_version": 1,
      "expression_environment": "bird.cel.v1",
      "nodes": [
        {
          "id": "start",
          "type": "trigger.start_call",
          "type_version": 1,
          "config": {
            "data_schema": {
              "type": "object",
              "additionalProperties": false,
              "required": ["appointment_id", "customer_name", "appointment_time"],
              "properties": {
                "appointment_id": { "type": "string", "minLength": 1 },
                "customer_name": { "type": "string", "minLength": 1 },
                "appointment_time": { "type": "string", "minLength": 1 }
              }
            }
          },
          "input": {},
          "connections": { "event": { "node_id": "confirm_menu", "port": "input" } }
        },
        {
          "id": "confirm_menu",
          "type": "voice.gather",
          "type_version": 1,
          "config": {},
          "input": {
            "prompts": [
              {
                "type": "say",
                "text": {
                  "$template": [
                    "Hello ",
                    { "$expr": "trigger.data.customer_name" },
                    ". Press 1 to confirm your appointment on ",
                    { "$expr": "trigger.data.appointment_time" },
                    ", or 2 if you need help."
                  ]
                },
                "language": "en"
              }
            ],
            "max_digits": 1,
            "timeout_seconds": 7,
            "inter_digit_timeout_seconds": 2,
            "finish_on_key": null,
            "private": false,
            "matches": { "confirm": "1", "help": "2" }
          },
          "connections": {
            "confirm": { "node_id": "confirmed", "port": "input" },
            "help": { "node_id": "help_requested", "port": "input" },
            "timeout": { "node_id": "no_response", "port": "input" },
            "fallback": { "node_id": "no_response", "port": "input" }
          }
        },
        {
          "id": "confirmed",
          "type": "logic.exit",
          "type_version": 1,
          "config": { "status": "succeeded", "reason": "appointment_confirmed" },
          "input": {
            "output": { "appointment_id": { "$expr": "trigger.data.appointment_id" } }
          }
        },
        {
          "id": "help_requested",
          "type": "logic.exit",
          "type_version": 1,
          "config": { "status": "succeeded", "reason": "appointment_help_requested" },
          "input": {
            "output": { "appointment_id": { "$expr": "trigger.data.appointment_id" } }
          }
        },
        {
          "id": "no_response",
          "type": "logic.exit",
          "type_version": 1,
          "config": { "status": "failed", "reason": "appointment_no_response" },
          "input": {
            "output": { "appointment_id": { "$expr": "trigger.data.appointment_id" } }
          }
        }
      ]
    }
  }
}

Pola status i reason każdego wyjścia oddzielają potwierdzenie, prośbę o pomoc i brak odpowiedzi. Obiekt trigger_data, który nie pasuje do data_schema, nie przechodzi walidacji, a jego lokalizacja jest wskazana w /sequence/trigger_data, i żadne połączenie nie zostaje zainicjowane.

Wyślij żądanie

Wybierz jedną z poniższych metod żądania dla zapisanego call.json.

Wybierz świeży, unikalny klucz idempotentności raz dla tego zamierzonego połączenia. Zachowaj ten klucz i oryginalne dane wejściowe na potrzeby ponowień lub odzyskiwania potwierdzenia. Wybierz inny klucz, gdy zamierzasz zainicjować osobne nowe połączenie, po rozwiązaniu nieznanego wyniku oryginalnego połączenia.

W przykładach powłoki ustaw IDEMPOTENCY_KEY na wybraną wartość przed wysłaniem. Przykłady zatrzymują się, jeśli zmienna jest nieustawiona lub pusta; nie generują kolejnego klucza przy powtórzeniu.

Dla HTTP ustaw BIRD_API_KEY na swój klucz, a BIRD_API_URL na jego regionalny bazowy URL, np. https://eu1.platform.bird.com dla klucza eu1, a następnie wyślij żądanie:

Przykład kodu
curl --request POST "$BIRD_API_URL/v1/voice/calls" \
  --header "Authorization: Bearer $BIRD_API_KEY" \
  --header 'Content-Type: application/json' \
  --header "Idempotency-Key: ${IDEMPOTENCY_KEY:?Set IDEMPOTENCY_KEY to the saved key for this intended call}" \
  --data-binary @call.json

Dla podglądu CLI zaloguj się z obydwoma uprawnieniami zapisu i przygotuj połączenie, używając tego samego pliku:

Przykład kodu
bird auth login --scope voice_management:write --scope voice:write
bird voice calls create --body-file call.json \
  --idempotency-key "${IDEMPOTENCY_KEY:?Set IDEMPOTENCY_KEY to the saved key for this intended call}"

Polecenie wyświetla link do przeglądu w przeglądarce i czeka na zakończenie. Otwórz link, sprawdź dzwoniącego, odbiorcę, sekwencję i dane wpisu, a następnie sam uruchom żądanie. Przygotowanie żądania nie inicjuje połączenia. Dodaj --dry-run, aby sprawdzić żądanie CLI bez tworzenia potwierdzenia. Jeśli potwierdzenie wygaśnie, zostanie anulowane lub zakończy się bez zarejestrowanego wyniku, polecenie kończy działanie z kodem 5; zastosuj wskazówki dotyczące ponawiania przed wysłaniem kolejnego żądania.

Dla podglądu MCP wywołaj voice_calls_create z polami z call.json i wymaganym idempotency_key. Zastąp <unique-key-for-this-request-reuse-for-retries> wybranym kluczem:

Przykład kodu
{
  "from": "+12025550100",
  "to": "+12025550101",
  "sequence": {
    "id": "YOUR_SEQUENCE_ID",
    "entry_node_id": "YOUR_ENTRY_NODE_ID",
    "trigger_data": {}
  },
  "idempotency_key": "<unique-key-for-this-request-reuse-for-retries>"
}

Otwórz zwrócony link do przeglądu w przeglądarce, aby uruchomić żądanie. Na dynamicznym endpoincie MCP wybierz voice_calls_create przez execute. Zgoda OAuth przyznaje uprawnienia obszaru roboczego; przegląd w przeglądarce uruchamia to konkretne połączenie.

Odpowiedź 202 Accepted potwierdza przyjęcie. Sekwencja rozpoczyna się po odebraniu połączenia przez odbiorcę. Opublikowanie nowszej wersji po akceptacji nie zmienia wybranej definicji ani danych wpisu tego połączenia.

Odczytaj wynik akceptacji

Zachowaj id, initial_leg_id i sequence.run_id z odpowiedzi do celów korelacji. id najwyższego poziomu identyfikuje połączenie we wszystkich jego etapach; initial_leg_id identyfikuje pierwszy etap.

Odpowiedź jest niezmiennym zrzutem akceptacji. Pola started_at i ended_at mają wartość null, wartości logiczne obserwacji mają wartość false, a parties jest puste. Te pola opisują akceptację, więc nie stają się raportem statusu na żywo przy ponownym odtworzeniu żądania.

Otwórz Runs sekwencji, aby sprawdzić postęp. Połączenie inline nie należy do żadnej sekwencji, więc śledź zamiast tego jego leg; jeśli połączenie zakończy się niepowodzeniem, zanim leg zostanie zarejestrowany, nie ma jeszcze sposobu na jego sprawdzenie. Gdy rekord leg istnieje, użyj GET /v1/voice/legs/{leg_id} z initial_leg_id lub sprawdź dziennik połączeń. Odczyt leg wymaga uprawnienia voice:read, które obejmuje voice:write.

Leg z status rejected został odrzucony przed połączeniem, więc jego sekwencja nie została uruchomiona. Jeśli nie ma powodu odrzucenia, druga strona odrzuciła połączenie; zobacz Odrzucone połączenia.

Za pomocą CLI bird voice calls get YOUR_CALL_ID pokazuje połączenie i jego strony. bird voice legs trace YOUR_LEG_ID pokazuje, które kroki zostały wykonane, zebrane cyfry (chyba że gather jest prywatny) oraz status i przyczynę zakończenia. Ślad jest gotowy wkrótce po zakończeniu połączenia; do tego momentu polecenie zwraca błąd, więc spróbuj ponownie. Sekwencja odrzuconego odcinka nigdy nie została wykonana, więc ślad może nie istnieć.

Akceptacja nie gwarantuje wybierania numeru, odebrania ani czytelnego rekordu połączenia. Połączenie, które nie powiedzie się przed rejestracją, może pojawić się w historii uruchomień bez rekordu etapu. Odebrane połączenie również nie potwierdza, że sekwencja wykonała zamierzone zadanie biznesowe.

Obsługa błędów i ponawianie

Dla bezpośrednich żądań HTTP idempotentność jest opcjonalna. Bez klucza każde żądanie przyjmuje nową próbę połączenia. SDK generują klucz do automatycznych ponowień. Aby chronić ponowienia między osobnymi połączeniami lub bezpośrednimi żądaniami HTTP, podaj klucz przy pierwszej próbie i użyj go ponownie z dokładnie oryginalnymi bajtami żądania. Zobacz przewodnik po idempotentności.

Identyczne powtórzenie w ciągu trzech godzin zwraca oryginalną akceptację i Idempotency-Replay: true. Zmienione dane wejściowe z tym kluczem zwracają 409. Autoryzacja i uprawnienie numeru dzwoniącego są ponownie sprawdzane przy powtórzeniu. Po upływie okna powtórzeń klucz może przyjąć nowe połączenie, więc uzgodnij oryginalny wynik przed ponownym wysłaniem.

Dla CLI i MCP podaj klucz idempotentności przy pierwszej próbie. Powtórzenie tego samego żądania i klucza z tą samą zgodą OAuth zwraca istniejące potwierdzenie, dopóki jego rekord jest zachowany. Zachowaj oryginalne dane wejściowe i identyfikator potwierdzenia. Zmiana klucza może przygotować kolejne płatne połączenie.

Jeśli polecenie CLI zostanie przerwane, wznów z oryginalnymi danymi wejściowymi, kluczem i zwróconym identyfikatorem potwierdzenia:

Przykład kodu
bird voice calls create --body-file call.json \
  --idempotency-key "${IDEMPOTENCY_KEY:?Set IDEMPOTENCY_KEY to the saved key for this intended call}" \
  --confirmation-id YOUR_CONFIRMATION_ID

Dla MCP powtórz oryginalne argumenty narzędzia, w tym ten sam idempotency_key, wraz ze zwróconym stanem żądania. Stan identyfikuje potwierdzenie i nie zastępuje tych argumentów. Alternatywnie powtórz to samo narzędzie i argumenty ze zwróconym identyfikatorem w metadanych żądania bird/confirmation-id. W przypadku dynamicznego MCP powtórz to samo żądanie execute i umieść te metadane na nim. Wznowienie odczytuje oryginalne potwierdzenie i zwraca jego zarejestrowany wynik po zakończeniu.

Potwierdzenie Create Call wygasa po 90 minutach. Potwierdzenie pending lub expired bez wyniku nie dowodzi, że połączenie nigdy nie zostało zrealizowane. Sprawdź oryginalne uruchomienie sekwencji i ewentualny rekord etapu połączenia, zanim zdecydujesz o zainicjowaniu kolejnego połączenia; nie twórz nowego klucza w celu rozwiązania nieznanego wyniku. Zakończone potwierdzenie z wynikiem 202 dowodzi akceptacji, więc kontynuuj sprawdzanie akceptacji, aby ustalić wynik połączenia.

ObjawCo sprawdzić
400 lub 422Przeczytaj szczegóły pól błędu. Sprawdź format numeru, uprawnienie i własność numeru dzwoniącego, identyfikatory sekwencji i wpisu, jawny obiekt danych oraz limity żądań.
401 lub 403Sprawdź klucz API lub login OAuth, oba wymagane uprawnienia zapisu oraz dostęp do obszaru roboczego.
404Sprawdź, czy sekwencja należy do wybranego obszaru roboczego i czy tworzenie połączeń jest dostępne w usłudze regionalnej.
409Sprawdź, czy nie nastąpiło ponowienie ze zmienionym ciałem żądania lub czy aktywna sekwencja produkcyjna jest niedostępna. Opublikuj lub wznów w razie potrzeby przed rozpoczęciem nowego połączenia.
429Zastosuj się do wskazówek dotyczących ponawiania z odpowiedzi. Jeśli podałeś klucz, użyj go ponownie dla tej samej próby połączenia.
Zaakceptowane, potem nieudaneSprawdź uruchomienie i ewentualny rekord etapu pod kątem celu, limitów, salda lub błędów wykonania, zanim zdecydujesz o zainicjowaniu kolejnego połączenia.

Następne kroki

Przejdź do dokumentacji, przewodników i przykładów dotyczących tego tematu.