{"id":285,"date":"2026-10-25T13:05:25","date_gmt":"2026-10-25T13:05:25","guid":{"rendered":"https:\/\/vectalk.com.br\/blog\/whatsapp-api-message-status-webhook\/"},"modified":"2026-10-25T13:05:28","modified_gmt":"2026-10-25T13:05:28","slug":"whatsapp-api-message-status-webhook","status":"publish","type":"post","link":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/","title":{"rendered":"Message status in the WhatsApp Business API: sent, delivered, read and failed via webhook"},"content":{"rendered":"\n<p><em>Updated on October 25, 2026<\/em><\/p>\n\n\n\n<p>In the WhatsApp Business API, the status of a sent message arrives through the webhook, in the <code>statuses<\/code> array, not in the send response. The possible values are <code>sent<\/code> (left WhatsApp&#8217;s servers), <code>delivered<\/code> (reached the device), <code>read<\/code> (displayed in an open chat), <code>played<\/code> (voice message played for the first time) and <code>failed<\/code> (couldn&#8217;t be sent or delivered, with the reason in <code>errors<\/code>). Each event carries the message <code>wamid<\/code>, and your system should keep the most advanced status without letting a late event roll the record back.<\/p>\n\n\n\n<p>This guide covers what each status means, the payloads, how to read errors and pricing, and a storage model in Node.js and Python.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The send response is not the status<\/h2>\n\n\n\n<p>When you call the messages endpoint, the 200 response returns the <code>wamid<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-json\">{\n  \"messaging_product\": \"whatsapp\",\n  \"contacts\": [{ \"input\": \"15551234567\", \"wa_id\": \"15551234567\" }],\n  \"messages\": [{ \"id\": \"wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBI0...\" }]\n}<\/code><\/pre>\n\n\n\n<p>That only means Meta accepted the request. The message can still fail, for example because of the per-user marketing limit or because the number isn&#8217;t on WhatsApp. Store the <code>wamid<\/code> at send time: it&#8217;s the key that links the message to the statuses that arrive later.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The five Cloud API statuses<\/h2>\n\n\n\n<p>The <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/webhooks\/reference\/messages\/status\" target=\"_blank\" rel=\"noreferrer noopener\">status webhook reference<\/a> defines:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Status<\/th><th>Meaning<\/th><th>In the customer&#8217;s app<\/th><\/tr><\/thead><tbody><tr><td><code>sent<\/code><\/td><td>The message left WhatsApp&#8217;s servers<\/td><td>One check mark<\/td><\/tr><tr><td><code>delivered<\/code><\/td><td>The message reached the recipient&#8217;s device<\/td><td>Two check marks<\/td><\/tr><tr><td><code>read<\/code><\/td><td>The message was displayed in an open chat on the device<\/td><td>Two blue check marks<\/td><\/tr><tr><td><code>played<\/code><\/td><td>First playback of a voice message<\/td><td>Blue microphone<\/td><\/tr><tr><td><code>failed<\/code><\/td><td>The message couldn&#8217;t be sent or delivered<\/td><td>Red error triangle<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Two details from the docs change how you process them:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>read<\/code> can come without <code>delivered<\/code>.<\/strong> If the customer has the chat open when the message arrives, Meta skips the <code>delivered<\/code> webhook and sends only <code>read<\/code>. Treat <code>read<\/code> as &#8220;delivered and read&#8221;.<\/li>\n\n\n<li><strong><code>played<\/code> only exists for voice messages.<\/strong> It fires the first time the customer plays an audio message sent as voice (see <a href=\"https:\/\/vectalk.com.br\/blog\/en\/send-media-whatsapp-api\/\">how to send audio and voice notes<\/a>).<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">The status payload<\/h2>\n\n\n\n<p>Every status arrives with <code>field: \"messages\"<\/code>, just like incoming messages. The difference is that <code>value<\/code> holds <code>statuses<\/code> instead of <code>messages<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-json\">{\n  \"object\": \"whatsapp_business_account\",\n  \"entry\": [{\n    \"id\": \"WABA_ID\",\n    \"changes\": [{\n      \"field\": \"messages\",\n      \"value\": {\n        \"messaging_product\": \"whatsapp\",\n        \"metadata\": { \"display_phone_number\": \"15550000000\", \"phone_number_id\": \"PHONE_NUMBER_ID\" },\n        \"statuses\": [{\n          \"id\": \"wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBI0...\",\n          \"status\": \"delivered\",\n          \"timestamp\": \"1761400000\",\n          \"recipient_id\": \"15551234567\",\n          \"pricing\": {\n            \"billable\": true,\n            \"pricing_model\": \"PMP\",\n            \"type\": \"regular\",\n            \"category\": \"marketing\"\n          }\n        }]\n      }\n    }]\n  }]\n}<\/code><\/pre>\n\n\n\n<p>Status object fields:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Field<\/th><th>When present<\/th><th>What it&#8217;s for<\/th><\/tr><\/thead><tbody><tr><td><code>id<\/code><\/td><td>Always<\/td><td>The sent message&#8217;s <code>wamid<\/code><\/td><\/tr><tr><td><code>status<\/code><\/td><td>Always<\/td><td>One of the five values above<\/td><\/tr><tr><td><code>timestamp<\/code><\/td><td>Always<\/td><td>When the event was generated (Unix, seconds)<\/td><\/tr><tr><td><code>recipient_id<\/code><\/td><td>Always<\/td><td>Recipient&#8217;s number (or group ID, for groups)<\/td><\/tr><tr><td><code>biz_opaque_callback_data<\/code><\/td><td>If you sent this field with the message<\/td><td>Echoes back your own identifier, such as an order or campaign ID<\/td><\/tr><tr><td><code>pricing<\/code><\/td><td>On <code>sent<\/code> and on one of <code>delivered<\/code> or <code>read<\/code><\/td><td>Rate category and billing type<\/td><\/tr><tr><td><code>errors<\/code><\/td><td>Only on <code>failed<\/code><\/td><td>Error code and description<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>For group messages, <code>recipient_id<\/code> holds the group ID, and the participant&#8217;s number goes in <code>recipient_participant_id<\/code>.<\/p>\n\n\n\n<p>A single <code>POST<\/code> can carry several statuses, including for different messages. Always iterate over the whole array.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The <code>pricing<\/code> object<\/h3>\n\n\n\n<p><code>pricing<\/code> is the most reliable way to know whether and how a message was billed:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>category<\/code><\/strong>: rate category, such as <code>marketing<\/code>, <code>utility<\/code>, <code>authentication<\/code> or <code>service<\/code>.<\/li>\n\n\n<li><strong><code>type<\/code><\/strong>: <code>regular<\/code> (billable), <code>free_customer_service<\/code>, <code>free_entry_point<\/code> (sent in the free window opened by a click-to-WhatsApp ad) or <code>free_group_customer_service<\/code>.<\/li>\n\n\n<li><strong><code>billable<\/code><\/strong>: deprecated by Meta. Use <code>type<\/code> and <code>category<\/code>.<\/li>\n\n<\/ul>\n\n\n\n<p>As of October 1, 2026, Meta changed what <code>type<\/code> means: utility messages sent inside the customer service window now come as <code>regular<\/code>, and <code>free_customer_service<\/code> now indicates a service message within the phone number&#8217;s free tier (1,000 per month). Service messages beyond that tier also come as <code>regular<\/code>. If your cost report relies on <code>type<\/code>, review the rule. See <a href=\"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-campaign-cost\/\">how much a WhatsApp campaign costs<\/a> for how to add it up.<\/p>\n\n\n\n<p>From Graph API version 24.0 onward, the <code>conversation<\/code> object is no longer included in statuses, except for messages sent inside a free entry point window.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><code>failed<\/code> status: reading the error<\/h2>\n\n\n\n<p>When a message fails, the status includes <code>errors<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-json\">{\n  \"id\": \"wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBI0...\",\n  \"status\": \"failed\",\n  \"timestamp\": \"1761400005\",\n  \"recipient_id\": \"15551234567\",\n  \"errors\": [{\n    \"code\": 131049,\n    \"title\": \"This message was not delivered to maintain healthy ecosystem engagement.\",\n    \"message\": \"This message was not delivered to maintain healthy ecosystem engagement.\",\n    \"error_data\": { \"details\": \"In order to maintain a healthy ecosystem engagement, the message failed to be delivered.\" },\n    \"href\": \"\/documentation\/business-messaging\/whatsapp\/support\/error-codes\"\n  }]\n}<\/code><\/pre>\n\n\n\n<p>Store <code>code<\/code> and <code>error_data.details<\/code>. The codes that show up most often in failed statuses, according to the <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/support\/error-codes\" target=\"_blank\" rel=\"noreferrer noopener\">official error code list<\/a>:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Code<\/th><th>Cause<\/th><th>Action<\/th><\/tr><\/thead><tbody><tr><td><code>131026<\/code><\/td><td>Recipient not on WhatsApp, hasn&#8217;t accepted the latest terms or uses an outdated app<\/td><td>Confirm the number; don&#8217;t retry in a loop<\/td><\/tr><tr><td><code>131047<\/code><\/td><td>More than 24 hours since the customer&#8217;s last message<\/td><td>Send a template<\/td><\/tr><tr><td><code>131049<\/code><\/td><td>Not delivered to protect engagement (per-user marketing limit)<\/td><td>Wait at least 24 hours; see <a href=\"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-error-131049-marketing-limit\/\">per-user marketing limits<\/a><\/td><\/tr><tr><td><code>131050<\/code><\/td><td>Customer stopped marketing messages from the business<\/td><td>Mark as opted out; don&#8217;t retry<\/td><\/tr><tr><td><code>131053<\/code><\/td><td>Media upload failed, usually an unsupported type<\/td><td>Check the file&#8217;s MIME type<\/td><\/tr><tr><td><code>131056<\/code><\/td><td>Too many messages to the same recipient in a short time<\/td><td>Wait before messaging that person again<\/td><\/tr><tr><td><code>132015<\/code><\/td><td>Template paused for low quality<\/td><td>Edit the template and wait for approval<\/td><\/tr><tr><td><code>131000<\/code><\/td><td>Unknown error<\/td><td>Retry; if it persists, open a support ticket<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>The full list with more codes is in <a href=\"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-error-codes\/\">WhatsApp API errors<\/a>.<\/p>\n\n\n\n<p>A <code>failed<\/code> message isn&#8217;t delivered and therefore isn&#8217;t billed under per-delivered-message pricing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Order, duplicates and delays<\/h2>\n\n\n\n<p>Meta&#8217;s documentation doesn&#8217;t promise that statuses arrive in order, and it warns that webhook delivery retries can produce duplicate notifications. Retries continue for up to 7 days. In practice:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>read<\/code> can arrive before <code>delivered<\/code><\/strong>, or <code>delivered<\/code> after <code>read<\/code>. Never overwrite a more advanced status with an older one.<\/li>\n\n\n<li><strong>The same status can arrive twice.<\/strong> Use <code>id<\/code> + <code>status<\/code> as the idempotency key.<\/li>\n\n\n<li><strong>A status can arrive hours or days later<\/strong> if your endpoint was down. Store the event&#8217;s <code>timestamp<\/code>, not the time you processed it.<\/li>\n\n\n<li><strong><code>delivered<\/code> may never arrive<\/strong>, for example if the customer&#8217;s phone stays off. Don&#8217;t treat &#8220;no <code>delivered<\/code> within 5 minutes&#8221; as a failure.<\/li>\n\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Storing statuses without regressing<\/h2>\n\n\n\n<p>The simplest model: one row per sent message, a timestamp column for each stage and a field with the most advanced status. Node.js example with PostgreSQL (<code>pg<\/code> library):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-js\">const ORDER = { sent: 1, delivered: 2, read: 3, played: 4 };\n\nexport async function saveStatus(db, st) {\n  const at = new Date(Number(st.timestamp) * 1000);\n\n  if (st.status === 'failed') {\n    const err = st.errors?.[0] ?? {};\n    await db.query(\n      `UPDATE sends SET failed_at = $2, error_code = $3, error_detail = $4,\n         status = CASE WHEN status_rank = 0 THEN 'failed' ELSE status END\n       WHERE wamid = $1`,\n      [st.id, at, err.code ?? null, err.error_data?.details ?? err.message ?? null],\n    );\n    return;\n  }\n\n  const rank = ORDER[st.status];\n  if (!rank) return; \/\/ unknown status: log it and move on\n\n  await db.query(\n    `UPDATE sends SET\n       ${st.status}_at = COALESCE(${st.status}_at, $2),\n       delivered_at = CASE WHEN $3 &gt;= 3 THEN COALESCE(delivered_at, $2) ELSE delivered_at END,\n       category = COALESCE($4, category),\n       billing_type = COALESCE($5, billing_type),\n       status = CASE WHEN $3 &gt; status_rank THEN $6 ELSE status END,\n       status_rank = GREATEST(status_rank, $3)\n     WHERE wamid = $1`,\n    [st.id, at, rank, st.pricing?.category ?? null, st.pricing?.type ?? null, st.status],\n  );\n}<\/code><\/pre>\n\n\n\n<p>What this code guarantees:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>No regression.<\/strong> <code>status_rank<\/code> only goes up; a late <code>delivered<\/code> doesn&#8217;t erase a <code>read<\/code>.<\/li>\n\n\n<li><strong>Idempotent.<\/strong> Saving the same event twice yields the same result, thanks to <code>COALESCE<\/code>.<\/li>\n\n\n<li><strong><code>read<\/code> implies delivery.<\/strong> If <code>delivered<\/code> was skipped, <code>delivered_at<\/code> is filled with the <code>read<\/code> time.<\/li>\n\n\n<li><strong>A failure doesn&#8217;t erase success.<\/strong> If the row already has a positive status, <code>failed<\/code> is recorded in the error fields without changing the main status, so you can investigate.<\/li>\n\n<\/ul>\n\n\n\n<p>The same logic in Python, without a database, for tests:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-python\">ORDER = {\"sent\": 1, \"delivered\": 2, \"read\": 3, \"played\": 4}\n\n\ndef apply_status(send: dict, st: dict) -&gt; dict:\n    at = int(st[\"timestamp\"])\n    if st[\"status\"] == \"failed\":\n        err = (st.get(\"errors\") or [{}])[0]\n        send.update(failed_at=at, error_code=err.get(\"code\"))\n        if send.get(\"status_rank\", 0) == 0:\n            send[\"status\"] = \"failed\"\n        return send\n\n    rank = ORDER.get(st[\"status\"])\n    if rank is None:\n        return send\n    send.setdefault(f\"{st['status']}_at\", at)\n    if rank &gt;= 3:\n        send.setdefault(\"delivered_at\", at)\n    if rank &gt; send.get(\"status_rank\", 0):\n        send.update(status=st[\"status\"], status_rank=rank)\n    return send<\/code><\/pre>\n\n\n\n<p>To test with real events on your machine, see <a href=\"https:\/\/vectalk.com.br\/blog\/en\/test-whatsapp-webhook-locally\/\">how to test the WhatsApp webhook locally<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Linking statuses to your business with <code>biz_opaque_callback_data<\/code><\/h3>\n\n\n\n<p>When sending, you can include <code>biz_opaque_callback_data<\/code> with your own identifier (for example <code>\"order:48213\"<\/code> or <code>\"campaign:black-friday\"<\/code>). It comes back on every status for that message. That saves a database lookup to find which order or campaign a <code>wamid<\/code> belongs to and makes per-campaign reporting easier.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Metrics you can derive from statuses<\/h2>\n\n\n\n<p>With the timestamps stored, the most common metrics are straightforward:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Metric<\/th><th>Calculation<\/th><\/tr><\/thead><tbody><tr><td>Delivery rate<\/td><td>messages with <code>delivered_at<\/code> or <code>read_at<\/code> \u00f7 messages sent<\/td><\/tr><tr><td>Read rate<\/td><td>messages with <code>read_at<\/code> \u00f7 messages delivered<\/td><\/tr><tr><td>Time to read<\/td><td><code>read_at<\/code> \u2212 <code>sent_at<\/code><\/td><\/tr><tr><td>Failure rate by code<\/td><td>count of <code>error_code<\/code> \u00f7 messages sent<\/td><\/tr><tr><td>Estimated cost<\/td><td>sum of rates by <code>category<\/code>, only for messages with <code>billing_type = regular<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>For customer service metrics (first response time, average handling time), see <a href=\"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-customer-service-metrics\/\">WhatsApp customer service metrics<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to do it with Vectalk<\/h2>\n\n\n\n<p>Vectalk forwards Meta&#8217;s status webhook to your URLs unchanged, with <code>statuses<\/code>, <code>pricing<\/code> and <code>errors<\/code> in the format described above. Register your URL with <code>POST https:\/\/apis.vectalk.com.br\/api\/webhooks<\/code> and return 200 within 20 seconds.<\/p>\n\n\n\n<p>Besides the webhook, Vectalk keeps a message history you can query by status or <code>wamid<\/code>, which helps reconcile events your system may have missed:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"language-bash\">curl \"https:\/\/apis.vectalk.com.br\/api\/messages?status=failed&amp;direction=outbound&amp;from=2026-10-01&amp;to=2026-10-25\" \\\n  -H \"Authorization: Bearer $VECTALK_TOKEN\"\n\ncurl \"https:\/\/apis.vectalk.com.br\/api\/messages?messageId=wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBI0...\" \\\n  -H \"Authorization: Bearer $VECTALK_TOKEN\"<\/code><\/pre>\n\n\n\n<p>The supported filters (<code>status<\/code>, <code>from<\/code>, <code>to<\/code>, <code>messageId<\/code>, <code>direction<\/code>, <code>page<\/code>, <code>limit<\/code>) are documented under <a href=\"https:\/\/docs.vectalk.com.br\/api-reference\/messages\/list\">List messages<\/a>, and the event format under <a href=\"https:\/\/docs.vectalk.com.br\/concepts\/webhooks\">Webhooks<\/a> (docs in Portuguese). Message costs come on your Vectalk invoice, with no card at Meta. Create your account at <a href=\"https:\/\/apps.vectalk.com.br\/register\">apps.vectalk.com.br\/register<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Frequently asked questions<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Why did I get <code>read<\/code> without <code>delivered<\/code>?<\/h3>\n\n\n\n<p>Because the customer had the chat open when the message arrived. In that case, Meta sends only <code>read<\/code>. Consider the message delivered.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The message is stuck on <code>sent<\/code>. What happened?<\/h3>\n\n\n\n<p>It left WhatsApp&#8217;s servers but hasn&#8217;t reached the device yet, for example because the phone is off or offline. <code>delivered<\/code> arrives when the device receives it. If <code>failed<\/code> arrives later, the code explains why.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Is a <code>failed<\/code> message billed?<\/h3>\n\n\n\n<p>No. Meta bills delivered messages. A message that failed wasn&#8217;t delivered.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Can I query a message&#8217;s status through Meta&#8217;s API instead of waiting for the webhook?<\/h3>\n\n\n\n<p>The Cloud API delivers statuses via webhook, so your endpoint needs to be up and storing events. On Vectalk, you can also check the history through the list messages endpoint.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How long after sending can a status arrive?<\/h3>\n\n\n\n<p>There&#8217;s no fixed limit. <code>read<\/code> depends on when the customer opens the chat, and webhook delivery retries can last up to 7 days if your endpoint is down.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><strong>Official sources consulted on October 25, 2026:<\/strong> <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/webhooks\/reference\/messages\/status\" target=\"_blank\" rel=\"noreferrer noopener\">Status webhook reference<\/a>, <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/webhooks\/overview\" target=\"_blank\" rel=\"noreferrer noopener\">Webhooks overview<\/a>, <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/support\/error-codes\" target=\"_blank\" rel=\"noreferrer noopener\">Error codes<\/a>, <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/pricing\" target=\"_blank\" rel=\"noreferrer noopener\">Pricing<\/a>, <a href=\"https:\/\/developers.facebook.com\/documentation\/business-messaging\/whatsapp\/messages\/audio-messages\" target=\"_blank\" rel=\"noreferrer noopener\">Audio messages<\/a>, <a href=\"https:\/\/docs.vectalk.com.br\/api-reference\/messages\/list\">Vectalk docs: List messages<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>What each WhatsApp Business API message status means, how it arrives via webhook, how to read errors and pricing, and how to store statuses without losing or regressing them.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[1],"tags":[],"class_list":["post-285","post","type-post","status-publish","format-standard","hentry","category-blog"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>WhatsApp API message status via webhook | Vectalk<\/title>\n<meta name=\"description\" content=\"WhatsApp API message status explained: what sent, delivered, read, played and failed mean, webhook payloads, errors, pricing and how to store them safely.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"WhatsApp API message status via webhook | Vectalk\" \/>\n<meta property=\"og:description\" content=\"WhatsApp API message status explained: what sent, delivered, read, played and failed mean, webhook payloads, errors, pricing and how to store them safely.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/\" \/>\n<meta property=\"og:site_name\" content=\"Blog Vectalk\" \/>\n<meta property=\"article:published_time\" content=\"2026-10-25T13:05:25+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2026-10-25T13:05:28+00:00\" \/>\n<meta name=\"author\" content=\"wanderleyfcunha\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"wanderleyfcunha\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/en\\\/whatsapp-api-message-status-webhook\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/en\\\/whatsapp-api-message-status-webhook\\\/\"},\"author\":{\"name\":\"wanderleyfcunha\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#\\\/schema\\\/person\\\/ff36ecd9d8257856f227f8e5d639db2b\"},\"headline\":\"Message status in the WhatsApp Business API: sent, delivered, read and failed via webhook\",\"datePublished\":\"2026-10-25T13:05:25+00:00\",\"dateModified\":\"2026-10-25T13:05:28+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/en\\\/whatsapp-api-message-status-webhook\\\/\"},\"wordCount\":1361,\"articleSection\":[\"Blog\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/en\\\/whatsapp-api-message-status-webhook\\\/\",\"url\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/en\\\/whatsapp-api-message-status-webhook\\\/\",\"name\":\"WhatsApp API message status via webhook | Vectalk\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#website\"},\"datePublished\":\"2026-10-25T13:05:25+00:00\",\"dateModified\":\"2026-10-25T13:05:28+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#\\\/schema\\\/person\\\/ff36ecd9d8257856f227f8e5d639db2b\"},\"description\":\"WhatsApp API message status explained: what sent, delivered, read, played and failed mean, webhook payloads, errors, pricing and how to store them safely.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/en\\\/whatsapp-api-message-status-webhook\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/en\\\/whatsapp-api-message-status-webhook\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/en\\\/whatsapp-api-message-status-webhook\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Message status in the WhatsApp Business API: sent, delivered, read and failed via webhook\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/\",\"name\":\"Blog Vectalk\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/vectalk.com.br\\\/blog\\\/#\\\/schema\\\/person\\\/ff36ecd9d8257856f227f8e5d639db2b\",\"name\":\"wanderleyfcunha\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g\",\"caption\":\"wanderleyfcunha\"},\"sameAs\":[\"https:\\\/\\\/vectalk.com.br\\\/blog\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"WhatsApp API message status via webhook | Vectalk","description":"WhatsApp API message status explained: what sent, delivered, read, played and failed mean, webhook payloads, errors, pricing and how to store them safely.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/","og_locale":"en_US","og_type":"article","og_title":"WhatsApp API message status via webhook | Vectalk","og_description":"WhatsApp API message status explained: what sent, delivered, read, played and failed mean, webhook payloads, errors, pricing and how to store them safely.","og_url":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/","og_site_name":"Blog Vectalk","article_published_time":"2026-10-25T13:05:25+00:00","article_modified_time":"2026-10-25T13:05:28+00:00","author":"wanderleyfcunha","twitter_card":"summary_large_image","twitter_misc":{"Written by":"wanderleyfcunha","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/#article","isPartOf":{"@id":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/"},"author":{"name":"wanderleyfcunha","@id":"https:\/\/vectalk.com.br\/blog\/#\/schema\/person\/ff36ecd9d8257856f227f8e5d639db2b"},"headline":"Message status in the WhatsApp Business API: sent, delivered, read and failed via webhook","datePublished":"2026-10-25T13:05:25+00:00","dateModified":"2026-10-25T13:05:28+00:00","mainEntityOfPage":{"@id":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/"},"wordCount":1361,"articleSection":["Blog"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/","url":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/","name":"WhatsApp API message status via webhook | Vectalk","isPartOf":{"@id":"https:\/\/vectalk.com.br\/blog\/#website"},"datePublished":"2026-10-25T13:05:25+00:00","dateModified":"2026-10-25T13:05:28+00:00","author":{"@id":"https:\/\/vectalk.com.br\/blog\/#\/schema\/person\/ff36ecd9d8257856f227f8e5d639db2b"},"description":"WhatsApp API message status explained: what sent, delivered, read, played and failed mean, webhook payloads, errors, pricing and how to store them safely.","breadcrumb":{"@id":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/vectalk.com.br\/blog\/en\/whatsapp-api-message-status-webhook\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/vectalk.com.br\/blog\/"},{"@type":"ListItem","position":2,"name":"Message status in the WhatsApp Business API: sent, delivered, read and failed via webhook"}]},{"@type":"WebSite","@id":"https:\/\/vectalk.com.br\/blog\/#website","url":"https:\/\/vectalk.com.br\/blog\/","name":"Blog Vectalk","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/vectalk.com.br\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/vectalk.com.br\/blog\/#\/schema\/person\/ff36ecd9d8257856f227f8e5d639db2b","name":"wanderleyfcunha","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/21c37077f1731eb558973f27a7b647d55f72fde5200a843ac5f5345b247ea725?s=96&d=mm&r=g","caption":"wanderleyfcunha"},"sameAs":["https:\/\/vectalk.com.br\/blog"]}]}},"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/posts\/285","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/comments?post=285"}],"version-history":[{"count":1,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/posts\/285\/revisions"}],"predecessor-version":[{"id":288,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/posts\/285\/revisions\/288"}],"wp:attachment":[{"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/media?parent=285"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/categories?post=285"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/vectalk.com.br\/blog\/wp-json\/wp\/v2\/tags?post=285"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}