Portal Community

When to Use

Configuration

Connection

FieldRequiredDescription
accessTokenRequiredPermanent System User access token. Store in BizFirst Credentials Manager.
phoneNumberIdRequiredNumeric string ID of the sending WhatsApp Business phone number.
apiVersionOptionalMeta Graph API version. Defaults to v18.0.

Operation

FieldRequiredDescription
toRequiredRecipient's phone number with country code, no + prefix (e.g. 14155552671).
mediaUrlRequired*Publicly accessible HTTPS URL to the document. Supported formats: PDF, DOCX, XLSX, PPTX, TXT, and many others. Maximum size: 100 MB.
mediaIdRequired*ID of a previously uploaded document from media/upload. Use for private documents or repeated sends.
filenameOptionalThe filename displayed in WhatsApp (e.g. Invoice_2024_001.pdf). If omitted, WhatsApp uses a generic name. Always specify for professional appearance.
captionOptionalText displayed below the document attachment. Maximum 1024 characters.

* Provide either mediaUrl or mediaId — exactly one is required.

Sample Configuration

{
  "resource": "message",
  "operation": "sendDocument",
  "accessToken": "{{ $credentials.whatsAppToken }}",
  "phoneNumberId": "123456789012345",
  "to": "{{ $input.clientPhone }}",
  "mediaUrl": "https://docs.example.com/invoices/{{ $input.invoiceId }}.pdf",
  "filename": "Invoice_{{ $input.invoiceId }}.pdf",
  "caption": "Invoice #{{ $input.invoiceId }} | Due: {{ $input.dueDate }} | Amount: ${{ $input.amount }}\n\nPlease confirm receipt by replying RECEIVED."
}

Validation Errors

ErrorCause
accessToken is requiredThe accessToken field is empty.
phoneNumberId is requiredThe phoneNumberId field is empty.
to is requiredThe to field is empty.
Either mediaId or mediaUrl is requiredBoth fields are empty. Provide exactly one.
131053 (Meta)Document download failed — URL inaccessible or returned a non-200 response.
131052 (Meta)Unsupported document format or file exceeds 100 MB.
131047 (Meta)24-hour window expired. Use a template with a document header component.

Output

Success Port

FieldTypeDescription
messageIdstringUnique WhatsApp message ID (wamid).
phoneNumberIdstringThe sending phone number ID.
tostringThe recipient phone number.
statusstring"sent" on success.
errorCodestringEmpty on success.
errorMessagestringEmpty on success.
rawResponsestringFull raw JSON from the Meta API.

Error Port

FieldTypeDescription
statusstring"failed" or "error".
errorCodestringMeta error code or BizFirst validation code.
errorMessagestringHuman-readable error description.
rawResponsestringRaw API error response.

Sample Output

{
  "messageId": "wamid.HBgLMTQxNTU1NTI2NzEVAgARGBIyRTI4QUY0NjhFMEI4NCMAA",
  "phoneNumberId": "123456789012345",
  "to": "14155552671",
  "status": "sent",
  "errorCode": null,
  "errorMessage": null,
  "rawResponse": "{\"messaging_product\":\"whatsapp\",\"contacts\":[{\"input\":\"14155552671\",\"wa_id\":\"14155552671\"}],\"messages\":[{\"id\":\"wamid.HBgLMTQxNTU1NTI2NzEVAgARGBIyRTI4QUY0NjhFMEI4NCMAA\"}]}"
}

Expression Reference

ValueExpressionNotes
Message ID{{ $output.sendDoc.messageId }}Retain for audit trail and potential deletion within 60 minutes.
Recipient{{ $output.sendDoc.to }}For delivery confirmation logging.
Status{{ $output.sendDoc.status }}Branch on "sent" vs "failed" in IfCondition.
Error code{{ $output.sendDoc.errorCode }}Log on the error port for failure analysis.

Node Policies & GuardRails

Policy AreaRecommendation
Credential storageStore the access token in BizFirst Credentials Manager. Never inline in configuration.
Filename conventionAlways set the filename field with a descriptive, professional name including the file extension. Default filenames from WhatsApp are generic and confusing for recipients.
URL access controlWhen using mediaUrl, ensure the URL is temporarily public during the Meta download window. If the document is sensitive, pre-sign the URL with a minimum 60-second expiry, or use media/upload and pass the mediaId.
Sensitive documentsDo not send documents containing unencrypted PII (e.g. social security numbers, full credit card numbers). WhatsApp provides end-to-end encryption but documents may be saved to device storage or forwarded by recipients.
24-hour windowDocument messages are free-form and subject to the 24-hour customer service window. For outbound-only document delivery (e.g. monthly statements), use a template with a document header.
Error portAlways connect the error port. URL access failures are common for documents hosted behind authenticated portals.

Examples

Automated Invoice Delivery

{
  "resource": "message",
  "operation": "sendDocument",
  "accessToken": "{{ $credentials.whatsAppToken }}",
  "phoneNumberId": "123456789012345",
  "to": "{{ $input.clientPhone }}",
  "mediaUrl": "https://storage.example.com/invoices/{{ $input.invoiceNumber }}.pdf",
  "filename": "Invoice_{{ $input.invoiceNumber }}_{{ $input.period }}.pdf",
  "caption": "Your invoice for {{ $input.period }} is attached.\nAmount due: ${{ $input.amount }}\nDue date: {{ $input.dueDate }}\n\nPay online: {{ $input.paymentUrl }}"
}

A billing workflow triggers this node when an invoice is generated. The URL is a presigned S3 link valid for 5 minutes — sufficient for Meta to download it. The caption includes a direct payment link to reduce the steps to payment.

Employee Handbook on Onboarding

{
  "resource": "message",
  "operation": "sendDocument",
  "accessToken": "{{ $credentials.whatsAppToken }}",
  "phoneNumberId": "123456789012345",
  "to": "{{ $input.employeePhone }}",
  "mediaId": "{{ $config.employeeHandbookMediaId }}",
  "filename": "BizFirst_Employee_Handbook_2024.pdf",
  "caption": "Welcome to BizFirst, {{ $input.employeeName }}! Your employee handbook is attached. Please read Section 3 (IT Policy) before your first meeting. Reply READ when done."
}

The handbook is uploaded once at the start of each year via media/upload, and the resulting mediaId is stored in workflow configuration. All new hire onboarding workflows reuse the same mediaId, avoiding repeated uploads.

Weekly Report Distribution

{
  "resource": "message",
  "operation": "sendDocument",
  "accessToken": "{{ $credentials.whatsAppToken }}",
  "phoneNumberId": "123456789012345",
  "to": "{{ $input.managerPhone }}",
  "mediaUrl": "{{ $output.generateReport.reportUrl }}",
  "filename": "Weekly_Report_{{ $input.weekEnding }}.xlsx",
  "caption": "Weekly performance report for week ending {{ $input.weekEnding }}.\nKey metrics: Revenue ${{ $input.revenue }} | Orders {{ $input.orderCount }} | NPS {{ $input.nps }}"
}

A ScheduledTrigger fires every Friday at 5 PM. A Function node generates the Excel report, uploads it to S3, and returns the presigned URL. This node sends the document with a summary in the caption so the manager can see key numbers without opening the file.