💬 Shared WhatsApp Inbox on the new PlatformMore
1msg official logo

Documents received confirmation via WhatsApp API

The scenario sends the client a personalised WhatsApp template when required documents are received and logged in the back office.

Use case overview

The scenario sends the client a personalised WhatsApp template when required documents are received and logged in the back office. The message includes the client name, the verification or document process, and what happens next. A static URL button opens the status portal or customer account page.

Template example

Hello, {{1}}! We have received your documents for {{2}}. {{3}} Thank you for submitting them — we will keep you updated on the progress.

Check status
  • {{1}}
    customer name
  • {{2}}
    verification or document process (e.g. KYC verification, onboarding documents, support ticket attachments)
  • {{3}}
    next step or expected timeline (e.g. review within 2 business days, we will notify you when complete)
  • “Check status”
    button — fixed in the Meta template
WhatsApp Business API for documents received confirmation

When to use it

Reach for this scenario when a client uploads required documents for onboarding, KYC, or a support request and needs acknowledgement that the files arrived — with no open WhatsApp conversation to confirm in session. It fits product teams processing KYC intake queues, support desks receiving ticket attachments, and agencies wiring document-intake webhooks from CRM, BPM, or eKYC platforms to WhatsApp outbound.

Fewer "did you get my documents?" calls
Three body variables carry the client name, the verification or document process, and the next review step, so the client has proof in WhatsApp without calling support or resending files.
Status checks one tap away
A static URL button labeled Check status opens the portal or account page — the link is fixed in the approved Meta template while only the body text is sent via the API.
Reach clients outside the 24-hour window
Because there is no active conversation, the send uses an approved WhatsApp template via the 1MSG API — the only channel that can confirm document receipt when the client has not written first.
No manual acknowledgement for every upload
When a documents-received trigger fires from onboarding, KYC, or support intake, the system resolves the phone number and sends the template on that event instead of someone copying confirmation text by hand.
Delivery logged for workflow follow-up
Delivery result is logged after send, so CRM or compliance teams can see who was notified and handle errors according to platform rules.

Workflow

  1. Trigger

    The client uploads required documents through a portal, app, or support channel.

    event · triggered

  2. Delivered

    The system captures the documents-received event and resolves the recipient phone number.

    delivered

  3. Build & send

    A personalised template message is built with three body variables and a static URL button.

    POST /sendTemplate

  4. Customer acts

    The client receives the WhatsApp confirmation with process context and next steps.

    user action

  5. Status tracked

    Delivery result is logged; errors are handled according to platform rules.

    status: "read"

WhatsApp Business API for documents received confirmation

Technical implementation

Prerequisites

  1. 1MSG API Key · How to get API Key
  2. WhatsApp Business account · How to Connect WABA
  3. WhatsApp Template · How to Approve WABA Template
  4. Customer opt-in · How to Manage Customers Consent

Code examples

#!/usr/bin/env bash
set -euo pipefail

# === Configuration (replace "___" placeholders) ===

API_BASE_URL="https://api.1msg.io"        # production 1MSG API base URL
CHANNEL_ID="___"                           # channel ID from 1MSG dashboard
API_TOKEN="___"                            # channel JWT token (Bearer)

TEMPLATE_NAME="___"                        # approved template name
TEMPLATE_NAMESPACE="___"                   # template namespace (required — send fails without it)
TEMPLATE_LANGUAGE="___"                    # template language code, e.g. "en"



# === Test data ===
TEST_PHONE="___"                 # client phone in international format
TEST_CUSTOMERNAME="___"         # {{1}} customer name
TEST_PROCESS="___"         # {{2}} process name
TEST_NEXTSTEP="___"         # {{3}} next step

PHONE_NORM="$(printf '%s' "$TEST_PHONE" | tr -cd '0-9')"

for pair in "CHANNEL_ID=$CHANNEL_ID" "API_TOKEN=$API_TOKEN" \
            "TEMPLATE_NAME=$TEMPLATE_NAME" "TEMPLATE_NAMESPACE=$TEMPLATE_NAMESPACE" \
            "TEMPLATE_LANGUAGE=$TEMPLATE_LANGUAGE" "TEST_PHONE=$TEST_PHONE" \
            "TEST_CUSTOMERNAME=$TEST_CUSTOMERNAME" \
            "TEST_PROCESS=$TEST_PROCESS" \
            "TEST_NEXTSTEP=$TEST_NEXTSTEP"; do
    val="${pair#*=}"
    if [ -z "$val" ] || [ "$val" = "___" ]; then
        echo "Missing configuration value: ${pair%%=*}" >&2
        exit 1
    fi
done

if [ -z "$PHONE_NORM" ]; then
    echo "Error: phone number has no digits after normalization" >&2
    exit 1
fi

URL="${API_BASE_URL%/}/${CHANNEL_ID}/sendTemplate"

# params carries body ONLY. Button text is fixed in the Meta template — no button param.

# {{1}} customer name → ${TEST_CUSTOMERNAME}
# {{2}} process name → ${TEST_PROCESS}
# {{3}} next step → ${TEST_NEXTSTEP}
read -r -d '' PAYLOAD <<JSON || true
{
  "phone": "${PHONE_NORM}",
  "template": "${TEMPLATE_NAME}",
  "namespace": "${TEMPLATE_NAMESPACE}",
  "language": { "policy": "deterministic", "code": "${TEMPLATE_LANGUAGE}" },
  "params": [
    {
      "type": "body",
      "parameters": [
        { "type": "text", "text": "${TEST_CUSTOMERNAME}" },
        { "type": "text", "text": "${TEST_PROCESS}" },
        { "type": "text", "text": "${TEST_NEXTSTEP}" }
      ]
    }

  ]
}
JSON

RESPONSE="$(curl -s -w '\n%{http_code}' -X POST "$URL" \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${API_TOKEN}" \
    -d "$PAYLOAD")"

HTTP_CODE="$(printf '%s' "$RESPONSE" | tail -n1)"
BODY="$(printf '%s' "$RESPONSE" | sed '$d')"

case "$BODY" in
    *'"sent":true'*) ok=1 ;;
    *) ok=0 ;;
esac

if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ] && [ "$ok" -eq 1 ]; then
    echo "Message sent to client."
    echo "API response: $BODY"
else
    echo "Send failed. HTTP status: $HTTP_CODE" >&2
    echo "$BODY" >&2
    exit 1
fi

Response and delivery status

HTTP 2xx and JSON "sent": true mean 1MSG accepted the message for sending — not that it already reached the customer's phone. Save the id field (looks like wamid.…) to correlate delivery callbacks.

200 OKResponse
{
  "sent": true,
  "message": "Sent to [email protected]",
  "description": "Message has been sent to the provider",
  "id": "wamid.HBgLMzgwNjM5..."
}
  • sent

    Accepted for sending — not yet on the customer's phone

  • id

    Store it; delivery callbacks and hookInfo are keyed on this

Delivery statuses and webhooks →

Common errors

StatusAPI responseCauseFix
200Message was not sent: template is not definednamespace, template or language is missing from the request body.Send all three. Take namespace and the exact template name from GET /templates; language is an object: {"policy": "deterministic", "code": "en"}.
200template name (…) does not exist in <language>The template is approved in a different language than the one requested.Use the exact language code the template was approved in (for example es_MX is not the same as es). Check it in GET /templates.
200Message was not sent: provide chatId, phone, bsuid, or usernameNo recipient the channel could resolve.Pass exactly one recipient: phone (country code plus number, digits only), chatId (for example [email protected]) or bsuid.

All error codes →

Common questions

Related

Build for WhatsApp in hours
without infrastructure hassle