Send WhatsApp message or attachment
Input
kind requiredWhat to send: a plain text message, an attached file of the given kind, or a saved contact's card.
name optionalExact chat/contact/group name to send to (the `name` field from get_inbox). Provide this OR `phone`, not both.
text optionalMessage text. Required when kind is "text".
phone optionalRecipient phone in international format, no saved contact needed. Confirm this number with the user before running; don't guess or reuse a number from context without checking. Non-digits are stripped, a leading "00" international prefix is removed, and a national number (leading trunk 0) is rejected with a clear error. e.g. "+1 555 123 4567", "15551234567" or "0015551234567". Provide this OR `name`, not both.
caption optionalOptional caption for image/video/document.
dry_run optionalWhen true, everything runs up to the send itself and then stops: the chat is opened and verified, a file is handed to WhatsApp and accepted by its media editor, a caption is typed, a contact card is resolved and its numbers counted. Nothing is delivered — sent comes back false, dry_run true and verified_on_page false. Use it to verify a recipient and a payload without sending a real message.
filename optionalFilename to send it as, e.g. photo.png / clip.mp4 / file.pdf. Required when kind is image/video/document. With the `attachment` file input the bytes are taken from that input, but this name is still what the send is verified against.
mimeType optionalMIME type; inferred from kind + filename extension when omitted.
attachment optionalThe file to send, bound through the platform's own file channel and handed to WhatsApp's hidden file input directly. Preferred over fileBase64: it carries the bytes outside the argument payload, so it is not limited by the request size. Use with kind image/video/document; WhatsApp still picks the input by kind, so the kind must match the file.
fileBase64 optionalFile contents, base64-encoded (no data: prefix), as an alternative to the `attachment` file input. The bytes ride inside the request, so a large file is limited by whatever the caller's own transport allows inline.
contactName optionalThe saved name of the contact whose card to send, exactly as WhatsApp's address book shows it. Every phone number saved for that contact is included. Required when kind is "contact".
Output
kind requiredWhat was sent: "text", "image", "video", "document" or "contact".
sent requiredTrue once the send is confirmed: for text, a delivery tick appeared and WhatsApp did not flag a failure; for an attachment, the upload cleared its pending state and stayed unflagged through a settle window; for a contact card, the outgoing bubble naming the contact appeared unflagged. False on a dry run, where nothing was sent.
recipient requiredThe chat name the message was sent to, read back from the conversation header.
account_used requiredThe phone number of the WhatsApp account that actually sent this, read back from the live session rather than taken from the request.
verified_on_page requiredTrue when the send was confirmed by inspecting the conversation afterwards, rather than assumed from the click. Always false on a dry run, where there is no sent message to inspect.
id optionalWhatsApp message id of the message that was sent. Populated for every kind. Null on a dry run, where nothing was sent.
text optionalThe text that was sent; null for attachment and contact sends.
time optionalTimestamp of the sent message as shown in the bubble (e.g. "3:14 PM"); null for attachment and contact sends, and null on a dry run.
caption optionalThe caption sent with the attachment, or null.
dry_run optionalTrue when this run stopped before the send. The chat was still opened and verified, and the payload still prepared — a file accepted by WhatsApp's media editor, or a contact resolved — only the send itself was skipped.
filename optionalThe filename the attachment was sent as, or null for text and contact sends.
contactName optionalThe saved contact whose card was sent, or null for other kinds.
numbersSent optionalHow many of the contact's phone numbers the card carried, counted on WhatsApp's own confirmation screen. Null for other kinds. On a dry run this is what WOULD have been sent, counted on that same screen.
already_present optionalWhether an outgoing message with exactly this text was already in the conversation before this send. Reported, not enforced - re-sending the same text is legitimate. Null for image/video and contact sends, where no comparable content is visible in the bubble.
