Documentation
Sign inGet started

WhatsApp contact info requests

A contact info request puts one button under a WhatsApp message that asks the recipient to share a phone number. Use it when you need a number to reach someone on, such as a callback or a booking confirmation, rather than a saved address. For a location instead, use location requests.

Send a contact info request

Set interactive.type to request_contact_info, with a body_text and nothing else. WhatsApp renders the button itself, so there is nothing to label it with:
const msg = await bird.whatsapp.send({
  to: "+16505551234",
  from: "+13124495648",
  interactive: {
    type: "request_contact_info",
    body_text:
      "To confirm your booking we need a number to reach you on. Tap below to share yours.",
  },
});
console.log(msg.id, msg.status);
from is required on every service message: a number your workspace owns, not a Bird-managed one. This type names no field of its own, and the schema bars a header, a footer_text, and every other type's field (buttons, list, cta_url, cards) outright, so body_text is the whole message, capped at 1024 characters. Meta states no body-length limit for this type at all; Bird applies the 1024-character bound every other interactive type but a list menu carries.
in_reply_to_message_id still works on this type, to quote an earlier message in the same conversation. See the hub's quoting a message to correlate a reply for how resolution works and what it can miss.

Reading the shared contact

A tap does not produce an interactive_reply. It arrives as an ordinary inbound message carrying a contact_cards array:
Contoh kode
{
  "id": "wam_01kyb2m4xq7whs0d8n3prv6tez",
  "direction": "inbound",
  "from": { "phone_number": "+16505551234", "bsuid": "US.13491208655302741918" },
  "to": { "phone_number": "+13124495648" },
  "status": "received",
  "contact_cards": [
    {
      "origin": "contact_request",
      "phone_numbers": [{ "phone_number": "+14155550829", "type": "cell" }]
    }
  ],
  "created_at": "2026-08-26T10:00:00Z"
}
contact_cards is an array, read-only, and inbound only: a contacts message that carried no card reads back as [], not as an absent field. Checking origin is mandatory before treating a card as your answer. origin is contact_request when the card answers this ask, or other when the contact shared a card unprompted, which may name a third party entirely and not the contact at all. A tap carries only phone_numbers[].{phone_number, type} and omits vcard; the full contact object, with name, org, birthday, and the rest, arrives only on origin: "other". You see this reply through the message list or GET /v1/whatsapp/messages/{id}; see the hub's reading a reply for that path in full.

Correlating the answer with the question

Unlike a location request, Meta puts no context on this type's reply, so in_reply_to_message_id is omitted rather than resolved. Correlate on from plus a recent send of your own, or accept that you cannot. Two outstanding asks to the same contact are indistinguishable: nothing on the reply names which ask it answers, so a workspace that sends a second contact info request before the first is answered cannot tell which card responds to which.
This is the deliberate contrast with location requests: that type's reply carries Meta's own context, so in_reply_to_message_id resolves and the hub's quoting a message to correlate a reply mechanism links the answer back on its own. A contact info request's reply has no such mechanism to lean on.

Asking inside a template instead

The request_contact_info interactive message is the free-form counterpart of the REQUEST_CONTACT_INFO template button, which asks for the same contact card but can reach a recipient whose customer service window is closed. Use the interactive message when the recipient messaged you recently and you want the ask worded for this conversation; use the template button when the window is closed, or when the ask rides on a message you already send as a template. See WhatsApp templates for sending with a template.

Things to watch

  • The customer service window has to be open. A contact info request is a service message, deliverable only inside an open window; see the hub's customer service window. The window check fails open, so a 202 is not proof the window was actually open when the send goes out.
  • from must be a number your workspace owns, and the window it needs open is keyed to that number, not to your workspace as a whole.
  • The reply cannot be tied to the ask by id. No context on Meta's side means in_reply_to_message_id is omitted on the reply; correlate on from plus a recent send of your own.
  • A decline is silent. WhatsApp shows the recipient a share sheet, and dismissing it produces no message and no webhook at all. The absence of a contact_cards message is the only signal, so any flow that waits on an answer needs its own timeout rather than a decline event to watch for.
  • No header, no footer, and no button label. The schema bars a header and footer_text on this type outright, and there is no field to label the button with. Everything the recipient reads has to be in body_text.
  • The disclosed number is not guaranteed to be the one the contact chats from. Meta warns that a user's ID and phone number may not always match, so do not assume the shared number equals from.phone_number. It is also not guaranteed to be E.164: Bird normalizes it where parseable and passes it through verbatim where not.
  • The reply is a contact_cards message, not an interactive_reply. An integration that only watches interactive_reply for a tap will miss this type entirely, and so will one that only watches inbound location for the other request type.
Everything the schema can express here, an over-long body_text, a header, a footer_text, or any of buttons, list, cta_url, cards, is a plain request-validation failure with no catalog code. The one interactive-specific pair that can fire on this type is E15057 and E15058, both on in_reply_to_message_id when a quote doesn't resolve or can't be quoted; see the hub's errors for the full interactive error table and How sending works for the errors any WhatsApp send can hit.

Next steps