Sign inGet started

Odbieranie kart kontaktów WhatsApp

contact_cards to jedyne ramię, które przenosi to samo pole w obu kierunkach. Kontakt może udostępnić kartę ze swojej książki adresowej, a kliknięcie wysłanego przez Ciebie żądania danych kontaktowych również trafia tutaj, z numerem, który kontakt zdecydował się ujawnić.

Co zawiera przychodząca karta kontaktu

contact_cards jest zawsze tablicą, a origin wskazuje, jak karta dotarła:
Przykład kodu
{
  "id": "wam_01kyg9v3timy1w7n0r4cbh9ukf",
  "direction": "inbound",
  "from": { "phone_number": "+14155550100" },
  "to": { "phone_number": "+13124495569" },
  "status": "received",
  "contact_cards": [
    {
      "origin": "contact_request",
      "phone_numbers": [{ "phone_number": "+14155550100", "type": "cell" }]
    }
  ],
  "created_at": "2026-08-25T09:27:45Z"
}
originJak karta dotarła
contact_requestKontakt kliknął przycisk, który wysłałeś, prosząc o numer
otherKontakt udostępnił kartę w czacie z własnej inicjatywy
Sprawdź origin, zanim potraktujesz kartę jako odpowiedź na swoje zapytanie. To jedyny sygnał odróżniający oba przypadki, a karta udostępniona z własnej inicjatywy może zawierać dane osoby trzeciej, a nie kontaktu. Lista wartości jest otwarta, więc nierozpoznaną wartość traktuj jako nowy sposób udostępniania dodany od tamtego czasu.
Karta wysłana przez ten obszar roboczy zwraca się bez origin, i tak właśnie odróżnisz kartę wychodzącą od przychodzącej na tym samym polu.

Co przenosi kliknięcie, a co udostępniona karta

Oba przypadki docierają z różną ilością szczegółów, a żadne pole na karcie nie jest wymagane: WhatsApp wysyła te części, które karta zawiera, i pomija resztę, więc karta z samym origin nadal dociera zamiast być odrzuconą.
PolePrzy kliknięciu przyciskuPrzy karcie udostępnionej w czacie
phone_numbers[].phone_number, typeNumer, który kontakt zdecydował się ujawnićNumery zawarte na karcie
vcardPominięte; kliknięcie przenosi sam numerKarta w formacie vCard
name, org, birthday, emails, urls, addressesTo, co WhatsApp wyśle, czyli zwykle nicObecne, gdy karta je zawiera
Przykład kodu
{
  "contact_cards": [
    {
      "origin": "other",
      "vcard": "BEGIN:VCARD\nVERSION:3.0\nN:Johnson;Barbara;;;\nTEL;type=CELL:+16505551234\nEND:VCARD\n",
      "name": {
        "formatted_name": "Barbara J. Johnson",
        "first_name": "Barbara",
        "last_name": "Johnson"
      },
      "org": { "company": "Northside Plumbing" },
      "phone_numbers": [{ "phone_number": "+16505551234", "type": "cell" }]
    }
  ]
}
Dwa pola wymagają ostrożności przy parsowaniu. phone_number jest normalizowane do E.164 tam, gdzie da się je sparsować, a tam, gdzie nie, przekazywane dokładnie tak, jak urządzenie kontaktu je zapisało (w tym numer wewnętrzny), więc parsuj defensywnie zamiast zakładać E.164. birthday przychodzi z urządzenia bez walidacji i jest przekazywane jako tekst w kształcie YYYY-MM-DD, a nie jako typowana data, więc nie zakładaj, że da się je sparsować. Etykieta type na odebranej karcie jest zapisana małymi literami, a WhatsApp nie definiuje dla niej słownika, więc dopasowuj ją bez uwzględniania wielkości liter zamiast przełączać na CELL.

Numer telefonu ujawniany przez kontakt

Kontakt, który przyjął nazwę użytkownika WhatsApp, dociera do Ciebie przez identyfikator użytkownika w zakresie firmy bez numeru telefonu w from. Żądanie danych kontaktowych służy do zapytania o numer, a to ramię jest miejscem, gdzie dociera odpowiedź, z origin: "contact_request" i numerem w phone_numbers.
Ujawniony numer nie musi być numerem, z którego kontakt pisze: Meta ostrzega, że identyfikator użytkownika i numer telefonu nie zawsze muszą się zgadzać, więc zapisuj ujawniony numer jako osobny fakt zamiast nadpisywać tożsamość w from.

Payload webhooka

whatsapp.received przenosi tablicę contact_cards w kopercie zdarzenia:
Przykład kodu
{
  "type": "whatsapp.received",
  "timestamp": "2026-08-25T09:27:45.019Z",
  "data": {
    "whatsapp_id": "wam_01kyg9v3timy1w7n0r4cbh9ukf",
    "workspace_id": "ws_01ky7m235keycbnwyajabe1a6b",
    "direction": "inbound",
    "from": { "phone_number": "+14155550100", "bsuid": "US.13491208655302741918" },
    "to": { "phone_number": "+13124495569" },
    "contact_cards": [
      {
        "origin": "contact_request",
        "phone_numbers": [{ "phone_number": "+14155550100", "type": "cell" }]
      }
    ],
    "tags": null,
    "metadata": null
  }
}

Na co uważać

  • Odrzucone żądanie nie generuje niczego. WhatsApp pokazuje kontaktowi arkusz udostępniania, a zamknięcie go nie wysyła wiadomości ani nie uruchamia webhooka, więc flow czekający na numer potrzebuje własnego limitu czasu zamiast zdarzenia odrzucenia.
  • Dwa oczekujące zapytania są nierozróżnialne. Karta będąca odpowiedzią na żądanie danych kontaktowych nie zawiera in_reply_to_message_id, więc drugiego zapytania wysłanego przed uzyskaniem odpowiedzi na pierwsze nie da się dopasować do własnej odpowiedzi.
  • Tablica może zawierać kilka kart. Kontakt udostępniający wiele kart w jednej wiadomości wypełnia kilka wpisów, każdy z własnym origin.
  • Karta to dane kontaktowe, których nie zebrałeś. Może zawierać imię, numery i datę urodzenia osoby trzeciej, więc stosuj te same zasady przechowywania i zgody, co do każdych innych danych osobowych, zanim ją zapiszesz.

Kolejne kroki