Start Typing

Show the 'typing...' or 'recording audio...' status in a chat.

POST
https://api.wawp.net/v2/send/start-typing?access_token=YOUR_ACCESS_TOKEN&chatId=201234567890%40c.us&instance_id=123456789

Authentication Required

Login to swap the placeholders with your real Instance ID and Access Token.

Log In
Test /v2/send/start-typing endpoint
POST
POST

No query parameters required

This endpoint doesn't expect data in the URL.

Best practices

  • Call this 2-3 seconds before sending the actual text message.

  • Use webhooks to detect when a user starts typing to your bot as well.

Organic Presence: Mastering the Start Typing Engine

The `/v2/send/start-typing", endpoint is a non-visual, high-impact tool for managing user psychology and conversational expectations. In a world where instant bot replies can often feel robotic and impersonal, the "typing..." indicator serves as a bridge of human mimicry. By explicitly signaling that a response is in progress, you reduce user anxiety, prevent "double-texting" from impatient customers, and create a premium, "Human-in-the-Loop" experience for your automated flows.


🏗️ The Presence and Attention Pipeline

When you trigger the /start-typing endpoint, Wawp initiates a "Presence Broadcast" across the WhatsApp network:

  1. Signaling Initialization: The engine sends a specialized COMPOSE packet to the chat identified by chatId. This packet instructs the recipient's phone to render the "typing..." text in the top bar of the chat window and the animated bubble in the message thread.
  2. Ephemeral Persistence: Unlike a message, this status is ephemeral. WhatsApp naturally clears it after approximately 10–20 seconds if no further activity is detected. However, Wawp allows you to maintain this status for longer durations by periodically re-calling the endpoint.
  3. Multi-Platform Sync: The "typing..." indicator is synchronized across the recipient's entire account—appearing on their mobile phone, WhatsApp Web, and Desktop apps simultaneously.

🛡️ Strategic Best Practices for Organic Simulation

1. The "Think Time" Strategy

Instantaneous text replies from a bot are a clear giveaway that no human is present.

  • Implementation: When your backend receives a message.received webhook, call /v2/send/start-typing immediately. Then, calculate your AI response or perform your database query, and wait a minimum of 2–3 seconds before sending the final /v2/send/text.
  • UX Impact: This brief pause with a "typing..." status makes the interaction feel like a considered reply from an attentive agent, significantly increasing user satisfaction and trust.

2. Managing impetuous Users

Users often send several messages in a row ("Hello?", "Are you there?", "I have a question").

  • Best Practice: As soon as you detect any activity, trigger /start-typing. This visual feedback often stops a user from sending follow-up messages, as they can see a response is already being formulated.

3. Coordinate with Media Prep

Large videos or PDFs can take a few seconds to process and upload.

  • Workflow: If you are about to send a high-resolution image or a long video, start the "typing..." indicator during the file-fetch phase. This fills the dead air and ensures the user doesn't close the chat thinking the bot has crashed.

🧩 Advanced Use Cases

High-Fidelity Bot Mimicry

Build a "Humanized AI" by varying the duration of the typing status based on the length of the predicted response. If the AI is about to send a 500-word explanation, show "typing..." for 4 seconds. If it's a simple "Yes," show it for only 1 second. This level of detail makes the bot virtually indistinguishable from a human agent at first glance.

Interactive Voice Preparation

If your bot is about to send a Voice Note (/v2/send/voice), you can actually signal that you are "recording audio..." (on supported engine versions). This alerts the user to turn up their volume and prepare for a non-textual interaction, smoothing the transition between media types.


🛠️ Common Pitfalls and Solutions

  • The "Stuck Typing" Bug: If you call /start-typing but then your backend crashes before sending the message, the user might see "typing..." for a long time only for it to disappear without a response. Solution: Use a try...finally block in your code to ensure that a /v2/send/stop-typing or a final message is always sent.
  • Over-Scheduling: Calling the start-typing endpoint every 100ms is unnecessary and can be flagged as "Abusive Behavior" by the WhatsApp network. We recommend a frequency of no more than once every 5–10 seconds if you need to sustain the indicator for a long-duration task.
  • Group Chaos: In very large groups, excessive typing indicators from a bot can become distracting. Use this feature sparingly in group environments, focusing primarily on 1-on-1 customer support situations.

Summary of Capabilities:

  • Explicitly trigger the native WhatsApp "typing..." or "recording audio..." indicators.
  • High-fidelity organic simulation for bot and human-agent flows.
  • Real-time presence broadcasting to individual, group, and channel recipients.
  • Ephemeral state management with automatic network-level timeouts.
  • Essential tool for managing user expectations and reducing conversational friction.
  • Seamless coordination with text, media, and document delivery endpoints.

Request Parameters

Configure the parameters required to interact with this endpoint. All query and body arguments are listed below with their details.

Request Body

Sent as a JSON object
string

Your unique WhatsApp Instance ID

Example:
string

Your API Access Token

Example:
string

Target phone number or group ID

Example:

Request Samples

Use these ready-to-go code snippets to integrate our API into your project quickly and efficiently. Choose your preferred language and library.

1const baseUrl = "https://api.wawp.net";
2const endpoint = "/v2/send/start-typing";
3const params = new URLSearchParams({
4 "instance_id": "123456789",
5 "access_token": "YOUR_ACCESS_TOKEN"
6}).toString();
7const body = {
8 "chatId": "201234567890@c.us"
9};
10
11fetch(`${baseUrl}${endpoint}${params ? '?' + params : ''}`, {
12 method: "POST",
13 headers: { "Content-Type": "application/json" },
14 body: JSON.stringify(body)
15})
16 .then(async (response) => {
17 if (response.ok) {
18 const data = await response.json();
19 console.log("Success:", data);
20 return data;
21 }
22
23 // Error Handling
24 if (response.status === 400) {
25 console.error("Error 400: Bad Request - Missing Required Parameter(s)");
26 }
27 if (response.status === 400) {
28 console.error("Error 400: Bad Request - Invalid Number (Egypt)");
29 }
30 if (response.status === 400) {
31 console.error("Error 400: Bad Request - Invalid Number (Saudi Arabia)");
32 }
33 if (response.status === 400) {
34 console.error("Error 400: Bad Request - Invalid Number (Unknown)");
35 }
36 if (response.status === 400) {
37 console.error("Error 400: Bad Request (XML Format)");
38 }
39 if (response.status === 400) {
40 console.error("Error 400: Bad Request (Plain Text)");
41 }
42 if (response.status === 401) {
43 console.error("Error 401: Unauthorized - Invalid or Missing Access Token");
44 }
45 if (response.status === 401) {
46 console.error("Error 401: Unauthorized (XML Format)");
47 }
48 if (response.status === 404) {
49 console.error("Error 404: Not Found - Session Does Not Exist");
50 }
51 if (response.status === 404) {
52 console.error("Error 404: Not Found (XML Format)");
53 }
54 if (response.status === 429) {
55 console.error("Error 429: Too Many Requests - Rate Limit Exceeded");
56 }
57 if (response.status === 500) {
58 console.error("Error 500: Internal Server Error - Unexpected Failure");
59 }
60 if (response.status === 500) {
61 console.error("Error 500: Internal Server Error (HTML)");
62 }
63 if (response.status === 502) {
64 console.error("Error 502: Bad Gateway - Connection Failed to Upstream");
65 }
66 if (response.status === 502) {
67 console.error("Error 502: Bad Gateway (XML Format)");
68 }
69
70 const errorText = await response.text();
71 console.error(`Error ${response.status}: ${errorText}`);
72 })
73 .catch((error) => console.error("Network Error:", error));
Interactive Samples
Ln 73, Col 1javascript

Expected Responses

Explore all possible responses and outcomes from the server. We have documented each status code with data examples to make success and error handling easier.

Message Sent Successfully
Type:
application/json
object *
string *
object *
number *
boolean *
string *
string *
number *
string *
string *
string *
boolean *
number *
boolean *
boolean *
boolean *
boolean *
boolean *
array *
array *
array *
boolean *
array *

Example

{
"_data": {
  "id": {
    "fromMe": true,
    "remote": "000000000000@c.us",
    "id": "MSG_ID_123456",
    "_serialized": "true_000000000000@c.us_MSG_ID_123456"
    },
  "viewed": false,
  "body": "BASE64_IMAGE_DATA",
  "type": "image",
  "t": 1759108866,
  "from": {
    "server": "c.us",
    "user": "111111111111",
    "_serialized": "111111111111@c.us"
    },
  "to": {
    "server": "c.us",
    "user": "000000000000",
    "_serialized": "000000000000@c.us"
    },
  "ack": 0,
  "isNewMsg": true,
  "star": false,
  "kicNotified": false,
  "caption": "Here's your requested image.",
  "deprecatedMms3Url": "https://example.com/media-url",
  "directPath": "/media/direct/path/example",
  "mimetype": "image/jpeg",
  "filehash": "FILE_HASH_PLACEHOLDER",
  "encFilehash": "ENC_FILE_HASH_PLACEHOLDER",
  "size": 192487,
  "mediaKey": "MEDIA_KEY_PLACEHOLDER",
  "mediaKeyTimestamp": 1759108865,
  "streamable": false,
  "mediaHandle": null,
  "isFromTemplate": false,
  "pollInvalidated": false,
  "isSentCagPollCreation": false,
  "latestEditMsgKey": null,
  "latestEditSenderTimestampMs": null,
  "mentionedJidList": {
    },
  "groupMentions": {
    },
  "isEventCanceled": false,
  "eventInvalidated": false,
  "isVcardOverMmsDocument": false,
  "isForwarded": false,
  "isQuestion": false,
  "questionReplyQuotedMessage": null,
  "questionResponsesCount": 0,
  "readQuestionResponsesCount": 0,
  "labels": {
    },
  "hasReaction": false,
  "disappearingModeInitiator": "chat",
  "disappearingModeTrigger": "chat_settings",
  "productHeaderImageRejected": false,
  "lastPlaybackProgress": 0,
  "isDynamicReplyButtonsMsg": false,
  "isCarouselCard": false,
  "parentMsgId": null,
  "callSilenceReason": null,
  "isVideoCall": false,
  "callDuration": null,
  "callCreator": null,
  "callParticipants": null,
  "isCallLink": null,
  "callLinkToken": null,
  "isMdHistoryMsg": false,
  "stickerSentTs": 0,
  "lastUpdateFromServerTs": 0,
  "invokedBotWid": null,
  "bizBotType": null,
  "botResponseTargetId": null,
  "botPluginType": null,
  "botPluginReferenceIndex": null,
  "botPluginSearchProvider": null,
  "botPluginSearchUrl": null,
  "botPluginSearchQuery": null,
  "botPluginMaybeParent": false,
  "botReelPluginThumbnailCdnUrl": null,
  "botMessageDisclaimerText": null,
  "botMsgBodyType": null,
  "requiresDirectConnection": false,
  "bizContentPlaceholderType": null,
  "hostedBizEncStateMismatch": false,
  "senderOrRecipientAccountTypeHosted": false,
  "placeholderCreatedWhenAccountIsHosted": false,
  "galaxyFlowDisabled": false,
  "links": {
    }
  },
"mediaKey": "MEDIA_KEY_PLACEHOLDER",
"id": {
  "fromMe": true,
  "remote": "000000000000@c.us",
  "id": "MSG_ID_123456",
  "_serialized": "true_000000000000@c.us_MSG_ID_123456"
  },
"ack": 0,
"hasMedia": true,
"body": "Here's your requested image.",
"type": "image",
"timestamp": 1759108866,
"from": "111111111111@c.us",
"to": "000000000000@c.us",
"deviceType": "android",
"isForwarded": false,
"forwardingScore": 0,
"isStatus": false,
"isStarred": false,
"fromMe": true,
"hasQuotedMsg": false,
"hasReaction": false,
"vCards": {
  },
"mentionedIds": {
  },
"groupMentions": {
  },
"isGif": false,
"links": {
  }
}
Bad Request - Missing Required Parameter(s)
Unauthorized - Invalid or Missing Access Token
Not Found - Session Does Not Exist
Too Many Requests - Rate Limit Exceeded
Internal Server Error - Unexpected Failure
Bad Gateway - Connection Failed to Upstream
Previous TopicMark message(s) as seen
Next TopicStop Typing

Command Palette

Search for a command to run...