{
  "openapi": "3.1.0",
  "info": {
    "title": "Wawp WhatsApp API",
    "description": "Advanced WhatsApp API for automation, messaging, and integrations. High-performance, scalable, and developer-friendly.",
    "version": "2.1.0",
    "contact": {
      "name": "Wawp Support",
      "url": "https://wawp.net",
      "email": "support@wawp.net"
    },
    "license": {
      "name": "Proprietary",
      "url": "https://wawp.net/terms"
    }
  },
  "servers": [
    {
      "url": "https://api.wawp.net",
      "description": "Production Server"
    }
  ],
  "components": {
    "securitySchemes": {
      "AccessToken": {
        "type": "apiKey",
        "in": "header",
        "name": "access-token"
      }
    },
    "schemas": {
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "status": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          },
          "error": {
            "type": "string"
          }
        }
      }
    }
  },
  "security": [
    {
      "AccessToken": []
    }
  ],
  "paths": {
    "/v2/session/create": {
      "post": {
        "operationId": "_v2_session_create_post",
        "summary": "Create Session",
        "description": "Provisions a fresh Wawp instance and returns metadata such as instance_id and session_name.\n\n### Developer Tips\n- **Metadata Storage**: Always store the 'server_name' alongside the 'instance_id'. It helps our support team resolve issues faster.\n- **Quota Limits**: If you receive a 'quota_reached' error, you must either delete an unused instance or upgrade your plan.\n\n\n# Provisioning Your Digital Infrastructure: The Create Session Endpoint\n\nThe `/v2/session/create` endpoint is the specialized \"Factory\" for Wawp instances. While it may seem like a simple registration step, it handles a sophisticated backend process of resource allocation, container provisioning, and server assignment. Understanding how to use this factory efficiently is the foundation of a scalable WhatsApp integration.\n\n---\n\n## 🛠️ The Provisioning Architecture\n\nWhen you call `create`, Wawp does not just create a record in a database; it orchestrates the following:\n1. **Node Selection**: Our balancer identifies the high-performance node with the lowest latency and highest availability for your region.\n2. **Instance Isolation**: A dedicated, isolated environment is carved out for your session, ensuring that your data and encryption keys never mingle with other users.\n3. **Identifier Assignment**: You are issued a unique `instance_id`, which serves as your permanent handle for all future interactions with that specific WhatsApp account.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. Data Integrity and Persistence\nAlways save the returned `instance_id` and `server_name` in your local database immediately. \n- **The \"Context Store\"**: Associate this ID with your internal User IDs or Business IDs. \n- **Troubleshooting**: If you ever need to contact support, providing the `server_name` allows our engineers to pinpoint the exact infrastructure node hosting your session, reducing resolution time from hours to minutes.\n\n### 2. Idempotency and Deduplication\nBefore calling `create`, always check your own system state. \n- **The Trap**: Re-creating instances every time a user refreshes their settings page will quickly exhaust your quota.\n- **The Solution**: Implement a \"Check-then-Create\" logic. Only call this endpoint if your database shows that the user has no existing `instance_id` or if they have explicitly requested to \"Delete and Start New.\"\n\n### 3. \"Lazy\" Provisioning\nDon't create sessions in bulk. Provision an instance only when a user is actively \"Onboarding.\" This maintains a clean environment and ensures that your allocated resources are being used by active, paying, or engaged customers.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Customer Relationship Management (CRM)\nAutomatically provision a unique WhatsApp instance for every new high-value account. This allows your sales team to have dedicated communication channels that are fully logged and auditable within your CRM.\n\n### B. Automated Appointment Reminders\nFor medical or service industries, use this endpoint to spin up \"Notification Engines.\" By separating \"Notifications\" from \"Customer Support\" across different instances, you reduce the risk of account flagging and ensure high delivery rates.\n\n### C. Multi-Tenant SaaS Platforms\nIf you build software for other businesses, you can use this endpoint to offer \"WhatsApp-as-a-Service\" to your clients. Each of your clients gets their own `instance_id`, giving them a private, secure connection to their own customers.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### \"quota_reached\" (403 Forbidden)\nThis is the most common error for growing applications. It means you have used all the \"slots\" provided by your current plan.\n- **Fix**: Either upgrade your plan or use the [`/v2/session/delete`](/v2/session/delete) endpoint to remove stagnant or unused sessions.\n\n### \"missing_param\" (400 Bad Request)\nThe \"Factory\" cannot verify your identity without the `access_token`. \n- **Fix**: Ensure your token is included in the request body (POST). Double-check for trailing spaces or hidden characters if copying from a dashboard.\n\n---\n\n## 🚀 The Next Step: \"The Warm Boot\"\nCreating a session is like \"registering a car.\" You now have the keys, but the engine isn't running yet. Your newly created session will be in the **STOPPED** state. To actually start the authentication process and generate a QR code, you **must** call the [`/v2/session/start`](/v2/session/start) endpoint immediately after success.\n    ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "201": {
            "description": "Success - Session Created",
            "content": {
              "application/json": {
                "example": {
                  "instance_id": "3EB0BCB2E3D4",
                  "session_name": "wawp-84729105",
                  "status": "STARTING",
                  "server_name": "wawp-api-prod-50",
                  "config": {}
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Missing Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "missing_param",
                  "message": "Missing required parameter: access_token",
                  "details": {
                    "missing": [
                      "access_token"
                    ],
                    "recommendation": "Ensure you are sending the 'access_token' in your request."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "403": {
            "description": "Forbidden - Quota or Limit Reached",
            "content": {
              "application/json": {
                "example": {
                  "code": "quota_reached",
                  "message": "You have reached your maximum instances limit.",
                  "details": {
                    "recommendation": "Upgrade your plan or delete unused instances to create new ones."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/session/start": {
      "post": {
        "operationId": "_v2_session_start_post",
        "summary": "Start Session",
        "description": "Boots up the WhatsApp engine for a specific instance. This is the trigger that transitions a session from 'STOPPED' to 'STARTING'.\n\n### Developer Tips\n- **Async Operation**: This endpoint returns 'STARTING' immediately. The actual connection happens asynchronously in the background.\n\n\n# Starting the Engine: The Deep Dive into /v2/session/start\n\nIf creating a session is like \"registering a car,\" then calling `/v2/session/start` is the act of \"turning the ignition.\" Without this step, your session is merely a passive record in our database, incapable of communicating with the WhatsApp network. This endpoint is the primary catalyst for the entire automation lifecycle.\n\n---\n\n## 🏗️ What Happens Technically During \"Start\"?\n\nWhen you trigger a start request, Wawp orchestrates several high-concurrency operations:\n1. **Container Awakening**: The isolated environment dedicated to your instance is powered on.\n2. **Library Initialization**: The underlying WhatsApp libraries (Baileys/WAWebJS) are loaded into memory and configured with your instance's specific security parameters.\n3. **Network Handshake**: The engine attempts to establish a secure WebSocket bridge between our high-performance nodes and WhatsApp's official servers.\n4. **Credential Fetching**: If previous authentication exists, the engine attempts to \"resume\" the session. If not, it transitions to a state where it can generate a fresh QR code.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. The \"State Check\" Prerequisite\nNever call `start` blindly. Always check the current status via [`/v2/session/info`](/v2/session/info) first.\n- **The Ideal Condition**: Only call `start` if the status is **STOPPED**.\n- **The Risk**: Calling `start` on a session that is already **WORKING** can cause a protocol conflict, potentially leading to a temporary disconnection or a \"Session conflict\" notice on the user's mobile device.\n\n### 2. Handling the \"Async\" Nature\nThe `start` command is non-blocking. It will return a success response (200 OK) almost immediately, but the engine may still be \"warming up\" for several seconds.\n- **Developer Action**: Do not poll for a QR code immediately. Implement a 5-10 second \"settle time\" before your application starts aggressively checking for status changes.\n\n### 3. \"Warm Booting\" for Better UX\nIn a production dashboard, don't wait for the user to click \"Connect.\" \n- **The Optimization**: If you detect a user has logged into your CRM and their WhatsApp status is `STOPPED`, call `start` in the background. By the time they click on the WhatsApp integration tab, the engine will be ready to display a QR code, making the experience feel instantaneous.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Automated Re-connection Workers\nBuild a background \"Watcher\" service that runs every hour. If it finds a session that should be online (e.g., a \"Gold Tier\" customer) but has a status of **STOPPED**, it should trigger a `start` command automatically.\n\n### B. \"Morning Boot\" Scheduling\nIf your business only operates during specific hours, you can call [`/v2/session/stop`](/v2/session/stop) at night to save system resources and call `start` 30 minutes before your agents start their shift.\n\n---\n\n## ⚠️ Common Errors and Troubleshooting\n\n### \"Instance Not Found\" (404 Not Found)\nThis occurs if the `instance_id` provided is incorrect or has been permanently deleted from our servers. Double-check your database persistence layer.\n\n### Stuck in \"STARTING\"\nOn very rare occasions, a session may hang in the \"STARTING\" state due to a network timeout at the WhatsApp bridge level.\n- **Fix**: If the status remains `STARTING` for more than 45 seconds, we recommend calling the [`/v2/session/restart`](/v2/session/restart) endpoint to force a clean environment reset.\n\n---\n\n## Summary of Responsibilities:\n- Power on the isolated WhatsApp engine.\n- Initiate the connection protocol with WhatsApp servers.\n- Transition the instance state from **STOPPED** to **STARTING** or **WORKING**.\n- Prepare the environment for QR code or Pairing code generation.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_session_start_get",
        "summary": "Start Session",
        "description": "Boots up the WhatsApp engine for a specific instance. This is the trigger that transitions a session from 'STOPPED' to 'STARTING'.\n\n### Developer Tips\n- **Async Operation**: This endpoint returns 'STARTING' immediately. The actual connection happens asynchronously in the background.\n\n\n# Starting the Engine: The Deep Dive into /v2/session/start\n\nIf creating a session is like \"registering a car,\" then calling `/v2/session/start` is the act of \"turning the ignition.\" Without this step, your session is merely a passive record in our database, incapable of communicating with the WhatsApp network. This endpoint is the primary catalyst for the entire automation lifecycle.\n\n---\n\n## 🏗️ What Happens Technically During \"Start\"?\n\nWhen you trigger a start request, Wawp orchestrates several high-concurrency operations:\n1. **Container Awakening**: The isolated environment dedicated to your instance is powered on.\n2. **Library Initialization**: The underlying WhatsApp libraries (Baileys/WAWebJS) are loaded into memory and configured with your instance's specific security parameters.\n3. **Network Handshake**: The engine attempts to establish a secure WebSocket bridge between our high-performance nodes and WhatsApp's official servers.\n4. **Credential Fetching**: If previous authentication exists, the engine attempts to \"resume\" the session. If not, it transitions to a state where it can generate a fresh QR code.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. The \"State Check\" Prerequisite\nNever call `start` blindly. Always check the current status via [`/v2/session/info`](/v2/session/info) first.\n- **The Ideal Condition**: Only call `start` if the status is **STOPPED**.\n- **The Risk**: Calling `start` on a session that is already **WORKING** can cause a protocol conflict, potentially leading to a temporary disconnection or a \"Session conflict\" notice on the user's mobile device.\n\n### 2. Handling the \"Async\" Nature\nThe `start` command is non-blocking. It will return a success response (200 OK) almost immediately, but the engine may still be \"warming up\" for several seconds.\n- **Developer Action**: Do not poll for a QR code immediately. Implement a 5-10 second \"settle time\" before your application starts aggressively checking for status changes.\n\n### 3. \"Warm Booting\" for Better UX\nIn a production dashboard, don't wait for the user to click \"Connect.\" \n- **The Optimization**: If you detect a user has logged into your CRM and their WhatsApp status is `STOPPED`, call `start` in the background. By the time they click on the WhatsApp integration tab, the engine will be ready to display a QR code, making the experience feel instantaneous.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Automated Re-connection Workers\nBuild a background \"Watcher\" service that runs every hour. If it finds a session that should be online (e.g., a \"Gold Tier\" customer) but has a status of **STOPPED**, it should trigger a `start` command automatically.\n\n### B. \"Morning Boot\" Scheduling\nIf your business only operates during specific hours, you can call [`/v2/session/stop`](/v2/session/stop) at night to save system resources and call `start` 30 minutes before your agents start their shift.\n\n---\n\n## ⚠️ Common Errors and Troubleshooting\n\n### \"Instance Not Found\" (404 Not Found)\nThis occurs if the `instance_id` provided is incorrect or has been permanently deleted from our servers. Double-check your database persistence layer.\n\n### Stuck in \"STARTING\"\nOn very rare occasions, a session may hang in the \"STARTING\" state due to a network timeout at the WhatsApp bridge level.\n- **Fix**: If the status remains `STARTING` for more than 45 seconds, we recommend calling the [`/v2/session/restart`](/v2/session/restart) endpoint to force a clean environment reset.\n\n---\n\n## Summary of Responsibilities:\n- Power on the isolated WhatsApp engine.\n- Initiate the connection protocol with WhatsApp servers.\n- Transition the instance state from **STOPPED** to **STARTING** or **WORKING**.\n- Prepare the environment for QR code or Pairing code generation.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/session/stop": {
      "post": {
        "operationId": "_v2_session_stop_post",
        "summary": "Stop Session",
        "description": "Gracefully shuts down the WhatsApp engine for an instance without logging it out. Used to save resources or restart a stuck session.\n\n### Developer Tips\n- **Data Persistence**: Stopping a session DOES NOT delete your authentication data. You can restart it anytime without re-scanning the QR code.\n\n\n# Controlled Hibernation: The Power of the /v2/session/stop Endpoint\n\nThe `/v2/session/stop` endpoint is the specialized \"Pause\" button for your WhatsApp instance. Unlike a deletion, which wipes the slate clean, a \"Stop\" command puts your engine into a state of **Controlled Hibernation**. It preserves your authentication data and settings while releasing the underlying compute resources on our high-performance infrastructure.\n\n---\n\n## 🏗️ The Technical Lifecycle of a Stopped Session\n\nWhen you initiate a stop command, Wawp executes a series of clean-up operations:\n1. **Queue Flushing**: The engine attempts to finalize any outbound transmission tasks currently in the buffer.\n2. **Library Shutdown**: The WhatsApp-bridge process is signaled to disconnect and save its internal state.\n3. **Container Freezing**: The isolated environment is paused, meaning it consumes 0% CPU and RAM on our nodes, allowing us to maintain a more efficient and cost-effective ecosystem for you.\n4. **Data Persistence**: Crucially, your **Session Keys** and **Encryption Secrets** are kept in secure persistent storage. This ensures that when you restart, no fresh QR scan is required.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. Resource Optimization\nIf you are a SaaS provider with thousands of instances, leaving every session running 24/7 is inefficient. \n- **The Idle-Shutdown Strategy**: Monitor your sessions. If a user has been inactive for 72 hours, call `/v2/session/stop`. This keeps your billing predictable and your dashboard organized.\n\n### 2. The \"Clean Reboot\" Sequence\nSometimes, the underlying WhatsApp WebSocket can become \"de-synced\" from the mobile device. \n- **The Fix**: Instead of calling `/v2/session/logout`, try a sequence of [`stop`](/v2/session/stop) followed by [`start`](/v2/session/start). This forces the engine to reload its libraries and establish a fresh connection to the WhatsApp servers, often resolving transient issues.\n\n### 3. Webhook Awareness\nRemember that a **STOPPED** session is effectively \"offline.\" \n- **The Warning**: You will not receive any `message` or `status` webhooks while an instance is stopped. WhatsApp's servers will buffer incoming messages for a limited time (usually 24-72 hours), but prolonged hibernation may lead to message loss once their internal TTL (Time-To-Live) expires.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Nightly Maintenance\nFor businesses that operate only during local business hours (e.g., a support desk open 9 AM - 5 PM), you can schedule a script to stop all support instances at 6 PM. This provides a clear \"Offline\" signal to anyone trying to message the business outside of hours.\n\n### B. Scalability Management\nIn a multi-agent environment, where agents log in and out throughout the day, use this endpoint to stop an agent's dedicated instance when they clock out. This ensures that no automated replies or background processes are running while the human agent is away.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### \"Instance Not Found\" (404)\nThis error occurs if the session was deleted before the stop command was issued. Ensure your front-end logic respects the sequence of operations.\n\n### Delay in Restarting\nAfter calling `stop`, we recommend waiting at least 3 seconds before calling [`start`](/v2/session/start) again. This gives our cloud orchestrator enough time to fully decommission the previous container before Spinning up a new one.\n\n---\n\n## Summary of Capabilities:\n- Gracefully disconnect from WhatsApp servers.\n- Preserve all authentication and QR scan data for future use.\n- Optimize infrastructure resource consumption.\n- Provide a \"Pause\" state for maintenance or off-peak hours.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_session_stop_get",
        "summary": "Stop Session",
        "description": "Gracefully shuts down the WhatsApp engine for an instance without logging it out. Used to save resources or restart a stuck session.\n\n### Developer Tips\n- **Data Persistence**: Stopping a session DOES NOT delete your authentication data. You can restart it anytime without re-scanning the QR code.\n\n\n# Controlled Hibernation: The Power of the /v2/session/stop Endpoint\n\nThe `/v2/session/stop` endpoint is the specialized \"Pause\" button for your WhatsApp instance. Unlike a deletion, which wipes the slate clean, a \"Stop\" command puts your engine into a state of **Controlled Hibernation**. It preserves your authentication data and settings while releasing the underlying compute resources on our high-performance infrastructure.\n\n---\n\n## 🏗️ The Technical Lifecycle of a Stopped Session\n\nWhen you initiate a stop command, Wawp executes a series of clean-up operations:\n1. **Queue Flushing**: The engine attempts to finalize any outbound transmission tasks currently in the buffer.\n2. **Library Shutdown**: The WhatsApp-bridge process is signaled to disconnect and save its internal state.\n3. **Container Freezing**: The isolated environment is paused, meaning it consumes 0% CPU and RAM on our nodes, allowing us to maintain a more efficient and cost-effective ecosystem for you.\n4. **Data Persistence**: Crucially, your **Session Keys** and **Encryption Secrets** are kept in secure persistent storage. This ensures that when you restart, no fresh QR scan is required.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. Resource Optimization\nIf you are a SaaS provider with thousands of instances, leaving every session running 24/7 is inefficient. \n- **The Idle-Shutdown Strategy**: Monitor your sessions. If a user has been inactive for 72 hours, call `/v2/session/stop`. This keeps your billing predictable and your dashboard organized.\n\n### 2. The \"Clean Reboot\" Sequence\nSometimes, the underlying WhatsApp WebSocket can become \"de-synced\" from the mobile device. \n- **The Fix**: Instead of calling `/v2/session/logout`, try a sequence of [`stop`](/v2/session/stop) followed by [`start`](/v2/session/start). This forces the engine to reload its libraries and establish a fresh connection to the WhatsApp servers, often resolving transient issues.\n\n### 3. Webhook Awareness\nRemember that a **STOPPED** session is effectively \"offline.\" \n- **The Warning**: You will not receive any `message` or `status` webhooks while an instance is stopped. WhatsApp's servers will buffer incoming messages for a limited time (usually 24-72 hours), but prolonged hibernation may lead to message loss once their internal TTL (Time-To-Live) expires.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Nightly Maintenance\nFor businesses that operate only during local business hours (e.g., a support desk open 9 AM - 5 PM), you can schedule a script to stop all support instances at 6 PM. This provides a clear \"Offline\" signal to anyone trying to message the business outside of hours.\n\n### B. Scalability Management\nIn a multi-agent environment, where agents log in and out throughout the day, use this endpoint to stop an agent's dedicated instance when they clock out. This ensures that no automated replies or background processes are running while the human agent is away.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### \"Instance Not Found\" (404)\nThis error occurs if the session was deleted before the stop command was issued. Ensure your front-end logic respects the sequence of operations.\n\n### Delay in Restarting\nAfter calling `stop`, we recommend waiting at least 3 seconds before calling [`start`](/v2/session/start) again. This gives our cloud orchestrator enough time to fully decommission the previous container before Spinning up a new one.\n\n---\n\n## Summary of Capabilities:\n- Gracefully disconnect from WhatsApp servers.\n- Preserve all authentication and QR scan data for future use.\n- Optimize infrastructure resource consumption.\n- Provide a \"Pause\" state for maintenance or off-peak hours.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/session/restart": {
      "post": {
        "operationId": "_v2_session_restart_post",
        "summary": "Restart Session",
        "description": "Reboots the WhatsApp instance. Useful for fixing stuck sessions or applying settings.\n\n### Developer Tips\n- **Zero Data Loss**: Restarting is safe. It does not delete your session data or log you out.\n\n\n# The Self-Healing Mechanism: Mastering the /v2/session/restart Endpoint\n\nThe `/v2/session/restart` endpoint is the specialized \"Soft Reboot\" tool for your WhatsApp instance. In the complex world of WhatsApp automation—where network jitter, WebSocket timeouts, and engine de-syncs are common—a well-implemented restart strategy is the difference between a fragile integration and a production-grade communication system.\n\n---\n\n## 🏗️ The Anatomy of a Restart Orchestration\n\nWhen you call `restart`, Wawp performs an atomic \"Stop and Start\" sequence within our cloud infrastructure:\n1. **Engine Shutdown**: The active WhatsApp-bridge process is signaled to close its connections cleanly and save its current authentication state to persistent storage.\n2. **Environment Flush**: The temporary caches and buffer memory of the isolated container are cleared to resolve any memory leaks or hanging processes.\n3. **Engine Boot**: A fresh bridge process is launched using the previously saved authentication keys.\n4. **Resumption**: The engine automatically attempts to re-establish the encrypted handshake with WhatsApp's servers.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. The \"Auto-Healing\" Pattern\nDon't wait for a human to notice a problem. Your application should monitor the delivery status of outbound messages.\n- **The Recovery Flow**: If you detect three consecutive \"Message Failed\" errors or if the [`/v2/session/info`](/v2/session/info) endpoint shows a status of `FAILED`, trigger a `/v2/session/restart` automatically. A single restart resolves approximately 85% of transient connection issues.\n\n### 2. The 30-Second Stabilization Window\nWhile the API returns a success message (200 OK) almost instantly, the internal handshake takes time.\n- **Developer Action**: Implement a \"Quiet Period\" after a restart. We recommend waiting at least 30 seconds before resuming high-frequency automated message campaigns. This allows the engine to fully synchronize the message history and stabilize the WebSocket connection.\n\n### 3. Avoiding the \"Restart Loop\"\nA common mistake is restarting an instance every few seconds if it's not working.\n- **The Limit**: If a restart doesn't transition the session to `WORKING` within 60 seconds, do not restart again immediately. Instead, check the [`/v2/session/info`](/v2/session/info) response. If it shows **SCAN_QR_CODE**, it means the user has been logged out from the mobile app, and no amount of restarting will fix it—they must scan the QR code again.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Maintenance \"Pulse\"\nFor mission-critical bots (e.g., 24/7 bank alert systems), schedule a weekly restart during low-traffic windows (e.g., Sunday at 3 AM). This ensures the engine is always running on fresh resources and clears any long-term memory accumulation.\n\n### B. Post-Update Synchronization\nIf you update high-level instance configurations (like changing your Webhook URL or adding a new proxy), a `restart` is the cleanest way to ensure all underlying library settings are refreshed and applied across the environment.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### Interruption of Active Queues\nRestarting acts as a \"hard stop\" for the internal message queue. If you have 500 messages currently being processed for delivery, they will be purged from the transient buffer. Ensure your campaign logic can handle \"Resuming\" from where it left off by tracking message IDs in your own database.\n\n### Stuck in \"STARTING\" post-restart\nThis is usually caused by a conflict with the previous process. Wait 15 seconds and try one more restart. If the issue persists, use the [`/v2/session/stop`](/v2/session/stop) command, wait 5 seconds, and then call [`/v2/session/start`](/v2/session/start) for a full lifecycle reset.\n\n---\n\n## Summary of Capabilities:\n- Perform an atomic reboot of the isolated engine.\n- Resolve 85% of transient connectivity and de-sync issues.\n- Preserve all session data and QR scan history.\n- Refresh container resources without requiring user interaction.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_session_restart_get",
        "summary": "Restart Session",
        "description": "Reboots the WhatsApp instance. Useful for fixing stuck sessions or applying settings.\n\n### Developer Tips\n- **Zero Data Loss**: Restarting is safe. It does not delete your session data or log you out.\n\n\n# The Self-Healing Mechanism: Mastering the /v2/session/restart Endpoint\n\nThe `/v2/session/restart` endpoint is the specialized \"Soft Reboot\" tool for your WhatsApp instance. In the complex world of WhatsApp automation—where network jitter, WebSocket timeouts, and engine de-syncs are common—a well-implemented restart strategy is the difference between a fragile integration and a production-grade communication system.\n\n---\n\n## 🏗️ The Anatomy of a Restart Orchestration\n\nWhen you call `restart`, Wawp performs an atomic \"Stop and Start\" sequence within our cloud infrastructure:\n1. **Engine Shutdown**: The active WhatsApp-bridge process is signaled to close its connections cleanly and save its current authentication state to persistent storage.\n2. **Environment Flush**: The temporary caches and buffer memory of the isolated container are cleared to resolve any memory leaks or hanging processes.\n3. **Engine Boot**: A fresh bridge process is launched using the previously saved authentication keys.\n4. **Resumption**: The engine automatically attempts to re-establish the encrypted handshake with WhatsApp's servers.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. The \"Auto-Healing\" Pattern\nDon't wait for a human to notice a problem. Your application should monitor the delivery status of outbound messages.\n- **The Recovery Flow**: If you detect three consecutive \"Message Failed\" errors or if the [`/v2/session/info`](/v2/session/info) endpoint shows a status of `FAILED`, trigger a `/v2/session/restart` automatically. A single restart resolves approximately 85% of transient connection issues.\n\n### 2. The 30-Second Stabilization Window\nWhile the API returns a success message (200 OK) almost instantly, the internal handshake takes time.\n- **Developer Action**: Implement a \"Quiet Period\" after a restart. We recommend waiting at least 30 seconds before resuming high-frequency automated message campaigns. This allows the engine to fully synchronize the message history and stabilize the WebSocket connection.\n\n### 3. Avoiding the \"Restart Loop\"\nA common mistake is restarting an instance every few seconds if it's not working.\n- **The Limit**: If a restart doesn't transition the session to `WORKING` within 60 seconds, do not restart again immediately. Instead, check the [`/v2/session/info`](/v2/session/info) response. If it shows **SCAN_QR_CODE**, it means the user has been logged out from the mobile app, and no amount of restarting will fix it—they must scan the QR code again.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Maintenance \"Pulse\"\nFor mission-critical bots (e.g., 24/7 bank alert systems), schedule a weekly restart during low-traffic windows (e.g., Sunday at 3 AM). This ensures the engine is always running on fresh resources and clears any long-term memory accumulation.\n\n### B. Post-Update Synchronization\nIf you update high-level instance configurations (like changing your Webhook URL or adding a new proxy), a `restart` is the cleanest way to ensure all underlying library settings are refreshed and applied across the environment.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### Interruption of Active Queues\nRestarting acts as a \"hard stop\" for the internal message queue. If you have 500 messages currently being processed for delivery, they will be purged from the transient buffer. Ensure your campaign logic can handle \"Resuming\" from where it left off by tracking message IDs in your own database.\n\n### Stuck in \"STARTING\" post-restart\nThis is usually caused by a conflict with the previous process. Wait 15 seconds and try one more restart. If the issue persists, use the [`/v2/session/stop`](/v2/session/stop) command, wait 5 seconds, and then call [`/v2/session/start`](/v2/session/start) for a full lifecycle reset.\n\n---\n\n## Summary of Capabilities:\n- Perform an atomic reboot of the isolated engine.\n- Resolve 85% of transient connectivity and de-sync issues.\n- Preserve all session data and QR scan history.\n- Refresh container resources without requiring user interaction.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/session/logout": {
      "post": {
        "operationId": "_v2_session_logout_post",
        "summary": "Logout Session",
        "description": "Logs the instance out of WhatsApp. This removes the paired device link but keeps the instance alive in a 'SCAN_QR_CODE' state.\n\n### Developer Tips\n- **Re-Pairing**: After logout, the instance ID remains valid. You do not need to create a new session.\n\n\n# Starting Fresh: The Deep Dive into /v2/session/logout\n\nThe `/v2/session/logout` endpoint is a critical component of session lifecycle management. It is not merely a \"disconnect\" button; it is a specialized command that communicates directly with WhatsApp's official servers to signal a clean **Unpairing** (Unlinking) of the device. Mastering this endpoint is the key to building secure, multi-account, and user-friendly automation platforms.\n\n---\n\n## 🏗️ The Technical Orchestration of a Logout\n\nWhen you trigger a logout, Wawp executes a series of coordinated steps across our infrastructure:\n1. **Unlink Signal**: The engine sends a specific \"Unpair\" message to the WhatsApp WebSocket. This ensures that the device is instantly removed from the \"Linked Devices\" list on the user's mobile phone.\n2. **State Purge**: The isolated container wipes the current encryption keys and session tokens from its active memory, ensuring no unauthorized access can persist.\n3. **Transition to Scan**: The instance is **not** deleted. Instead, it transitions immediately from **WORKING** to **SCAN_QR_CODE**, effectively returning the session to \"Square One\" and making it ready for a fresh link.\n4. **Configuration Retention**: Importantly, all your instance-level settings (like Webhook URLs or Proxy configurations) remain intact. Only the WhatsApp identity is removed.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. The \"Account Switching\" Pattern\nLogout is the correct way to handle situations where a user wants to change the WhatsApp number associated with an instance.\n- **The Workflow**: Do not delete the instance and create a new one. Simply call `logout`. This preserves the `instance_id` and the API endpoint structure in your own backend while allowing the user to scan a different phone.\n\n### 2. Security and Data Privacy\nIn any SaaS platform, security is paramount.\n- **The Best Practice**: Encourage your users to use the \"Log Out\" button whenever they are performing a security audit or decommissioning a specific employee's dashboard access. This provides them with peace of mind that the link has been truly severed at the protocol level.\n\n### 3. Graceful Handling of Sudden Disconnects\nUsers can manually log out of your session directly from their mobile app's \"Linked Devices\" settings.\n- **The Strategy**: Your application should listen for the `DISCONNECTED` or `LOGOUT` event via our status webhooks. When this occurs, you should update your UI to show a \"Disconnected\" state and prompt the user to re-scan the QR code.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Team Rotation Dashboards\nIf you manage a business where different agents use the same WhatsApp number at different times of the day, you can use `logout` to ensure that a previous agent's session is completely terminated before the next agent takes over.\n\n### B. Self-Service Troubleshooting\nAdd a \"Reset Connection\" button in your user settings. Often, if a user experiences message delivery delays or sync issues, a clean `logout` and re-link will reset the internal WhatsApp state and solve the problem without requiring manual support intervention.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### Sync Latency\nOccasionally, the WhatsApp mobile app might continue to show the \"Linked Device\" as active for a few seconds after the API call. This is due to internal WhatsApp sync latency. Rest assured, the API has severed the link, and the phone's UI will eventually catch up.\n\n### Calling Logout on a Stopped Session\nYou cannot execute a clean protocol logout if the engine is **STOPPED**.\n- **Fix**: The engine must be in a **STARTING** or **WORKING** state to communicate the logout signal to WhatsApp. If the session is stopped, you must call [`/v2/session/start`](/v2/session/start) first, or simply perform a [`/v2/session/delete`](/v2/session/delete) if you wish to wipe everything.\n\n---\n\n## Summary of Capabilities:\n- Sever the secure link with the WhatsApp mobile app.\n- Transition the instance to a state ready for a fresh QR scan.\n- Ensure data privacy by purging encryption keys from memory.\n- Provide a clean \"Start Over\" mechanism without losing instance configurations.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The ID of the instance to logout",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_session_logout_get",
        "summary": "Logout Session",
        "description": "Logs the instance out of WhatsApp. This removes the paired device link but keeps the instance alive in a 'SCAN_QR_CODE' state.\n\n### Developer Tips\n- **Re-Pairing**: After logout, the instance ID remains valid. You do not need to create a new session.\n\n\n# Starting Fresh: The Deep Dive into /v2/session/logout\n\nThe `/v2/session/logout` endpoint is a critical component of session lifecycle management. It is not merely a \"disconnect\" button; it is a specialized command that communicates directly with WhatsApp's official servers to signal a clean **Unpairing** (Unlinking) of the device. Mastering this endpoint is the key to building secure, multi-account, and user-friendly automation platforms.\n\n---\n\n## 🏗️ The Technical Orchestration of a Logout\n\nWhen you trigger a logout, Wawp executes a series of coordinated steps across our infrastructure:\n1. **Unlink Signal**: The engine sends a specific \"Unpair\" message to the WhatsApp WebSocket. This ensures that the device is instantly removed from the \"Linked Devices\" list on the user's mobile phone.\n2. **State Purge**: The isolated container wipes the current encryption keys and session tokens from its active memory, ensuring no unauthorized access can persist.\n3. **Transition to Scan**: The instance is **not** deleted. Instead, it transitions immediately from **WORKING** to **SCAN_QR_CODE**, effectively returning the session to \"Square One\" and making it ready for a fresh link.\n4. **Configuration Retention**: Importantly, all your instance-level settings (like Webhook URLs or Proxy configurations) remain intact. Only the WhatsApp identity is removed.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. The \"Account Switching\" Pattern\nLogout is the correct way to handle situations where a user wants to change the WhatsApp number associated with an instance.\n- **The Workflow**: Do not delete the instance and create a new one. Simply call `logout`. This preserves the `instance_id` and the API endpoint structure in your own backend while allowing the user to scan a different phone.\n\n### 2. Security and Data Privacy\nIn any SaaS platform, security is paramount.\n- **The Best Practice**: Encourage your users to use the \"Log Out\" button whenever they are performing a security audit or decommissioning a specific employee's dashboard access. This provides them with peace of mind that the link has been truly severed at the protocol level.\n\n### 3. Graceful Handling of Sudden Disconnects\nUsers can manually log out of your session directly from their mobile app's \"Linked Devices\" settings.\n- **The Strategy**: Your application should listen for the `DISCONNECTED` or `LOGOUT` event via our status webhooks. When this occurs, you should update your UI to show a \"Disconnected\" state and prompt the user to re-scan the QR code.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Team Rotation Dashboards\nIf you manage a business where different agents use the same WhatsApp number at different times of the day, you can use `logout` to ensure that a previous agent's session is completely terminated before the next agent takes over.\n\n### B. Self-Service Troubleshooting\nAdd a \"Reset Connection\" button in your user settings. Often, if a user experiences message delivery delays or sync issues, a clean `logout` and re-link will reset the internal WhatsApp state and solve the problem without requiring manual support intervention.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### Sync Latency\nOccasionally, the WhatsApp mobile app might continue to show the \"Linked Device\" as active for a few seconds after the API call. This is due to internal WhatsApp sync latency. Rest assured, the API has severed the link, and the phone's UI will eventually catch up.\n\n### Calling Logout on a Stopped Session\nYou cannot execute a clean protocol logout if the engine is **STOPPED**.\n- **Fix**: The engine must be in a **STARTING** or **WORKING** state to communicate the logout signal to WhatsApp. If the session is stopped, you must call [`/v2/session/start`](/v2/session/start) first, or simply perform a [`/v2/session/delete`](/v2/session/delete) if you wish to wipe everything.\n\n---\n\n## Summary of Capabilities:\n- Sever the secure link with the WhatsApp mobile app.\n- Transition the instance to a state ready for a fresh QR scan.\n- Ensure data privacy by purging encryption keys from memory.\n- Provide a clean \"Start Over\" mechanism without losing instance configurations.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The ID of the instance to logout",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/session/delete": {
      "delete": {
        "operationId": "_v2_session_delete_delete",
        "summary": "Delete Session",
        "description": "Permanently deletes a WhatsApp session locally and from the server. This action is irreversible.\n\n### Developer Tips\n- **No Undo**: There is no 'trash bin'. Deleted sessions cannot be recovered.\n\n\n# The Point of No Return: Mastering the /v2/session/delete Endpoint\n\nThe `/v2/session/delete` endpoint is the most decisive action in our API suite. It is not merely a shutdown command; it is an instruction for the **Atomic Deconstruction** of the instance. It permanently removes the isolated environment, all associated session data, and the authentication credentials from our high-performance infrastructure.\n\n---\n\n## 🏗️ The Anatomy of a Clean Deletion\n\nWhen you trigger a deletion, Wawp orchestrates several high-concurrency cleanup tasks in milliseconds:\n1. **Container Termination**: The active engine process is signaled to shut down immediately.\n2. **Data Purge**: All transient files, message buffers, and encryption keys stored in the instance's isolated directory are wiped from our disks.\n3. **Resource Recovery**: The RAM and CPU overhead allocated to that session is instantly released and returned to the server pool, allowing for fresh allocations.\n4. **Credential Expiry**: The `instance_id` and `session_name` are decoupled from your account, and any future requests using those identifiers will result in a `404 Not Found` error.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. The \"Danger Zone\" UX\nBecause this action is permanent, it must be protected by significant UI guardrails.\n- **The Best Practice**: Never trigger a deletion from a single click. Implement a \"Danger Zone\" in your dashboard that requires the user to type \"DELETE\" or the instance ID to confirm their intent. This prevents catastrophic data loss from accidental clicks.\n\n### 2. The \"Logout First\" Recommendation\nWhile deletion severs the bridge, it doesn't always signal the mobile phone to \"Unpair\" if the engine is stopped.\n- **The Strategy**: For the most professional experience, call [`/v2/session/logout`](/v2/session/logout) before calling `delete`. This ensures that the device is cleanly removed from the \"Linked Devices\" list on the user's phone, preventing \"Ghost Device\" entries that can clutter the WhatsApp app UI.\n\n### 3. Subscription and Churn Lifecycle\nIntegrate this endpoint into your platform's subscription management.\n- **The Workflow**: If a user cancels their plan or fails to pay, your system should automatically call `/v2/session/delete` after a grace period. This ensures your instance quota remains available for active, paying customers.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Data Compliance (GDPR/SOC2)\nIf your application handles highly sensitive data, use the delete endpoint to ensure that once a customer interaction is finished, no residue of their session remains on our servers. This is a core part of building a \"Zero-Trust\" communication architecture.\n\n### B. Development and Testing\nDuring the development phase, you may frequently create and destroy instances while testing your integration. Using the delete endpoint allows you to keep your test environment clean and avoid hitting your plan's quota limits.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### \"Instance Not Found\" (404)\nThis occurs if the deletion has already been processed or if the ID provided is incorrect. In your backend, you should treat a 404 response to a delete request as a \"de-facto success,\" meaning the instance is indeed gone.\n\n### Is Recovery Possible?\n**No.** We prioritize data privacy and server efficiency. Once the delete command is executed, the encryption keys are purged from our secure persistent storage. There is no \"Trash Bin\" or \"Restore\" feature. Always ensure your internal database is updated to reflect that the session no longer exists.\n\n---\n\n## Summary of Capabilities:\n- Permanently decommission an isolated engine.\n- Purge all encryption keys and transient data for maximum privacy.\n- Free up instance slots within your Wawp plan quota.\n- Ensure a clean architectural slate for future provisioning.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance to delete",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/session/info": {
      "post": {
        "operationId": "_v2_session_info_post",
        "summary": "Session Info",
        "description": "Retrieve complete information about a WhatsApp session, including connection status, authenticated user info, and server details.\n\n### Developer Tips\n- **Real-time Updates**: This endpoint fetches data directly from the container. It is always the source of truth for connection status.\n\n\n# The Pulse of the Engine: Decoding the Session Info Endpoint\n\nThe `/v2/session/info` endpoint is the most critical monitoring tool in your Wawp toolkit. It serves as the \"Heartbeat\" of your instance, providing real-time data on connection health, authentication state, and identity metadata. Mastering this endpoint is the key to building responsive, self-healing applications.\n\n---\n\n## 🔍 The Anatomy of a Status Response\n\nThe `status` field in the response is the primary director for your front-end logic. Understanding each state is essential:\n\n### 1. **WORKING (Active)**\n✅ The engine is fully connected to WhatsApp's servers and authenticated.\n- **Developer Action**: You are clear to send messages, fetch contacts, or update profile settings. No restrictions apply.\n\n### 2. **SCAN_QR_CODE (Authentication Pending)**\n⚠️ The engine is running but lacks valid credentials.\n- **Developer Action**: This is the **only** time the `qr` field in the response will contain a Base64 string. Display this QR code to the user immediately.\n- **Pro Tip**: QR codes expire rapidly (approx. 20-40 seconds). You must refresh your UI whenever a new QR string is returned by this endpoint.\n\n### 3. **STARTING (Warming Up)**\n⏳ The dedicated engine is booting and preparing the secure bridge.\n- **Developer Action**: Show a \"Connecting...\" spinner. Prevent the user from attempting to send messages until the state transitions.\n\n### 4. **STOPPED (Hibernating)**\n🛑 The instance is dormant. No system resources are being consumed.\n- **Developer Action**: Call the [`/v2/session/start`](/v2/session/start) endpoint to wake the engine.\n\n---\n\n## 🏗️ Monitoring Architecture: Best Practices\n\n### The \"Intelligent Polling\" Strategy\nPolling is efficient if done correctly. We recommend the following orchestration for user-facing dashboards:\n1. **Initial Check**: When the user opens their dashboard, call `/session/info`.\n2. **The QR Loop**: If the status is `SCAN_QR_CODE`, poll every 3-5 seconds. This ensures the QR code on the screen is always \"fresh\" and detects the successful scan the moment it happens.\n3. **The Stop Condition**: Once the status transitions to `WORKING`, stop polling immediately to save network overhead and battery life on mobile clients.\n\n### Leveraging the \"Me\" Object\nWhen a session is **WORKING**, the `me` object provides essential identity metadata:\n- **pushName**: Use this to welcome the user (e.g., \"Welcome back, Sarah!\").\n- **platform**: Understand if the user is connected via a specific OS, which can help in tailoring support if they report sync issues.\n\n---\n\n## 🛡️ Reliability and Health Monitoring\n\n### Building a \"Health Check\" Cron\nFor mission-critical bots, run a background task every 15 minutes that calls `/session/info`. \n- **Auto-Recovery**: If a session that should be active returns `STOPPED` or `FAILED`, your system should automatically trigger a [`start`](/v2/session/start) or [`restart`](/v2/session/restart) call.\n- **Alerting**: If a session transitions to `SCAN_QR_CODE` unexpectedly, it means the user has logged out from their phone. Send them a push notification or email to re-link their account.\n\n---\n\n## Troubleshooting Guide\n\n### Why is the QR field empty?\nThe `qr` field is context-aware. It will only contain data when the `status` is explicitly **SCAN_QR_CODE**. In any other state (like `STARTING` or `WORKING`), the field will be `null` or omitted because a handshake is either not ready or no longer needed.\n\n### Latency in Status Updates\nWhile our engine is near real-time, there can be a 1-3 second delay as the WhatsApp handshake completes. If a session is stuck in `STARTING` for more than 60 seconds, it indicates a transient network failure. We recommend calling the [`/v2/session/restart`](/v2/session/restart) endpoint to clear the state.\n\n---\n\n## Summary of Capabilities:\n- Verify message-sending readiness.\n- Retrieve the latest QR or Pairing Code.\n- Identify the phone number and name of the connected account.\n- Monitor server-side resource allocation and engine health.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance to check",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/session/me": {
      "get": {
        "operationId": "_v2_session_me_get",
        "summary": "About WhatsApp Data",
        "description": "Retrieves the profile information of the WhatsApp account connected to this session.\n\n### Developer Tips\n- **Cached Data**: This information is fetched directly from the WhatsApp engine. If you just changed your profile picture or name, it might take a moment to reflect.\n\n\n# Mirror of Identity: The Deep Dive into /v2/session/me\n\nThe `/v2/session/me` endpoint is your direct window into the \"Digital Persona\" currently linked to your Wawp instance. While [`/v2/session/info`](/v2/session/info) tells you about the technical health of the engine, `me` provides the identity details of the actual WhatsApp account that was scanned. Mastering this endpoint is essential for building personalized dashboards and verifying user intentions.\n\n---\n\n## 🏗️ Anatomy of the Digital Identity\n\nWhen you call this endpoint, you receive a payload containing the following pivotal fields:\n\n### 1. **The WhatsApp ID (JID - `id`)**\nThis is the immutable, unique identifier for the account on the WhatsApp network (e.g., `15551234567@c.us`).\n- **Technical Importance**: Use this ID as the \"Primary Key\" in your database to link inbound and outbound messages to a specific business unit or agent.\n\n### 2. **The Push Name (Display Name)**\nThis is the public name configured by the user in their WhatsApp mobile settings.\n- **Developer Action**: Use this string to personalize your dashboard. Instead of showing \"Instance #482,\" you can show \"Connected as: **Global Sales Dept**.\" This significantly improves the user experience for your non-technical staff.\n\n### 3. **The Platform Identifier**\nIdentifies whether the connected device is running on `android`, `ios`, or a `web` client.\n- **Analytics Insight**: Understanding the distribution of hardware among your connected instances can help you optimize your support procedures and predict sync behaviors, as different OS platforms have slight variations in how they handle long-lived WebSocket connections.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. The \"Intent Verification\" Pattern\nIn enterprise environments, it's common for a staff member to accidentally scan a QR code with their personal WhatsApp instead of the corporate one.\n- **The Solution**: Immediately after a session hits the **WORKING** status, call `/v2/session/me`. Compare the returned JID with the expected phone number in your database. If they don't match, trigger an automated alert or call [`/v2/session/logout`](/v2/session/logout) to prevent data crossing.\n\n### 2. Intelligent Caching\nIdentity data (Name, ID, Platform) is relatively static and does not change often.\n- **The Optimization**: Do not call `/v2/session/me` every time you send a message. Instead, call it once during the \"Successful Connection\" event and store the result in your application's cache (Redis or local DB). Clear the cache only when you detect a `LOGOUT` or `DISCONNECTED` event via webhooks.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Dynamic Message Signatures\nIf you are running a multi-agent helpdesk where all agents share one Wawp instance, use `/v2/session/me` to verify the current \"Sender Identity\" and dynamically append a signature like \"Sent by: {{pushName}}\" to outbound texts.\n\n### B. Account Syncing Dashboards\nBuild a \"Profile Page\" in your SaaS that automatically pulls in the connected account's name and JID. This allows your customers to visually confirm which of their office numbers is currently active without checking their physical phones.\n\n---\n\n## ⚠️ Common Pitfalls and Troubleshooting\n\n### \"Session Not Connected\" (404/401)\nYou cannot fetch identity data if the engine is not in a **WORKING** state. The underlying WhatsApp libraries cannot \"see\" the identity until the secure handshake is complete.\n- **Fix**: Always verify the status via [`/v2/session/info`](/v2/session/info) before calling `me`.\n\n### Missing Push Name\nIn rare cases, if a user has never set a name in their WhatsApp settings, the field may be empty or `null`.\n- **Recommendation**: Implement a fallback in your code that uses the numeric portion of the JID if the `pushName` is missing.\n\n---\n\n## Summary of Capabilities:\n- Confirm the legal and technical identity of the connected account.\n- Personalize multi-tenant dashboards with user-specific names.\n- Analyze device platform distribution for technical optimizations.\n- Implement security guardrails to ensure only authorized numbers are linked.\n            ",
        "tags": [
          "Session Management"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/auth/qr": {
      "post": {
        "operationId": "_v2_auth_qr_post",
        "summary": "GET QR raw",
        "description": "Retrieves the raw QR payload as binary/base64 plus a mimetype.\n\n### Developer Tips\n- **Freshness**: This endpoint returns a non-cached response header to ensure you always get the latest QR code.\n- **Expiry**: The returned QR string has a short lifespan (20-60s). Use the 'expiry' timestamp to refresh it.\n\n\n# Deciphering the Protocol: The Raw QR Payload Guide\n\nThe `/v2/auth/qr` endpoint is the specialized \"Engine Access\" tool for developers who require surgical control over the authentication process. Unlike the image-based endpoint, which is optimized for quick rendering, this route provides the raw, Base64-encoded protocol string. This is essential for building custom QR generators, CLI-based tools, or native mobile implementations where binary data is preferred over a static image.\n\n---\n\n## 🏗️ Technical Breakdown: The JSON Envelope\n\nThe response from this endpoint is a JSON object containing two primary components:\n1. **mimetype**: Typically `application/json`, indicating that the payload is a structured data object.\n2. **data**: A Base64-encoded string. Once decoded, this string yields a JSON object containing the **Protocol Signature** required by the WhatsApp WebSocket.\n\n### The Decoded Payload Structure\nWhen you decode the `data` field, you will find:\n- **value**: The actual alphanumeric string that needs to be encoded into a QR pattern.\n- **expiry**: A Unix timestamp representing the exact millisecond when this specific QR code will be invalidated by the WhatsApp servers.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. Implementing a CLI-Based ASCII Renderer\nIf you are building a headless tool (like a VPS manager or a terminal-based bot), fetching the raw QR string allows you to render the code directly in the terminal using ASCII characters.\n- **Developer Action**: Use a library like `qrcode-terminal` in Node.js or `qrcode` in Python. Pass the `value` from the decoded response to the library to display the scanable pattern directly to your server administrators.\n\n### 2. Synchronization and Rate Limiting\nFetching the raw QR is a relatively resource-intensive task for the underlying engine as it involves a real-time probe of the browser state.\n- **The Polling Window**: We recommend a polling interval of **5-7 seconds**. Polling faster than this will not yield a \"fresher\" code (as WhatsApp only rotates codes every 20-30 seconds) and may lead to 429 Rate Limit responses from our infrastructure.\n\n### 3. Handling the Recovery Window (422 Status)\nIf the engine is busy resetting its internal WhatsApp bridge, you will receive a `422 Session Status Not Expected` error. \n- **The Fix**: This is not a failure; it’s a \"Please Wait\" signal. Your application should implement an exponential backoff. Wait 10 seconds, then 20 seconds, before attempting to fetch the QR again. This gives the engine time to finalize its background handshake.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Deep-Link Mobile Integration\nIf you are building a native iOS or Android app, you can fetch the raw QR string and use the mobile OS's native QR generation libraries (like CoreImage on iOS). This results in a much sharper, high-contrast QR code that is easier for the user's secondary device to scan compared to a compressed PNG image.\n\n### B. Security-Hardened Dashboards\nFor high-security environments where you do not want to load external images from our servers, you can fetch the raw string on your backend, verify its integrity, and then generate the QR pattern locally using your own internal corporate styling.\n\n---\n\n## ⚠️ Common Pitfalls\n\n- **Binary vs. String**: The `data` field is **Base64 encoded**. If you try to pass the raw Base64 string directly into a QR generator without decoding it first, the scan will fail because the data will be interpreted as a literal Base64 string rather than the underlying WhatsApp protocol ID.\n- **Expiry Ignorance**: Always check the `expiry` field. If your frontend displays a QR code that has already passed its expiry timestamp, the user will scan it only to see an \"Expired\" error on their phone, leading to significant UX frustration.\n\n---\n\n## Summary of Responsibilities:\n- Retrieve the raw cryptographic string required for a WhatsApp handshake.\n- Provide a Base64-wrapped JSON envelope for protocol compatibility.\n- Enable custom rendering in non-browser environments (CLI, Mobile).\n- Facilitate advanced monitoring of QR rotation cycles and expiration.\n            ",
        "tags": [
          "Authentication - Login"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output format (default: raw)",
            "schema": {
              "type": "string"
            },
            "example": "raw"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity - Session Status Mismatch",
            "content": {
              "application/json": {
                "example": {
                  "code": "session_unexpected_status",
                  "message": "Session status is not as expected for this operation. We are attempting to auto-recover.",
                  "details": {
                    "current_status": "FAILED",
                    "expected_status": [
                      "SCAN_QR_CODE"
                    ],
                    "action": "auto_restart_triggered",
                    "recommendation": "The instance encountered an error and is being restarted. Please wait a few seconds and try again."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_auth_qr_get",
        "summary": "GET QR raw",
        "description": "Retrieves the raw QR payload as binary/base64 plus a mimetype.\n\n### Developer Tips\n- **Freshness**: This endpoint returns a non-cached response header to ensure you always get the latest QR code.\n- **Expiry**: The returned QR string has a short lifespan (20-60s). Use the 'expiry' timestamp to refresh it.\n\n\n# Deciphering the Protocol: The Raw QR Payload Guide\n\nThe `/v2/auth/qr` endpoint is the specialized \"Engine Access\" tool for developers who require surgical control over the authentication process. Unlike the image-based endpoint, which is optimized for quick rendering, this route provides the raw, Base64-encoded protocol string. This is essential for building custom QR generators, CLI-based tools, or native mobile implementations where binary data is preferred over a static image.\n\n---\n\n## 🏗️ Technical Breakdown: The JSON Envelope\n\nThe response from this endpoint is a JSON object containing two primary components:\n1. **mimetype**: Typically `application/json`, indicating that the payload is a structured data object.\n2. **data**: A Base64-encoded string. Once decoded, this string yields a JSON object containing the **Protocol Signature** required by the WhatsApp WebSocket.\n\n### The Decoded Payload Structure\nWhen you decode the `data` field, you will find:\n- **value**: The actual alphanumeric string that needs to be encoded into a QR pattern.\n- **expiry**: A Unix timestamp representing the exact millisecond when this specific QR code will be invalidated by the WhatsApp servers.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. Implementing a CLI-Based ASCII Renderer\nIf you are building a headless tool (like a VPS manager or a terminal-based bot), fetching the raw QR string allows you to render the code directly in the terminal using ASCII characters.\n- **Developer Action**: Use a library like `qrcode-terminal` in Node.js or `qrcode` in Python. Pass the `value` from the decoded response to the library to display the scanable pattern directly to your server administrators.\n\n### 2. Synchronization and Rate Limiting\nFetching the raw QR is a relatively resource-intensive task for the underlying engine as it involves a real-time probe of the browser state.\n- **The Polling Window**: We recommend a polling interval of **5-7 seconds**. Polling faster than this will not yield a \"fresher\" code (as WhatsApp only rotates codes every 20-30 seconds) and may lead to 429 Rate Limit responses from our infrastructure.\n\n### 3. Handling the Recovery Window (422 Status)\nIf the engine is busy resetting its internal WhatsApp bridge, you will receive a `422 Session Status Not Expected` error. \n- **The Fix**: This is not a failure; it’s a \"Please Wait\" signal. Your application should implement an exponential backoff. Wait 10 seconds, then 20 seconds, before attempting to fetch the QR again. This gives the engine time to finalize its background handshake.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Deep-Link Mobile Integration\nIf you are building a native iOS or Android app, you can fetch the raw QR string and use the mobile OS's native QR generation libraries (like CoreImage on iOS). This results in a much sharper, high-contrast QR code that is easier for the user's secondary device to scan compared to a compressed PNG image.\n\n### B. Security-Hardened Dashboards\nFor high-security environments where you do not want to load external images from our servers, you can fetch the raw string on your backend, verify its integrity, and then generate the QR pattern locally using your own internal corporate styling.\n\n---\n\n## ⚠️ Common Pitfalls\n\n- **Binary vs. String**: The `data` field is **Base64 encoded**. If you try to pass the raw Base64 string directly into a QR generator without decoding it first, the scan will fail because the data will be interpreted as a literal Base64 string rather than the underlying WhatsApp protocol ID.\n- **Expiry Ignorance**: Always check the `expiry` field. If your frontend displays a QR code that has already passed its expiry timestamp, the user will scan it only to see an \"Expired\" error on their phone, leading to significant UX frustration.\n\n---\n\n## Summary of Responsibilities:\n- Retrieve the raw cryptographic string required for a WhatsApp handshake.\n- Provide a Base64-wrapped JSON envelope for protocol compatibility.\n- Enable custom rendering in non-browser environments (CLI, Mobile).\n- Facilitate advanced monitoring of QR rotation cycles and expiration.\n            ",
        "tags": [
          "Authentication - Login"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Output format (default: raw)",
            "schema": {
              "type": "string"
            },
            "example": "raw"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity - Session Status Mismatch",
            "content": {
              "application/json": {
                "example": {
                  "code": "session_unexpected_status",
                  "message": "Session status is not as expected for this operation. We are attempting to auto-recover.",
                  "details": {
                    "current_status": "FAILED",
                    "expected_status": [
                      "SCAN_QR_CODE"
                    ],
                    "action": "auto_restart_triggered",
                    "recommendation": "The instance encountered an error and is being restarted. Please wait a few seconds and try again."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/auth/qr-image": {
      "post": {
        "operationId": "_v2_auth_qr-image_post",
        "summary": "Get QR Image",
        "description": "Returns a base64-encoded PNG image of the WhatsApp QR code for easy rendering in web and mobile applications.\n\n### Developer Tips\n- **Direct Rendering**: The 'qr' field is a full Data URI. Bind it directly to an <img src='...'> tag.\n- **Wait for Engine**: After starting a session, it may take 5-15 seconds for the QR code to be ready.\n\n\n# The Visual Gateway: A Masterclass in QR Image Authentication\n\nThe `/v2/auth/qr-image` endpoint is the gold standard for web-based WhatsApp integrations. It abstracts away the complexity of raw binary data and Base64 decoding, providing a ready-to-use **Data URI** that can be injected directly into any modern browser environment. This endpoint is specifically tuned for speed and ease of use in React, Vue, and vanilla JS dashboards.\n\n---\n\n## 🏗️ Anatomy of the Data URI Response\n\nWhen you call this endpoint, you receive a JSON response containing a single `qr` field. This field contains a string prefixed with `data:image/png;base64,...`.\n- **The Core Value**: This is a high-contrast, optimized PNG image of the WhatsApp pairing code.\n- **Frontend Implementation**:\n  ```javascript\n  // Example: Updating an image element in Vanilla JS\n  fetch('/v2/auth/qr-image', { method: 'POST', body: JSON.stringify({ instance_id, access_token }) })\n    .then(res => res.json())\n    .then(data => {\n      document.getElementById('qr-container').src = data.qr;\n    });\n  ```\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. Intelligent UI Polling\nBecause QR codes refresh frequently (every 20-40 seconds), your UI needs a \"Heartbeat.\"\n- **The Strategy**: Set an interval to refresh the image every 5-10 seconds. This ensures that when the user finally holds up their phone to scan, the code they see is guaranteed to be within its valid window.\n- **Visual UX**: Implement a subtle \"Pulse\" animation or a loading overlay when the image is refreshing to inform the user that the system is keeping the link alive.\n\n### 2. Mastering the 422 Auto-Recovery State\nOne of Wawp’s unique features is the **Background Engine Healer**. If you call this endpoint and the engine is currently de-synced from WhatsApp, it will return a `422 Session Status Not Expected` error.\n- **The Lifecycle**: This response signals that our cloud orchestrator has detected a stall and is currently performing a `Stop -> Start` sequence for you automatically.\n- **Developer Action**: Do not show an \"Operation Failed\" error. Instead, show a message like \"Recovering the engine bridge... please wait 15 seconds.\" After the delay, retry the request—you will likely be greeted with a fresh, working QR code.\n\n### 3. Cache Management\nTo prevent accidental exposure of sensitive QR data, this endpoint is served with strict `Cache-Control: no-store` headers.\n- **Warning**: Never attempt to bypass these headers. Storing a QR image in a CDN or browser cache is a security risk and will lead to \"Failed to scan\" errors for the user, as the cached code will be stale.\n\n---\n\n## 💡 Developer Use Cases\n\n### A. Mobile-Responsive Dashboards\nThe PNG returned by this endpoint is dynamically generated to be high-contrast and clear even on low-budget smartphone displays. This makes it perfect for \"Scan on iPad\" or \"Scan on Chromebook\" scenarios where screen glare can sometimes interfere with lower-quality QR renderers.\n\n### B. Onboarding Progress Bars\nBy monitoring the response of this endpoint in parallel with [`/v2/session/info`](/v2/session/info), you can build a multi-step onboarding wizard:\n1. **Step 1**: \"Warming up engine\" (Poll until Status is `SCAN_QR_CODE`).\n2. **Step 2**: \"Ready to Scan\" (Fetch and display the QR image).\n3. **Step 3**: \"Success!\" (Transition to `WORKING`).\n\n---\n\n## ⚠️ Common Pitfalls\n\n- **GET Request Leakage**: Avoid using GET requests for this endpoint in production dashboards. Browsers often log GET parameters (like your `access_token`) in the command history or developer console. Use POST to keep your credentials in the request body.\n- **Ignoring the Mimetype**: Always ensure your image tag or CSS background-image property correctly handles the `data:image/png;base64` prefix. Omitting this part of the string will result in a \"Broken Image\" icon.\n\n---\n\n## Summary of Capabilities:\n- Instantly retrieve a scan-ready PNG image of the WhatsApp QR code.\n- Leverage the \"One-Click\" rendering power of Data URIs.\n- Trigger automatic environment healing during state de-syncs.\n- Maintain high security with non-persistent, non-cached visual data.\n            ",
        "tags": [
          "Authentication - Login"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity - Session Status Mismatch",
            "content": {
              "application/json": {
                "example": {
                  "code": "session_unexpected_status",
                  "message": "Session status is not as expected for this operation. We are attempting to auto-recover.",
                  "details": {
                    "current_status": "FAILED",
                    "expected_status": [
                      "SCAN_QR_CODE"
                    ],
                    "action": "auto_restart_triggered",
                    "recommendation": "The instance encountered an error and is being restarted. Please wait a few seconds and try again."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_auth_qr-image_get",
        "summary": "Get QR Image",
        "description": "Returns a base64-encoded PNG image of the WhatsApp QR code for easy rendering in web and mobile applications.\n\n### Developer Tips\n- **Direct Rendering**: The 'qr' field is a full Data URI. Bind it directly to an <img src='...'> tag.\n- **Wait for Engine**: After starting a session, it may take 5-15 seconds for the QR code to be ready.\n\n\n# The Visual Gateway: A Masterclass in QR Image Authentication\n\nThe `/v2/auth/qr-image` endpoint is the gold standard for web-based WhatsApp integrations. It abstracts away the complexity of raw binary data and Base64 decoding, providing a ready-to-use **Data URI** that can be injected directly into any modern browser environment. This endpoint is specifically tuned for speed and ease of use in React, Vue, and vanilla JS dashboards.\n\n---\n\n## 🏗️ Anatomy of the Data URI Response\n\nWhen you call this endpoint, you receive a JSON response containing a single `qr` field. This field contains a string prefixed with `data:image/png;base64,...`.\n- **The Core Value**: This is a high-contrast, optimized PNG image of the WhatsApp pairing code.\n- **Frontend Implementation**:\n  ```javascript\n  // Example: Updating an image element in Vanilla JS\n  fetch('/v2/auth/qr-image', { method: 'POST', body: JSON.stringify({ instance_id, access_token }) })\n    .then(res => res.json())\n    .then(data => {\n      document.getElementById('qr-container').src = data.qr;\n    });\n  ```\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. Intelligent UI Polling\nBecause QR codes refresh frequently (every 20-40 seconds), your UI needs a \"Heartbeat.\"\n- **The Strategy**: Set an interval to refresh the image every 5-10 seconds. This ensures that when the user finally holds up their phone to scan, the code they see is guaranteed to be within its valid window.\n- **Visual UX**: Implement a subtle \"Pulse\" animation or a loading overlay when the image is refreshing to inform the user that the system is keeping the link alive.\n\n### 2. Mastering the 422 Auto-Recovery State\nOne of Wawp’s unique features is the **Background Engine Healer**. If you call this endpoint and the engine is currently de-synced from WhatsApp, it will return a `422 Session Status Not Expected` error.\n- **The Lifecycle**: This response signals that our cloud orchestrator has detected a stall and is currently performing a `Stop -> Start` sequence for you automatically.\n- **Developer Action**: Do not show an \"Operation Failed\" error. Instead, show a message like \"Recovering the engine bridge... please wait 15 seconds.\" After the delay, retry the request—you will likely be greeted with a fresh, working QR code.\n\n### 3. Cache Management\nTo prevent accidental exposure of sensitive QR data, this endpoint is served with strict `Cache-Control: no-store` headers.\n- **Warning**: Never attempt to bypass these headers. Storing a QR image in a CDN or browser cache is a security risk and will lead to \"Failed to scan\" errors for the user, as the cached code will be stale.\n\n---\n\n## 💡 Developer Use Cases\n\n### A. Mobile-Responsive Dashboards\nThe PNG returned by this endpoint is dynamically generated to be high-contrast and clear even on low-budget smartphone displays. This makes it perfect for \"Scan on iPad\" or \"Scan on Chromebook\" scenarios where screen glare can sometimes interfere with lower-quality QR renderers.\n\n### B. Onboarding Progress Bars\nBy monitoring the response of this endpoint in parallel with [`/v2/session/info`](/v2/session/info), you can build a multi-step onboarding wizard:\n1. **Step 1**: \"Warming up engine\" (Poll until Status is `SCAN_QR_CODE`).\n2. **Step 2**: \"Ready to Scan\" (Fetch and display the QR image).\n3. **Step 3**: \"Success!\" (Transition to `WORKING`).\n\n---\n\n## ⚠️ Common Pitfalls\n\n- **GET Request Leakage**: Avoid using GET requests for this endpoint in production dashboards. Browsers often log GET parameters (like your `access_token`) in the command history or developer console. Use POST to keep your credentials in the request body.\n- **Ignoring the Mimetype**: Always ensure your image tag or CSS background-image property correctly handles the `data:image/png;base64` prefix. Omitting this part of the string will result in a \"Broken Image\" icon.\n\n---\n\n## Summary of Capabilities:\n- Instantly retrieve a scan-ready PNG image of the WhatsApp QR code.\n- Leverage the \"One-Click\" rendering power of Data URIs.\n- Trigger automatic environment healing during state de-syncs.\n- Maintain high security with non-persistent, non-cached visual data.\n            ",
        "tags": [
          "Authentication - Login"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity - Session Status Mismatch",
            "content": {
              "application/json": {
                "example": {
                  "code": "session_unexpected_status",
                  "message": "Session status is not as expected for this operation. We are attempting to auto-recover.",
                  "details": {
                    "current_status": "FAILED",
                    "expected_status": [
                      "SCAN_QR_CODE"
                    ],
                    "action": "auto_restart_triggered",
                    "recommendation": "The instance encountered an error and is being restarted. Please wait a few seconds and try again."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/auth/request-code": {
      "post": {
        "operationId": "_v2_auth_request-code_post",
        "summary": "Request Code (Phone Login)",
        "description": "Requests a linking code for phone-based WhatsApp authentication (OTP style).\n\n### Developer Tips\n- **Wait Time**: WhatsApp generation takes 2-5 seconds. UI should show a spinner.\n- **Rate Limit**: Do not request codes frequently. WhatsApp may temporarily block the number.\n\n\n# Headless Onboarding: The Power of Phone-Based Pairing Codes\n\nThe `/v2/auth/request-code` endpoint is a game-changer for WhatsApp automation, specifically designed for \"Headless\" environments where scanning a QR code is physically impossible or technically inconvenient. This method—often referred to as **OTP-style Linking**—allows you to link a WhatsApp account to a Wawp instance by entering an 8-character alphanumeric code directly into the WhatsApp mobile app.\n\n---\n\n## 🏗️ The Dual-Handshake Architecture\n\nWhen you call this endpoint with a `phone_number`, Wawp initiates a complex background orchestration:\n1. **Targeting**: The engine establishes a connection to WhatsApp’s servers and \"announces\" its intent to link with the specific phone number provided.\n2. **Code Generation**: Wawp’s cloud infrastructure negotiates a unique, short-lived 8-character pairing code (e.g., `ABCD-1234`).\n3. **Session Binding**: The generated code is cryptographically bound to your `instance_id`.\n4. **Interactive Waiting**: The engine enters an \"Interactive Listening\" mode, waiting for the user to type this code into their mobile device.\n\n---\n\n## 🛡️ Strategic Best Practices\n\n### 1. Global Number Normalization\nWhatsApp follows a strict international numbering format. Provisioning will fail if the format is incorrect.\n- **Developer Action**: Before passing the `phone_number` to this API, strictly normalize it on your backend:\n  - Remove all spaces, dashes, and parentheses.\n  - Remove any leading `+` or `00` (the global prefix).\n  - Ensure the Country Code is present (e.g., Use `201112223333` instead of `01112223333`).\n\n### 2. Building an OTP-Style UX\nSince the user needs to enter the code on their phone, the UX of your dashboard is critical.\n- **The Workflow**:\n  - Show the 8-character code in a **Big, Bold font**.\n  - Provide a countdown timer (codes are valid for approx. 2-5 minutes).\n  - Include a \"How to Link\" guide: **WhatsApp -> Settings -> Linked Devices -> Link with Phone Number**.\n\n### 3. Handling the 422 \"Not Ready\" State\nIf the engine is still initializing or has just been started, it may not be ready to generate a code instantly.\n- **The Response**: You will receive a `422 Session Status Not Expected` error. This indicates the engine is currently performing an internal warm-up. Implement a 10-second wait on your frontend before allowing the user to click the \"Generate Code\" button again.\n\n---\n\n## 💡 Industry-Standard Use Cases\n\n### A. Headless Server Provisioning\nFor enterprise clients running hundreds of bots on isolated linux servers without any GPU or display, the Pairing Code method is the only way to scale. Devs can generate codes on their central management panel and send them to field agents to link their work numbers.\n\n### B. Remote Support & Onboarding\nIf your customer is non-technical and struggling to scan a QR code (due to a cracked camera or low screen brightness), your support agent can generate a Pairing Code for them and read it aloud during a support call, resulting in a successful link in seconds.\n\n---\n\n## ⚠️ Common Pitfalls\n\n- **Retry Limit Abuse**: WhatsApp has a hidden internal rate limit for pairing codes. Requesting a code more than 3-5 times in a short window can cause WhatsApp to temporarily block the pairing feature for that phone number. \n- **Incorrect Status**: You can only request a code if the session status is **SCAN_QR_CODE**. If the session is already **WORKING**, the request will be rejected to prevent accidental hijacking of an active session.\n\n---\n\n## Summary of Responsibilities:\n- Initiate the Phone-Based Pairing protocol.\n- Retrieve a unique 8-character linking code.\n- Prepare the engine to listen for remote credential injection.\n- Support \"Mobile-Only\" onboarding flows where cameras are not used.\n            ",
        "tags": [
          "Authentication - Login"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "The 12-character ID of the instance",
            "schema": {
              "type": "string"
            },
            "example": "Your_Instance_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "phone_number",
            "in": "query",
            "required": true,
            "description": "The phone number to link (e.g., 201145202826)",
            "schema": {
              "type": "string"
            },
            "example": "201145202826"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity - Session Status Mismatch",
            "content": {
              "application/json": {
                "example": {
                  "code": "session_unexpected_status",
                  "message": "Session status is not as expected for this operation. We are attempting to auto-recover.",
                  "details": {
                    "current_status": "FAILED",
                    "expected_status": [
                      "SCAN_QR_CODE"
                    ],
                    "action": "auto_restart_triggered",
                    "recommendation": "The instance encountered an error and is being restarted. Please wait a few seconds and try again."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/text": {
      "post": {
        "operationId": "_v2_send_text_post",
        "summary": "Send Text Message",
        "description": "Use for core text messaging. Required params: instance_id, access_token, chatId, message.\n\n### Developer Tips\n- **Optimistic UI**: Send instantly with optimistic UI ( [show “typing...”](https://docs.wawp.net/start-typing-19609223e0) then update on response).\n- **Character Limits**: WhatsApp supports up to 4096 characters per message. However, for marketing or automated alerts, keep it under 1000 for better readability.\n\n\n# Narrative Power: Mastering the Core Text Engine\n\nThe `/v2/send/text` endpoint is the most fundamental and frequently used tool in the Wawp arsenal. While it may seem simple to \"just send text,\" this endpoint is powered by a high-performance rendering engine that manages character encoding, markdown parsing, and delivery synchronization. For businesses, this is the primary channel for notifications, support responses, and conversational marketing.\n\n![send text.png](https://api.apidog.com/api/v1/projects/1017306/resources/369237/image-preview)\n\n---\n\n## 🏗️ Technical Architecture of the Text Pipeline\n\nWhen a POST request hits this endpoint, Wawp initiates a stateless workflow:\n1. **Normalization**: The `chatId` is sanitized (removing `+` or extraneous spaces) and verified against the WhatsApp network routing table.\n2. **Text Bufferings**: The `message` string is buffered to prevent memory overflow. WhatsApp supports up to **4,096 characters**, and our proxy enforces this limit to ensure upstream delivery remains atomic.\n3. **Markdown Pre-processing**: Wawp preserves WhatsApp-specific markdown (e.g., `*bold*`, `_italic_`, `~strikethrough~`, and ```code blocks```). This allows you to send rich, structured text without needing complex HTML or XML wrappers.\n\n---\n\n## 🛡️ Strategic Best Practices for Developers\n\n### 1. The Optimistic UI Pattern\nFor high-quality user experiences, don't make the user wait for the API response before showing the message in your frontend. \n- **Implementation**: When the user clicks \"Send,\" immediately render the message in your chat UI with a \"Sending...\" indicator. Call [`/v2/send/start-typing`](/v2/send/start-typing) a few seconds before the actual POST to mimic human behavior. Once the `/send/text` returns a `message_id`, update the UI state to \"Sent.\"\n\n### 2. Handling Character Complexity\nIf you are sending technical logs, code snippets, or non-Latin character sets (Arabic, Mandarin, etc.), note that:\n- **Encoding**: Wawp uses UTF-8 encoding by default. Ensure your application server sends the correct `Content-Type: application/json` headers to prevent character corruption.\n- **Truncation Safety**: If your text exceeds 4,000 characters, we recommend splitting it into multiple logical messages or using the CLIP (Copy Link in Profile) strategy to host longer content on a web page.\n\n### 3. Error Recovery and Upstream Reliability\nOccasionally, the WhatsApp network (Upstream) may experience transient lag.\n- **The \"2xx vs Delivery\" Fallacy**: A `200 OK` from Wawp means the message was successfully accepted and queued for delivery to the engine. It does not guarantee the recipient's phone is on.\n- **Monitoring**: Always use **Webhooks** (`message.ack`) to track when the status moves from \"Sent\" (1 checkmark) to \"Delivered\" (2 checkmarks) and finally \"Read\" (blue checkmarks).\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Variable Injection and Templating\nBecause Wawp is stateless, you can easily build a templating engine on your side. \n- **Example**: \"Hi {{name}}, your order #{{order_id}} is ready!\"\n- **Technique**: Perform the string replacement in your backend before sending the final string to Wawp. This keeps the logic localized to your business rules while Wawp handles the heavy lifting of delivery.\n\n### Threaded Conversations (Reply-to)\nBy including the `reply_to` parameter (the `message_id` of a previous message), you can create structured threads. This is crucial for:\n- Support systems where the agent needs to clarify a specific customer question.\n- Group chats where multiple topics are being discussed simultaneously.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Forbidden Characters**: While emojis are fully supported, stay away from low-level control characters (`\\x00-\\x1F`) which can trigger security flags or cause the engine to crash.\n- **Empty Messages**: Sending an empty `message` or one consisting only of whitespace will return a `400 Bad Request`. Always validate your input fields.\n- **Rate Overload**: Sending 1,000 text messages to the same user in 60 seconds is a guaranteed \"spam\" flag. Use a sane \"Consumer Protection\" delay (minimum 1 second between messages to the same recipient).\n\n---\n\n## Summary of Capabilities:\n- Send structured, rich text with full support for WhatsApp Markdown.\n- High-concurrency support for notification and alert systems.\n- Seamless integration with threading/replies via `reply_to`.\n- Real-time event tracking through consistent `message_id` generation.\n- Support for all global languages and emoji sets via UTF-8.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "message",
            "in": "query",
            "required": true,
            "description": "Message text to be sent",
            "schema": {
              "type": "string"
            },
            "example": "Hi from Wawp"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_send_text_get",
        "summary": "Send Text Message",
        "description": "Use for core text messaging. Required params: instance_id, access_token, chatId, message.\n\n### Developer Tips\n- **Optimistic UI**: Send instantly with optimistic UI ( [show “typing...”](https://docs.wawp.net/start-typing-19609223e0) then update on response).\n- **Character Limits**: WhatsApp supports up to 4096 characters per message. However, for marketing or automated alerts, keep it under 1000 for better readability.\n\n\n# Narrative Power: Mastering the Core Text Engine\n\nThe `/v2/send/text` endpoint is the most fundamental and frequently used tool in the Wawp arsenal. While it may seem simple to \"just send text,\" this endpoint is powered by a high-performance rendering engine that manages character encoding, markdown parsing, and delivery synchronization. For businesses, this is the primary channel for notifications, support responses, and conversational marketing.\n\n![send text.png](https://api.apidog.com/api/v1/projects/1017306/resources/369237/image-preview)\n\n---\n\n## 🏗️ Technical Architecture of the Text Pipeline\n\nWhen a POST request hits this endpoint, Wawp initiates a stateless workflow:\n1. **Normalization**: The `chatId` is sanitized (removing `+` or extraneous spaces) and verified against the WhatsApp network routing table.\n2. **Text Bufferings**: The `message` string is buffered to prevent memory overflow. WhatsApp supports up to **4,096 characters**, and our proxy enforces this limit to ensure upstream delivery remains atomic.\n3. **Markdown Pre-processing**: Wawp preserves WhatsApp-specific markdown (e.g., `*bold*`, `_italic_`, `~strikethrough~`, and ```code blocks```). This allows you to send rich, structured text without needing complex HTML or XML wrappers.\n\n---\n\n## 🛡️ Strategic Best Practices for Developers\n\n### 1. The Optimistic UI Pattern\nFor high-quality user experiences, don't make the user wait for the API response before showing the message in your frontend. \n- **Implementation**: When the user clicks \"Send,\" immediately render the message in your chat UI with a \"Sending...\" indicator. Call [`/v2/send/start-typing`](/v2/send/start-typing) a few seconds before the actual POST to mimic human behavior. Once the `/send/text` returns a `message_id`, update the UI state to \"Sent.\"\n\n### 2. Handling Character Complexity\nIf you are sending technical logs, code snippets, or non-Latin character sets (Arabic, Mandarin, etc.), note that:\n- **Encoding**: Wawp uses UTF-8 encoding by default. Ensure your application server sends the correct `Content-Type: application/json` headers to prevent character corruption.\n- **Truncation Safety**: If your text exceeds 4,000 characters, we recommend splitting it into multiple logical messages or using the CLIP (Copy Link in Profile) strategy to host longer content on a web page.\n\n### 3. Error Recovery and Upstream Reliability\nOccasionally, the WhatsApp network (Upstream) may experience transient lag.\n- **The \"2xx vs Delivery\" Fallacy**: A `200 OK` from Wawp means the message was successfully accepted and queued for delivery to the engine. It does not guarantee the recipient's phone is on.\n- **Monitoring**: Always use **Webhooks** (`message.ack`) to track when the status moves from \"Sent\" (1 checkmark) to \"Delivered\" (2 checkmarks) and finally \"Read\" (blue checkmarks).\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Variable Injection and Templating\nBecause Wawp is stateless, you can easily build a templating engine on your side. \n- **Example**: \"Hi {{name}}, your order #{{order_id}} is ready!\"\n- **Technique**: Perform the string replacement in your backend before sending the final string to Wawp. This keeps the logic localized to your business rules while Wawp handles the heavy lifting of delivery.\n\n### Threaded Conversations (Reply-to)\nBy including the `reply_to` parameter (the `message_id` of a previous message), you can create structured threads. This is crucial for:\n- Support systems where the agent needs to clarify a specific customer question.\n- Group chats where multiple topics are being discussed simultaneously.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Forbidden Characters**: While emojis are fully supported, stay away from low-level control characters (`\\x00-\\x1F`) which can trigger security flags or cause the engine to crash.\n- **Empty Messages**: Sending an empty `message` or one consisting only of whitespace will return a `400 Bad Request`. Always validate your input fields.\n- **Rate Overload**: Sending 1,000 text messages to the same user in 60 seconds is a guaranteed \"spam\" flag. Use a sane \"Consumer Protection\" delay (minimum 1 second between messages to the same recipient).\n\n---\n\n## Summary of Capabilities:\n- Send structured, rich text with full support for WhatsApp Markdown.\n- High-concurrency support for notification and alert systems.\n- Seamless integration with threading/replies via `reply_to`.\n- Real-time event tracking through consistent `message_id` generation.\n- Support for all global languages and emoji sets via UTF-8.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "message",
            "in": "query",
            "required": true,
            "description": "Message text to be sent",
            "schema": {
              "type": "string"
            },
            "example": "Hi from Wawp"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/image": {
      "post": {
        "operationId": "_v2_send_image_post",
        "summary": "Send Image",
        "description": "SendImage expects a file object (url, mimetype, filename) and required caption/reply_to.\n\n### Developer Tips\n- **Direct Rendering**: Display a client-side thumbnail before sending to give users immediate feedback.\n- **Supported Formats**: WhatsApp primarily accepts PNG and JPEG. Ensure your URLs point to valid image files.\n\n\n# Visual Storytelling: Harnessing the Image Messaging Engine\n\nImages are the most engaging form of communication on WhatsApp. Whether it's a product catalog, a promotional banner, or a technical screenshot, the `/v2/send/image` endpoint provides a robust way to deliver high-quality visuals to your users. Wawp’s image engine handles the heavy lifting of fetching remote assets, validating MIME types, and ensuring that images are rendered correctly on all WhatsApp clients (Mobile, Web, and Desktop).\n\n---\n\n## 🏗️ The Multi-Stage Media Pipeline\n\nWhen you call the `/send/image` endpoint, Wawp orchestrates a complex background process:\n1. **Asynchronous Fetching**: The engine uses a high-speed fetcher to retrieve the file from the providing URL. We recommend using a Content Delivery Network (CDN) to ensure low-latency transfers.\n2. **Format Verification**: WhatsApp is strict about image standards. Our engine verifies that the file is a valid **PNG** or **JPEG**. If the upstream server provides a different format (like WebP or SVG via a mismatched extension), Wawp attempts to normalize the stream or returns an informative error code.\n3. **Caption Injection**: Unlike simple attachments, captions in Wawp are treated as first-class text citizens. They support full UTF-8 encoding and WhatsApp markdown (`*bold*`, etc.), allowing you to provide context directly alongside the visual.\n\n---\n\n## 🛡️ Strategic Best Practices for Media Delivery\n\n### 1. The Pre-fetch Metadata Pattern\nTo provide the best user experience, your application should know what it's sending before it hits our API.\n- **Validation**: Before calling the API, perform a `HEAD` request to the image URL to verify the `Content-Length` and `Content-Type`. This prevents \"Blind Sending\" which leads to higher failure rates.\n- **Client-Side Thumbs**: In your frontend, render a local thumbnail of the image. This gives the user immediate visual feedback while our engine handles the upstream delivery.\n\n### 2. File Size and Resolution Strategy\nWhile WhatsApp supports large files, efficiency is key to engagement.\n- **Optimal Resolution**: Aim for **1200x1600 pixels**. This provides a sharp, full-screen experience on most mobile devices without excessive bandwidth consumption.\n- **Compression**: Leverage our [`/v2/media/convert`](/v2/media/convert) endpoint if you need to downscale or compress high-resolution photography before sending it to a mass audience.\n\n### 3. URL Accessibility and Security\n- **Public Accessibility**: The `file[url]` must be publicly accessible via HTTPS. Our engine cannot bypass login screens or VPN-locked assets.\n- **Expiring Links**: If you use signed S3 URLs, ensure the expiration time is at least **5 minutes**. This gives the Wawp engine enough time to fetch and process the file even during peak traffic periods.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Catalog Branding\nImages are perfect for sending product highlights. Pair the image with a long, descriptive caption that includes a CTA (Call to Action) link. Since the caption remains attached to the image upon forwarding, your branding stays intact.\n\n### Technical Support via Visuals\nUse images to send \"Before/After\" comparisons or flow diagrams. By using the `reply_to` field, you can link an instruction image directly to a user's specific query, creating a seamless support thread.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Invalid Mime-Types**: Sending a `.jpg` file with an `image/gif` header is a common technical error. Wawp will return an `Unsupported Mimetype` error. Always ensure your server headers are correct.\n- **Filename Ambiguity**: Use descriptive but clean filenames (e.g., `invoice_123.jpg`). Avoid using special characters or spaces in the `file[filename]` parameter to ensure compatibility across different OS file systems.\n- **The \"Broken Thumbnail\" Issue**: If an image appears as a grey box on the recipient's phone, it usually means the source URL was cut off mid-download or the server returned a 404/500 code during Wawp's fetch phase.\n\n---\n\n## Summary of Capabilities:\n- Deliver high-fidelity JPEG and PNG images with integrated captions.\n- Remote fetching from any secure HTTPS URL.\n- Support for complex thread-nesting via the `reply_to` parameter.\n- Reliable MIME-type validation and header normalization.\n- Consistent success reporting with unique `message_id` generation for delivery tracking.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Publicly accessible HTTPS URL of the image",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/cat.jpg"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Filename for the image",
            "schema": {
              "type": "string"
            },
            "example": "image.jpg"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type (image/jpeg or image/png)",
            "schema": {
              "type": "string"
            },
            "example": "image/jpeg"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Caption for the image",
            "schema": {
              "type": "string"
            },
            "example": "Here's your requested image."
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_send_image_get",
        "summary": "Send Image",
        "description": "SendImage expects a file object (url, mimetype, filename) and required caption/reply_to.\n\n### Developer Tips\n- **Direct Rendering**: Display a client-side thumbnail before sending to give users immediate feedback.\n- **Supported Formats**: WhatsApp primarily accepts PNG and JPEG. Ensure your URLs point to valid image files.\n\n\n# Visual Storytelling: Harnessing the Image Messaging Engine\n\nImages are the most engaging form of communication on WhatsApp. Whether it's a product catalog, a promotional banner, or a technical screenshot, the `/v2/send/image` endpoint provides a robust way to deliver high-quality visuals to your users. Wawp’s image engine handles the heavy lifting of fetching remote assets, validating MIME types, and ensuring that images are rendered correctly on all WhatsApp clients (Mobile, Web, and Desktop).\n\n---\n\n## 🏗️ The Multi-Stage Media Pipeline\n\nWhen you call the `/send/image` endpoint, Wawp orchestrates a complex background process:\n1. **Asynchronous Fetching**: The engine uses a high-speed fetcher to retrieve the file from the providing URL. We recommend using a Content Delivery Network (CDN) to ensure low-latency transfers.\n2. **Format Verification**: WhatsApp is strict about image standards. Our engine verifies that the file is a valid **PNG** or **JPEG**. If the upstream server provides a different format (like WebP or SVG via a mismatched extension), Wawp attempts to normalize the stream or returns an informative error code.\n3. **Caption Injection**: Unlike simple attachments, captions in Wawp are treated as first-class text citizens. They support full UTF-8 encoding and WhatsApp markdown (`*bold*`, etc.), allowing you to provide context directly alongside the visual.\n\n---\n\n## 🛡️ Strategic Best Practices for Media Delivery\n\n### 1. The Pre-fetch Metadata Pattern\nTo provide the best user experience, your application should know what it's sending before it hits our API.\n- **Validation**: Before calling the API, perform a `HEAD` request to the image URL to verify the `Content-Length` and `Content-Type`. This prevents \"Blind Sending\" which leads to higher failure rates.\n- **Client-Side Thumbs**: In your frontend, render a local thumbnail of the image. This gives the user immediate visual feedback while our engine handles the upstream delivery.\n\n### 2. File Size and Resolution Strategy\nWhile WhatsApp supports large files, efficiency is key to engagement.\n- **Optimal Resolution**: Aim for **1200x1600 pixels**. This provides a sharp, full-screen experience on most mobile devices without excessive bandwidth consumption.\n- **Compression**: Leverage our [`/v2/media/convert`](/v2/media/convert) endpoint if you need to downscale or compress high-resolution photography before sending it to a mass audience.\n\n### 3. URL Accessibility and Security\n- **Public Accessibility**: The `file[url]` must be publicly accessible via HTTPS. Our engine cannot bypass login screens or VPN-locked assets.\n- **Expiring Links**: If you use signed S3 URLs, ensure the expiration time is at least **5 minutes**. This gives the Wawp engine enough time to fetch and process the file even during peak traffic periods.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Catalog Branding\nImages are perfect for sending product highlights. Pair the image with a long, descriptive caption that includes a CTA (Call to Action) link. Since the caption remains attached to the image upon forwarding, your branding stays intact.\n\n### Technical Support via Visuals\nUse images to send \"Before/After\" comparisons or flow diagrams. By using the `reply_to` field, you can link an instruction image directly to a user's specific query, creating a seamless support thread.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Invalid Mime-Types**: Sending a `.jpg` file with an `image/gif` header is a common technical error. Wawp will return an `Unsupported Mimetype` error. Always ensure your server headers are correct.\n- **Filename Ambiguity**: Use descriptive but clean filenames (e.g., `invoice_123.jpg`). Avoid using special characters or spaces in the `file[filename]` parameter to ensure compatibility across different OS file systems.\n- **The \"Broken Thumbnail\" Issue**: If an image appears as a grey box on the recipient's phone, it usually means the source URL was cut off mid-download or the server returned a 404/500 code during Wawp's fetch phase.\n\n---\n\n## Summary of Capabilities:\n- Deliver high-fidelity JPEG and PNG images with integrated captions.\n- Remote fetching from any secure HTTPS URL.\n- Support for complex thread-nesting via the `reply_to` parameter.\n- Reliable MIME-type validation and header normalization.\n- Consistent success reporting with unique `message_id` generation for delivery tracking.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Publicly accessible HTTPS URL of the image",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/cat.jpg"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Filename for the image",
            "schema": {
              "type": "string"
            },
            "example": "image.jpg"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type (image/jpeg or image/png)",
            "schema": {
              "type": "string"
            },
            "example": "image/jpeg"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Caption for the image",
            "schema": {
              "type": "string"
            },
            "example": "Here's your requested image."
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/pdf": {
      "post": {
        "operationId": "_v2_send_pdf_post",
        "summary": "Send PDF",
        "description": "Treat PDFs as general file deliveries via the file endpoint. Require file.url and required caption.\n\n\n# Document Integrity: Empowering the PDF Messaging Engine\n\nIn the world of business automation, PDFs are the primary vehicle for high-value data—invoices, contracts, medical reports, and technical manuals. The `/v2/send/pdf` endpoint is designed to bridge the gap between your cloud storage and your user's WhatsApp conversation, ensuring that critical documents arrive with their integrity and formatting intact. Unlike media messages which are often compressed, Wawp treats PDFs as authoritative documents, preserving their binary structure for professional use.\n\n![send pdf.png](https://api.apidog.com/api/v1/projects/1017306/resources/369241/image-preview)\n\n---\n\n## 🏗️ The Document Delivery Architecture\n\nWhen you initiate a PDF transfer, Wawp’s document engine follows a specialized protocol:\n1. **Header Inspection**: Before downloading the full file, Wawp inspects the `Content-Type` to ensure it aligns with `application/pdf`. This prevents the \"Mangled File\" error that occurs if a server accidentally serves an HTML page instead of a PDF during a transient error.\n2. **Authoritative Naming**: The `file[filename]` parameter is crucial. Wawp injects this name into the WhatsApp metadata, ensuring that when the user saves the document, it retains the professional name you’ve assigned it (e.g., `Inv_2025_001.pdf`) rather than a random UUID.\n3. **Caption Correlation**: Wawp allows you to attach a markdown-rich caption to the document. This is ideal for providing instructions (e.g., \"Please sign and return to this chat\") without sending a separate, disconnected text message.\n\n---\n\n## 🛡️ Strategic Best Practices for Corporate Document Flow\n\n### 1. The Security First Approach\nSince PDFs often contain sensitive Personal Identifiable Information (PII):\n- **Short-Lived URLs**: Host your PDFs on URLs that expire shortly after the transfer is complete. Wawp only needs access for a few seconds to fetch and hand off the file to the WhatsApp network.\n- **No-Log Policy**: Wawp adheres to a **Zero-Secrets Policy**. We do not archive your PDF contents. Once we receive the \"Sent\" acknowledgement from the WhatsApp WebSocket, the binary buffer is purged from our engine's volatile memory.\n\n### 2. File Size and Optimization Strategy\nWhile WhatsApp supports documents up to **100MB** (and sometimes up to 2GB in newer versions), user experience dictates a leaner approach.\n- **The \"Mobile Friendly\" Rule**: Most users are on mobile data. We recommend keeping PDFs under **5MB** for instant loading. If you are sending a 50MB manual, consider compressing it or sending a link via [`/v2/send/link-preview`](/v2/send/link-preview) instead.\n- **Fast Serialization**: Use linearized (web-optimized) PDFs. This allows the recipient's phone to start rendering the first page before the entire document has finished downloading.\n\n### 3. Error Handling and Verification\n- **Upstream Timeouts**: For very large PDFs, ensure your file server has a high enough bandwidth to serve the entire file to Wawp within 15–20 seconds.\n- **Webhook Monitoring**: Listen for the `message.ack` events. For a PDF, the \"Delivered\" status is your confirmation that the document is safely on the user's encrypted device.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Automated Invoicing and Billing\nIntegrate this endpoint with your billing system. As soon as a payment is processed, generate a PDF and send it via Wawp. The `reply_to` parameter can be used to link the invoice to the customer's previous \"Payment Confirmation\" message, creating a professional audit trail for the user.\n\n### Legal and Contractual Workflows\nSend contracts for digital review. Use the `caption` field to explain the terms briefly. Because Wawp supports international character sets, your captions can support legal terminology in any language while maintaining the structural integrity of the PDF attachment.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Invalid MIME-Type**: If your server sends `text/html` (often due to a 404 page) but you specified `application/pdf`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Size',\n            content: 'WhatsApp has a file size limit (approx 100MB).'\n        },\n        {\n            type: 'positive',\n            title: 'Preview',\n            content: 'Shows the first page as a thumbnail on some devices.'\n        }\n    ],\n  recommendations: [\n        \"Compress large PDFs before sending to ensure delivery.\",\n        \"Use descriptive filenames; users see this when downloading.\"\n    ]\n  \n   Wawp will fail the request to prevent sending corrupted files to your users.\n- **Complex Filenames**: Avoid using emojis or non-ASCII characters in the `file[filename]` string. While Wawp supports them, some older Android PDF readers may fail to open files with complex filenames.\n- **The \"Attachment Only\" UI**: Remind your frontend developers that PDFs do not show a visual preview in the chat bubble (unlike images). Use a descriptive caption to tell the user what the file is before they download it.\n\n---\n\n## Summary of Capabilities:\n- Deliver professional-grade PDF documents with custom filenames and captions.\n- Support for large files (up to 100MB) with reliable fetching from HTTPS sources.\n- End-to-end markdown support for document captions and instructions.\n- Seamless integration with conversational threads via `reply_to`.\n- Consistent delivery tracking through unique `message_id` generation and Webhook support.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Publicly accessible HTTPS URL of the PDF file",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/file-sample.pdf"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Filename for the document",
            "schema": {
              "type": "string"
            },
            "example": "document.pdf"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type (e.g., application/pdf)",
            "schema": {
              "type": "string"
            },
            "example": "application/pdf"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Caption for the document",
            "schema": {
              "type": "string"
            },
            "example": "Here's your requested document."
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_send_pdf_get",
        "summary": "Send PDF",
        "description": "Treat PDFs as general file deliveries via the file endpoint. Require file.url and required caption.\n\n\n# Document Integrity: Empowering the PDF Messaging Engine\n\nIn the world of business automation, PDFs are the primary vehicle for high-value data—invoices, contracts, medical reports, and technical manuals. The `/v2/send/pdf` endpoint is designed to bridge the gap between your cloud storage and your user's WhatsApp conversation, ensuring that critical documents arrive with their integrity and formatting intact. Unlike media messages which are often compressed, Wawp treats PDFs as authoritative documents, preserving their binary structure for professional use.\n\n![send pdf.png](https://api.apidog.com/api/v1/projects/1017306/resources/369241/image-preview)\n\n---\n\n## 🏗️ The Document Delivery Architecture\n\nWhen you initiate a PDF transfer, Wawp’s document engine follows a specialized protocol:\n1. **Header Inspection**: Before downloading the full file, Wawp inspects the `Content-Type` to ensure it aligns with `application/pdf`. This prevents the \"Mangled File\" error that occurs if a server accidentally serves an HTML page instead of a PDF during a transient error.\n2. **Authoritative Naming**: The `file[filename]` parameter is crucial. Wawp injects this name into the WhatsApp metadata, ensuring that when the user saves the document, it retains the professional name you’ve assigned it (e.g., `Inv_2025_001.pdf`) rather than a random UUID.\n3. **Caption Correlation**: Wawp allows you to attach a markdown-rich caption to the document. This is ideal for providing instructions (e.g., \"Please sign and return to this chat\") without sending a separate, disconnected text message.\n\n---\n\n## 🛡️ Strategic Best Practices for Corporate Document Flow\n\n### 1. The Security First Approach\nSince PDFs often contain sensitive Personal Identifiable Information (PII):\n- **Short-Lived URLs**: Host your PDFs on URLs that expire shortly after the transfer is complete. Wawp only needs access for a few seconds to fetch and hand off the file to the WhatsApp network.\n- **No-Log Policy**: Wawp adheres to a **Zero-Secrets Policy**. We do not archive your PDF contents. Once we receive the \"Sent\" acknowledgement from the WhatsApp WebSocket, the binary buffer is purged from our engine's volatile memory.\n\n### 2. File Size and Optimization Strategy\nWhile WhatsApp supports documents up to **100MB** (and sometimes up to 2GB in newer versions), user experience dictates a leaner approach.\n- **The \"Mobile Friendly\" Rule**: Most users are on mobile data. We recommend keeping PDFs under **5MB** for instant loading. If you are sending a 50MB manual, consider compressing it or sending a link via [`/v2/send/link-preview`](/v2/send/link-preview) instead.\n- **Fast Serialization**: Use linearized (web-optimized) PDFs. This allows the recipient's phone to start rendering the first page before the entire document has finished downloading.\n\n### 3. Error Handling and Verification\n- **Upstream Timeouts**: For very large PDFs, ensure your file server has a high enough bandwidth to serve the entire file to Wawp within 15–20 seconds.\n- **Webhook Monitoring**: Listen for the `message.ack` events. For a PDF, the \"Delivered\" status is your confirmation that the document is safely on the user's encrypted device.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Automated Invoicing and Billing\nIntegrate this endpoint with your billing system. As soon as a payment is processed, generate a PDF and send it via Wawp. The `reply_to` parameter can be used to link the invoice to the customer's previous \"Payment Confirmation\" message, creating a professional audit trail for the user.\n\n### Legal and Contractual Workflows\nSend contracts for digital review. Use the `caption` field to explain the terms briefly. Because Wawp supports international character sets, your captions can support legal terminology in any language while maintaining the structural integrity of the PDF attachment.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Invalid MIME-Type**: If your server sends `text/html` (often due to a 404 page) but you specified `application/pdf`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Size',\n            content: 'WhatsApp has a file size limit (approx 100MB).'\n        },\n        {\n            type: 'positive',\n            title: 'Preview',\n            content: 'Shows the first page as a thumbnail on some devices.'\n        }\n    ],\n  recommendations: [\n        \"Compress large PDFs before sending to ensure delivery.\",\n        \"Use descriptive filenames; users see this when downloading.\"\n    ]\n  \n   Wawp will fail the request to prevent sending corrupted files to your users.\n- **Complex Filenames**: Avoid using emojis or non-ASCII characters in the `file[filename]` string. While Wawp supports them, some older Android PDF readers may fail to open files with complex filenames.\n- **The \"Attachment Only\" UI**: Remind your frontend developers that PDFs do not show a visual preview in the chat bubble (unlike images). Use a descriptive caption to tell the user what the file is before they download it.\n\n---\n\n## Summary of Capabilities:\n- Deliver professional-grade PDF documents with custom filenames and captions.\n- Support for large files (up to 100MB) with reliable fetching from HTTPS sources.\n- End-to-end markdown support for document captions and instructions.\n- Seamless integration with conversational threads via `reply_to`.\n- Consistent delivery tracking through unique `message_id` generation and Webhook support.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Publicly accessible HTTPS URL of the PDF file",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/file-sample.pdf"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Filename for the document",
            "schema": {
              "type": "string"
            },
            "example": "document.pdf"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type (e.g., application/pdf)",
            "schema": {
              "type": "string"
            },
            "example": "application/pdf"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Caption for the document",
            "schema": {
              "type": "string"
            },
            "example": "Here's your requested document."
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/list": {
      "post": {
        "operationId": "_v2_send_list_post",
        "summary": "Send List Message",
        "description": "Sends an interactive List Message (menu) to a chat. This message type displays a button that, when tapped, opens a list of options.\n\n### Developer Tips\n- **Better Conversions**: List messages have a significantly higher engagement rate than plain text menus because they reduce typing effort for the user.\n- **Unique rowId**: Always ensure your `rowId` is unique within the list to correctly identify the user's choice in your backend logic.\n\n\n# Conversational Navigation: Mastering the Interactive List Engine\n\nIn the evolution of commercial messaging, the `/v2/send/list` endpoint represents a shift from \"Command-Line\" style interactions to a modern, \"App-like\" user experience. List messages provide a structured, high-conversion way for users to select from a menu of options without the friction of typing words or numbers. By organizing choices into sections and rows, you can build complex navigation menus, product directories, or support triage flows that feel native to the WhatsApp ecosystem.\n\n![List.png](https://api.apidog.com/api/v1/projects/1017306/resources/369238/image-preview)\n\n![list options.png](https://api.apidog.com/api/v1/projects/1017306/resources/369239/image-preview)\n\n---\n\n## 🏗️ The List Message Hierarchy\n\nA List message is a multi-layered object designed for clarity and scannability:\n1. **The Header (Title)**: This is the first thing the user sees. It should clearly state the purpose of the menu (e.g., \"Customer Support Menu\").\n2. **The Body (Description)**: Use this for the primary instruction or context (e.g., \"Please select the department you wish to speak with\").\n3. **The Activation Button**: A custom label (max 20 characters) that triggers the overlay.\n4. **Sections and Rows**: The core content. Sections allow you to group related options (e.g., \"Technical Support\" vs. \"Billing Queries\"), while rows represent the individual clickable items.\n\n---\n\n## 🛡️ Strategic Best Practices for Menu Design\n\n### 1. The 10-Row Boundary\nWhatsApp enforces a hard limit of **10 rows** across all sections in a single list.\n- **Developer Action**: If you have 20 products to show, do not try to squeeze them into one list. Instead, use a \"Category\" list first, and then have the user's selection trigger a *second* list message for that specific category. This \"Multi-Step Triage\" prevents the user from being overwhelmed by a single, monolithic menu.\n- **Row Descriptions**: Each row has an optional `description` field. Use this to provide \"Hint Text\" (e.g., \"Fastest response time\") to guide the user's decision process.\n\n### 2. Unique Identifier (rowId) Strategy\nThe `rowId` is for your backend, while the `title` is for the user.\n- **Decoupling**: Never rely on the row title for your logic. Always use a unique, alphanumeric `rowId` (e.g., `dept_billing_v1`). This allows you to change the display text for marketing purposes without breaking your backend processing logic.\n- **State Persistence**: You can include small bits of state metadata in the `rowId` (e.g., `user_123_opt_4`) if your system is completely stateless, though we recommend maintaining user state in your own database associated with the `chatId`.\n\n### 3. Visual Scannability and Emojis\n- **Section Headers**: Use section titles as \"Visual Anchors.\" \n- **Emoji Bullet Points**: Prefix your row titles with emojis (e.g., \"💳 Billing,\" \"🛠️ Technical\"). This significantly reduces the cognitive load on the user, allowing them to find their desired option via icons rather than reading every word.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Automated Product Catalogs\nBuild a mini-storefront within the chat. The first section can be \"New Arrivals,\" and the second \"Best Sellers.\" When a user clicks a row, your **Webhooks** (`list_response`) will capture the `rowId`. Your system can then immediately send an [`/v2/send/image`](/v2/send/image) of that product with a \"Buy Now\" link.\n\n### Intelligent Support Triage\nInstead of a human greeting every user, send a List message. Section 1: \"Urgent Issues,\" Section 2: \"General Info.\" Based on the user's selection, the bot can route the conversation to the most qualified agent or provide an automated knowledge-base article.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Button Text Length**: If your button text exceeds 20 characters, the message will fail to send with a `Validation Error`. Keep it punchy: \"See Options,\" \"Start Here,\" or \"Main Menu.\"\n- **Empty Sections**: Every section must contain at least one row. Sending an empty section will cause a rendering failure on the WhatsApp network.\n- **The \"No Response\" Trap**: Users sometimes open a list but don't select anything. Ensure your bot has a \"Timeout\" or follow-up logic to re-engage the user if they've been inactive for more than 5 minutes after receiving a menu.\n\n---\n\n## Summary of Capabilities:\n- Deliver interactive, overlay-style list menus with up to 10 rows.\n- Support for multiple logically grouped sections with custom titles.\n- High-conversion UX using custom buttons and descriptive row metadata.\n- Real-time interaction tracking via specialized `list_response` Webhook events.\n- Full markdown support for header titles and body descriptions.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        },
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "instance_id": {
                    "type": "string",
                    "description": "Unique ID of the WhatsApp session"
                  },
                  "access_token": {
                    "type": "string",
                    "description": "API access token"
                  },
                  "chatId": {
                    "type": "string",
                    "description": "Recipient's WhatsApp number"
                  },
                  "message": {
                    "type": "string",
                    "description": "The interactive list message structure."
                  },
                  "message.title": {
                    "type": "string",
                    "description": "Header title of the list message."
                  },
                  "message.description": {
                    "type": "string",
                    "description": "Body text of the message."
                  },
                  "message.footer": {
                    "type": "string",
                    "description": "Small text at the bottom."
                  },
                  "message.button": {
                    "type": "string",
                    "description": "Text on the button that opens the list."
                  },
                  "message.sections": {
                    "type": "string",
                    "description": "Array of sections, each containing a title and rows."
                  },
                  "reply_to": {
                    "type": "string",
                    "description": "The ID of the message you are replying to"
                  }
                },
                "required": [
                  "instance_id",
                  "access_token",
                  "chatId",
                  "message",
                  "message.title",
                  "message.description",
                  "message.footer",
                  "message.button",
                  "message.sections"
                ]
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_send_list_get",
        "summary": "Send List Message",
        "description": "Sends an interactive List Message (menu) to a chat. This message type displays a button that, when tapped, opens a list of options.\n\n### Developer Tips\n- **Better Conversions**: List messages have a significantly higher engagement rate than plain text menus because they reduce typing effort for the user.\n- **Unique rowId**: Always ensure your `rowId` is unique within the list to correctly identify the user's choice in your backend logic.\n\n\n# Conversational Navigation: Mastering the Interactive List Engine\n\nIn the evolution of commercial messaging, the `/v2/send/list` endpoint represents a shift from \"Command-Line\" style interactions to a modern, \"App-like\" user experience. List messages provide a structured, high-conversion way for users to select from a menu of options without the friction of typing words or numbers. By organizing choices into sections and rows, you can build complex navigation menus, product directories, or support triage flows that feel native to the WhatsApp ecosystem.\n\n![List.png](https://api.apidog.com/api/v1/projects/1017306/resources/369238/image-preview)\n\n![list options.png](https://api.apidog.com/api/v1/projects/1017306/resources/369239/image-preview)\n\n---\n\n## 🏗️ The List Message Hierarchy\n\nA List message is a multi-layered object designed for clarity and scannability:\n1. **The Header (Title)**: This is the first thing the user sees. It should clearly state the purpose of the menu (e.g., \"Customer Support Menu\").\n2. **The Body (Description)**: Use this for the primary instruction or context (e.g., \"Please select the department you wish to speak with\").\n3. **The Activation Button**: A custom label (max 20 characters) that triggers the overlay.\n4. **Sections and Rows**: The core content. Sections allow you to group related options (e.g., \"Technical Support\" vs. \"Billing Queries\"), while rows represent the individual clickable items.\n\n---\n\n## 🛡️ Strategic Best Practices for Menu Design\n\n### 1. The 10-Row Boundary\nWhatsApp enforces a hard limit of **10 rows** across all sections in a single list.\n- **Developer Action**: If you have 20 products to show, do not try to squeeze them into one list. Instead, use a \"Category\" list first, and then have the user's selection trigger a *second* list message for that specific category. This \"Multi-Step Triage\" prevents the user from being overwhelmed by a single, monolithic menu.\n- **Row Descriptions**: Each row has an optional `description` field. Use this to provide \"Hint Text\" (e.g., \"Fastest response time\") to guide the user's decision process.\n\n### 2. Unique Identifier (rowId) Strategy\nThe `rowId` is for your backend, while the `title` is for the user.\n- **Decoupling**: Never rely on the row title for your logic. Always use a unique, alphanumeric `rowId` (e.g., `dept_billing_v1`). This allows you to change the display text for marketing purposes without breaking your backend processing logic.\n- **State Persistence**: You can include small bits of state metadata in the `rowId` (e.g., `user_123_opt_4`) if your system is completely stateless, though we recommend maintaining user state in your own database associated with the `chatId`.\n\n### 3. Visual Scannability and Emojis\n- **Section Headers**: Use section titles as \"Visual Anchors.\" \n- **Emoji Bullet Points**: Prefix your row titles with emojis (e.g., \"💳 Billing,\" \"🛠️ Technical\"). This significantly reduces the cognitive load on the user, allowing them to find their desired option via icons rather than reading every word.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Automated Product Catalogs\nBuild a mini-storefront within the chat. The first section can be \"New Arrivals,\" and the second \"Best Sellers.\" When a user clicks a row, your **Webhooks** (`list_response`) will capture the `rowId`. Your system can then immediately send an [`/v2/send/image`](/v2/send/image) of that product with a \"Buy Now\" link.\n\n### Intelligent Support Triage\nInstead of a human greeting every user, send a List message. Section 1: \"Urgent Issues,\" Section 2: \"General Info.\" Based on the user's selection, the bot can route the conversation to the most qualified agent or provide an automated knowledge-base article.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Button Text Length**: If your button text exceeds 20 characters, the message will fail to send with a `Validation Error`. Keep it punchy: \"See Options,\" \"Start Here,\" or \"Main Menu.\"\n- **Empty Sections**: Every section must contain at least one row. Sending an empty section will cause a rendering failure on the WhatsApp network.\n- **The \"No Response\" Trap**: Users sometimes open a list but don't select anything. Ensure your bot has a \"Timeout\" or follow-up logic to re-engage the user if they've been inactive for more than 5 minutes after receiving a menu.\n\n---\n\n## Summary of Capabilities:\n- Deliver interactive, overlay-style list menus with up to 10 rows.\n- Support for multiple logically grouped sections with custom titles.\n- High-conversion UX using custom buttons and descriptive row metadata.\n- Real-time interaction tracking via specialized `list_response` Webhook events.\n- Full markdown support for header titles and body descriptions.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/event": {
      "post": {
        "operationId": "_v2_send_event_post",
        "summary": "Send Event",
        "description": "Sends a calendar event message to a chat. Users can tap on the event to view details, add it to their calendar, or join a call.\n\n### Developer Tips\n- **Unix Timestamps**: Double-check your timestamp logic. Ensure you are sending seconds (e.g. 1735920000) not milliseconds.\n\n\n# Orchestrating Time: Mastering the WhatsApp Event Engine\n\nThe `/v2/send/event` endpoint introduces a sophisticated way to manage time and attendance directly within a chat. Instead of sending a plain text reminder that a user might forget, \"Event Messages\" create a professional, structured calendar object. These objects allow users to view duration, location, and description in a dedicated UI and, most importantly, add the event to their local mobile calendar (Google Calendar, iCal, etc.) with a single tap.\n\n![Send Event.png](https://api.apidog.com/api/v1/projects/1017306/resources/369240/image-preview)\n\n---\n\n## 🏗️ The Event Lifecycle Architecture\n\nAn Event message is more than a notification; it's a persistent state-object within the chat:\n1. **Timestamp Precision**: The engine uses Unix timestamps (in seconds) to define the `startTime` and `endTime`. Wawp validates that the end time occurs after the start time and handles the translation of these timestamps into the recipient's local phone time zone automatically.\n2. **Metadata Aggregation**: The `event.name`, `event.description`, and `event.location.name` are aggregated into a native WhatsApp Event packet. This packet is interactive—users can click it to expand a \"Full Details\" view that remains accessible even after the chat has moved on.\n3. **Guest Management**: The `extraGuestsAllowed` flag is a structural signal. If true, it signals to the user that the event is open for broader participation, often used in webinars or community gatherings.\n\n---\n\n## 🛡️ Strategic Best Practices for Event Engagement\n\n### 1. The \"Call-to-Action\" Description\nThe `event.description` is your most valuable text field.\n- **Deep Linking**: If the event is a virtual meeting (Zoom, Google Meet, WhatsApp Call), include the join link directly in the description. Most mobile OSs will recognize the URL and make it clickable within the event details view.\n- **Engagement**: Use the description to provide a high-level agenda. Since the event persists at the top of the chat or in the \"Media/Links/Docs\" section, it acts as a permanent reference point for the user.\n\n### 2. Timezone Integrity\nOne of the biggest causes of missed appointments is timezone confusion.\n- **The Global Standard**: Wawp expects Unix timestamps in **UTC**. Never send timestamps in a local format without first normalizing them to the UTC epoch. \n- **User Experience**: Because Wawp hands the UTC timestamp to the WhatsApp network, the recipient's phone will automatically display the time in *their* local time (e.g., if you send an event for 3 PM UTC, a user in London sees 3 PM, while a user in New York sees 10 AM).\n\n### 3. Location Clarity (Physical vs. Virtual)\n- **Physical Events**: Use the `event.location.name` for the room number or building name. \n- **Virtual Events**: Set the location name to \"💻 Virtual Meeting\" or \"🎥 Live Stream.\" This provides instant visual context before the user even opens the details.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Automated Webinar Onboarding\nWhen a user signs up for a webinar via a bot, trigger a `/v2/send/event` immediately. This allows the user to click \"Add to Calendar\" while their intent is high. Combine this with the `reply_to` parameter to link the event card to their \"Successful Registration\" text message.\n\n### Service Appointment Booking\nFor hair salons, doctors, or repair services, send an event card as soon as the appointment is confirmed. The professional look of an Event card significantly increases the \"Perceived Quality\" of the service and reduces the rate of \"No-Shows\" by integrating with the user's primary planning tool (their calendar).\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Seconds vs. Milliseconds**: A common technical error is sending JS `Date.now()` (which is milliseconds) instead of the required Unix seconds. This will result in an event scheduled thousands of years in the future. Always divide by 1000.\n- **Short Durations**: While WhatsApp allows very short events, we recommend a minimum duration of **15 minutes** to ensure the calendar block is visually significant enough for the user to notice.\n- **The \"Overlapping\" Conflict**: WhatsApp doesn't prevent you from sending overlapping events, but your system should. If a session is already busy, consider using a poll first to find an available slot before sending the final Event card.\n\n---\n\n## Summary of Capabilities:\n- Deliver interactive, native-style WhatsApp Event cards with one-tap calendar integration.\n- Full support for Unix-timestamp based scheduling with automatic timezone normalization.\n- High-fidelity metadata support for event names, descriptions, and custom locations.\n- Structural signaling for guest permissions via the `extraGuestsAllowed` flag.\n- Seamless integration with conversational threads via the `reply_to` parameter.\n- Persistent UI presence within the chat, acting as a permanent reference for scheduled activities.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_INSTANCE_ID"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp number",
            "schema": {
              "type": "string"
            },
            "example": "447441429009"
          },
          {
            "name": "event.name",
            "in": "query",
            "required": true,
            "description": "Name of the event (e.g. Team Meeting 📅)",
            "schema": {
              "type": "string"
            },
            "example": "Team Meeting 📅"
          },
          {
            "name": "event.description",
            "in": "query",
            "required": true,
            "description": "Discussing Q1 Roadmap",
            "schema": {
              "type": "string"
            },
            "example": "Discussing Q1 Roadmap"
          },
          {
            "name": "event.startTime",
            "in": "query",
            "required": true,
            "description": "Start time (Unix timestamp in seconds)",
            "schema": {
              "type": "integer"
            },
            "example": "1735920000"
          },
          {
            "name": "event.endTime",
            "in": "query",
            "required": true,
            "description": "End time (Unix timestamp in seconds)",
            "schema": {
              "type": "integer"
            },
            "example": "1735923600"
          },
          {
            "name": "event.location.name",
            "in": "query",
            "required": true,
            "description": "Meeting Room A",
            "schema": {
              "type": "string"
            },
            "example": "Meeting Room A"
          },
          {
            "name": "event.extraGuestsAllowed",
            "in": "query",
            "required": true,
            "description": "Whether extra guests are allowed",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/voice": {
      "post": {
        "operationId": "_v2_send_voice_post",
        "summary": "Send Voice",
        "description": "Voice messages accept OGG/Opus. Required params: instance_id, access_token, chatId, file[url], file[filename], file[mimetype], convert.\n\n### Developer Tips\n- **Format**: Requires OGG format with Opus codec for PTT (Push-to-Talk) styling.\n- **Experience**: Appears as a playable waveform in the chat.\n\n\n# The Human Touch: Mastering the Voice Messaging Engine\n\nVoice messages are the most personal way to communicate on WhatsApp, often preferred for their convenience and emotional resonance. The `/v2/send/voice` endpoint provides a specialized pipeline for delivering high-fidelity audio notes that appear as the native \"blue-microphone\" messages users expect. Wawp’s voice engine manages the intricate requirements of audio transcoding, MIME-type enforcement, and network buffering to ensure a seamless listening experience.\n\n![send voice.png](https://api.apidog.com/api/v1/projects/1017306/resources/369242/image-preview)\n\n---\n\n## 🏗️ The Intelligent Audio Transcoding Pipeline\n\nWhatsApp is extremely specific about its voice message format. Unlike standard audio file transfers (which appear as documents), true voice notes must be **OGG/Opus** with specific metadata headers. Wawp simplifies this for you:\n1. **Source Evaluation**: The engine analyzes the source file from your `file[url]`. It determines the bitrate, sample rate, and codec.\n2. **The \"Convert\" Logic**: When `convert: true` is set, Wawp initiates a high-performance cloud transcoding process. It takes standard formats like MP3, AAC, or WAV and transforms them into the exact OGG/Opus profile optimized for the WhatsApp mobile app.\n3. **MIME-Type Alignment**: The engine ensures that the emitted file has the correct `audio/ogg; codecs=opus` header, which triggers the specialized \"Voice Note\" UI on the recipient's phone.\n\n---\n\n## 🛡️ Strategic Best Practices for Audio Delivery\n\n### 1. Recording for Quality\nTo ensure your automated voice messages sound professional:\n- **Sample Rate**: Record your source audio at **16kHz or 24kHz**. WhatsApp’s Opus implementation is optimized for these lower-to-mid ranges, and higher fidelity (like 48kHz) often leads to unnecessary file size increases without a perceptible gain in mobile speaker quality.\n- **Mono vs. Stereo**: Always use **Mono**. WhatsApp will down-mix stereo signals anyway, and mono files half the bandwidth requirements for both your server and your user.\n\n### 2. The Conversion Lifecycle\n- **Efficiency Hint**: If your source is already OGG/Opus, you can set `convert: false`. However, we recommend defaulting to `true` to protect against edge cases where the source metadata might be slightly off-spec, which can cause the play button to fail on some Android devices.\n- **Transcoding Latency**: Cloud transcoding adds a small amount of latency (typically 1–3 seconds) to the processing time. Factor this into your application's timeout logic.\n\n### 3. UX and Accessibility\nVoice messaging isn't just about the audio; it's about the context.\n- **Typing Indicator**: Before sending a voice note, call the [`/v2/send/start-typing`](/v2/send/start-typing) endpoint. This creates the \"Typing...\" or \"Recording audio...\" status on the recipient's phone, making the message feel more organic and less like an automated broadcast.\n- **Interactive Feedback**: In your frontend, show a \"Transcoding...\" spinner after the user submits an audio file to manage expectations during the cloud processing phase.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Voice-Powered Notification Banners\nInstead of a text-based order update, send a 5-second voice note saying, \"Hi there! Your order is on the way.\" The personal touch significantly increases engagement and brand loyalty in localized markets.\n\n### Interactive Voice Response (IVR) for WhatsApp\nBuild a support bot where users can send voice notes for queries. Your backend can transcribe the audio using an AI service, and then respond with a pre-recorded voice note via Wawp, creating a truly conversational voice interface.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Mismatched Mime-Types**: Providing a `.mp3` extension with an `audio/ogg` mimetype will often cause the engine to return a `Bad Request`. Ensure your `file[filename]` and `file[mimetype]` align with the actual source file on your server.\n- **Corrupted Headers**: Some audio recorders produce OGG files with non-standard page sizes. If a voice note arrives but won't play, it’s a sign that the headers are corrupted. Enabling `convert: true` almost always fixes this by rebuilding the file from the raw audio stream.\n- **Volume Normalization**: Automated voices can sometimes be too loud or too quiet. We recommend normalizing your source clips to **-3dB** to ensure consistent volume regardless of the recipient's phone settings.\n\n---\n\n## Summary of Capabilities:\n- Deliver native WhatsApp \"Voice Notes\" (OGG/Opus) from any public HTTPS URL.\n- Full support for cloud-based transcoding from MP3, AAC, and WAV via the `convert` flag.\n- Precise integration with threading and replies using the `reply_to` parameter.\n- Consistent success reporting with unique `message_id` generation.\n- Optimized for low-bandwidth mobile consumption while maintaining high vocal clarity.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Publicly accessible HTTPS URL of the audio file",
            "schema": {
              "type": "string"
            },
            "example": "https://raw.githubusercontent.com/rafaelreis-hotmart/Audio-Sample-files/master/sample.ogg"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Filename for the audio note",
            "schema": {
              "type": "string"
            },
            "example": "voice.ogg"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type (audio/ogg; codecs=opus recommended)",
            "schema": {
              "type": "string"
            },
            "example": "audio/ogg; codecs=opus"
          },
          {
            "name": "convert",
            "in": "query",
            "required": true,
            "description": "Automatically transcode to WhatsApp compatible OGG/Opus",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_send_voice_get",
        "summary": "Send Voice",
        "description": "Voice messages accept OGG/Opus. Required params: instance_id, access_token, chatId, file[url], file[filename], file[mimetype], convert.\n\n### Developer Tips\n- **Format**: Requires OGG format with Opus codec for PTT (Push-to-Talk) styling.\n- **Experience**: Appears as a playable waveform in the chat.\n\n\n# The Human Touch: Mastering the Voice Messaging Engine\n\nVoice messages are the most personal way to communicate on WhatsApp, often preferred for their convenience and emotional resonance. The `/v2/send/voice` endpoint provides a specialized pipeline for delivering high-fidelity audio notes that appear as the native \"blue-microphone\" messages users expect. Wawp’s voice engine manages the intricate requirements of audio transcoding, MIME-type enforcement, and network buffering to ensure a seamless listening experience.\n\n![send voice.png](https://api.apidog.com/api/v1/projects/1017306/resources/369242/image-preview)\n\n---\n\n## 🏗️ The Intelligent Audio Transcoding Pipeline\n\nWhatsApp is extremely specific about its voice message format. Unlike standard audio file transfers (which appear as documents), true voice notes must be **OGG/Opus** with specific metadata headers. Wawp simplifies this for you:\n1. **Source Evaluation**: The engine analyzes the source file from your `file[url]`. It determines the bitrate, sample rate, and codec.\n2. **The \"Convert\" Logic**: When `convert: true` is set, Wawp initiates a high-performance cloud transcoding process. It takes standard formats like MP3, AAC, or WAV and transforms them into the exact OGG/Opus profile optimized for the WhatsApp mobile app.\n3. **MIME-Type Alignment**: The engine ensures that the emitted file has the correct `audio/ogg; codecs=opus` header, which triggers the specialized \"Voice Note\" UI on the recipient's phone.\n\n---\n\n## 🛡️ Strategic Best Practices for Audio Delivery\n\n### 1. Recording for Quality\nTo ensure your automated voice messages sound professional:\n- **Sample Rate**: Record your source audio at **16kHz or 24kHz**. WhatsApp’s Opus implementation is optimized for these lower-to-mid ranges, and higher fidelity (like 48kHz) often leads to unnecessary file size increases without a perceptible gain in mobile speaker quality.\n- **Mono vs. Stereo**: Always use **Mono**. WhatsApp will down-mix stereo signals anyway, and mono files half the bandwidth requirements for both your server and your user.\n\n### 2. The Conversion Lifecycle\n- **Efficiency Hint**: If your source is already OGG/Opus, you can set `convert: false`. However, we recommend defaulting to `true` to protect against edge cases where the source metadata might be slightly off-spec, which can cause the play button to fail on some Android devices.\n- **Transcoding Latency**: Cloud transcoding adds a small amount of latency (typically 1–3 seconds) to the processing time. Factor this into your application's timeout logic.\n\n### 3. UX and Accessibility\nVoice messaging isn't just about the audio; it's about the context.\n- **Typing Indicator**: Before sending a voice note, call the [`/v2/send/start-typing`](/v2/send/start-typing) endpoint. This creates the \"Typing...\" or \"Recording audio...\" status on the recipient's phone, making the message feel more organic and less like an automated broadcast.\n- **Interactive Feedback**: In your frontend, show a \"Transcoding...\" spinner after the user submits an audio file to manage expectations during the cloud processing phase.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Voice-Powered Notification Banners\nInstead of a text-based order update, send a 5-second voice note saying, \"Hi there! Your order is on the way.\" The personal touch significantly increases engagement and brand loyalty in localized markets.\n\n### Interactive Voice Response (IVR) for WhatsApp\nBuild a support bot where users can send voice notes for queries. Your backend can transcribe the audio using an AI service, and then respond with a pre-recorded voice note via Wawp, creating a truly conversational voice interface.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Mismatched Mime-Types**: Providing a `.mp3` extension with an `audio/ogg` mimetype will often cause the engine to return a `Bad Request`. Ensure your `file[filename]` and `file[mimetype]` align with the actual source file on your server.\n- **Corrupted Headers**: Some audio recorders produce OGG files with non-standard page sizes. If a voice note arrives but won't play, it’s a sign that the headers are corrupted. Enabling `convert: true` almost always fixes this by rebuilding the file from the raw audio stream.\n- **Volume Normalization**: Automated voices can sometimes be too loud or too quiet. We recommend normalizing your source clips to **-3dB** to ensure consistent volume regardless of the recipient's phone settings.\n\n---\n\n## Summary of Capabilities:\n- Deliver native WhatsApp \"Voice Notes\" (OGG/Opus) from any public HTTPS URL.\n- Full support for cloud-based transcoding from MP3, AAC, and WAV via the `convert` flag.\n- Precise integration with threading and replies using the `reply_to` parameter.\n- Consistent success reporting with unique `message_id` generation.\n- Optimized for low-bandwidth mobile consumption while maintaining high vocal clarity.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Publicly accessible HTTPS URL of the audio file",
            "schema": {
              "type": "string"
            },
            "example": "https://raw.githubusercontent.com/rafaelreis-hotmart/Audio-Sample-files/master/sample.ogg"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Filename for the audio note",
            "schema": {
              "type": "string"
            },
            "example": "voice.ogg"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type (audio/ogg; codecs=opus recommended)",
            "schema": {
              "type": "string"
            },
            "example": "audio/ogg; codecs=opus"
          },
          {
            "name": "convert",
            "in": "query",
            "required": true,
            "description": "Automatically transcode to WhatsApp compatible OGG/Opus",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/video": {
      "post": {
        "operationId": "_v2_send_video_post",
        "summary": "Send Video",
        "description": "Send a video file to a chat.\n\n### Developer Tips\n- **Auto-Download**: Most users have auto-download enabled for videos on Wi-Fi but disabled on data. Consider this for your marketing hooks.\n- **Compression**: Sending raw 4K video is not recommended. Pre-compress your videos to 720p or 480p.\n\n\n# Moving Pictures: Mastering the Video Messaging Engine\n\nVideo is the ultimate medium for complex information delivery, whether it's an educational tutorial, a personalized message from a CEO, or a visually rich product demonstration. The `/v2/send/video` endpoint is engineered to handle the substantial data and processing requirements of video files, ensuring they arrive on the recipient's phone in a format that is ready for instant playback.\n\n---\n\n## 🏗️ The Intelligent Video Processing Pipeline\n\nUnlike basic file transfers, Wawp treats videos as dynamic assets. Our pipeline includes several specialized stages:\n1. **Validation & Mime-Type Consistency**: The engine checks the `file[mimetype]` against the actual binary headers. While MP4 is the standard, our engine can handle various containers and normalize them for the WhatsApp network.\n2. **The \"Conversion\" Engine**: One of Wawp's most powerful features is the `convert` flag. When enabled, the engine evaluates the source video's bitrate, resolution, and encoding (H.264/AAC). If the video is likely to be rejected by WhatsApp due to incompatible parameters, Wawp performs a cloud-based re-encoding to ensure a successful delivery.\n3. **Stream Buffering**: To prevent transient network failures from killing a transfer, our engine uses an adaptive buffering strategy when fetching videos from your remote `file[url]`.\n\n---\n\n## 🛡️ Strategic Best Practices for Video Optimization\n\n### 1. The 16MB Frontier\nWhatsApp has a hard limit of **16MB** for video transfers on most mobile devices.\n- **Developer Action**: If your source video is 50MB, do not send it directly. Use a pre-processing tool or our [`/v2/media/convert`](/v2/media/convert) utility to bring it under the 16MB threshold.\n- **Target Bitrate**: Aim for a bitrate of **1.5 Mbps to 2 Mbps** with a resolution of **480p or 720p**. This strikes the perfect balance between visual clarity and file size safety.\n\n### 2. Formatting for Success (MP4 vs. Others)\nWhile many formats exist, **MP4 (H.264)** is the gold standard for Wawp.\n- **Universal Playback**: By sticking to H.264, you ensure that even users on older Android or iOS devices can play the video instantly without downloading additional codecs.\n- **Audio Sync**: Always ensure your audio is encoded in **AAC** at 44.1kHz or 48kHz to prevent \"Mute Video\" errors on the recipient's device.\n\n### 3. AsNote: The \"Video Note\" Advantage\nThe `asNote` parameter allows you to send videos in the distinctive circular \"Video Note\" format. \n- **UX Impact**: Round video notes feel more personal and spontaneous. They are perfect for \"Thank You\" messages or quick status updates. \n- **Constraint**: Video notes are typically limited to **60 seconds** and do not support captions. Ensure your content fits these constraints when switching to \"Note\" mode.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Educational Drip Campaigns\nVideos are perfect for daily educational content. By using the `caption` field, you can provide a textual summary of the video's key points. Because Wawp supports full markdown, you can use `*bold*` headers to make the caption as engaging as the video itself.\n\n### Customer Support via Screen-Cast\nInstead of explaining a complex UI step-by-step in text, send a 30-second screen-cast. Use the `reply_to` field to link the video directly to the user's specific support ticket, creating a high-resolution support experience.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Failed Fetches**: If your video server is behind a slow connection, the Wawp engine might timeout. Ensure your video host responds to `GET` requests within **5-10 seconds**.\n- **The \"No Thumbnail\" Bug**: If a video arrives but the thumbnail is black, it’s often because the first frame of the video is black. Consider fading into your content or ensuring the metadata isn't corrupted.\n- **Unsupported Codecs**: Attempting to send H.265 (HEVC) or AV1 without setting `convert: true` may lead to a \"Format Not Supported\" error on older devices. Always default to `true` if you aren't 100% sure of your source encoding.\n\n---\n\n## Summary of Capabilities:\n- Deliver high-quality MP4 videos with integrated, markdown-rich captions.\n- Automated cloud-based video re-encoding via the `convert` flag.\n- Support for the \"Video Note\" circular format for high-engagement messaging.\n- Remote fetching from any secure HTTPS URL with adaptive buffering.\n- Consistent success reporting with unique `message_id` generation for full delivery tracking.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Video caption",
            "schema": {
              "type": "string"
            },
            "example": "Watch this clip"
          },
          {
            "name": "convert",
            "in": "query",
            "required": true,
            "description": "Attempt to convert video to compatible MP4 if needed",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "asNote",
            "in": "query",
            "required": true,
            "description": "Send as a round 'Video Note' (if supported by engine)",
            "schema": {
              "type": "boolean"
            },
            "example": "false"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Publicly accessible URL of the video",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/file_example_MP4_480_1_5MG.mp4"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Filename for the video",
            "schema": {
              "type": "string"
            },
            "example": "video.mp4"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type of the video",
            "schema": {
              "type": "string"
            },
            "example": "video/mp4"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_send_video_get",
        "summary": "Send Video",
        "description": "Send a video file to a chat.\n\n### Developer Tips\n- **Auto-Download**: Most users have auto-download enabled for videos on Wi-Fi but disabled on data. Consider this for your marketing hooks.\n- **Compression**: Sending raw 4K video is not recommended. Pre-compress your videos to 720p or 480p.\n\n\n# Moving Pictures: Mastering the Video Messaging Engine\n\nVideo is the ultimate medium for complex information delivery, whether it's an educational tutorial, a personalized message from a CEO, or a visually rich product demonstration. The `/v2/send/video` endpoint is engineered to handle the substantial data and processing requirements of video files, ensuring they arrive on the recipient's phone in a format that is ready for instant playback.\n\n---\n\n## 🏗️ The Intelligent Video Processing Pipeline\n\nUnlike basic file transfers, Wawp treats videos as dynamic assets. Our pipeline includes several specialized stages:\n1. **Validation & Mime-Type Consistency**: The engine checks the `file[mimetype]` against the actual binary headers. While MP4 is the standard, our engine can handle various containers and normalize them for the WhatsApp network.\n2. **The \"Conversion\" Engine**: One of Wawp's most powerful features is the `convert` flag. When enabled, the engine evaluates the source video's bitrate, resolution, and encoding (H.264/AAC). If the video is likely to be rejected by WhatsApp due to incompatible parameters, Wawp performs a cloud-based re-encoding to ensure a successful delivery.\n3. **Stream Buffering**: To prevent transient network failures from killing a transfer, our engine uses an adaptive buffering strategy when fetching videos from your remote `file[url]`.\n\n---\n\n## 🛡️ Strategic Best Practices for Video Optimization\n\n### 1. The 16MB Frontier\nWhatsApp has a hard limit of **16MB** for video transfers on most mobile devices.\n- **Developer Action**: If your source video is 50MB, do not send it directly. Use a pre-processing tool or our [`/v2/media/convert`](/v2/media/convert) utility to bring it under the 16MB threshold.\n- **Target Bitrate**: Aim for a bitrate of **1.5 Mbps to 2 Mbps** with a resolution of **480p or 720p**. This strikes the perfect balance between visual clarity and file size safety.\n\n### 2. Formatting for Success (MP4 vs. Others)\nWhile many formats exist, **MP4 (H.264)** is the gold standard for Wawp.\n- **Universal Playback**: By sticking to H.264, you ensure that even users on older Android or iOS devices can play the video instantly without downloading additional codecs.\n- **Audio Sync**: Always ensure your audio is encoded in **AAC** at 44.1kHz or 48kHz to prevent \"Mute Video\" errors on the recipient's device.\n\n### 3. AsNote: The \"Video Note\" Advantage\nThe `asNote` parameter allows you to send videos in the distinctive circular \"Video Note\" format. \n- **UX Impact**: Round video notes feel more personal and spontaneous. They are perfect for \"Thank You\" messages or quick status updates. \n- **Constraint**: Video notes are typically limited to **60 seconds** and do not support captions. Ensure your content fits these constraints when switching to \"Note\" mode.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Educational Drip Campaigns\nVideos are perfect for daily educational content. By using the `caption` field, you can provide a textual summary of the video's key points. Because Wawp supports full markdown, you can use `*bold*` headers to make the caption as engaging as the video itself.\n\n### Customer Support via Screen-Cast\nInstead of explaining a complex UI step-by-step in text, send a 30-second screen-cast. Use the `reply_to` field to link the video directly to the user's specific support ticket, creating a high-resolution support experience.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Failed Fetches**: If your video server is behind a slow connection, the Wawp engine might timeout. Ensure your video host responds to `GET` requests within **5-10 seconds**.\n- **The \"No Thumbnail\" Bug**: If a video arrives but the thumbnail is black, it’s often because the first frame of the video is black. Consider fading into your content or ensuring the metadata isn't corrupted.\n- **Unsupported Codecs**: Attempting to send H.265 (HEVC) or AV1 without setting `convert: true` may lead to a \"Format Not Supported\" error on older devices. Always default to `true` if you aren't 100% sure of your source encoding.\n\n---\n\n## Summary of Capabilities:\n- Deliver high-quality MP4 videos with integrated, markdown-rich captions.\n- Automated cloud-based video re-encoding via the `convert` flag.\n- Support for the \"Video Note\" circular format for high-engagement messaging.\n- Remote fetching from any secure HTTPS URL with adaptive buffering.\n- Consistent success reporting with unique `message_id` generation for full delivery tracking.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Video caption",
            "schema": {
              "type": "string"
            },
            "example": "Watch this clip"
          },
          {
            "name": "convert",
            "in": "query",
            "required": true,
            "description": "Attempt to convert video to compatible MP4 if needed",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "asNote",
            "in": "query",
            "required": true,
            "description": "Send as a round 'Video Note' (if supported by engine)",
            "schema": {
              "type": "boolean"
            },
            "example": "false"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Publicly accessible URL of the video",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/file_example_MP4_480_1_5MG.mp4"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Filename for the video",
            "schema": {
              "type": "string"
            },
            "example": "video.mp4"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type of the video",
            "schema": {
              "type": "string"
            },
            "example": "video/mp4"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/link-preview": {
      "post": {
        "operationId": "_v2_send_link-preview_post",
        "summary": "Send Link Preview",
        "description": "Send a message with a custom rich link preview card.\n\n### Developer Tips\n- **Marketing Power**: Use custom titles and descriptions to create compelling Call-to-Actions (CTAs) that standard links cannot provide.\n- **High Quality Flag**: The `linkPreviewHighQuality` flag attempts to render a larger image card, which takes more visual space in the chat.\n\n# Click-Through Authority: Mastering the Rich Link Preview Engine\n\nIn a vertical feed of text and media, a \"Rich Link Preview\" (`/v2/send/link-preview`) is the most effective way to drive traffic from a WhatsApp chat to an external web property. While standard apps generate previews only when a human slow-types a URL, Wawp allows you to programmatically **force** a high-fidelity preview card. This is essential for professional broadcasts, product links, and personalized landing pages where you want total control over the visual branding and the narrative.\n\n---\n\n## 🏗️ The Link-Card Synthetic Engine\n\nWawp’s link engine doesn't just \"scrape\" the destination; it actively constructs a synthetic OpenGraph card:\n1. **Metadata Override**: Unlike standard link sharing, Wawp allows you to override the `title`, `description`, and `thumbnail` even if the destination website has no metadata or blocked crawlers. This ensures your link always looks professional.\n2. **Binary Fetching**: The engine retrieves your custom `thumbnail` and optimizes it for the WhatsApp mobile app. It supports **JPEG** and **PNG**, ensuring the thumbnail loads instantly even on poor connections.\n3. **The High-Quality Mesh**: Setting `linkPreviewHighQuality: true` triggers a specialized rendering mode. If the recipient's phone supports it, WhatsApp will render a much larger image card (similar to a native image message) instead of the small square icon. This drastically increases the \"Visual Real-Estate\" your message occupies in the user's thread.\n\n---\n\n## 🛡️ Strategic Best Practices for Click-Through Rates (CTR)\n\n### 1. The \"Call-to-Action\" Title\nYour `title` should be a directive, not just a label.\n- **Example**: Instead of \"Our Blog,\" use \"🔥 Read Now: 5 Ways to Scale your API.\"\n- **UX Impact**: High-action titles combined with a high-quality preview card can increase CTR by up to **400%** compared to a raw URL string.\n\n### 2. Thumbnail Composition\nThe thumbnail is the visual anchor of the card.\n- **Ratio**: Use **1:1 (Square)** images for standard previews or **1.91:1 (Wide)** images if you are using the `linkPreviewHighQuality` flag.\n- **Clarity**: Avoid putting small text in the thumbnail. Because thumbnails are compressed and rendered small on mobile screens, use bold icons or clear photography that represents the link's destination.\n\n### 3. URL Transparency and Hygiene\n- **Text Inclusion**: The `text` field allows you to provide a preceding message (e.g., \"Check this out:\"). We recommend including the URL again at the end of the text field as a fallback for the rare cases where a user's phone has preview rendering disabled.\n- **Tracking**: Use UTM parameters in your `url` (e.g., `?utm_source=whatsapp&utm_medium=wawp`). This allows you to measure the exact effectiveness of your API campaigns in your analytics dashboard.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Dynamic Checkout Previews\nWhen a user adds an item to their cart, send them a link preview of the checkout page. Use a custom `thumbnail` that shows the exact product they are buying. This creates a deeply personalized and trustworthy path to purchase directly within the chat.\n\n### Content Gating and Personalized Reports\nIf you provide personalized PDF reports or secure dashboard links, use the `/v2/send/link-preview` to create a \"Dashboard Card.\" Use the `description` to show a snippet of the user's data (e.g., \"Your Q1 Savings: $1,250\"), encouraging them to click through to the full site for the detailed breakdown.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Blocked Crawlers**: If you rely on auto-previews (not providing a custom thumbnail), the WhatsApp network may fail to scrape sites behind Cloudflare or login screens. Always provide your own **Custom Thumbnail URL** to ensure 100% reliability.\n- **Image Type Errors**: Using a `thumbnail` URL that points to a WebP or SVG file will often result in a generic \"Link\" icon with no image. Stick to standard **JPEG** for the highest compatibility.\n- **Protocol Requirements**: The `url` and `thumbnail` must both use the **HTTPS** protocol. Unsecured HTTP links will frequently be rejected or show security warnings to the recipient.\n\n---\n\n## Summary of Capabilities:\n- Programmatically force high-fidelity interactive link cards with or without OpenGraph support.\n- Full control over Title, Description, and Thumbnail metadata overrides.\n- \"High Quality\" mode for large-format visual cards with extreme visibility.\n- Seamless conversion from raw URLs to \"App-like\" interactive elements.\n- Integrated threading support via the `reply_to` parameter for contextual sharing.\n- Reliable delivery tracking with integrated `message_id` generation.",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number with country code",
            "schema": {
              "type": "string"
            },
            "example": "447441429009"
          },
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "The URL to preview",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net"
          },
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "Optional text message accompanying the link.",
            "schema": {
              "type": "string"
            },
            "example": "Check out our new website!"
          },
          {
            "name": "thumbnail",
            "in": "query",
            "required": true,
            "description": "URL for a custom thumbnail image (JPEG/PNG)",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/cat.jpg"
          },
          {
            "name": "title",
            "in": "query",
            "required": true,
            "description": "Custom title for the preview card",
            "schema": {
              "type": "string"
            },
            "example": "Wawp - Advanced WhatsApp API"
          },
          {
            "name": "description",
            "in": "query",
            "required": true,
            "description": "Custom description for the preview card",
            "schema": {
              "type": "string"
            },
            "example": "The ultimate platform for WhatsApp automation."
          },
          {
            "name": "linkPreviewHighQuality",
            "in": "query",
            "required": true,
            "description": "Try to generate a larger, high-quality preview",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of a message to reply to",
            "schema": {
              "type": "string"
            },
            "example": "null"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_send_link-preview_get",
        "summary": "Send Link Preview",
        "description": "Send a message with a custom rich link preview card.\n\n### Developer Tips\n- **Marketing Power**: Use custom titles and descriptions to create compelling Call-to-Actions (CTAs) that standard links cannot provide.\n- **High Quality Flag**: The `linkPreviewHighQuality` flag attempts to render a larger image card, which takes more visual space in the chat.\n\n# Click-Through Authority: Mastering the Rich Link Preview Engine\n\nIn a vertical feed of text and media, a \"Rich Link Preview\" (`/v2/send/link-preview`) is the most effective way to drive traffic from a WhatsApp chat to an external web property. While standard apps generate previews only when a human slow-types a URL, Wawp allows you to programmatically **force** a high-fidelity preview card. This is essential for professional broadcasts, product links, and personalized landing pages where you want total control over the visual branding and the narrative.\n\n---\n\n## 🏗️ The Link-Card Synthetic Engine\n\nWawp’s link engine doesn't just \"scrape\" the destination; it actively constructs a synthetic OpenGraph card:\n1. **Metadata Override**: Unlike standard link sharing, Wawp allows you to override the `title`, `description`, and `thumbnail` even if the destination website has no metadata or blocked crawlers. This ensures your link always looks professional.\n2. **Binary Fetching**: The engine retrieves your custom `thumbnail` and optimizes it for the WhatsApp mobile app. It supports **JPEG** and **PNG**, ensuring the thumbnail loads instantly even on poor connections.\n3. **The High-Quality Mesh**: Setting `linkPreviewHighQuality: true` triggers a specialized rendering mode. If the recipient's phone supports it, WhatsApp will render a much larger image card (similar to a native image message) instead of the small square icon. This drastically increases the \"Visual Real-Estate\" your message occupies in the user's thread.\n\n---\n\n## 🛡️ Strategic Best Practices for Click-Through Rates (CTR)\n\n### 1. The \"Call-to-Action\" Title\nYour `title` should be a directive, not just a label.\n- **Example**: Instead of \"Our Blog,\" use \"🔥 Read Now: 5 Ways to Scale your API.\"\n- **UX Impact**: High-action titles combined with a high-quality preview card can increase CTR by up to **400%** compared to a raw URL string.\n\n### 2. Thumbnail Composition\nThe thumbnail is the visual anchor of the card.\n- **Ratio**: Use **1:1 (Square)** images for standard previews or **1.91:1 (Wide)** images if you are using the `linkPreviewHighQuality` flag.\n- **Clarity**: Avoid putting small text in the thumbnail. Because thumbnails are compressed and rendered small on mobile screens, use bold icons or clear photography that represents the link's destination.\n\n### 3. URL Transparency and Hygiene\n- **Text Inclusion**: The `text` field allows you to provide a preceding message (e.g., \"Check this out:\"). We recommend including the URL again at the end of the text field as a fallback for the rare cases where a user's phone has preview rendering disabled.\n- **Tracking**: Use UTM parameters in your `url` (e.g., `?utm_source=whatsapp&utm_medium=wawp`). This allows you to measure the exact effectiveness of your API campaigns in your analytics dashboard.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Dynamic Checkout Previews\nWhen a user adds an item to their cart, send them a link preview of the checkout page. Use a custom `thumbnail` that shows the exact product they are buying. This creates a deeply personalized and trustworthy path to purchase directly within the chat.\n\n### Content Gating and Personalized Reports\nIf you provide personalized PDF reports or secure dashboard links, use the `/v2/send/link-preview` to create a \"Dashboard Card.\" Use the `description` to show a snippet of the user's data (e.g., \"Your Q1 Savings: $1,250\"), encouraging them to click through to the full site for the detailed breakdown.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Blocked Crawlers**: If you rely on auto-previews (not providing a custom thumbnail), the WhatsApp network may fail to scrape sites behind Cloudflare or login screens. Always provide your own **Custom Thumbnail URL** to ensure 100% reliability.\n- **Image Type Errors**: Using a `thumbnail` URL that points to a WebP or SVG file will often result in a generic \"Link\" icon with no image. Stick to standard **JPEG** for the highest compatibility.\n- **Protocol Requirements**: The `url` and `thumbnail` must both use the **HTTPS** protocol. Unsecured HTTP links will frequently be rejected or show security warnings to the recipient.\n\n---\n\n## Summary of Capabilities:\n- Programmatically force high-fidelity interactive link cards with or without OpenGraph support.\n- Full control over Title, Description, and Thumbnail metadata overrides.\n- \"High Quality\" mode for large-format visual cards with extreme visibility.\n- Seamless conversion from raw URLs to \"App-like\" interactive elements.\n- Integrated threading support via the `reply_to` parameter for contextual sharing.\n- Reliable delivery tracking with integrated `message_id` generation.",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number with country code",
            "schema": {
              "type": "string"
            },
            "example": "447441429009"
          },
          {
            "name": "url",
            "in": "query",
            "required": true,
            "description": "The URL to preview",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net"
          },
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "Optional text message accompanying the link.",
            "schema": {
              "type": "string"
            },
            "example": "Check out our new website!"
          },
          {
            "name": "thumbnail",
            "in": "query",
            "required": true,
            "description": "URL for a custom thumbnail image (JPEG/PNG)",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/cat.jpg"
          },
          {
            "name": "title",
            "in": "query",
            "required": true,
            "description": "Custom title for the preview card",
            "schema": {
              "type": "string"
            },
            "example": "Wawp - Advanced WhatsApp API"
          },
          {
            "name": "description",
            "in": "query",
            "required": true,
            "description": "Custom description for the preview card",
            "schema": {
              "type": "string"
            },
            "example": "The ultimate platform for WhatsApp automation."
          },
          {
            "name": "linkPreviewHighQuality",
            "in": "query",
            "required": true,
            "description": "Try to generate a larger, high-quality preview",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of a message to reply to",
            "schema": {
              "type": "string"
            },
            "example": "null"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/location": {
      "post": {
        "operationId": "_v2_send_location_post",
        "summary": "Send Location",
        "description": "Send a static geographic location to a chat.\n\n### Developer Tips\n- **Exact Coordinates**: Always Use GPS-accurate decimal coordinates. Avoid rounding to ensure the pin lands exactly on the right roof.\n- **Apple/Google Maps**: The \"title\" and \"message\" fields often appear as the label in the recipient's map app.\n\n\n# Precision Positioning: Mastering the Geographic Location Engine\n\nLocation sharing is a powerful tool for bridging the gap between the digital conversation and the physical world. Whether you are helping a customer find a brick-and-mortar store, directing a delivery rider to a precise drop-off point, or organizing a physical meetup, the `/v2/send/location` endpoint provides a reliable way to send interactive map pins directly into a WhatsApp chat. \n\n---\n\n## 🏗️ The Geolocation Pipeline: From Data to Pin\n\nWhen you call the `/send/location` endpoint, Wawp’s engine translates raw geographic data into a rich, interactive bubble on the recipient's phone:\n1. **Coordinate Verification**: The engine accepts `latitude` and `longitude` as decimal strings. It validates that these coordinates fall within the valid ranges (-90 to 90 for latitude, -180 to 180 for longitude).\n2. **Metadata Injection**: The `title` and `message` fields are injected into the message's metadata. These don't just appear on the bubble; they are often used as the \"Label\" when the user clicks the pin and opens it in external apps like Google Maps or Waze.\n3. **Interactive Rendering**: Wawp ensures the resulting message is rendered with a clickable map thumbnail. This thumbnail is generated by the WhatsApp network based on the coordinates provided, giving the user an instant visual \"Context\" of the surrounding area.\n\n---\n\n## 🛡️ Strategic Best Practices for Geographic Data\n\n### 1. Decimal Precision (The Roof-Top Rule)\nFor location data, precision is everything. \n- **Developer Action**: Use at least **6 decimal places** for your coordinates (e.g., `38.893725`). This level of precision is accurate to approximately 0.1 meters—the difference between a pin landing on a building's roof and landing in the middle of a busy intersection.\n- **Safety**: Avoid rounding coordinates in your backend, as even slight changes in the 4th decimal place can shift a location by dozens of meters.\n\n### 2. Crafting Meaningful Labels\nThe `title` and `message` fields are your chance to provide brand clarity.\n- **Title (Place Name)**: Use the name of the destination (e.g., \"Grand Plaza Hotel - Main Entrance\"). \n- **Message (Context/Address)**: Use this for the specific address or helpful hints (e.g., \"1st Floor, next to the fountain\"). \n- **UX Impact**: High-quality labels reduce user anxiety and make the automated message feel deliberate and professional.\n\n### 3. Static vs. Dynamic Locations\n- **Static Pins**: This endpoint sends a **Static Pin**. It represents a specific \"Snapshot\" in space. \n- **Live Location**: Note that Wawp currently focuses on static pins for high-concurrency business flows. If your use case requires a real-time moving dot (Live Location), we recommend combining static pins with regular text updates or external tracking links via [`/v2/send/link-preview`](/v2/send/link-preview).\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Last-Mile Delivery Support\nIn a delivery app, as soon as the rider clicks \"Arrived,\" your system can automatically send the exact location pin to the customer. This enables the customer to open the pin in their preferred navigation app to cross-verify the rider's position, drastically reducing support calls.\n\n### Geo-Fenced Personalized Offers\nIf your system detects a user is near a specific retail branch, you can trigger an automated \"Welcome\" message that includes the location pin for that exact branch. Using the `reply_to` parameter, you can link this location to a specific discount coupon message, creating a highly relevant \"Online-to-Offline\" funnel.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Swapped Coordinates**: Mixing up latitude and longitude is a common developer error that results in pins landing in the middle of the ocean. Always double-check your coordinate pairs.\n- **Blank Labels**: Sending a location with an empty `title` often results in a generic \"Location\" bubble. To maintain brand authority, always provide a descriptive title.\n- **Coordinate Strings**: Ensure you send the coordinates as strings through the API to prevent floating-point precision loss that sometimes occurs with JSON number types at high decimal counts.\n\n---\n\n## Summary of Capabilities:\n- Send interactive, clickable static map pins with custom titles and addresses.\n- High-precision support for decimal coordinates (latitude/longitude).\n- Seamless integration with Google Maps, Apple Maps, and Waze for the end-user.\n- Support for complex thread-nesting via the `reply_to` parameter.\n- Reliable success reporting with unique `message_id` generation for full delivery tracking.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp number",
            "schema": {
              "type": "string"
            },
            "example": "447441429009"
          },
          {
            "name": "latitude",
            "in": "query",
            "required": true,
            "description": "Geographic latitude (e.g. 38.8937255)",
            "schema": {
              "type": "string"
            },
            "example": "38.8937255"
          },
          {
            "name": "longitude",
            "in": "query",
            "required": true,
            "description": "Geographic longitude (e.g. -77.0969763)",
            "schema": {
              "type": "string"
            },
            "example": "-77.0969763"
          },
          {
            "name": "title",
            "in": "query",
            "required": true,
            "description": "Name of the place (e.g., 'Our Office')",
            "schema": {
              "type": "string"
            },
            "example": "Our office"
          },
          {
            "name": "message",
            "in": "query",
            "required": true,
            "description": "Address or additional description text",
            "schema": {
              "type": "string"
            },
            "example": "123 Main St, New York"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "Message ID to reply to",
            "schema": {
              "type": "string"
            },
            "example": "null"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_send_location_get",
        "summary": "Send Location",
        "description": "Send a static geographic location to a chat.\n\n### Developer Tips\n- **Exact Coordinates**: Always Use GPS-accurate decimal coordinates. Avoid rounding to ensure the pin lands exactly on the right roof.\n- **Apple/Google Maps**: The \"title\" and \"message\" fields often appear as the label in the recipient's map app.\n\n\n# Precision Positioning: Mastering the Geographic Location Engine\n\nLocation sharing is a powerful tool for bridging the gap between the digital conversation and the physical world. Whether you are helping a customer find a brick-and-mortar store, directing a delivery rider to a precise drop-off point, or organizing a physical meetup, the `/v2/send/location` endpoint provides a reliable way to send interactive map pins directly into a WhatsApp chat. \n\n---\n\n## 🏗️ The Geolocation Pipeline: From Data to Pin\n\nWhen you call the `/send/location` endpoint, Wawp’s engine translates raw geographic data into a rich, interactive bubble on the recipient's phone:\n1. **Coordinate Verification**: The engine accepts `latitude` and `longitude` as decimal strings. It validates that these coordinates fall within the valid ranges (-90 to 90 for latitude, -180 to 180 for longitude).\n2. **Metadata Injection**: The `title` and `message` fields are injected into the message's metadata. These don't just appear on the bubble; they are often used as the \"Label\" when the user clicks the pin and opens it in external apps like Google Maps or Waze.\n3. **Interactive Rendering**: Wawp ensures the resulting message is rendered with a clickable map thumbnail. This thumbnail is generated by the WhatsApp network based on the coordinates provided, giving the user an instant visual \"Context\" of the surrounding area.\n\n---\n\n## 🛡️ Strategic Best Practices for Geographic Data\n\n### 1. Decimal Precision (The Roof-Top Rule)\nFor location data, precision is everything. \n- **Developer Action**: Use at least **6 decimal places** for your coordinates (e.g., `38.893725`). This level of precision is accurate to approximately 0.1 meters—the difference between a pin landing on a building's roof and landing in the middle of a busy intersection.\n- **Safety**: Avoid rounding coordinates in your backend, as even slight changes in the 4th decimal place can shift a location by dozens of meters.\n\n### 2. Crafting Meaningful Labels\nThe `title` and `message` fields are your chance to provide brand clarity.\n- **Title (Place Name)**: Use the name of the destination (e.g., \"Grand Plaza Hotel - Main Entrance\"). \n- **Message (Context/Address)**: Use this for the specific address or helpful hints (e.g., \"1st Floor, next to the fountain\"). \n- **UX Impact**: High-quality labels reduce user anxiety and make the automated message feel deliberate and professional.\n\n### 3. Static vs. Dynamic Locations\n- **Static Pins**: This endpoint sends a **Static Pin**. It represents a specific \"Snapshot\" in space. \n- **Live Location**: Note that Wawp currently focuses on static pins for high-concurrency business flows. If your use case requires a real-time moving dot (Live Location), we recommend combining static pins with regular text updates or external tracking links via [`/v2/send/link-preview`](/v2/send/link-preview).\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Last-Mile Delivery Support\nIn a delivery app, as soon as the rider clicks \"Arrived,\" your system can automatically send the exact location pin to the customer. This enables the customer to open the pin in their preferred navigation app to cross-verify the rider's position, drastically reducing support calls.\n\n### Geo-Fenced Personalized Offers\nIf your system detects a user is near a specific retail branch, you can trigger an automated \"Welcome\" message that includes the location pin for that exact branch. Using the `reply_to` parameter, you can link this location to a specific discount coupon message, creating a highly relevant \"Online-to-Offline\" funnel.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Swapped Coordinates**: Mixing up latitude and longitude is a common developer error that results in pins landing in the middle of the ocean. Always double-check your coordinate pairs.\n- **Blank Labels**: Sending a location with an empty `title` often results in a generic \"Location\" bubble. To maintain brand authority, always provide a descriptive title.\n- **Coordinate Strings**: Ensure you send the coordinates as strings through the API to prevent floating-point precision loss that sometimes occurs with JSON number types at high decimal counts.\n\n---\n\n## Summary of Capabilities:\n- Send interactive, clickable static map pins with custom titles and addresses.\n- High-precision support for decimal coordinates (latitude/longitude).\n- Seamless integration with Google Maps, Apple Maps, and Waze for the end-user.\n- Support for complex thread-nesting via the `reply_to` parameter.\n- Reliable success reporting with unique `message_id` generation for full delivery tracking.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp number",
            "schema": {
              "type": "string"
            },
            "example": "447441429009"
          },
          {
            "name": "latitude",
            "in": "query",
            "required": true,
            "description": "Geographic latitude (e.g. 38.8937255)",
            "schema": {
              "type": "string"
            },
            "example": "38.8937255"
          },
          {
            "name": "longitude",
            "in": "query",
            "required": true,
            "description": "Geographic longitude (e.g. -77.0969763)",
            "schema": {
              "type": "string"
            },
            "example": "-77.0969763"
          },
          {
            "name": "title",
            "in": "query",
            "required": true,
            "description": "Name of the place (e.g., 'Our Office')",
            "schema": {
              "type": "string"
            },
            "example": "Our office"
          },
          {
            "name": "message",
            "in": "query",
            "required": true,
            "description": "Address or additional description text",
            "schema": {
              "type": "string"
            },
            "example": "123 Main St, New York"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "Message ID to reply to",
            "schema": {
              "type": "string"
            },
            "example": "null"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/poll": {
      "post": {
        "operationId": "_v2_send_poll_post",
        "summary": "Send Poll",
        "description": "Send an interactive poll with multiple options.\n\n### Developer Tips\n- **Engagement Booster**: Polls have the highest response rate for customer feedback surveys.\n- **Option Limit**: Keep options under 5 for the best mobile experience. Too many choices can lead to \"decision fatigue\".\n\n\n# Democracy in Chat: Mastering the Interactive Poll Engine\n\nPolls (`/v2/send/poll`) are the gold standard for gathering structured feedback in a conversational environment. They eliminate the \"Decision Fatigue\" associated with typing out text responses and provide a clean, visual way for users to express preferences. In a Wawp-powered application, polls act as interactive data entry points that can trigger complex backend workflows based on user selection.\n\n---\n\n## 🏗️ The Multi-Option Synchronization Pipeline\n\nWhen you call the `/send/poll` endpoint, Wawp initiates a specialized synchronization flow:\n1. **Schema Validation**: The engine verifies that your `options` array contains at least two choices and does not exceed the WhatsApp maximum of **12 options**. It also ensures each option string is under 255 characters.\n2. **Metadata Consistency**: The `name` (your question) and `options` are serialized into a native WhatsApp Poll packet. Wawp maintains a mapping between these string options and their internal index IDs, ensuring that when a user votes, you get a clean, predictable value in your Webhook.\n3. **The MultipleAnswers Logic**: Setting `multipleAnswers: true` instructs the WhatsApp network to render checkboxes instead of radio buttons. This changes the fundamental nature of the engagement from a \"Choice\" to a \"Survey,\" allowing for more complex data collection.\n\n---\n\n## 🛡️ Strategic Best Practices for Feedback Engagement\n\n### 1. The \"Power of Five\" Rule\nWhile you *can* send 12 options, research indicates that conversion drops significantly after five.\n- **UX Impact**: On mobile screens, long polls require scrolling, which leads to user abandonment. Keep your most important choices in the top three slots.\n- **Clarity**: Use emojis in your option strings (e.g., \"✅ Yes,\" \"❌ No\") to provide immediate visual cues that transcend language barriers.\n\n### 2. High-Fidelity Vote Tracking\nA poll is only as good as the data it produces.\n- **Monitoring**: Always use **Webhooks** (`poll.vote`) to capture user interaction. When a user changes their vote, WhatsApp sends a new event. Your backend should be idempotent, updating the user's choice based on the latest `poll_vote` timestamp.\n- **De-duplication**: In `multipleAnswers` mode, remember to handle arrays of choices. Every time a user checks or unchecks a box, a new event is triggered reflecting the *entire current state* of that user's selections.\n\n### 3. Contextual Follow-ups\nDon't let a vote be the end of the conversation.\n- **Workflow**: When your webhook receives a vote for Option A, have your system automatically trigger a [`/v2/send/text`](/v2/send/text) or [`/v2/send/image`](/v2/send/image) that specifically addresses that choice. This \"Decision-Tree\" automation makes the bot feel intelligent and responsive.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Real-Time Event Scheduling\nSend a poll with time slots for a meeting: \"When are you free? 1) 10 AM, 2) 2 PM, 3) 4 PM.\" As users vote, your system can see which slot has the most votes in real-time and send a confirmation once a consensus is reached.\n\n### Customer Satisfaction (CSAT) Surveys\nInstead of asking \"Rate us 1 to 5,\" send a poll with descriptive stars or labels: \"⭐ Poor\" to \"⭐⭐⭐⭐⭐ Excellent.\" The visual feedback of the \"Voted\" indicator on the user's screen provides a sense of closure that a text-based reply cannot match.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Duplicate Options**: Sending a poll with two identical option strings will cause the WhatsApp network to reject the message. Always ensure your options are unique in your backend logic.\n- **The \"Lost Vote\" Trap**: Unlike text messages, votes are binary updates. If a user votes while your webhook server is down, you may miss the event. We recommend using our **Polling Logs** or a robust message queue to process delayed webhook deliveries.\n- **Question Length**: A question that is too long can be truncated on the chat preview. Keep your `name` concise and put the detailed context in a preceding text message.\n\n---\n\n## Summary of Capabilities:\n- Deliver native, interactive WhatsApp polls with up to 12 custom options.\n- Support for Single-Choice (Radio) and Multi-Choice (Checkbox) modes.\n- Real-time vote tracking via consistent `poll_vote` Webhook events.\n- Advanced threading support using the `reply_to` parameter.\n- High-fidelity synchronization between poll question and selectable choice indices.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number or group ID",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "poll",
            "in": "query",
            "required": true,
            "description": "The poll structure containing name and options.",
            "schema": {
              "type": "string"
            },
            "example": "{\n  \"name\": \"How are you?\",\n  \"options\": [\n    \"Awesome!\",\n    \"Good!\",\n    \"Not bad!\"\n  ],\n  \"multipleAnswers\": true\n}"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "Message ID to reply to",
            "schema": {
              "type": "string"
            },
            "example": "null"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/poll/vote": {
      "post": {
        "operationId": "_v2_send_poll_vote_post",
        "summary": "Send Poll Vote",
        "description": "Programmatically vote on a WhatsApp poll.\n\n\n# Programmatic Participation: Mastering the Poll Vote Engine\n\nIn highly automated environments, bots often need to participate in the decision-making process alongside human users. The `/v2/send/poll/vote` endpoint provides the capability to cast, change, or rescind votes on existing WhatsApp polls programmatically. This enables complex \"Bot-in-the-Loop\" scenarios where an AI agent can express its findings, preferences, or status via the native interactive poll UI.\n\n---\n\n## 🏗️ The Programmatic Voting Architecture\n\nDynamic voting via an API requires a precise understanding of the poll's state machine:\n1. **Target Attachment**: The engine requires a valid `messageId` of a previously sent poll. This ensures the vote is anchored to the correct interactive context.\n2. **Option Indexing**: Wawp allows you to vote using either the literal string name of an option (e.g., `\"Awesome!\"`) or its 0-indexed position within the poll. Our engine automatically resolves these to the internal binary IDs required by the WhatsApp network, preventing \"Ghost Vote\" errors.\n3. **State Overwriting**: WhatsApp follows an \"Overwrite\" model for voting. When you call this endpoint, your new `votes` array completely replaces your previous selection for that poll. If you send an empty array `[]`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Mechanism',\n            content: 'Casts a vote on an existing poll message.'\n        },\n        {\n            type: 'warning',\n            title: 'Validation',\n            content: 'Fails if the poll is closed or the option ID is invalid.'\n        }\n    ],\n  recommendations: [\n        \"Verify the Poll Message ID before attempting to vote.\",\n        \"Use this for automated testing of poll workflows.\"\n    ]\n  \n   your previous vote is retracted entirely.\n\n---\n\n## 🛡️ Strategic Best Practices for Bot Participation\n\n### 1. Verification Before Voting\nTo ensure high reliability, your system should verify the poll exists and is still \"active.\"\n- **Implementation**: Before voting, check your local database or use a listener to confirm the poll hasn't been deleted. Programmatically voting on a non-existent or expired poll will return a `Message Not Found` error.\n- **Timing**: Avoid voting immediately (within milliseconds) after a poll is created by another user. Adding a small delay (1–2 seconds) mimics natural processing time and ensures the poll has fully propagated across the WhatsApp WebSocket mesh.\n\n### 2. Managing Multi-Answer Logic\nThe `votes` parameter is an array for a reason. \n- **Checkboxes vs. Radio Buttons**: If the original poll was created with `multipleAnswers: true`, your array can contain multiple indices (e.g., `[0, 2]`). If it was a single-choice poll, provided arrays with more than one element will typically result in only the *last* item being counted by the WhatsApp client UI.\n- **UX Consistency**: Ensure your bot's votes align with any previous text-based statements it made to avoid confusing human participants.\n\n### 3. The Power of Selective Retraction\nProgrammatic voting allows for \"Temporary Consensus.\"\n- **Scenario**: Your bot can vote for an option while it's \"investigating\" a problem, and then retract its vote or switch to a \"Success\" option once the investigation is complete. This provides a visual progress indicator that is much more subtle and professional than spamming the chat with status messages.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Automated Consensus Building\nBuild a \"Moderator Bot\" that monitors a group poll. Once a specific option reaches a threshold (e.g., 5 votes), the bot can cast its own vote for that option to \"Seal the Deal\" and then automatically trigger a coordination message or calendar invite.\n\n### Sentiment Re-alignment\nIn an AI-driven support flow, if a user starts a poll to rate their experience, the bot can programmatically vote for the \"Neutral\" option initially. As the conversation improves and sentiment analysis scores rise, the bot can update its vote to \"Positive,\" providing the human agent with a visual cue of the AI's current assessment of the interaction.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **License Barriers**: Ensure your instance is correctly provisioned before integrating programmatic voting into your production workflow.\n- **Case Sensitivity**: When voting via string names, ensured your strings match the poll options *exactly* (including case and trailing spaces). A mismatch will cause the vote to be ignored or return an error. Using **Indices** (integers) is the recommended best practice for high-reliability systems.\n- **Race Conditions**: If multiple instances of your bot attempt to update a vote on the same poll simultaneously, the last request received by the Wawp proxy will define the final state. Use a centralized queue or locking mechanism in your backend if you have multiple bot clusters interacting with the same chat.\n\n---\n\n## Summary of Capabilities:\n- Programmatically cast, update, or retract votes on native WhatsApp polls.\n- Support for voting by literal option strings or numeric indices.\n- Exclusive for advanced automation and AI integration.\n- Full support for multi-choice (checkbox) and single-choice (radio) poll architectures.\n- Real-time synchronization with the WhatsApp network for instantaneous UI updates on recipient devices.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number or group ID",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "messageId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the poll message",
            "schema": {
              "type": "string"
            },
            "example": "ABC123456789"
          },
          {
            "name": "votes",
            "in": "query",
            "required": true,
            "description": "Array of selected option names or indices",
            "schema": {
              "type": "string"
            },
            "example": "[\"Awesome!\"]"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/contact": {
      "post": {
        "operationId": "_v2_send_contact_post",
        "summary": "Send Contact Vcard",
        "description": "Send professional contact cards (vCards) to a chat. Supports single or multiple contacts in one bubble.\n\n\n# Professional Identity: Mastering the Contact Card (vCard) Engine\n\nIn a professional ecosystem, sharing contact information shouldn't be about typing out phone numbers. The `/v2/send/contact` endpoint allows you to share digital business cards (vCards) that are interactive, easy to save, and high-fidelity. By automating the sharing of contact cards, you can streamline the \"Agent Handoff\" process, provide instant access to emergency helplines, or share specialized technician details with a single API call.\n\n![send contact.png](https://api.apidog.com/api/v1/projects/1017306/resources/369243/image-preview)\n\n---\n\n## 🏗️ The VCard Serialization Pipeline\n\nSharing a contact via Wawp is more than just sending a name. Our engine manages a sophisticated serialization process to ensure compatibility with both Android and iOS contact managers:\n1. **vCard Specification Encoding**: Wawp takes your JSON contact array and transcribes it into the standard **vCard (VCF) v3.0** format. This format is universally recognized by mobile operating systems, ensuring that when the user clicks \"Save,\" the fields map correctly to their local address book.\n2. **Identity Verification**: The `whatsappId` field is critical. Our engine uses this to link the vCard directly to a WhatsApp profile. This allows the recipient to immediately see the contact's profile picture and start a one-click message thread without even saving the number first.\n3. **Multi-Contact Batching**: Wawp supports sending multiple contacts in a single \"Message Bubble.\" This is handled by concatenating the serialized VCF blocks into a single payload, providing a clean \"Team\" or \"Directory\" view for the user.\n\n---\n\n## 🛡️ Strategic Best Practices for Digital Identity\n\n### 1. The \"Wholesale Profile\" Strategy\nA bare-bones contact card looks suspicious to users. To build brand authority:\n- **Rich Metadata**: Always provide the `organization` and `fullName`. \n- **Professionalism**: If the contact is an agent, include their department (e.g., \"Sarah - Senior Consultant\"). \n- **Formatting**: Ensure `phoneNumber` includes the international `+` prefix. This is distinct from the `whatsappId`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Format',\n            content: 'Sends a vCard (VCF) file that can be saved directly to contacts.'\n        },\n        {\n            type: 'info',\n            title: 'Fields',\n            content: 'Supports multiple phone numbers, emails, and addresses.'\n        }\n    ],\n  recommendations: [\n        \"Include a properly formatted name (N, FN properties) for best compatibility.\",\n        \"Use this to share support line numbers efficiently.\"\n    ]\n  \n   which is just the numeric digits used for network routing.\n\n### 2. Streamlining the Agent Handoff\nIn a bot-to-human transition:\n- **Implementation**: Instead of the bot saying \"Now talking to Mark, his number is 123,\" have the system automatically trigger a `/v2/send/contact` call for Mark's vCard. \n- **UX Impact**: This gives the customer a clear \"Professional Point of Contact\" bubble that they can refer back to later, increasing the transparency of your support flow.\n\n### 3. Validation and Filename Integrity\n- **Character Limits**: Keep the `fullName` under **40 characters**. Longer names can be truncated in the chat preview or result in messy address book entries.\n- **Emoji Usage**: While emojis are supported in the name field, use them sparingly. Excessive emojis in a vCard name can sometimes interfere with search indexing in a user's local contact app.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Corporate Staff Directories\nSend a \"Support Directory\" message containing three distinct contact cards: \"Billing Support,\" \"Technical Desk,\" and \"Human Resources.\" By sending these as a single array, the user receives one clean interactive list rather than three separate messages.\n\n### Referral and Loyalty Programs\nAutomate your referral system. When a user qualifies for a partner offer, send the partner's professional contact card via Wawp. The `reply_to` parameter can be used to link this contact card to the specific \"Reward Earned\" text message, making the context immediately clear.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Malformed WhatsApp IDs**: If the `whatsappId` doesn't match a real account, the \"Message\" button on the vCard will be disabled on the recipient's phone. Always verify your agent IDs before sharing.\n- **Header Discrepancies**: If you provide a `vcard` string directly (via the legacy fields), ensure it starts with `BEGIN:VCARD` and ends with `END:VCARD`. Wawp will return a `Serialization Error` if the block is malformed.\n- **Phone Number Confusion**: Users often forget the `+` in the `phoneNumber` field. While Wawp attempts to normalize this, provide it explicitly to ensure the user's phone recognizes it as a clickable dialer link.\n\n---\n\n## Summary of Capabilities:\n- Deliver interactive, native-style WhatsApp contact cards (vCards).\n- Support for batching multiple contacts (Staff/Directory) in a single message.\n- One-click \"Save Contact\" and \"Message\" functionality for the end-user.\n- Automated VCF v3.0 serialization for universal iOS/Android compatibility.\n- Seamless integration with threading/replies via the `reply_to` parameter.\n- High-fidelity identity sharing with full support for Organization and Job Title fields.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Unique ID of the WhatsApp session",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API access token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp number",
            "schema": {
              "type": "string"
            },
            "example": "447441429009"
          },
          {
            "name": "contacts",
            "in": "query",
            "required": true,
            "description": "Array of contact objects containing name and phone info.",
            "schema": {
              "type": "string"
            },
            "example": "[\n  {\n    \"fullName\": \"Wawp Support\",\n    \"organization\": \"Wawp HQ\",\n    \"phoneNumber\": \"+201111111111\",\n    \"whatsappId\": \"201111111111\"\n  }\n]"
          },
          {
            "name": "reply_to",
            "in": "query",
            "required": false,
            "description": "The ID of the message you are replying to",
            "schema": {
              "type": "string"
            },
            "example": "false_111...AAAA"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/seen": {
      "post": {
        "operationId": "_v2_send_seen_post",
        "summary": "Mark message(s) as seen",
        "description": "Mark specific messages or an entire chat as seen/read (Blue Ticks).\n\n### Developer Tips\n- **Customer Experience**: Marking messages as seen shows your customers that you are active and attending to their needs.\n\n\n# State Synchronization: Mastering the Read Receipt Engine\n\nThe `/v2/send/seen` endpoint is the primary mechanism for managing \"Presence and Attention\" within a WhatsApp conversation. In the WhatsApp ecosystem, the transition from grey ticks (delivered) to blue ticks (read) is a high-signal event that dictates user expectation. By programmatically marking messages as seen, you can synchronize your custom CRM, dashboard, or bot state with the native WhatsApp interface, ensuring the customer feels heard and the agent's workspace remains organized.\n\n---\n\n## 🏗️ The Read-Receipt Pipeline\n\nMarking a message as \"Seen\" is a two-way synchronization event handled by Wawp:\n1. **Target Identification**: The engine accepts an array of `messageIds`. These IDs are the unique cryptographic hashes generated when the message was first sent or received. Wawp locates these specific entries within the session's local message store.\n2. **The Blue-Tick Broadcast**: Once identified, Wawp sends a specialized \"Read Acknowledgment\" packet over the WhatsApp WebSocket. This packet is then propagated to the original sender's device, where the delivery ticks instantly turn blue.\n3. **Internal Unread Clearing**: Simultaneously, Wawp instructs the WhatsApp network to clear the \"Unread Count\" badge for that specific chat on all linked devices (e.g., if you have WhatsApp Web or Desktop open alongside your API instance).\n\n---\n\n## 🛡️ Strategic Best Practices for Read Management\n\n### 1. The \"Human-in-the-Loop\" Sync\nAutomating seen receipts requires careful alignment with actual agent activity.\n- **Workflow**: Only trigger `/v2/send/seen` when an agent actually *opens* the chat in your custom dashboard. \n- **UX Impact**: If you mark everything as seen automatically, the customer expects an immediate reply. If an agent isn't actually there, you create a \"Response Gap\" that leads to customer frustration. \n\n### 2. High-Efficiency Batching\nWawp supports batching multiple messages in a single API call for a reason.\n- **Implementation**: If a user sends five messages (Text, Image, then more Text) while your agent is away, do not call the seen endpoint five times. Instead, collect all five `messageIds` and send them in a single array. \n- **Performance**: Batching reduces the number of WebSocket transmissions, preserving your instance's bandwidth and reducing the load on the WhatsApp network.\n\n### 3. Simulating Natural Reading (The Delay Strategy)\nBots that respond instantly and mark messages as seen in milliseconds can often feel \"Robotic\" and inhuman.\n- **Recommendation**: For automated bot flows, implement a small, random delay (e.g., 800ms to 2s) between receiving the message and marking it as seen. This mimics the human process of picking up a phone and reading a message, making the interaction feel more organic.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Native CRM \"Open\" Tracking\nIf you are building a custom CRM on top of Wawp, use the seen endpoint to track agent performance. By measuring the time between a `message.received` webhook and your system's `/v2/send/seen` call, you can calculate the \"Average Time to View,\" a critical KPI for support teams.\n\n### Bot Flow \"Triage\"\nIn a complex multi-stage bot, you can use read receipts to signal milestones. For example, mark the user's initial inquiry as seen only after the bot has successfully categorized the intent. This provides the user with a visual confirmation that the system has \"Understood\" the input and is now processing the result.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **The Participant ID (Groups)**: In group chats, marking a message as seen requires the `chatId` of the group AND optionally the `participant` ID of the original sender. If you omit the participant ID in high-concurrency group environments, some engine versions may fail to identify the specific message hash, resulting in a `Receipt Error`.\n- **Already-Read Loops**: Avoid calling the seen endpoint for messages that you yourself sent. While harmless, it's a wasted API call. Most CRM logic should focus exclusively on incoming (unread) messages.\n- **Security Key Resync**: In rare cases, if a session is under heavy load, a \"Seen\" packet might time out. Wawp provides an `acknowledged: true` flag in the response to confirm the proxy has forwarded the request to the network. If you receive a failure, verify the session status via [`/v2/session/status`](/v2/session/status).\n\n---\n\n## Summary of Capabilities:\n- Programmatically trigger the native WhatsApp \"Blue Ticks\" (Read Receipts).\n- Support for batch-marking multiple messages as seen in a single API call.\n- Synchronization of unread counters across all linked WhatsApp devices.\n- Native support for individual, group, and channel read receipting.\n- High-fidelity integration with CRM dashboards for agent activity tracking.\n- Reliable delivery confirmation via the Wawp proxy acknowledged delivery mesh.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number or group ID",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "messageIds",
            "in": "query",
            "required": true,
            "description": "Array of message IDs to mark as seen.",
            "schema": {
              "type": "string"
            },
            "example": "[\"false_447441429009@c.us_AAAAAAAAAAAAAAAAAAAA\"]"
          },
          {
            "name": "participant",
            "in": "query",
            "required": false,
            "description": "The participant who sent the message (for groups).",
            "schema": {
              "type": "string"
            },
            "example": "null"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/start-typing": {
      "post": {
        "operationId": "_v2_send_start-typing_post",
        "summary": "Start Typing",
        "description": "Show the 'typing...' or 'recording audio...' status in a chat.\n\n### Developer Tips\n- **Bot Strategy**: Using typing status increases trust as it mimics a human agent preparing a response.\n\n\n# Organic Presence: Mastering the Start Typing Engine\n\nThe `/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.\n\n---\n\n## 🏗️ The Presence and Attention Pipeline\n\nWhen you trigger the `/start-typing` endpoint, Wawp initiates a \"Presence Broadcast\" across the WhatsApp network:\n1. **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.\n2. **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.\n3. **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.\n\n---\n\n## 🛡️ Strategic Best Practices for Organic Simulation\n\n### 1. The \"Think Time\" Strategy\nInstantaneous text replies from a bot are a clear giveaway that no human is present. \n- **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`](/v2/send/text).\n- **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.\n\n### 2. Managing impetuous Users\nUsers often send several messages in a row (\"Hello?\", \"Are you there?\", \"I have a question\").\n- **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.\n\n### 3. Coordinate with Media Prep\nLarge videos or PDFs can take a few seconds to process and upload.\n- **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.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### High-Fidelity Bot Mimicry\nBuild 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.\n\n### Interactive Voice Preparation\nIf 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.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **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`](/v2/send/stop-typing) or a final message is always sent.\n- **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.\n- **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.\n\n---\n\n## Summary of Capabilities:\n- Explicitly trigger the native WhatsApp \"typing...\" or \"recording audio...\" indicators.\n- High-fidelity organic simulation for bot and human-agent flows.\n- Real-time presence broadcasting to individual, group, and channel recipients.\n- Ephemeral state management with automatic network-level timeouts.\n- Essential tool for managing user expectations and reducing conversational friction.\n- Seamless coordination with text, media, and document delivery endpoints.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number or group ID",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/stop-typing": {
      "post": {
        "operationId": "_v2_send_stop-typing_post",
        "summary": "Stop Typing",
        "description": "Remove the 'typing...' or 'recording audio...' status from a chat.\n\n### Developer Tips\n- **Auto-Stop**: WhatsApp will naturally stop the typing indicator after ~10 seconds of inactivity even if you do not call this.\n\n\n# State Cleanup: Mastering the Stop Typing Engine\n\nThe `/v2/send/stop-typing` endpoint is the essential \"Cleanup Crew\" of the Wawp presence system. While simple in its objective—to remove the \"typing...\" or \"recording audio...\" indicators—it plays a critical role in maintaining the professional polish of your WhatsApp integration. In a high-stakes customer support or sales environment, a \"typing...\" indicator that lingers indefinitely without a resulting message is a significant UX failure that signals system malfunction or agent indecision.\n\n---\n\n## 🏗️ The Presence Termination Pipeline\n\nWhen you explicitly call `/stop-typing`, Wawp executes a coordinated cleanup across the WhatsApp stack:\n1. **The PAUSE Signal**: The engine transmits a specialized `PAUSE` packet to the target `chatId`. This packet instructs the recipient's WhatsApp client to immediately hide all presence indicators.\n2. **Override of Implicit Timeouts**: While WhatsApp has a native timeout (usually 10–20 seconds), explicit calls to `/stop-typing` provide instant feedback. This is crucial for fast-paced, multi-step conversational flows where states change rapidly.\n3. **Internal Buffer Clearance**: Wawp clears the local session's presence-tracking buffer to ensure that subsequent typing requests are treated as fresh starts, preventing \"Presence Stuttering\" on the recipient's UI.\n\n---\n\n## 🛡️ Strategic Best Practices for Presence Hygiene\n\n### 1. The \"Message-Sent\" Auto-Stop\nIt is a common misconception that you must call `/stop-typing` immediately before sending a message.\n- **Fact**: Sending *any* message (Text, Image, PDF, etc.) to a chat automatically triggers the \"Stop Typing\" behavior on the WhatsApp network.\n- **Optimization**: To save API calls and reduce latency, **do not** call `/v2/send/stop-typing` before or after sending your final message. The message delivery itself is the most efficient way to clear the status.\n\n### 2. Handling Workflow Cancellations\nThis is the most critical use case for the explicit stop endpoint.\n- **Scenario**: An agent starts a response in your CRM but then decides the inquiry belongs to a different department. They close the chat tab or transfer the ticket.\n- **Best Practice**: Your CRM should automatically trigger `/v2/send/stop-typing` whenever an agent's focus leaves a chat that was previously in a \"Typing\" state. This prevents the \"Phantom Agent\" effect where a customer sees someone typing for minutes with no result.\n\n### 3. Graceful AI Failure Recovery\nIf your AI backend (e.g., GPT-4 or Claude) times out or returns an error while a \"typing...\" indicator is active, your system must handle the cleanup.\n- **Implementation**: Wrap your AI generation logic in a `try...catch...finally` block. In the `finally` section, if no message was successfully sent, trigger `/v2/send/stop-typing`. This ensures that even in the event of a crash, the customer isn't left staring at a perpetual typing status.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### The \"Search Transition\" UX\nIn complex bot flows where a user requests a search (e.g., \"Find my order\"), you can use [`/v2/send/start-typing`](/v2/send/start-typing) to show work is in progress. If the search returns 0 results, trigger `/v2/send/stop-typing` before sending the \"No results found\" text. This momentary clearing of the status creates a distinct visual \"Beat\" in the conversation, signaling that one phase of logic has ended and another (the error message) has begun.\n\n### Agent Transfer Synchronization\nWhen transferring a chat between human agents, the secondary agent may want to \"Pick up\" the thread quietly. Triggering `stop-typing` during the handoff ensures the transition is visually seamless for the customer, with no overlapping or conflicting indicators from two different sessions.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **Double-Counting Latency**: If your network is slow, calling `/stop-typing` followed immediately by a message might cause the message to arrive before the stop signal is processed, leading to a brief flicker. **Solution**: Rely on the \"Auto-Stop\" property of messages whenever possible.\n- **Rate Limit Caution**: While presence signals are lightweight, WhatsApp still tracks the frequency of these specialized packets. Avoid sending more than 3 `stop-typing` calls per second to the same chat to ensure your instance maintains a high trust score.\n- **Group Environment Noise**: In group chats with 200+ participants, presence indicators can be noisy. Use `/stop-typing` only when an agent was definitely \"Active\" and now definitely is \"Not.\"\n\n---\n\n## Summary of Capabilities:\n- Explicitly terminate the \"typing...\" or \"recording audio...\" presence indicators.\n- Native integration with WhatsApp PAUSE signaling for instant recipient feedback.\n- Essential for cleaning up states after agent transfers or workflow cancellations.\n- Zero-latency override of standard 20-second network-level timeouts.\n- Foundation for reliable \"Try/Finally\" error handling in automated AI bot systems.\n- Ensures a polished, professional conversational aesthetic by preventing \"Phantom Typing.\"\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number or group ID",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/send/reaction": {
      "put": {
        "operationId": "_v2_send_reaction_put",
        "summary": "Reaction",
        "description": "React to a specific message with an emoji (👍, ❤️, 😂, etc.).\n\n### Developer Tips\n- **Modern UI**: Reactions keep chat history clean and are significantly faster to process for the user than text replies.\n\n\n# Micro-Interactions: Mastering the Message Reaction Engine\n\nReactions (`/v2/send/reaction`) are one of the most powerful micro-interactions in a modern messaging ecosystem. They allow users and bots to acknowledge information, express sentiment, or provide feedback without the friction of a full text reply. In a Wawp-powered application, reactions aren't just cosmetic; they are structural signals that can be used to track engagement, build interactive voting systems, or simplify bot-to-user acknowledgements.\n\n---\n\n## 🏗️ The Reaction Lifecycle Architecture\n\nUnlike full messages, reactions are additive metadata attached to an existing message. Wawp’s reaction engine manages this attachment with high precision:\n1. **Target Identification**: The engine uses the `messageId` to locate the specific message on the WhatsApp backend. This must be the unique ID of an existing message in the chat identified by `chatId`.\n2. **Emoji Normalization**: While you can send any emoji, Wawp ensures the character is correctly encoded for the WhatsApp WebSocket. If you send an empty string (`\"\"`), the engine interprets this as a \"Delete Reaction\" command, instructing the WhatsApp network to remove your previous sentiment from that particular message.\n3. **Atomic Delivery**: Reactions are delivered as light-weight, high-priority packets. This ensures that a reaction appears almost instantaneously on the recipient's phone, making the chat feel \"Live\" and responsive.\n\n---\n\n## 🛡️ Strategic Best Practices for Sentiment Engagement\n\n### 1. The \"Standard Set\" Strategy\nWhile WhatsApp supports any emoji as a reaction, users are most accustomed to the \"Standard Quick Actions\": 👍 (Acknowledgement), ❤️ (Love/Quality), 😂 (Laughter), 😮 (Surprise), 😢 (Sympathy), and 🙏 (Thanks).\n- **UX Impact**: By sticking to these standards, you match the user's muscle memory. \n- **Compatibility**: Rare or complex combined emojis (like multi-colored family units) can sometimes render inconsistently across older Android or Desktop versions. Standard emojis are universally safe.\n\n### 2. Automated Acknowledgements\nModern bots shouldn't always respond with text.\n- **Example**: If a user says \"Got it!\" or \"Thanks!\", instead of the bot replying with \"You're welcome!\" (another message for the user to clear), have the bot react with a 👍 or 💙.\n- **Value**: This keeps the chat history clean while still providing the user with positive reinforcement that their input was received.\n\n### 3. Removal and Cleanup\nDon't let outdated sentiments linger.\n- **Workflow**: If your bot reacts with a ⏳ (Processing) while it’s working on a long task, make sure to call the endpoint again with an empty string `\"\"` to remove the ⏳ once the task is finished, or replace it with a ✅ (Done). This prevents the UI from becoming cluttered with conflicting status emojis.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Lightweight Interactive Voting\nYou can build a low-friction voting system by asking a question and having users react with different emojis for different options. \n- **Logic**: Use your **Webhooks** (`message.reaction`) للاستماع إلى التفاعلات الواردة من المستخدمين. Your backend then tallies the counts for each emoji type, enabling \"Reactions-as-Votes\" functionality without a single line of extra UI code.\n\n### Sentiment Monitoring for Human Agents\nWhen an automated flow is running, have your system monitor the emojis users react with. If a user consistently reacts with 😢 or 😠 to bot messages, your system can interpret this as a \"Frustration Signal\" and automatically escalate the chat to a human agent.\n\n---\n\n## 🛠️ Common Pitfalls and Solutions\n\n- **The \"Missing ID\" Error**: If you provide a correctly formatted `messageId` but the message was sent too long ago (typically several weeks), the reaction may fail. Reactions are most reliable when applied to recent (active) conversation history.\n- **Rapid Re-Reaction**: Sending five different reactions to the same message in one second can be flagged as \"Suspicious Scripting.\" Implement a small jitter or debounce (at least 200ms) between reaction updates to the same target message.\n- **Encryption Resync**: In rare cases, if a session's security keys are out of sync, a reaction might fail while standard text succeeds. A quick [`/v2/session/restart`](/v2/session/restart) usually resolves these synchronization edge cases.\n\n---\n\n## Summary of Capabilities:\n- Apply and remove native WhatsApp reactions (emojis) to any existing message.\n- Support for \"Delete Reaction\" via empty string payloads.\n- High-concurrency support for voting and acknowledgement systems.\n- Real-time event tracking through `message.reaction` Webhooks.\n- Lightweight and low-priority execution to minimize chat-history clutter.\n",
        "tags": [
          "Send Messages"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "messageId",
            "in": "query",
            "required": true,
            "description": "The ID of the message you want to react to.",
            "schema": {
              "type": "string"
            },
            "example": "false_20123456789@c.us_3F351BFA105BA281C054"
          },
          {
            "name": "reaction",
            "in": "query",
            "required": true,
            "description": "The emoji reaction. Use an empty string to remove.",
            "schema": {
              "type": "string"
            },
            "example": "👍"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "429": {
            "description": "Too Many Requests - Rate Limit Exceeded",
            "content": {
              "application/json": {
                "example": {
                  "code": "rate_limit_exceeded",
                  "message": "Too many requests. Please slow down.",
                  "details": {
                    "retryAfter": 60,
                    "recommendation": "Implement a retry strategy with exponential backoff or reduce the frequency of your requests.",
                    "upstream": {
                      "error": "Rate limit",
                      "statusCode": 429
                    }
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/chats": {
      "get": {
        "operationId": "_v2_chats_get",
        "summary": "Chats list & overview",
        "description": "Get a list of all active chats (individuals and groups) with pagination support.\n\n### Developer Tips\n- **Rate Limits**: Be mindful of API rate limits to act responsibly.\n- **Error Handling**: Always handle potential API errors.\n\n\n# Chat List & Management\n\nRetrieve an overview of all conversations currently available in your WhatsApp instance.\n\n### 🛡️ Best Practices\n# Mastering the Inbox: High-Scale Chat Retrieval and Synchronization\n\nThe `/v2/chats` endpoint is the administrative gateway to your WhatsApp instance's history. Unlike the overview endpoint, which provides a snapshot, the Chats List API is designed for **exhausive discovery** and **deep synchronization**. Whether you are migrating data to a new CRM or building a searchable archive, mastering the nuances of this endpoint is essential for professional WhatsApp integrations.\n\n---\n\n## 🏗️ The Mechanics of Chat Discovery\n\nWhen you request the chat list, the Wawp engine interfaces with its internal encrypted database to reconstruct the conversation graph. This process involves:\n1.  **Hydration**: Associating the raw JIDs (e.g., `447441429009@c.us`) with their display names and latest status.\n2.  **State Categorization**: Identifying which chats are \"Pinned,\" \"Archived,\" or \"Muted.\"\n3.  **Pagination Processing**: Calculating the offset and limit logic to deliver a deterministic subset of results.\n\n---\n\n## 🚀 Advanced Pagination and Indexing Strategies\n\nIn high-volume accounts (5,000+ chats), requesting the \"full list\" is an anti-pattern that leads to memory spikes and network latency. Follow these professional guidelines:\n\n### 1. The \"Sliding Window\" Sync\nIf you are synchronizing your local database with Wawp for the first time:\n- **Phase 1**: Fetch the first 50 results (`limit=50, offset=0`) to get the most recent activity.\n- **Phase 2**: Use a recursive loop to fetch subsequent pages (`offset=50, 100, ...`) until the response array is empty.\n- **Interrupt Resilience**: Store the last successful `offset` in your local database so you can resume the sync if the connection drops.\n\n### 2. Strategic Sorting\n- **`sortBy=id`**: Useful for alphabetical indexing or consistency checks.\n- **`sortOrder=DESC`**: The default and most recommended setting. It ensures that the newest threads — those most likely to require immediate attention — are returned first.\n\n---\n\n## 🛡️ Best Practices for Efficient Polling\n\nWhile **Webhooks** are the preferred way to receive *new* messages, the `/v2/chats` endpoint remains the source of truth for *chat state changes* (like a user changing their group name or archiving a thread).\n\n*   **The Delta Sync**: Instead of polling the whole list, poll only the first page (`limit=20`) every hour. If you detect a change in a `chatId` that your system didn't know about, trigger a deep dive for that specific conversation.\n*   **Archiving Policy**: To keep this list manageable, implement an auto-archiving script. Use the chat list to identify \"Zombie\" chats (no messages for 90 days) and call the archive endpoint to move them out of the \"Active\" list.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Building a \"WhatsApp Explorer\"\nCreate a custom search interface for your team.\n- **Logic**: Fetch the entire chat list (paginated) and index the `name` and `id` fields in an ElasticSearch or Meilisearch instance. This allows your support agents to find any customer instantly without waiting for the engine to respond.\n\n### Bot \"Self-Audit\"\nIn a multi-bot environment, use this endpoint to ensure that your bot hasn't been \"orphaned\" in groups it shouldn't be in. Regularly scan the list for unknown group IDs (`@g.us`) and programmatically leave them.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **Engine Restarts**: During an engine \"Cold Boot,\" the chat list may take a few seconds to populate as it re-syncs with the phone's encrypted storage. Handle `202 Accepted` or `empty` responses gracefully during the first 30 seconds of a session.\n*   **Group Permissions**: For groups, this endpoint returns the group metadata available to your instance. If you were removed from a group, it may still appear in the list for a short \"grace period\" before disappearing.\n*   **Memory Management**: Each chat object in the response occupies a small amount of memory. In very large requests (e.g., `limit=500`), ensure your application layer (Node.js/Python) has sufficient heap space to parse the JSON payload.\n\n---\n\n## Summary of Capabilities:\n- Exhaustive retrieval of all chat threads (Individuals and Groups).\n- Deterministic pagination for large-scale data migrations.\n- Support for custom sorting to prioritize active conversations.\n- Reliable metadata retrieval for CRM and Database indexing.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "sortBy",
            "in": "query",
            "required": false,
            "description": "Field to sort by (e.g., id)",
            "schema": {
              "type": "string"
            },
            "example": "id"
          },
          {
            "name": "sortOrder",
            "in": "query",
            "required": false,
            "description": "Sort direction (ASC or DESC)",
            "schema": {
              "type": "string"
            },
            "example": "DESC"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Number of chats to return",
            "schema": {
              "type": "integer"
            },
            "example": "20"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of chats to skip",
            "schema": {
              "type": "integer"
            },
            "example": "0"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "post": {
        "operationId": "_v2_chats_post",
        "summary": "Chats list & overview",
        "description": "Get a list of all active chats (individuals and groups) with pagination support.\n\n### Developer Tips\n- **Rate Limits**: Be mindful of API rate limits to act responsibly.\n- **Error Handling**: Always handle potential API errors.\n\n\n# Chat List & Management\n\nRetrieve an overview of all conversations currently available in your WhatsApp instance.\n\n### 🛡️ Best Practices\n# Mastering the Inbox: High-Scale Chat Retrieval and Synchronization\n\nThe `/v2/chats` endpoint is the administrative gateway to your WhatsApp instance's history. Unlike the overview endpoint, which provides a snapshot, the Chats List API is designed for **exhausive discovery** and **deep synchronization**. Whether you are migrating data to a new CRM or building a searchable archive, mastering the nuances of this endpoint is essential for professional WhatsApp integrations.\n\n---\n\n## 🏗️ The Mechanics of Chat Discovery\n\nWhen you request the chat list, the Wawp engine interfaces with its internal encrypted database to reconstruct the conversation graph. This process involves:\n1.  **Hydration**: Associating the raw JIDs (e.g., `447441429009@c.us`) with their display names and latest status.\n2.  **State Categorization**: Identifying which chats are \"Pinned,\" \"Archived,\" or \"Muted.\"\n3.  **Pagination Processing**: Calculating the offset and limit logic to deliver a deterministic subset of results.\n\n---\n\n## 🚀 Advanced Pagination and Indexing Strategies\n\nIn high-volume accounts (5,000+ chats), requesting the \"full list\" is an anti-pattern that leads to memory spikes and network latency. Follow these professional guidelines:\n\n### 1. The \"Sliding Window\" Sync\nIf you are synchronizing your local database with Wawp for the first time:\n- **Phase 1**: Fetch the first 50 results (`limit=50, offset=0`) to get the most recent activity.\n- **Phase 2**: Use a recursive loop to fetch subsequent pages (`offset=50, 100, ...`) until the response array is empty.\n- **Interrupt Resilience**: Store the last successful `offset` in your local database so you can resume the sync if the connection drops.\n\n### 2. Strategic Sorting\n- **`sortBy=id`**: Useful for alphabetical indexing or consistency checks.\n- **`sortOrder=DESC`**: The default and most recommended setting. It ensures that the newest threads — those most likely to require immediate attention — are returned first.\n\n---\n\n## 🛡️ Best Practices for Efficient Polling\n\nWhile **Webhooks** are the preferred way to receive *new* messages, the `/v2/chats` endpoint remains the source of truth for *chat state changes* (like a user changing their group name or archiving a thread).\n\n*   **The Delta Sync**: Instead of polling the whole list, poll only the first page (`limit=20`) every hour. If you detect a change in a `chatId` that your system didn't know about, trigger a deep dive for that specific conversation.\n*   **Archiving Policy**: To keep this list manageable, implement an auto-archiving script. Use the chat list to identify \"Zombie\" chats (no messages for 90 days) and call the archive endpoint to move them out of the \"Active\" list.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Building a \"WhatsApp Explorer\"\nCreate a custom search interface for your team.\n- **Logic**: Fetch the entire chat list (paginated) and index the `name` and `id` fields in an ElasticSearch or Meilisearch instance. This allows your support agents to find any customer instantly without waiting for the engine to respond.\n\n### Bot \"Self-Audit\"\nIn a multi-bot environment, use this endpoint to ensure that your bot hasn't been \"orphaned\" in groups it shouldn't be in. Regularly scan the list for unknown group IDs (`@g.us`) and programmatically leave them.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **Engine Restarts**: During an engine \"Cold Boot,\" the chat list may take a few seconds to populate as it re-syncs with the phone's encrypted storage. Handle `202 Accepted` or `empty` responses gracefully during the first 30 seconds of a session.\n*   **Group Permissions**: For groups, this endpoint returns the group metadata available to your instance. If you were removed from a group, it may still appear in the list for a short \"grace period\" before disappearing.\n*   **Memory Management**: Each chat object in the response occupies a small amount of memory. In very large requests (e.g., `limit=500`), ensure your application layer (Node.js/Python) has sufficient heap space to parse the JSON payload.\n\n---\n\n## Summary of Capabilities:\n- Exhaustive retrieval of all chat threads (Individuals and Groups).\n- Deterministic pagination for large-scale data migrations.\n- Support for custom sorting to prioritize active conversations.\n- Reliable metadata retrieval for CRM and Database indexing.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "sortBy",
            "in": "query",
            "required": false,
            "description": "Field to sort by (e.g., id)",
            "schema": {
              "type": "string"
            },
            "example": "id"
          },
          {
            "name": "sortOrder",
            "in": "query",
            "required": false,
            "description": "Sort direction (ASC or DESC)",
            "schema": {
              "type": "string"
            },
            "example": "DESC"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Number of chats to return",
            "schema": {
              "type": "integer"
            },
            "example": "20"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of chats to skip",
            "schema": {
              "type": "integer"
            },
            "example": "0"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/chats/overview": {
      "get": {
        "operationId": "_v2_chats_overview_get",
        "summary": "Get Chats Overview",
        "description": "Retrieve a summary of all active chats and messages metadata.\n\n### Developer Tips\n- **Performance Tip**: Use the overview for the initial load, then use Webhooks to patch the UI state. Avoid constant polling for the entire list.\n\n\n# The Pulse of the Inbox: Mastering Chat Overviews\n\nThe `/v2/chats/overview` endpoint is the most efficient way to build a high-performance messaging dashboard. Instead of fetching the full history of every chat, this endpoint provides a \"snapshot\" of your entire inbox, allowing you to display active conversations, unread sharded counts, and the most recent message fragments in a single, lightweight API call.\n\nFor developers building CRMs, helpdesk software, or monitoring tools, this endpoint is the primary source of truth for the user's \"Inbox View.\"\n\n---\n\n## 🏗️ Architecture of an Overview\n\nThe response is an array of objects, each representing a single conversation. Each object includes critical metadata:\n1.  **Identity (`id`, `name`)**: The JID and the display name (as seen by the Wawp engine).\n2.  **Unread Count (`unreadCount`)**: A real-time shard of messages that have not yet been marked as \"seen.\"\n3.  **Last Message Fragment (`lastMessage`)**: A preview of the latest interaction, including its content, timestamp, and unique ID.\n\n---\n\n## 🚀 Performance Optimization Strategies\n\nWhen your Wawp instance manages thousands of chats, fetching the overview can become a heavy operation. Follow these strategies to maintain sub-second response times:\n\n### 1. Client-Side Virtualization\nDo not attempt to render all chats at once if the user has hundreds of active threads.\n- **Implementation**: Fetch the overview, store it in a local state (Redux/Vuex), and use a \"Virtual List\" component to render only the visible rows.\n- **Update Logic**: Instead of re-fetching the entire overview every time a message arrives, use the **Webhooks** (`message.any`) to update only the specific row in your local cache.\n\n### 2. Handling Large Pagination\nWhile `/chats/overview` is built for speed, very large inboxes (10,000+ chats) should be managed proactively.\n- **The \"Warm Cache\" Approach**: Periodically fetch the overview in the background (e.g., every 5 minutes) and store it in your own Redis cache. Your UI should then query your Redis store for instant loading.\n\n---\n\n## 🛡️ Best Practices for Inbox Management\n\n### 1. The \"Read Sync\" Loop\nThe `unreadCount` returned by this endpoint is dynamically updated. To clear a red badge in your UI:\n- Call [`/v2/chat/read`](/v2/chat/read) for that specific chat ID.\n- The next call to `/chats/overview` will return `unreadCount: 0`.\n\n### 2. Differentiating Groups vs. Individuals\nUse the JID suffix to format your UI:\n- **`@c.us`**: Individual chat. Use a user avatar.\n- **`@g.us`**: Group chat. Use a group icon and potentially prefix the last message with the sender's name for clarity.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Priority Inboxing\nBuild a \"Priority\" tab by filtering the overview array on your backend.\n- **Logic**: Sort by `lastMessage.timestamp` (descending) and highlight any row where `unreadCount > 0`.\n- **SLA Tracking**: If a last message timestamp is older than 2 hours and still \"Unread,\" trigger an internal escalation to a human agent.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **JID Consistency**: Always use the full JID (e.g., `447441429009@c.us`) when cross-referencing this data with other endpoints.\n*   **Archived Chats**: By default, the overview includes active chats. To see archived threads, you may need to use specific filter flags (if available in your version) or use the full [`/v2/chats/list`](/v2/chats/list) endpoint for exhaustive searching.\n*   **Media Previews**: The `lastMessage.body` will show a truncated text version of media messages (e.g., \"📷 Photo\" or \"📄 Document\"). Your UI should handle these strings gracefully by adding corresponding icons.\n\n---\n\n## Summary of Capabilities:\n- Lightweight snapshot of the entire WhatsApp inbox.\n- Real-time unread count synchronization.\n- Last message previews for context-aware dashboards.\n- Optimal for building \"Inbox View\" sidebars in CRMs.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/chats/picture": {
      "get": {
        "operationId": "_v2_chats_picture_get",
        "summary": "Get chat picture",
        "description": "Retrieve the profile picture URL of a chat (individual or group).\n\n\n# Chat Profile Picture\n\nIdentify your contacts visually by fetching their latest WhatsApp profile picture.\n# Visual Identity: Mastering Chat Profile Picture Retrieval\n\nIn a professional messaging environment, visual context is key to reducing agent fatigue and improving response accuracy. The `/v2/chats/picture` endpoint allows you to programmatically fetch the latest high-resolution profile picture for any individual (`@c.us`) or group (`@g.us`). This ensures your internal CRM or dashboard feels integrated and up-to-date with the user's WhatsApp presence.\n\n---\n\n## 🏗️ The Lifecycle of a Profile Picture Fetch\n\nWhen you call this endpoint, the Wawp engine handles a complex multi-step process:\n1.  **Cache Verification**: The engine checks its local 24-hour cache for an existing URL.\n2.  **Privacy Check**: It queries the WhatsApp network. If the user's privacy settings (e.g., \"Profile Photo: My Contacts\") restrict your instance from seeing the image, the network returns a `null` or `restricted` response.\n3.  **High-Res Acquisition**: If the image is available, Wawp attempts to fetch the highest resolution thumbnail provided by the network.\n4.  **Base64/URL Delivery**: The final result is returned as a direct URL (valid for a limited time) or can be cached locally by your system for persistence.\n\n---\n\n## 🚀 Performance and Cache Management\n\nTo maintain a responsive UI while respecting WhatsApp's rate limits, we implement a **24-Hour Smart Cache**.\n\n### 1. The \"Bypass\" Flag (`refresh`)\n*   **Default Behavior**: Calling the endpoint without `refresh: true` will always prioritize the locally cached URL if it's less than 24 hours old. This is lightning fast and prevents unnecessary network round-trips.\n*   **Forced Update**: Only use `refresh: true` if your user explicitly triggers a \"Refresh Profile\" action in your UI. Overusing this flag can lead to temporary \"Visual Rate Limiting\" where the network returns empty images to save bandwidth.\n\n### 2. Strategic UI Placeholders (The \"Initials\" Fallback)\nBecause profile pictures can be restricted by privacy settings or deleted by the user, your UI must be resilient.\n- **Pattern**: \n    1. Try to fetch the URL via Wawp.\n    2. If the response is null, render a fallback avatar with the contact's initials (e.g., \"JD\" for John Doe) on a colored background.\n    3. Update the avatar only when a successful response is received.\n\n---\n\n## 🛡️ Best Practices for Identity Sync\n\n*   **Group vs. Individual**: Group icons are usually easier to fetch because they use the \"Public\" group visibility. Individual pictures are more likely to be hidden by privacy settings.\n*   **Resolution Awareness**: The returned URL usually points to a square thumbnail (e.g., 640x640). This is perfect for list views but may look pixelated in full-screen \"About\" sections. Always design your UI around a square aspect ratio.\n*   **CDN Validity**: The URLs returned are often hosted on WhatsApp's CDNs and have a limited lifespan (TTL). **Do not** store these URLs permanently in your own database. Instead, store the binary image data or re-fetch the URL every time the user session starts.\n\n---\n\n## 🧩 Advanced Use Case: Contact Enricher\n\nBuild a routine that scans your \"Top 50 Active Conversations\" every morning.\n- **Logic**: Use [`/v2/chats/overview`](/v2/chats/overview) to identify active users, then call `/v2/chats/picture` for each. Store the images locally on your own server (S3/GCS) to ensure they are available even if the user changes their privacy settings later. This creates a permanent \"Face-to-ID\" mapping for your agents.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **JID Precision**: You must use the full JID. For groups, this is the ID ending in `@g.us`. If you use only the phone number without the suffix, the engine will fail to resolve the entity.\n*   **Privacy Walls**: If a user has blocked your instance, you will **never** be able to see their profile picture. An empty response is often the first technical indicator of a block.\n*   **Engine State**: Like other metadata endpoints, this works best when the session is in the `WORKING` state. If the session is `STOPPED`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Scope',\n            content: 'Works for both Group chats and Private chats.'\n        },\n        {\n            type: 'warning',\n            title: 'Privacy',\n            content: 'May fail if the user's privacy settings hide their picture.'\n        }\n    ],\n  recommendations: [\n        \"Use 'contacts-profile-picture' for individual contacts.\",\n        \"Handle 404/401 errors gracefully in your UI.\"\n    ]\n  \n   the engine cannot query the network for fresh images.\n\n---\n\n## Summary of Capabilities:\n- High-resolution retrieval of contact and group avatars.\n- Integrated 24-hour caching for sub-second performance.\n- Support for forced refreshes to ensure visual data integrity.\n- Privacy-aware responses that respect user-level WhatsApp settings.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target Chat ID (phone@c.us or group@g.us)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "refresh",
            "in": "query",
            "required": false,
            "description": "Force refresh (bypass 24h cache)",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/chats/messages": {
      "get": {
        "operationId": "_v2_chats_messages_get",
        "summary": "Get messages in chat",
        "description": "Retrieve messages from a specific chat with filtering and pagination.\n\n\n# Fetch Chat History\n\nRetrieve previous messages to build a complete conversation view in your application.\n# Deep Context: Mastering Message Retrieval and Media Hydration\n\nThe `/v2/chats/messages` endpoint is the technical core of any WhatsApp-based CRM or Support Dashboard. It allows your application to \"look back in time,\" reconstructing the conversational flow with precision. This endpoint handles everything from simple text history to complex media acquisition, making it a powerful but resource-intensive tool that requires a thoughtful implementation strategy.\n\n---\n\n## 🏗️ Technical Architecture of Retrieval\n\nWhen you query for messages, the Wawp engine performs several operations:\n1.  **JID Resolution**: It verifies the `chatId` and identifies the local storage partition for that specific conversation.\n2.  **Pointer Management**: Using `limit` and `offset`,\n  tips: [\n    {\n        \"type\": \"info\",\n        \"title\": \"Rate Limits\",\n        \"content\": \"Be mindful of API rate limits to act responsibly.\"\n    },\n    {\n        \"type\": \"warning\",\n        \"title\": \"Error Handling\",\n        \"content\": \"Always handle potential API errors.\"\n    }\n],\n  recommendations: [\n    \"Consult the official documentation for detailed parameter descriptions.\",\n    \"Test endpoints in a sandbox environment before production.\",\n    \"Keep your API client library up to date.\"\n],\n  \n   it navigates the indexed message store to retrieve a deterministic slice of history.\n3.  **Media \"Lazy Loading\"**: If `downloadMedia` is enabled, the engine actively attempts to fetch regional binary data from WhatsApp's CDN, decrypt it using the session's keys, and return it as a Base64 payload.\n\n---\n\n## 🚀 Optimized History Synchronization Strategies\n\nFor developers building a local message archive, we recommend the **Recursive Backfill** pattern:\n\n### 1. The \"Infinite Scroll\" Implementation\nIn your UI, when a user scrolls to the top of the chat:\n- **Trigger**: Detact the scroll event and call `/v2/chats/messages` with the next `offset`.\n- **Loading State**: Show a subtle spinner. Once the messages arrive, prepend them to your local array.\n- **Deduplication**: Always check for duplicate `messageId` strings before updating your UI to avoid \"Ghost Messages\" during fast scrolling.\n\n### 2. Strategic Media Handling (The \"Pay-As-You-Go\" Model)\nDownloading media for every message in a history fetch is inefficient and can cause significant network lag.\n- **The Best Practice**: Always set `downloadMedia: false` when retrieving lists.\n- **Hydration on Demand**: Your UI should show a placeholder icon (e.g., a \"Download\" button) for media messages. Only when the user clicks that specific message should you call [`/v2/message/get`](/v2/message/get) with `downloadMedia: true`.\n\n---\n\n## 🛡️ Best Practices for Data Integrity\n\n*   **Message Types**: WhatsApp has dozens of message types (text, image, video, document, link-preview, location, contact). Ensure your frontend \"Message Component\" is flexible enough to render these different structures based on the `type` field in the response.\n*   **Timestamp Synchronization**: Wawp returns timestamps in Unix Epoch format. Always convert these to the user's local timezone on the client-side to ensure conversational context.\n*   **The \"Forwarded\" Flag**: Pay attention to the `isForwarded` metadata. In security-sensitive applications, this helps agents identify if a customer is sharing original content or potentially circulating spam/template information.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Conversational AI Memory (RAG)\nIf you are building an AI bot using RAG (Retrieval-Augmented Generation), use this endpoint to provide the LLM with the last 20 messages of context.\n- **Logic**: Fetch the messages without media, concatenate the text bodies, and pass them as \"Context\" to your AI prompt. This ensures the bot \"remembers\" what was said earlier in the session.\n\n### Quality Assurance (QA) Auditing\nManagers can use this endpoint to review agent performance. By fetching the history of \"Closed Tickets,\" you can calculate \"Time to Resolution\" and evaluate the tone/accuracy of responses.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **Temporary Files**: When `downloadMedia` is true, the engine uses temporary disk space to decrypt the file. Ensure your hosting environment has sufficient temporary storage if you expect high-volume media downloads.\n*   **Expired Media**: WhatsApp's CDN eventually deletes older media files (usually after 30-60 days). If a message is very old, the download may fail with a `Media Not Found` error even if the message metadata exists.\n*   **Group Context**: In groups, the message object includes the `author` (the JID of the participant who sent the message). Use this to identify who said what within a group thread.\n\n---\n\n## Summary of Capabilities:\n- Robust retrieval of conversational history for individuals and groups.\n- Granular control over media downloading to optimize bandwidth.\n- Native support for all WhatsApp message types and metadata.\n- Integrated pagination logic for seamless infinite-scroll interfaces.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target Chat ID (phone@c.us or group@g.us)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Number of messages to retrieve",
            "schema": {
              "type": "integer"
            },
            "example": "50"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of messages to skip",
            "schema": {
              "type": "integer"
            },
            "example": "0"
          },
          {
            "name": "downloadMedia",
            "in": "query",
            "required": false,
            "description": "Whether to download and return media content",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/chats/read": {
      "post": {
        "operationId": "_v2_chats_read_post",
        "summary": "Mark as read",
        "description": "Mark unread messages as read for a specific chat.\n\n### Developer Tips\n- **Pro-Tip: Blue Tick Delay**: To make bots feel more human, add a random 1-2 second delay before marking a message as read.\n\n\n# The Art of the Blue Tick: Mastering Read States\n\nIn WhatsApp, the transition from grey ticks (delivered) to blue ticks (read) is a high-stakes psychological event. The `/v2/chats/read` endpoint allows your application to programmatically trigger this state change. Whether you are building an automated helpdesk or a synchronized multi-agent CRM, managing \"Read Receipts\" correctly is critical for maintaining user trust and professional responsiveness.\n\n---\n\n## 🏗️ Technical Workflow of a Read Event\n\nWhen you mark a chat as read via Wawp, the engine performs a specialized \"Acknowledgment Handshake\":\n1.  **Selection**: Based on your `messages` or `days` parameters, the engine identifies the unread message cluster in the specified `chatId`.\n2.  **Network Broadcast**: A \"Seen\" packet is transmitted via the WhatsApp WebSocket.\n3.  **UI Synchronization**: This event ripples across all other devices linked to the account (WhatsApp Web, Mobile, Desktop), instantly clearing the unread badges and turning the sender's ticks blue.\n\n---\n\n## 🚀 Strategic Implementation Patterns\n\n### 1. The \"Human-Agent\" Sync\nIf you are building a custom dashboard for agents:\n- **Trigger**: Detact when an agent clicks on a chat thread to open it.\n- **Action**: Immediately call `/v2/chats/read` for that JID. This signals to the customer that \"Someone is looking at your message,\" which drastically improves the perceived quality of service.\n\n### 2. The \"Bot-First\" Approach\nIf an AI bot handles the initial triage:\n- **Best Practice**: Mark the messages as read as soon as the bot processes them. This keeps the agent's \"Unread\" list clean, ensuring they only focus on chats where the bot needs human escalation.\n- **Tip**: Use the `messages: 1` parameter if you only want to acknowledge the most recent interaction.\n\n---\n\n## 🛡️ Best Practices for UX Management\n\n*   **Avoid \"Ghost Reading\"**: High-scale automation should be careful not to mark every incoming message as read instantly. This creates a \"Responsiveness Gap\"—the user sees the blue ticks and expects a reply in seconds. If your bot isn't ready to reply, consider delaying the \"read\" action until the processing is complete.\n*   **Batching reads**: Use the `days` parameter for \"Inbox Cleanup\" routines. For example, mark all messages from the last 7 days as read for any chat you are about to archive.\n*   **JID Accuracy**: Ensure you use the full JID (`@c.us` or `@g.us`). Marking a group as read will clear the sharded unread count for every participant's message within that group.\n\n---\n\n## 🧩 Advanced Use Case: Session Completion Logic\n\nWhen an agent resolves a support ticket:\n1. Call `/v2/chats/read` to ensure everything is marked as seen.\n2. Send a \"Thank you\" closing message.\n3. Archive the chat.\nThis three-step flow represents the gold standard of professional WhatsApp chat management.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **Privacy Settings**: If the *sender* of the message has turned off \"Read Receipts\" in their WhatsApp settings, your blue ticks will not show for them, but your unread counts inside Wawp will still be cleared.\n*   **Engine State**: This endpoint requires the session to be in the `WORKING` state. If the engine is starting or stopped, the \"Read\" packet cannot be transmitted to the WhatsApp network.\n*   **Irreversibility**: Once a message is marked as read, it cannot be \"un-read\" (turning the ticks back to grey) on the sender's device. While Wawp has a [`/v2/chats/unread`](/v2/chats/unread) endpoint, that only affects the *local* badge on your side, not the sender's blue ticks.\n\n---\n\n## Summary of Capabilities:\n- Programmatic triggering of WhatsApp blue ticks (Read Receipts).\n- Global synchronization across all linked devices (Web/Mobile/Desktop).\n- Granular control via message count or time-based (days) selection.\n- Critical for building professional agent Dashboards and CRM integrations.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "messages",
            "in": "query",
            "required": false,
            "description": "How many latest to read",
            "schema": {
              "type": "integer"
            },
            "example": "10"
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "How many latest days to read",
            "schema": {
              "type": "integer"
            },
            "example": "1"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/messages/get": {
      "post": {
        "operationId": "_v2_messages_get_post",
        "summary": "Get message by id",
        "description": "Retrieve a specific message by its ID.\n\n### Developer Tips\n- **Performance Optimization**: Always use lazy loading for media. Use this endpoint only when the user explicitly needs to view an image or video.\n\n\n# Precision Access: Mastering Pinpoint Message Retrieval\n\nThe `/v2/messages/get` endpoint is the most granular tool in the Wawp Chat Actions suite. While other endpoints handle lists and overviews, this endpoint is designed for **high-fidelity retrieval** of a single interaction. It is the primary mechanism for fetching message metadata, tracking status history, and performing \"on-demand\" media hydration without overloading your network with unnecessary binary data.\n\n---\n\n## 🏗️ Technical Workflow: The \"Deep Probe\" Logic\n\nWhen you request a message by ID, the Wawp engine performs a targeted index lookup:\n1.  **Identity Verification**: The engine uses the `messageId` (a unique cryptographic hash) to locate the exact entry in the local sharded database for the given `chatId`.\n2.  **State Reconstruction**: It gathers not just the body text, but all associated metadata, including sender JID, timestamps, forwarding flags, and current ACK status (Delivered vs. Read).\n3.  **Media Decryption (Optional)**: If `downloadMedia` is enabled, the engine performs an \"Active Fetch.\" It connects to the WhatsApp CDN, downloads the encrypted blob, decrypts it using the keys stored in your session, and returns the result as a Base64 string.\n\n---\n\n## 🚀 Optimized Strategic Patterns\n\n### 1. The \"Media on Click\" Pattern\nFor high-performance dashboards, downloading media for every message is a significant performance bottleneck.\n- **Workflow**: \n    1. Fetch the conversation history using [`/v2/chats/messages`](/v2/chats/messages) with `downloadMedia: false`.\n    2. Render the message list. For images/videos, show a \"Download\" icon.\n    3. When the user clicks the icon, call `/v2/messages/get` with `downloadMedia: true`.\n- **Benefit**: This \"Lazy Hydration\" approach minimizes bandwidth and CPU usage for both your server and the client's browser.\n\n### 2. Post-Sent Verification\nUse this endpoint to verify exactly what reached the WhatsApp network.\n- **Logic**: After sending a complex message (like a list or a template), capture the returned `messageId`. Call `/v2/messages/get` a few seconds later to verify that the structure was hdyrated correctly and check the current `ack` status.\n\n---\n\n## 🛡️ Best Practices for Identification\n\n*   **Handling Non-Existent IDs**: If a `messageId` is incorrect or has been deleted from the phone's local database, the API will return a `404 Not Found`. Ensure your application handles this gracefully by showing a \"Message no longer available\" state.\n*   **Media TTL (Time To Live)**: Remember that media files on WhatsApp's CDN are ephemeral (typically 30-90 days). If you try to fetch an old message with `downloadMedia: true`, the fetch might fail even if the text data is still available.\n*   **JID Scoping**: Always provide the `chatId`. While message IDs are globally unique, providing the JID allows the engine to narrow its search to the correct conversation partition, improving response speed.\n\n---\n\n## 🧩 Advanced Use Cases\n\n### Message Interaction Tracking\nBuild an analytics dashboard.\n- **Logic**: Periodically call `/v2/messages/get` for important marketing messages to track the progression of the `ack` field (from 1=Sent to 2=Delivered to 3=Read). This allows you to calculate \"Time to Open\" metrics for your campaigns.\n\n### Forensic Auditing\nIn support scenarios where a customer claims a message contained specific info, use this endpoint to fetch the *original* record from the Wawp engine, bypassing any potential UI-level caching or local database inaccuracies. This ensures your audit trail is 100% consistent with the WhatsApp network state.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **Base64 Payload Size**: When downloading media, the JSON response can become quite large (e.g., several megabytes for a high-res video). Ensure your application layer can handle large JSON buffers.\n*   **Engine state**: The instance must be in the `WORKING` state to perform network-level media downloads. Metadata retrieval from the local cache may work in other states but is most reliable when active.\n*   **Forwarded Messages**: Pay attention to the `contextInfo` block in the response. It tells you if a message was a reply to another message or if it was forwarded, providing critical context for AI processing.\n\n---\n\n## Summary of Capabilities:\n- Pinpoint retrieval of any message using its unique ID.\n- On-demand high-speed media downloading and decryption.\n- Comprehensive metadata access (timestamps, sender identity, status).\n- Essential for implementing efficient \"Lazy Loading\" in CRM UIs.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target Chat ID (phone@c.us or group@g.us)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "messageId",
            "in": "query",
            "required": true,
            "description": "Unique ID of the message",
            "schema": {
              "type": "string"
            },
            "example": "true_..._..."
          },
          {
            "name": "downloadMedia",
            "in": "query",
            "required": false,
            "description": "Whether to download and return media content",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/messages/delete": {
      "delete": {
        "operationId": "_v2_messages_delete_delete",
        "summary": "Delete a message",
        "description": "Delete a specific message by its ID.\n\n### Developer Tips\n- **Time Limit**: Delete for Everyone is usually only available for about 48 hours after the message was sent.\n\n\n# Controlled Erasure: Mastering the Message Deletion Lifecycle\n\nIn a professional messaging ecosystem, the ability to remove content is just as important as the ability to send it. The `/v2/messages/delete` endpoint provides a programmatic way to invoke WhatsApp's deletion protocols. However, deletion is not a simple \"remove\" command; it is a complex negotiation between your instance, the WhatsApp network, and the recipient's device states.\n\n---\n\n## 🏗️ Technical Logic: \"Delete for Everyone\" vs. \"Delete for Me\"\n\nWhatsApp distinguishes between local and network-wide deletion. Wawp attempts to execute the most effective deletion based on the context:\n\n1.  **Delete for Everyone (Network-Wide)**:\n    *   **The Signature**: The original message is replaced by a system placeholder: *\"This message was deleted\"*.\n    *   **The Handshake**: Your instance sends a \"Revocation\" packet. The WhatsApp server then broadcasts this to all active recipients.\n    *   **Constraint**: This only works if the message was sent by *your* instance and is within the **~48-hour window**.\n2.  **Delete for Me (Local Cleanup)**:\n    *   If the time limit has passed, or if you are deleting a message sent by someone else (and you are not a group admin), the deletion is local. The message disappears from your Wawp instance and linked devices, but remains visible to the sender and other recipients.\n\n---\n\n## 🚀 Strategic Use Cases for Deletion\n\n### 1. Compliance and Data Privacy (GDPR)\nIf a customer exercises their \"Right to Erasure,\" you must remove their messages.\n- **Workflow**: Identify all `messageId` strings associated with the customer's JID in your local database and iterate through them using this endpoint to ensure they are removed from the Wawp engine's storage.\n\n### 2. Correcting Bot Hallucinations\nIf an AI bot sends incorrect information (e.g., a wrong price or private data):\n- **Immediate Action**: Call the delete endpoint for that `messageId` within seconds. Even if the user saw the notification, removing the content prevents it from being archived or used as a reference point later.\n\n### 3. Group Moderation\nAs a Group Admin, your Wawp instance has the power to \"Delete for Everyone\" regardless of who sent the message.\n- **Implementation**: Build a \"Profanity Filter.\" When a webhook detects a message with blacklisted words, automatically trigger a deletion to keep the group professional and safe.\n\n---\n\n## 🛡️ Best Practices for Effective Cleanup\n\n*   **The 48-Hour Threshold**: Always log the `timestamp` of outgoing messages. Do not attempt a \"Delete for Everyone\" UI action if the message is older than 48 hours, as the API will likely fallback to a local delete, which might confuse your agents.\n*   **Handle \"Ghost\" Messages**: Occasionally, a deletion packet might reach a recipient's phone while it's offline. When they reconnect, the message might briefly appear before being deleted. This is a network-level behavior; your system should handle the `message.revoked` webhook to update your local CRM UI.\n*   **Media Persistence**: Deleting a message that contained media typically removes the pointer to that media. However, if the recipient has \"Auto-Download to Gallery\" enabled on their phone, the file may still exist in their physical phone storage even after being \"deleted for everyone.\"\n\n---\n\n## 🧩 Advanced Use Case: The \"Secret\" Handover\n\nIn high-security support scenarios, you might need to send a temporary credential or link.\n- **Logic**: Send the message, wait for the `message.ack` (blue tick), and then automatically call the delete endpoint after 60 seconds. This ensures the data is only available during the active interaction window.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **Admin Requirements**: You **MUST** be an admin to delete messages sent by others in a group. Use [`/v2/groups/participants`](/v2/groups/participants) to verify your status.\n*   **Linked Devices Sync**: Deletions are high-priority sync events. They will propagate to your WhatsApp Web and Mobile instances almost instantly.\n*   **No \"Undo\"**: Once a message is deleted for everyone, there is no \"undelete\" action. Always implement a \"Confirm Deletion\" step in your human-agent UI.\n\n---\n\n## Summary of Capabilities:\n- Programmatic \"Delete for Everyone\" (within the WhatsApp time window).\n- Local \"Delete for Me\" for history management and hygiene.\n- Administrative deletion of participant messages in group chats.\n- Full integration with Webhooks to track revocation status.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target Chat ID (phone@c.us or group@g.us)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "messageId",
            "in": "query",
            "required": true,
            "description": "Unique ID of the message",
            "schema": {
              "type": "string"
            },
            "example": "true_..._..."
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/messages/edit": {
      "put": {
        "operationId": "_v2_messages_edit_put",
        "summary": "Edit a text message",
        "description": "Edit the content of a previously sent text message.\n\n### Developer Tips\n- **15-Minute Window**: You can usually only edit messages within 15 minutes of sending. Plan your correction logic accordingly.\n\n\n# Precision Correction: Mastering the Message Editing Lifecycle\n\nThe `/v2/messages/edit` endpoint allows your application to maintain a high standard of professional communication by correcting errors post-transmission. In a business context, an \"Edited\" label is significantly more professional than deleting a message and re-sending it, as it preserves the conversational thread while ensuring data accuracy. However, editing is a time-bound and type-constrained operation that requires careful orchestration.\n\n---\n\n## 🏗️ Technical Logic of an Edit Operation\n\nWhen you submit an edit request, the Wawp engine initiates a specialized state update:\n1.  **Integrity Check**: The engine verifies that the `messageId` was sent by the current instance and that the current time is within the allowed window.\n2.  **Update Broadcast**: A \"Message Edit\" packet is sent to the WhatsApp network.\n3.  **Client-Side Hydration**: The recipient's device receives the update and replaces the old body with the new one, adding the mandatory \"Edited\" disclaimer next to the timestamp.\n\n---\n\n## 🚀 Advanced Strategic Implementation\n\n### 1. The \"Zero-Downtime\" Bot Correction\nIf your AI bot sends a message that contains a factual error (e.g., a wrong appointment date or pricing):\n- **Scenario**: The bot detects the error 5 seconds after sending via an internal validation check.\n- **Improved UX**: Instead of deleting the message (which creates a \"deleted\" placeholder), call `/v2/messages/edit` immediately. For the user, it looks like a seamless update, maintaining the flow of the interaction.\n\n### 2. Live Pricing and Status Updates\nFor e-commerce integrations, you can use edits to show \"Real-Time\" status in a single message.\n- **Workflow**: Send a message like: \"Payment Status: Pending...\". Once the transaction clears, edit the *same* message to say \"Payment Status: ✅ Success\". This prevents chat clutter and provides a single \"Source of Truth\" for the customer.\n\n---\n\n## 🛡️ Best Practices for Message Integrity\n\n*   **The 15-Minute Rule**: WhatsApp typically allows edits for only **15 minutes** after the original message was sent. Your system should track the `sentAt` timestamp and hide \"Edit\" buttons in your agent UI once this window closes.\n*   **Media Caption Constraints**: Currently, the primary support is for **Text-only** messages. Some engine versions may allow editing captions of images/videos, but for maximum reliability, assume that only the `type: text` messages can be modified.\n*   **Avoid Substantial Semantic Changes**: Use edits for typos, formatting, and minor data corrections. Avoid changing the \"intent\" of a message significantly (e.g., changing \"Yes, I agree\" to \"No, I disagree\") as this can confuse users and undermine conversational trust.\n\n---\n\n## 🧩 Advanced Use Case: The \"Thinking\" Indicator\n\nBuild a sophisticated AI interaction:\n1.  **Initial Message**: Send \"Please wait, I am generating your report... ⏳\".\n2.  **Process**: Run your background AI logic.\n3.  **Final Edit**: Once the result is ready, edit the initial message to contain the full report text. This creates a \"dynamic\" feeling in the interaction and keeps the history clean.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **Notification Behavior**: Note that edited messages usually do not trigger a second \"New Message\" notification or ping on the recipient's phone. If the user isn't currently looking at the chat, they might miss the correction unless you send a follow-up.\n*   **Revision History**: While the official WhatsApp app only shows the \"current\" edited version, some unofficial clients or historical logs might still contain the original text. Never use edits to \"hide\" sensitive information that was accidentally sent—use [`/v2/messages/delete`](/v2/messages/delete) for security-related removals.\n*   **Read State Persistence**: Editing a message does not affect its \"Seen\" (blue tick) status. If it was already read, it remains read.\n\n---\n\n## Summary of Capabilities:\n- Programmatic editing of previously sent text messages.\n- seamless UI updates via the \"Edited\" label protocol.\n- Preserves conversation thread continuity without deletion artifacts.\n- Ideal for bot self-correction and real-time status updates.\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target Chat ID (phone@c.us or group@g.us)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          },
          {
            "name": "messageId",
            "in": "query",
            "required": true,
            "description": "Unique ID of the message",
            "schema": {
              "type": "string"
            },
            "example": "true_..._..."
          },
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "New text content for the message",
            "schema": {
              "type": "string"
            },
            "example": "Updated message text"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/chats/unread": {
      "post": {
        "operationId": "_v2_chats_unread_post",
        "summary": "Mark chat as unread",
        "description": "Explicitly mark a chat as having unread messages.\n\n### Developer Tips\n- **Internal Workflow**: Use 'Mark as Unread' as a lightweight ticketing system inside WhatsApp without needing external software.\n\n\n# The Reminder Flag: Mastering the \"Unread\" State\n\nThe `/v2/chats/unread` endpoint is an essential tool for inbox organization and workflow management. Unlike marking as read, which sends a network-wide signal to the other party, marking as unread is a **Local Identity Action**. It places a visual \"Unread\" dot next to a conversation in your Wawp instance and linked devices, serving as a powerful \"To-Do\" flag for agents who need to return to a conversation later.\n\n---\n\n## 🏗️ Technical Impact of \"Marking as Unread\"\n\nWhen you invoke this endpoint, the Wawp engine performs a state mutation within the session's internal database:\n1.  **State Toggle**: The `unreadCount` for the specified `chatId` is set to an \"indicated\" state (usually representing at least 1 unread item).\n2.  **Display Leveling**: On WhatsApp Web and Mobile, a green/blue dot appears next to the conversation.\n3.  **Does NOT Affect Ticks**: It is crucial to understand that this action **does not** turn the sender's blue ticks back to grey. The sender still sees the message as read if it was previously acknowledged.\n\n---\n\n## 🚀 Strategic Implementation Patterns\n\n### 1. The \"Escalation Flag\"\nIn a helpdesk scenario, an agent might open a chat, realize it belongs to a different department, and need to hand it off.\n- **Workflow**: The agent clicks \"Transfer,\" and your system automatically calls `/v2/chats/unread`. This ensures the heart of the new department sees the chat as a \"New/Urgent\" item in their filtered inbox.\n\n### 2. The \"Reminder\" Loop\nIf a bot handles a request but requires a human to verify the final data:\n- **Best Practice**: After the bot finishes its work, have it call `/v2/chats/unread`. This keeps the conversation at the top of the \"To-Read\" queue for the human supervisor.\n\n---\n\n## 🛡️ Best Practices for Inbox Triage\n\n*   **Filter-Ready Architecture**: When fetching your chat list via [`/v2/chats/overview`](/v2/chats/overview), use the unread state to drive your \"Pending Action\" tab. Any chat marked as unread should be treated as an open ticket.\n*   **Clear Before Unread**: If you want to use the unread dot as a clean \"Reminder,\" it's often best to call [`/v2/chats/read`](/v2/chats/read) first to clear any *real* unread counts, and then immediately call `/v2/chats/unread` to set the single \"Reminder Dot.\"\n*   **JID Precision**: Ensure you are targeting the correct conversation. Marking a group as unread is a common way for moderators to flag messages that need a policy review later.\n\n---\n\n## 🧩 Advanced Use Case: Multi-Agent Synchronization\n\nBuild a \"Bookmark\" feature in your CRM.\n- **Logic**: When an agent clicks \"Follow Up Later,\" the CRM calls the unread endpoint. Because this state syncs via the WhatsApp WebSocket, every other agent on that same Wawp instance will also see the unread indicator, preventing the conversation from being forgotten during shift changes.\n\n---\n\n## ⚠️ Important Considerations\n\n*   **Local UI Only**: This is a non-destructive, non-broadcast action. It is the only \"Chat Action\" that doesn't significantly impact the customer's view of the conversation.\n*   **Engine State**: Requires the session to be in the `WORKING` state to synchronize the indicator with linked devices.\n*   **Overwrite Behavior**: If the chat already has real unread messages (e.g., 5 unread), calling this endpoint might not change the visual state significantly, as it's already \"Unread.\" It is most effective when moving a conversation from a \"Read/Processed\" state back to \"Attention Required.\"\n\n---\n\n## Summary of Capabilities:\n- Explicitly setting of the \"Unread\" visual indicator for any chat.\n- Synchronized bookmarking across all linked devices.\n- Powerful tool for agent handoffs and \"Follow Up\" reminders.\n- Non-impactful to the customer experience (does not change blue ticks).\n    ",
        "tags": [
          "Chat Actions"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Recipient's WhatsApp ID (JID). Supports Individuals (@c.us), Groups (@g.us), and Newsletters (@newsletter).",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/profile": {
      "get": {
        "operationId": "_v2_profile_get",
        "summary": "Get profile",
        "description": "Retrieve your own WhatsApp profile information (name, status, etc.).",
        "tags": [
          "Whatsapp Profile info"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/profile/name": {
      "put": {
        "operationId": "_v2_profile_name_put",
        "summary": "Set Profile Name",
        "description": "Update your WhatsApp display name (push name).",
        "tags": [
          "Whatsapp Profile info"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "New display name",
            "schema": {
              "type": "string"
            },
            "example": "Wawp Support"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/profile/status": {
      "put": {
        "operationId": "_v2_profile_status_put",
        "summary": "Set 'About' status",
        "description": "Update your WhatsApp 'About' (bio) status.",
        "tags": [
          "Whatsapp Profile info"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "status",
            "in": "query",
            "required": true,
            "description": "New status text",
            "schema": {
              "type": "string"
            },
            "example": "Available for support"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/profile/picture": {
      "put": {
        "operationId": "_v2_profile_picture_put",
        "summary": "Upload Whatsapp picture",
        "description": "Upload a new profile picture for your WhatsApp account.",
        "tags": [
          "Whatsapp Profile info"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Direct URL to the image",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/logo.jpg"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Name of the file",
            "schema": {
              "type": "string"
            },
            "example": "logo.jpg"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type of the image (image/jpeg recommended)",
            "schema": {
              "type": "string"
            },
            "example": "image/jpeg"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/profile/picture-delete": {
      "delete": {
        "operationId": "_v2_profile_picture-delete_delete",
        "summary": "Delete profile picture",
        "description": "Remove your current WhatsApp profile picture.",
        "tags": [
          "Whatsapp Profile info"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/presence": {
      "post": {
        "operationId": "_v2_presence_post",
        "summary": "Set session presence",
        "description": "Sets the presence for the current session (online/offline).",
        "tags": [
          "Presence information"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "presence",
            "in": "query",
            "required": true,
            "description": "Presence state: online or offline",
            "schema": {
              "type": "string"
            },
            "example": "online"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "_v2_presence_get",
        "summary": "Get General Presence",
        "description": "Get the current presence status (online/offline) for the authenticated session.\n\n\n# Mirror, Mirror: Checking Your Own Reflection\n\nThe `/v2/presence` (GET) endpoint allows you to programmatically verify how your WhatsApp session appears to the outside world. While you can *set* your status using the POST method, this GET method is crucial for auditing and synchronization.\n\n---\n\n## 🏗️ State Verification\n\nWhy check your own status?\n\n### 1. Audit Loops\nIf you manage a fleet of 50 support bots, you need a dashboard to see which ones are currently \"Online\" and accepting chats.\n*   **Workflow**: Central Monitor calls `/v2/presence` on each instance every minute.\n*   **Alert**: If a bot is supposed to be Online but returns `offline`,\n  tips: [\n    {\n        \"type\": \"positive\",\n        \"title\": \"User Experience\",\n        \"content\": \"Show \"typing...\" status to make the bot feel more human-like.\"\n    },\n    {\n        \"type\": \"info\",\n        \"title\": \"Status\",\n        \"content\": \"Online status updates can trigger automation flows.\"\n    }\n],\n  recommendations: [\n    \"Do not keep \"typing\" status active for too long without sending a message.\",\n    \"Respect user privacy regarding online presence.\",\n    \"Use presence webhooks to trigger immediate responses.\"\n],\n  \n   trigger a slack alert to the engineering team. The session might have crashed or been manually toggled by a human using the mobile app.\n\n### 2. UI Synchronization\nIf you are building a custom CRM with a \"Go Online\" toggle button:\n*   **Problem**: You don't know the *initial* state of the button when the page loads.\n*   **Solution**: Call this endpoint on page load. If it returns `available`, render the toggle as green (Active). If `unavailable`, render it as grey (Inactive).\n\n### 3. Debugging \"Ghost\" Issues\nSometimes users complain: \"I see you online but you aren't replying!\"\n*   **Debugger**: Call this endpoint. content:\n    *   Result: `offline`.\n    *   Conclusion: The user is seeing a *cached* state on their device, or you have privacy settings hiding your real status. The API confirms you are effectively invisible.\n\n---\n\n## 🔄 The Feedback Loop\n\n### The \"Auto-Correction\" Pattern\nWhatsApp sessions can sometimes drift. For example, if the physical phone loses internet connection for 10 minutes, WhatsApp might automatically mark the session as `unavailable`.\n*   **Script**:\n    1.  Cron job runs every 5 minutes.\n    2.  Step A: Call `GET /v2/presence`.\n    3.  Step B: If result is `offline` AND expected state is `online` -> Call `POST /v2/presence` to force it back.\n    4.  Result: Self-healing availability.\n\n---\n\n## ⚠️ Limitations\n\n*   **Internal State Only**: This endpoint only returns what the *WhatsApp Web* protocol thinks your status is. It does not strictly guarantee that your phone is reachable (e.g., if the battery died 30 seconds ago, the server might still think you are online for another minute).\n*   **Privacy Masks**: If your privacy settings are set to \"Nobody\", this endpoint might still return `available` (because *you* know you are online), but external users will see nothing. Usage of this data must be combined with an understanding of your privacy configuration.\n    ",
        "tags": [
          "Presence"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/presence/{chatId}": {
      "get": {
        "operationId": "_v2_presence_chatId_get",
        "summary": "Get the presence for the chat id",
        "description": "Retrieves the current presence information for a specific chat ID.",
        "tags": [
          "Presence information"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "The chatId to check presence for",
            "schema": {
              "type": "string"
            },
            "example": "123456789@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/presence/{chatId}/subscribe": {
      "post": {
        "operationId": "_v2_presence_chatId_subscribe_post",
        "summary": "Subscribe to Presence",
        "description": "Subscribe to real-time presence updates (online/offline) for a specific contact.\n\n### Developer Tips\n- **Monitoring**: Great for CRM systems that need to know when a customer is active to initiate a chat.",
        "tags": [
          "Presence"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "The identifier for the contact (@c.us)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/status/text": {
      "post": {
        "operationId": "_v2_status_text_post",
        "summary": "Text status",
        "description": "Post a text-based status (story) to WhatsApp.",
        "tags": [
          "24 Hour Status"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "Text content for the status",
            "schema": {
              "type": "string"
            },
            "example": "Have a look! https://github.com/"
          },
          {
            "name": "backgroundColor",
            "in": "query",
            "required": true,
            "description": "Background color in #RRGGBB format",
            "schema": {
              "type": "string"
            },
            "example": "#38b42f"
          },
          {
            "name": "font",
            "in": "query",
            "required": true,
            "description": "Font ID (0-5 mostly)",
            "schema": {
              "type": "integer"
            },
            "example": "0"
          },
          {
            "name": "linkPreview",
            "in": "query",
            "required": true,
            "description": "Enable link preview",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "linkPreviewHighQuality",
            "in": "query",
            "required": true,
            "description": "High quality link preview",
            "schema": {
              "type": "boolean"
            },
            "example": "false"
          },
          {
            "name": "contacts",
            "in": "query",
            "required": true,
            "description": "Optional contacts to mention or target",
            "schema": {
              "type": "string"
            },
            "example": "null"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/status/image": {
      "post": {
        "operationId": "_v2_status_image_post",
        "summary": "Image status",
        "description": "Post an image status (story) to WhatsApp.",
        "tags": [
          "24 Hour Status"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "Direct URL to the image",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/cat.jpg"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Name of the file",
            "schema": {
              "type": "string"
            },
            "example": "image.jpg"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type of the image",
            "schema": {
              "type": "string"
            },
            "example": "image/jpeg"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Caption for the image",
            "schema": {
              "type": "string"
            },
            "example": "Check our new menu!"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/status/voice": {
      "post": {
        "operationId": "_v2_status_voice_post",
        "summary": "Voice status",
        "description": "Post a voice status (story) to WhatsApp.\n\n### Developer Tips\n- **Background**: Voice statuses allow you to share audio updates with contacts.\n- **Duration**: Limited to 30 seconds, similar to video status.\n\n\n# The Personal Touch: Voice Status\n\nThe `/v2/status/voice` endpoint allows you to post audio recordings directly to your Status feed. Users see an audio player with a waveform visualization, making it distinct from standard video or music files.\n\n---\n\n## 🎙️ Why Voice?\n\n### 1. Intimacy at Scale\nVoice notes are the most personal form of digital communication. Hearing a founder's voice explaining a delay or wishing a \"Happy New Year\" creates a connection that text cannot replicate.\n*   **Trust**: It proves there is a human behind the automation.\n*   **Nuance**: Tone, excitement, and empathy are lost in text but preserved in voice.\n\n### 2. High Accessibility\n*   **Passive Consumption**: Users can listen while driving or walking.\n*   **Literacy**: Great for markets where oral communication is preferred over reading long text blocks.\n\n---\n\n## 🎧 Technical Requirements\n\nWhatsApp is extremely strict about audio formats for Voice Status.\n\n### The \"Opus in OGG\" Rule\nTo get the authentic \"Voice Note\" look (with the waveform), you cannot just upload an MP3.\n*   **Container**: **OGG**.\n*   **Codec**: **Opus**.\n*   **Channels**: **Mono** (1 channel). Stereo often causes the waveform to look flat.\n*   **Sample Rate**: **16000 Hz** or **48000 Hz**.\n\n### How to Convert using FFmpeg\nIf you have an MP3 file, use this command before uploading:\n```bash\nffmpeg -i input.mp3 -c:a libopus -b:a 64k -vbr on -compression_level 10 output.ogg\n```\n\n### The `convert` Solution\nIf you don't want to handle FFmpeg, set `convert: true` in your API call.\n*   **Mechanism**: The API will take your MP3/WAV/AAC and transcode it to OGG/Opus.\n*   **Trade-off**: Adds latency.\n\n---\n\n## 🎨 Visual Customization\n\nUnlike Video (which fills the screen with pixels), a Voice Status is essentially an audio player on top of a colored background.\n\n### Background Colors\nJust like Text Status, you can (and should) strictly define a `backgroundColor`.\n*   **Default**: If you don't specify one, WhatsApp picks a random color (often a garish purple or green).\n*   **Branding**: Use your brand's hex code to maintain visual consistency.\n    *   *Example*: A Red background (`#FF0000`) for urgent alerts.\n    *   *Example*: A Blue background (`#0000FF`) for calm updates.\n\n---\n\n## 🚀 Use Case Ideas\n\n### 1. The \"Morning Briefing\"\n*   **Concept**: A 30-second summary of the stock market or daily news.\n*   **Execution**:\n    1.  Text-to-Speech (TTS) engine generates audio.\n    2.  FFmpeg converts to OGG.\n    3.  API Call: Upload with `backgroundColor: #000000`.\n*   **User Value**: Users get a mini-podcast in their Status feed.\n\n### 2. The \"Pronunciation Guide\"\n*   **Concept**: An educational bot teaching languages.\n*   **Execution**:\n    1.  Image Status: Shows the word \"Bonjour\".\n    2.  Voice Status (Immediately after): Plays the correct pronunciation.\n*   **Result**: A multi-modal verified lesson.\n\n### 3. Music Teasers\n*   **Concept**: An artist dropping a new track.\n*   **Execution**: Upload the 30-second \"hook\" of the song.\n*   **Note**: Ensure `convert: true` is on if uploading MP3 snippets.\n\n---\n\n## ⚠️ Limitations\n\n### The 30-Second Limit (Again)\nJust like video, Voice Statuses are capped at **30 seconds**.\n*   **Truncation**: If you upload a 5-minute podcast, only the first 30 seconds will play. The rest is discarded silently.\n*   **Splitting**: You generally *cannot* split audio as elegantly as video because the pause between statuses breaks the flow of speech. Keep it succinct.\n\n### No \"Seek\" Bar\nVoice Statuses do not always have a seek bar (scrubber) depending on the user's OS version. Users expect to listen from start to finish.\n\n### Privacy\nVoice Statuses obey the same privacy rules (My Contacts, etc.) as the rest of the ecosystem.\n    ",
        "tags": [
          "24 Hour Status"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "URL to the audio file (ogg/opus recommended)",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/file_example_OOG_1MG.ogg"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Name of the file",
            "schema": {
              "type": "string"
            },
            "example": "note.ogg"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type",
            "schema": {
              "type": "string"
            },
            "example": "audio/ogg; codecs=opus"
          },
          {
            "name": "convert",
            "in": "query",
            "required": true,
            "description": "Enable auto-conversion",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Caption for the voice status",
            "schema": {
              "type": "string"
            },
            "example": "Listen to this!"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/status/video": {
      "post": {
        "operationId": "_v2_status_video_post",
        "summary": "Video status",
        "description": "Post a video status (story) to WhatsApp.",
        "tags": [
          "24 Hour Status"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "file[url]",
            "in": "query",
            "required": true,
            "description": "URL to the video file",
            "schema": {
              "type": "string"
            },
            "example": "https://wawp.net/samples/file_example_MP4_480_1_5MG.mp4"
          },
          {
            "name": "file[filename]",
            "in": "query",
            "required": true,
            "description": "Name of the file",
            "schema": {
              "type": "string"
            },
            "example": "video.mp4"
          },
          {
            "name": "file[mimetype]",
            "in": "query",
            "required": true,
            "description": "MIME type",
            "schema": {
              "type": "string"
            },
            "example": "video/mp4"
          },
          {
            "name": "convert",
            "in": "query",
            "required": true,
            "description": "Enable auto-conversion",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          },
          {
            "name": "asNote",
            "in": "query",
            "required": true,
            "description": "Send as video note",
            "schema": {
              "type": "boolean"
            },
            "example": "false"
          },
          {
            "name": "caption",
            "in": "query",
            "required": true,
            "description": "Caption for the video",
            "schema": {
              "type": "string"
            },
            "example": "Watch this clip"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/status/new-message-id": {
      "get": {
        "operationId": "_v2_status_new-message-id_get",
        "summary": "Get New Status ID",
        "description": "Generate a new message ID for a status update. Useful for idempotent status updates.\n\n### Developer Tips\n- **Format**: Generates a hexadecimal ID required for creating new status updates.\n- **Uniqueness**: Ensures your status update doesn't collide with others.\n\n\n# The Architect's Tool: Pre-Generating IDs\n\nThe `/v2/status/new-message-id` endpoint is a utility for advanced developers building high-reliability systems. It allows you to reserve a valid WhatsApp Message ID *before* you actually send the content.\n\n---\n\n## 🏗️ The Problem: The \"Lost Response\"\n\nIn a typical API flow:\n1.  You call `POST /v2/status/image`.\n2.  The server processes it and sends it to WhatsApp.\n3.  The server returns `200 OK` with `{ id: \"ABC\" }`.\n4.  **Failure**: Your internet cuts out *after* sending the request but *before* receiving the response.\n\n**Outcome**: The status was posted, but your database doesn't know the ID. You try to post it again -> **Duplicate Content**.\n\n---\n\n## 🛡️ The Solution: Idempotency with Proper IDs\n\nBy generating the ID first, you invert the control flow.\n\n### Step 1: Generate & Store\nCall `GET /v2/status/new-message-id`.\n*   Response: `{ id: \"3EB0...123\" }`\n*   Action: Save to DB: `{ status_id: \"3EB0...123\", state: \"pending_upload\" }`\n\n### Step 2: The Upload\nCall `POST /v2/status/image` but include the ID in the payload (if supported) or simply map it internally.\n*   *Note*: Currently, the Wawp API auto-assigns IDs on send. However, this endpoint is crucial for **correlation**.\n\n### Use Case: Tracking Viewers\nIf you want to track who viewed a specific status:\n1.  You need the ID *immediately* to set up your webhook listener.\n2.  By generating it first (conceptually), you can prepare your analytics system:\n    ```javascript\n    const nextId = await api.getNewId();\n    analytics.subscribeTo(nextId); // Ready to listen\n    await api.postStatus(image, { id: nextId }); // Send\n    ```\n\n---\n\n## 🔮 Implementation Details\n\n### Format\nThe ID returned is a standard WhatsApp Message ID (e.g., `3EB0...`).\n*   It is unique to your session.\n*   It implies \"From Me\" (key.fromMe = true).\n\n### Collision Safety\nWhatsApp IDs are time-based and random. The chance of collision is astronomically low. You can safely generate 100 IDs in parallel without conflict.\n\n---\n\n## ⚠️ Limitations\n\n*   **Ephemeral**: Generating an ID does not \"reserve\" it on WhatsApp servers. It just gives you a string that *will be valid* if used.\n*   **Scope**: This ID is for **Status Updates** only. Do not try to use it for sending text messages to chats, as the ID structure might differ slightly in future protocol versions.\n    ",
        "tags": [
          "Status"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/status/delete": {
      "post": {
        "operationId": "_v2_status_delete_post",
        "summary": "Delete status",
        "description": "Delete a specific status (story) by ID.",
        "tags": [
          "24 Hour Status"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "YOUR_ACCESS_TOKEN"
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The status message ID to delete",
            "schema": {
              "type": "string"
            },
            "example": "status-msg-id"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/channels": {
      "get": {
        "operationId": "_v2_channels_get",
        "summary": "Get Channels List",
        "description": "Retrieve a list of WhatsApp channels known to the instance, filtered by role if specified.\n\n### Developer Tips\n- **Scope**: Returns channels you follow or own.\n- **Pagination**: This list can be long. Use pagination cursors if available.\n\n\n# The Inventory: Listing Your Channels\n\nThe `/v2/channels` endpoint acts as your personal registry. It returns a list of all channels that your Wawp instance interacts with, whether as a Creator (Owner) or a Follower (Subscriber).\n\n---\n\n## 📋 Understanding Channel Roles\n\nThe response includes a `role` field for each channel, which dictates your permissions.\n\n### 1. OWNER\n*   **Definition**: You created this channel.\n*   **Capabilities**: \n    *   Post updates (Text, Media, Polls).\n    *   Change settings (Name, Picture, Description).\n    *   Delete the channel.\n\n### 2. ADMIN\n*   **Definition**: You were promoted to admin by the Owner (Note: Admin promotion via API is currently limited).\n*   **Capabilities**: similar to owner but usually cannot delete the channel.\n\n### 3. SUBSCRIBER (GUEST)\n*   **Definition**: You followed this channel from the directory.\n*   **Capabilities**: \n    *   Read messages.\n    *   React with emojis.\n    *   Mute/Unmute.\n    *   **Cannot** post updates.\n\n---\n\n## 🛠️ Sync Strategies\n\n### The Startup Sync\nWhen your application boots up, you should call this endpoint to populate your local state.\n1.  **Fetch**: Call `GET /v2/channels`.\n2.  **Filter**: Separate the list into \"My Channels\" (`role=OWNER`) and \"Subscriptions\" (`role=SUBSCRIBER`).\n3.  **Display**: \n    *   Show \"My Channels\" in a \"Broadcast Dashboard\".\n    *   Show \"Subscriptions\" in a \"News Feed\" view.\n\n### The \"Stale Data\" Problem\nChannel metadata (like name or picture) changes rarely.\n*   **Optimization**: Do not call this endpoint on every page load. Cache the result for 10-60 minutes.\n*   **Invalidation**: If you perform a `create` or `follow` action, manually add that new item to your local cache instead of re-fetching the entire list.\n\n---\n\n## 🔍 Advanced Filtering\n\nYou can server-side filter the results to save bandwidth.\n\n*   **`role=OWNER`**: Useful for \"Creator Studios\" where you only want to see channels you can post to.\n*   **`role=SUBSCRIBER`**: Useful for \"Reader Apps\" where you only want to see content consumption sources.\n\n---\n\n## ⚠️ Common Pitfalls\n\n*   **Missing Channels**: If you just followed a channel but it doesn't appear here immediately, give it 1-2 seconds. The sync between the WhatsApp server and the Wawp instance is asynchronous.\n*   **Duplicate Names**: Remember that multiple channels can have the name \"Test Channel\". Always use the `id` (`@newsletter`) as the unique key in your UI.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "role",
            "in": "query",
            "required": false,
            "description": "Filter by role. Available values: OWNER, ADMIN, SUBSCRIBER",
            "schema": {
              "type": "string"
            },
            "example": "OWNER"
          }
        ],
        "responses": {
          "200": {
            "description": "List of channels retrieved successfully",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "1234567890@newsletter",
                    "name": "Wawp Updates",
                    "role": "OWNER",
                    "description": "Official updates from Wawp"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/create": {
      "post": {
        "operationId": "_v2_channels_create_post",
        "summary": "Create Channel",
        "description": "Create a new WhatsApp channel with a name, description, and profile picture.\n\n### Developer Tips\n- **Visibility**: Channels are public by default. Anyone can search and find them.\n- **Broadcast**: Channels are one-way broadcast tools; followers cannot reply with text.\n\n\n# The Genesis Block: Programmatic Channel Creation\n\nThe `/v2/channels/create` endpoint is your gateway to becoming a broadcaster on WhatsApp. Unlike Groups, which require adding phone numbers one by one, a Channel is a public entity that users choose to follow. This endpoint allows you to instantly provision a new broadcasting outlet for your brand, topic, or community.\n\n---\n\n## 🏗️ Anatomy of a Channel\n\nWhen you create a channel, you are defining three key public-facing attributes. Getting these right is crucial for subscriber growth.\n\n### 1. The Name (`name`)\n*   **Constraint**: Maximum ~100 characters (though WhatsApp recommends < 25 for visibility).\n*   **Strategy**: This is the searchable title. If you are a news agency, include your brand name. If you are a niche bot, include the topic (e.g., \"Daily Crypto Alerts\").\n*   **Uniqueness**: Names are *not* unique. You can have multiple channels with the same name, but they will have different JIDs.\n\n### 2. The Description (`description`)\n*   **Constraint**: Supports text and emojis.\n*   **SEO Value**: This field is indexed by WhatsApp's directory search. Include keywords here.\n    *   *Bad*: \"Updates from us.\"\n    *   *Good*: \"Daily alerts for **Bitcoin**, **Ethereum**, and **DeFi** market trends. Official channel for CryptoNews.\"\n*   **Trust**: Use this space to link to your official website or privacy policy to establish legitimacy.\n\n### 3. The Picture (`picture`)\n*   **Format**: JPG or PNG.\n*   **Dimensions**: Recommended 640x640 pixels (square).\n*   **Behavior**: If omitted, the channel will have a default generic icon. It is **highly recommended** to set this during creation to increase click-through rates from the directory.\n\n---\n\n## 🚀 Post-Creation Workflow\n\nOnce you receive a `201 Created` response, your channel is live on the network, but it has 0 followers.\n\n### Step 1: Capture the JID\nThe response will contain an `id` ending in `@newsletter` (e.g., `123456789@newsletter`).\n*   **Action**: Store this permanently in your database. You cannot send messages without it.\n\n### Step 2: Get the Invite Link\nWhile not always returned in the creation response (depending on API version), you can usually construct a deep link or fetch channel info to get the `invite_link`.\n*   **Format**: `https://whatsapp.com/channel/...`\n*   **Distribution**: Embed this link in your email footers, website banners, and SMS campaigns.\n\n### Step 3: The \"First Post\"\nA empty channel looks abandoned.\n*   **Best Practice**: Immediately after creation, use [`/v2/channels/{id}/messages`](/v2/channels/{id}/messages) to post a \"Welcome\" message explaining what subscribers can expect.\n\n---\n\n## ⚠️ Limits & Restrictions\n\n*   **Rate Limits**: You can usually create a limited number of channels per phone number per day (e.g., 1-10 depending on trust score) to prevent spam.\n*   **Admin Rights**: The Wawp instance that creates the channel is the **Sole Admin**. Currently, the API may not support adding other admins programmatically. Ensure you do not lose access to this session.\n*   **Compliance**: Channel content is moderated by Meta. Creating channels for illegal topics or hate speech can result in an instant ban of your entire Wawp instance.\n\n---\n\n## 💡 Advanced: Dynamic Channel Provisioning\n\nIf you are a SaaS platform (e.g., a Real Estate CRM), you can automate this:\n1.  Real Estate Agent signs up on your site.\n2.  Your system calls `/v2/channels/create` with name \"Home Listings: [Agent Name]\".\n3.  Your system stores the JID.\n4.  Every time the agent adds a new property to your CRM, your system automatically broadcasts the photo and price to their specific Channel.\n\nThis turns every user of your software into a micro-broadcaster.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "The name of the channel",
            "schema": {
              "type": "string"
            },
            "example": "Channel Name"
          },
          {
            "name": "description",
            "in": "query",
            "required": false,
            "description": "A brief description of the channel",
            "schema": {
              "type": "string"
            },
            "example": "Channel Description"
          },
          {
            "name": "picture",
            "in": "query",
            "required": false,
            "description": "Channel profile picture details",
            "schema": {
              "type": "string"
            },
            "example": "{\n  \"mimetype\": \"image/jpeg\",\n  \"filename\": \"filename.jpg\",\n  \"url\": \"https://wawp.net/wp-content/uploads/2025/08/icon-256x256-1.jpg\"\n}"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Channel type",
            "schema": {
              "type": "string"
            },
            "example": "string"
          }
        ],
        "responses": {
          "201": {
            "description": "Channel created successfully",
            "content": {
              "application/json": {
                "example": {
                  "id": "1234567890@newsletter",
                  "status": "success",
                  "message": "Channel created successfully"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/{id}": {
      "get": {
        "operationId": "_v2_channels_id_get",
        "summary": "Get Channel Info",
        "description": "Get detailed information about a specific channel.\n\n### Developer Tips\n- **Verification**: Returns verification status (Green checkmark).\n- **Stats**: Includes subscriber count and channel creation date.\n\n\n# Deep Dive: Channel Metadata\n\nThe `/v2/channels/{id}` endpoint allows you to retrieve the full profile of any public channel, provided you have its ID (JID). This is useful for refreshing metadata like subscriber counts or profile pictures.\n\n---\n\n## 🏗️ The Data Payload\n\nBeyond the basic name, this endpoint returns critical fields for integration:\n\n### 1. `invite_link`\n*   **Usage**: The `https://whatsapp.com/channel/...` URL.\n*   **Strategy**: If you are building a directory, display this link to let users open the channel directly in their native WhatsApp app.\n\n### 2. `subscribers` (Count)\n*   **Accuracy**: This is an approximate count (e.g., 1.2M), not an exact integer down to the last digit for large channels.\n*   **Analytics**: Track this over time to measure growth or campaign effectiveness.\n\n### 3. `verified`\n*   **Green Tick**: Indicates if the channel belongs to an authentic, notable brand.\n*   **UI Tip**: Always display a verification badge next to the name if this is `true`. It builds trust with your users.\n\n---\n\n## 🔄 Refresh Strategy\n\n### When to call this?\nChannel metadata is static for long periods.\n*   **Do**: Call this when a user clicks on a channel to view its details.\n*   **Don't**: Call this in a loop for every channel in your list. Use [`/v2/channels`](/v2/channels) for bulk retrieval.\n\n### Handling 404s\nIf this endpoint returns a `404 Session not found` or similar error regarding the channel ID:\n*   **Meaning**: The channel may have been deleted by the owner or banned by WhatsApp.\n*   **Action**: Automatically remove this channel from your local database or mark it as \"Inactive\".\n\n---\n\n## 🔒 Privacy Note\nFetching channel info is a public action. The channel owner does not know you requested this data. It is similar to loading a public web page.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the channel",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@newsletter"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Channel info retrieved successfully",
            "content": {
              "application/json": {
                "example": {
                  "id": "1234567890@newsletter",
                  "name": "Channel Name",
                  "description": "Channel Description",
                  "subscribers": 1500
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "404": {
            "description": "Not Found - Session Does Not Exist",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_session",
                  "message": "Session not found. Please verify your instance_id or session_name.",
                  "details": {
                    "recommendation": "Check if the instance exists and is currently active. You might need to start it first."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/{invite}/messages/preview": {
      "get": {
        "operationId": "_v2_channels_invite_messages_preview_get",
        "summary": "Preview Channel Messages",
        "description": "Preview messages from a public channel using an invite code or link. (Wawp PLUS Feature)",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "invite",
            "in": "query",
            "required": true,
            "description": "Channel invite code or full link",
            "schema": {
              "type": "string"
            },
            "example": "https://whatsapp.com/channel/..."
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/channels/{id}/follow": {
      "post": {
        "operationId": "_v2_channels_id_follow_post",
        "summary": "Follow Channel",
        "description": "Start following a WhatsApp channel to receive its updates.\n\n### Developer Tips\n- **Privacy**: Channel admins cannot see the phone numbers of followers.\n- **Updates**: Following ensures updates appear in the Updates tab.\n\n\n# The Subscription Model: Following Channels\n\nThe `/v2/channels/{id}/follow` endpoint establishes a subscription relationship between your Wawp instance and a public Channel. This is the programmatic equivalent of pressing the \"Follow\" button in the WhatsApp app.\n\n---\n\n## 🔗 How Subscriptions Work\n\n### 1. Privacy First\nThe \"Follow\" action is designed with privacy at its core.\n*   **Anonymity**: The Channel Admin (creator) **cannot see your phone number**. They only see an increment in their follower count.\n*   **Safety**: You cannot be messaged directly by the admin or other followers. The communication is strictly one-way (Admin -> You).\n\n### 2. The Data Flow\nOnce you successfully follow a channel:\n*   **Updates**: New messages posted by the admin will arrive in your webhook stream (usually under the `message` event with `from: \"123...@newsletter\"`).\n*   **History**: You immediately gain access to the channel's recent history, which you can fetch using [`/v2/channels/{id}/messages`](/v2/channels/{id}/messages).\n\n### 3. Mute Status\nBy default, following a channel *may* mute it depending on your account settings.\n*   **Recommendation**: If you are building a real-time monitor, follow up this call with [`/v2/channels/{id}/unmute`](/v2/channels/{id}/unmute) to ensure you receive push notifications for every update.\n\n---\n\n## 🤖 Automating Market Intelligence\n\nThis endpoint is the cornerstone of \"Listening\" strategies.\n\n### Scenario: The Industry Dashboard\nYou want to track 50 competing news outlets.\n1.  **Ingest**: Load a list of Channel JIDs into your database.\n2.  **Loop**: Iterate through them and call `/follow`.\n3.  **Listen**: Set up a webhook listener for `message` events where `remoteJid` ends in `@newsletter`.\n4.  **Process**: When a message comes in, analyze the text/media and display it on your internal dashboard.\n\n### Scenario: The Fan Engagement Bot\nYou run a fan club for a sports team.\n1.  **Proxy Follow**: Your bot follows the official team channel.\n2.  **Relay**: When the team posts a \"Goal!\" update, your bot instantly forwards that text to a private Group Chat of your paying members.\n\n---\n\n## ⚠️ Limits & Etiquette\n\n*   **Follow Limit**: A single WhatsApp account can follow up to ~2,000 channels (subject to change by Meta).\n*   **Rate Limiting**: Do not follow 100 channels in 1 second. WhatsApp may flag this as \"automated behavior\" (spam). Use a randomized delay of 5-15 seconds between follows.\n*   **Unfollowing**: If you no longer need updates, always use [`/v2/channels/{id}/unfollow`](/v2/channels/{id}/unfollow) to clean up your state and respect the network resources.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the channel",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@newsletter"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Followed channel successfully",
            "content": {
              "application/json": {
                "example": {
                  "status": "success",
                  "message": "Now following the channel"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/{id}/unfollow": {
      "post": {
        "operationId": "_v2_channels_id_unfollow_post",
        "summary": "Unfollow Channel",
        "description": "Stop following a WhatsApp channel.\n\n\n# Breaking Up: Unfollowing Channels\n\nThe `/v2/channels/{id}/unfollow` endpoint terminates your subscription to a channel. This is the \"Cleanup\" operation of the Channels lifecycle.\n\n---\n\n## 🛑 Why Unfollow?\n\n### 1. Reducing Noise\nEvery channel you follow sends messages to your webhook. If you follow 1,000 active news channels, your server might receive 50+ messages per second.\n*   **Best Practice**: Periodically audit your subscriptions using [`/v2/channels`](/v2/channels) and unfollow inactive or low-relevance channels to save bandwidth.\n\n### 2. Privacy & Opt-Out\nIf you are building a \"User Proxy\" service (where your users ask your bot to follow channels for them), you **must** provide an Unsubscribe mechanism. When a user says \"Stop,\" you must call this endpoint to respect their choice and the channel owner's analytics.\n\n---\n\n## ⚙️ Technical Behavior\n\n*   **Webhook Cessation**: The moment this call returns `200 OK`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Cleanup',\n            content: 'Removes the channel from your updates list.'\n        },\n        {\n            type: 'warning',\n            title: 'Analytics',\n            content: 'You will no longer receive view metrics for this channel.'\n        }\n    ],\n  recommendations: [\n        \"Ask for feedback upon unfollowing to improve your content recommendation engine.\",\n        \"Confirm the action if it's accidental.\"\n    ]\n  \n   your instance will stop receiving `message` events from this JID.\n*   **History Retention**: You will still retain access to the messages you *already* received and stored in your own database, but you may lose access to fetch *historical* messages from the WhatsApp server for this channel.\n*   **Idempotency**: If you call this on a channel you are not following, it will likely return a success or a harmless error. It is safe to retry.\n\n---\n\n## ⚠️ The \"Zombie\" State\nIn rare cases, if you unfollow a channel but still have it cached locally in your app as \"Active,\" you might try to send reactions/messages to it. These will fail with `403 Forbidden`.\n*   **Action**: Always update your local \"Inventory\" immediately after calling this endpoint.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the channel",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@newsletter"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Unfollowed channel successfully",
            "content": {
              "application/json": {
                "example": {
                  "status": "success",
                  "message": "No longer following the channel"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/{id}/mute": {
      "post": {
        "operationId": "_v2_channels_id_mute_post",
        "summary": "Mute Channel",
        "description": "Mute notifications for a specific channel.\n\n\n# Silence is Golden: Muting Channels\n\nThe `/v2/channels/{id}/mute` endpoint allows you to programmatically silence notifications for a specific channel. This corresponds to the \"Mute\" action in the mobile app.\n\n---\n\n## 🔇 What Does \"Mute\" Actually Do?\n\nIt is important to understand the distinction between \"Muting\" and \"Unfollowing\".\n\n### 1. Webhook delivery \n**Muting does NOT stop webhooks.**\n*   Even if a channel is muted, your Wawp instance will still receive every new message via the `message` webhook event.\n*   **Why?** The API assumes that if you are following a channel programmatically, you want the data for processing, regardless of whether you want the phone to ring.\n\n### 2. Device Behavior\n*   **Notifications**: The connected physical phone (if any) will **stop vibrating/ringing** for new updates from this channel.\n*   **Badge Count**: New messages will not increment the unread badge count on the main \"Updates\" tab icon, reducing visual clutter.\n*   **Sorting**: Muted channels are often pushed to the bottom of the list in the mobile UI.\n\n---\n\n## 🎯 Use Cases\n\n### The \"Silent Collector\" Bot\nYou are building a market research tool that follows 500 news channels.\n*   **Problem**: If you don't mute them, the phone connected to the Wawp instance will crash or drain its battery due to thousands of push notifications per hour.\n*   **Solution**: Immediately after calling `/follow`,\n  tips: [\n        {\n            type: 'info',\n            title: 'User Experience',\n            content: 'Muting stops push notifications but keeps the channel in the list.'\n        },\n        {\n            type: 'info',\n            title: 'Default',\n            content: 'New follows are often muted by default unless the user opts in.'\n        }\n    ],\n  recommendations: [\n        \"Respect user preference; do not auto-unmute.\",\n        \"Suggest muting for high-volume channels to prevent notification fatigue.\"\n    ]\n  \n   call `/mute`. This keeps the phone cool while your server happily ingests the data stream.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the channel",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@newsletter"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Channel muted successfully",
            "content": {
              "application/json": {
                "example": {
                  "status": "success",
                  "message": "Channel muted"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/{id}/unmute": {
      "post": {
        "operationId": "_v2_channels_id_unmute_post",
        "summary": "Unmute Channel",
        "description": "Unmute notifications for a specific channel.\n\n### Developer Tips\n- **Engagement**: Enables push notifications for new updates.\n- **Volume**: Ensure you want notifications for every broadcast.\n\n\n# Loud and Clear: Unmuting Channels\n\nThe `/v2/channels/{id}/unmute` endpoint restores the notification privileges for a channel. This corresponds to the \"Unmute\" action in the mobile app.\n\n---\n\n## 🔊 Restoring Priority\n\nWhen you unmute a channel, you are elevating its status in the user's perception.\n\n### Behavior Changes:\n*   **Push Notifications**: The connected phone will now vibrate/ring for every new post.\n*   **Badge Count**: New messages will increment the unread counter.\n*   **Visibility**: The channel will likely move to the top of the \"Updates\" list when new content arrives.\n\n---\n\n## 💡 Strategic Usage\n\n### 1. The \"VIP\" Subscription\nIf your application allows users to follow many topics, you might offer a \"VIP Alert\" feature.\n*   **Workflow**:\n    1.  User follows 50 channels (all muted by default or by script).\n    2.  User marks \"Breaking News\" as a Priority in your UI.\n    3.  Your backend calls `/unmute` specifically for that channel.\n    4.  Result: The user gets buzzes *only* for what matters most, while still having access to the broad feed of other data.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the channel",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@newsletter"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Channel unmuted successfully",
            "content": {
              "application/json": {
                "example": {
                  "status": "success",
                  "message": "Channel unmuted"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/search/view": {
      "get": {
        "operationId": "_v2_channels_search_view_get",
        "summary": "Search Channels by View",
        "description": "Search for channels based on views like RECOMMENDED.\n\n### Developer Tips\n- **Visuals**: Optimized for rendering search result cards.\n- **Badges**: Includes verification badge status in the response.\n\n\n# Discovering Trends: Search by View\n\nThe `/v2/channels/search/view` endpoint allows you to tap into WhatsApp's curated lists. Instead of searching for a specific keyword, you are asking: \"What is popular right now?\"\n\n---\n\n## 🔭 Available Views\n\nThe `view` parameter controls the ranking algorithm:\n\n### 1. **RECOMMENDED**\n*   **Algorithm**: Based on the phone number's region and general popularity.\n*   **Use Case**: The default \"Discovery\" feed for a new user.\n\n### 2. **POPULAR**\n*   **Algorithm**: Strictly ranked by subscriber count (highest to lowest).\n*   **Use Case**: Finding the \"Giants\" of the platform.\n\n### 3. **NEW**\n*   **Algorithm**: Recently created channels that are gaining traction.\n*   **Use Case**: Finding emerging creators.\n\n---\n\n## 🌍 Geo-Targeting\n\nYou can combine a View with a Country Code.\n*   **Example**: `view=POPULAR` + `countries=EG` (Egypt)\n*   **Result**: Returns the most followed channels specifically within Egypt, rather than global celebrities.\n\n---\n\n## 💡 Implementation Tip\nIf you are building a \"Channel Browser\" in your app:\n1.  **Tab 1 (Trending)**: Call `view=RECOMMENDED`.\n2.  **Tab 2 (Top Charts)**: Call `view=POPULAR`.\n3.  **Tab 3 (Local)**: Call `view=POPULAR` + `country={User's Country}`.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "view",
            "in": "query",
            "required": true,
            "description": "The view to search by (e.g. RECOMMENDED, POPULAR, NEW)",
            "schema": {
              "type": "string"
            },
            "example": "RECOMMENDED"
          },
          {
            "name": "countries",
            "in": "query",
            "required": true,
            "description": "Filter by countries (comma separated). e.g. EG,US,SA",
            "schema": {
              "type": "string"
            },
            "example": "US"
          },
          {
            "name": "categories",
            "in": "query",
            "required": true,
            "description": "Filter by categories. e.g. ENTERTAINMENT,SPORTS",
            "schema": {
              "type": "string"
            },
            "example": "ENTERTAINMENT"
          },
          {
            "name": "limit",
            "in": "query",
            "required": true,
            "description": "Maximum number of results",
            "schema": {
              "type": "integer"
            },
            "example": "10"
          },
          {
            "name": "startCursor",
            "in": "query",
            "required": true,
            "description": "Cursor for pagination. Leave as empty string for the first page.",
            "schema": {
              "type": "string"
            },
            "example": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Channels retrieved successfully",
            "content": {
              "application/json": {
                "example": {
                  "channels": [],
                  "nextCursor": "cursor_456"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/search/text": {
      "get": {
        "operationId": "_v2_channels_search_text_get",
        "summary": "Search Channels by Text",
        "description": "Search for channels using a text query.\n\n\n# The Global Directory: Searching WhatsApp Channels\n\nThe `/v2/channels/search/text` endpoint provides programmatic access to WhatsApp's global directory of public channels. This is the same search engine used by the WhatsApp mobile app in the \"Updates\" tab.\n\n---\n\n## 🔍 How Search Works\n\nThe search engine performs a fuzzy match against the **Channel Name** and **Description**. It uses an internal relevance score to rank results, prioritizing Verified (Green Tick) channels and those with high follower counts in the requested region.\n\n### The \"Cursor\" Pagination Model\nUnlike SQL databases that use `OFFSET/LIMIT`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Keywords',\n            content: 'Searches channel titles and descriptions.'\n        },\n        {\n            type: 'positive',\n            title: 'Filters',\n            content: 'Combine with country or category filters for better results.'\n        }\n    ],\n  recommendations: [\n        \"Debounce search inputs to avoid hitting rate limits.\",\n        \"Highlight matching keywords in the search results UI.\",\n        \"Cache common search terms locally.\"\n    ]\n  \n   WhatsApp Search uses an opaque cursor string for pagination to handle millions of records efficiently.\n\n**The Workflow:**\n1.  **First Request**: Send `startCursor=\"\"` (empty string).\n2.  **Response**: You receive a list of channels and a `nextCursor` string (e.g., `\"cursor_Au9s...\"`).\n3.  **Next Page**: Send the *exact* `nextCursor` string as the `startCursor` parameter in your next request.\n4.  **End of Results**: When `nextCursor` is `null` or empty, you have reached the end of the query results.\n\n---\n\n## 🎯 Filtering Strategies\n\nRefine your search to cut through the noise.\n\n### 1. By Category (`categories`)\nYou can filter results to specific topics. This is useful for building niche discovery tools.\n*   **Available Values**:\n    *   `ENTERTAINMENT`: Celebrity and media channels.\n    *   `SPORTS`: Teams, leagues, and athletes.\n    *   `LIFESTYLE`: Fashion, cooking, and hobbies.\n    *   `BUSINESS`: Companies and brands.\n    *   `NEWS`: Global and local news outlets.\n    *   `ORGANIZATIONS`: Non-profits and government bodies.\n\n### 2. By Text Query (`text`)\n*   **Broad Match**: Searching \"Foo\" will return \"Foo Fighters\", \"Foodies\", and \"Football\".\n*   **No Wildcards**: You do not need `*` characters; the fuzzy matching is automatic.\n\n---\n\n## 💡 Use Case: The \"Trend Watcher\" Bot\n\nImagine you want to monitor the cryptocurrency market sentiment on WhatsApp.\n\n1.  **Script Loop**: Run a cron job every 24 hours.\n2.  **Search**: Query for terms like \"Bitcoin\", \"Crypto\", \"Trading\".\n3.  **Filter**: Iterate through the results and check the `subscribers_count`.\n4.  **Action**: If a new channel appears with >10,000 followers, automatically trigger the [`Follow API`](/v2/channels/{id}/follow) and alert your team via Slack.\n\nThis allows you to detect emerging influencers *before* they become mainstream.\n\n---\n\n## ⚠️ Important Notes\n\n*   **Region Locking**: The results are global but may be biased towards the region of the phone number connected to the instance.\n*   **Rate Limits**: Searching is expensive. Do not use this endpoint for high-frequency autocomplete (typing) features. Debounce your requests by at least 1-2 seconds.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "text",
            "in": "query",
            "required": true,
            "description": "The search query text",
            "schema": {
              "type": "string"
            },
            "example": "Tesla"
          },
          {
            "name": "categories",
            "in": "query",
            "required": true,
            "description": "Filter by categories. e.g. ENTERTAINMENT,SPORTS",
            "schema": {
              "type": "string"
            },
            "example": "ENTERTAINMENT"
          },
          {
            "name": "limit",
            "in": "query",
            "required": true,
            "description": "Maximum number of results",
            "schema": {
              "type": "integer"
            },
            "example": "10"
          },
          {
            "name": "startCursor",
            "in": "query",
            "required": true,
            "description": "Cursor for pagination. Leave as empty string for the first page.",
            "schema": {
              "type": "string"
            },
            "example": ""
          }
        ],
        "responses": {
          "200": {
            "description": "Channels retrieved successfully",
            "content": {
              "application/json": {
                "example": {
                  "channels": [],
                  "nextCursor": "cursor_456"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/search/views": {
      "get": {
        "operationId": "_v2_channels_search_views_get",
        "summary": "Get Channel Views",
        "description": "Retrieve available view types for searching channels (e.g. RECOMMENDED, MOST_ACTIVE).\n\n### Developer Tips\n- **Analytics**: Returns view counts and interaction metrics.\n- **Privacy**: Metrics are aggregated and approximate to protect user privacy.\n\n\n# Filter Keys: View Types\n\nThe `/v2/channels/search/views` endpoint returns the valid sorting algorithms you can use in the Main Search API.\n\n---\n\n## 🏗️ Dynamic Sorting\n\nThe WhatsApp algorithm provides different lenses to view the channel directory.\n\n### Key Views:\n*   **`RECOMMENDED`**: The default \"For You\" experience.\n*   **`POPULAR`**: Highest subscriber count.\n*   **`NEW`**: Recently created channels.\n*   **`MOST_ACTIVE`**: Channels with high posting frequency (useful for finding bots/news).\n\n### Usage\nPass any of these strings to the [`/v2/channels/search/view`](/v2/channels/search/view) endpoint as the `view` parameter.\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Views retrieved successfully",
            "content": {
              "application/json": {
                "example": [
                  "RECOMMENDED",
                  "MOST_ACTIVE",
                  "POPULAR"
                ]
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/search/countries": {
      "get": {
        "operationId": "_v2_channels_search_countries_get",
        "summary": "Get Channel Countries",
        "description": "Retrieve available country filters for searching channels.\n\n### Developer Tips\n- **ISO Codes**: Uses standard ISO 3166-1 alpha-2 country codes.\n- **Localization**: Channels are often region-locked or ranked by country.\n\n\n# Filter Keys: Country Codes\n\nThe `/v2/channels/search/countries` endpoint returns the list of ISO 3166-1 alpha-2 country codes supported by WhatsApp Search.\n\n---\n\n## 🌍 Implementation Strategy\n\n### Localization\nWhen building a \"Trends\" tab:\n1.  **Detect User Location**: Use the user's IP or profile settings to guess their country (e.g., `BR` for Brazil).\n2.  **Validate**: Check if `BR` exists in this list.\n3.  **Search**: if valid, call `search/view?view=POPULAR&country=BR`.\n\n### Common Codes\n*   `US`: United States\n*   `IN`: India\n*   `ID`: Indonesia\n*   `BR`: Brazil\n*   `EG`: Egypt\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Countries retrieved successfully",
            "content": {
              "application/json": {
                "example": [
                  "US",
                  "EG",
                  "SA",
                  "AE"
                ]
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/channels/search/categories": {
      "get": {
        "operationId": "_v2_channels_search_categories_get",
        "summary": "Get Channel Categories",
        "description": "Retrieve available channel categories for searching.\n\n### Developer Tips\n- **Directory**: Lists available categories (e.g., News, Sports, Entertainment).\n- **Discovery**: Use correct categories to improve your channel's visibility.\n\n\n# Filter Keys: Channel Categories\n\nThe `/v2/channels/search/categories` endpoint returns the official list of topic filters supported by the WhatsApp directory.\n\n---\n\n## 🎯 Implementation Strategy\n\n### Dynamic Dropdowns\nDo not hardcode these values in your frontend code. WhatsApp may add new categories (e.g., \"Gaming\" or \"Science\") in the future.\n*   **Best Practice**: Fetch this list once on app load and populate your \"Filter by Topic\" dropdown dynamically.\n\n### Standard Values\nCommon categories include:\n*   `ENTERTAINMENT`\n*   `SPORTS`\n*   `LIFESTYLE`\n*   `BUSINESS`\n*   `NEWS`\n*   `ORGANIZATIONS`\n    ",
        "tags": [
          "Channels Control"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Categories retrieved successfully",
            "content": {
              "application/json": {
                "example": [
                  "Entertainment",
                  "News",
                  "Technology"
                ]
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/contacts/all": {
      "get": {
        "operationId": "_v2_contacts_all_get",
        "summary": "Get All Contacts",
        "description": "Retrieves a list of all known contacts from the connected WhatsApp account's address book and chat history.\n\n### Developer Tips\n- **Sync**: Returns all contacts sync'd from the phone's address book.\n- **Performance**: Can be slow for accounts with thousands of contacts. Use caching.\n\n\n# Digging for Gold: Retrieving Your Address Book\n\nThe `/v2/contacts/all` endpoint is the heavy lifter of the Contacts API. It downloads, filters, and paginates the entire list of entities your WhatsApp account knows about.\n\n---\n\n## 🏗️ What is \"All\"?\n\nWhen you ask for \"All Contacts\", WhatsApp doesn't just return your saved address book. It returns a mix of:\n1.  **Saved Contacts**: People in your phone's address book (with names).\n2.  **Unsaved Interactions**: People who messaged you, but you never saved properly.\n3.  **Business Identities**: Official Business Accounts (OBAs) you have interacted with.\n4.  **Legacy Groups**: Occasionally, old group metadata might appear here (though usually filtered).\n\n### The ID Mix\nYou will see two types of IDs in the response:\n*   **@c.us** (Standard): `123456789@c.us`. This is a normal phone number.\n*   **@lid** (Lookup ID): `123456789@lid`. This is a privacy-preserving identifier used by some modern WhatsApp features.\n    *   *Advice*: If you see an @lid, store it alongside the @c.us if possible, but your UI should primarily index on the phone number (@c.us) for human readability.\n\n---\n\n## ⚡ Pagination & Performance\n\nIf your bot has been running for 5 years, this list could contain 50,000 entries.\n*   **Default Limit**: The API defaults to returning a manageable chunk (e.g., 50 or 100).\n*   **Max Limit**: You can request up to `1000` contacts per call, but this increases latency.\n\n### The Pagination Loop\nTo fetch *everything*, use a `while` loop:\n```javascript\nlet allContacts = [];\nlet offset = 0;\nwhile (true) {\n    const batch = await api.getContacts({ limit: 1000, offset: offset });\n    if (batch.length === 0) break;\n    allContacts.push(...batch);\n    offset += 1000;\n}\n```\n\n---\n\n## 🔍 Filtering & Sorting\n\nThe API provides server-side utilities to help you find what you need without downloading the whole world.\n\n### Sorting\n*   **ByName**: `sortBy=name`. Helpful for building an A-Z contact picker UI.\n*   **ByPushName**: `sortBy=pushname`. Useful if your address book is empty and you rely on user-set names.\n\n### Filtering (Implicit)\nCurrently, the API returns *valid* contacts. It automatically filters out invalid JIDs or malformed entries that might exist in the raw database, ensuring you get a clean list.\n\n---\n\n## 🛡️ Best Practices\n\n### 1. Don't Poll This\n*   **Bad**: Calling `/v2/contacts/all` every 5 minutes \"just in case\".\n*   **Why**: It's an expensive database scan.\n*   **Good**: Call it **once** on startup to hydrate your cache. Then, listen for `message.upsert` and `contact.update` events to incrementally update your local state.\n\n### 2. Matching Names\n*   **Scenario**: You have a number `+12345`.\n*   **Goal**: Find the name.\n*   **Method**: Do *not* call `/v2/contacts/all` and search the array. That's O(N).\n*   **Method**: Call `/v2/contacts/+12345@c.us` directly. That's O(1). Use the list endpoint only for \"Directory\" views.\n\n### 3. Privacy Respect\n*   **Data Minimization**: If you are building a dashboard for your agents, do not display the raw @lid or internal IDs. Show `name || pushname || number`.\n*   **Staleness**: Be aware that `pushname` changes. A user might change their name from \"John\" to \"Crypto King\" overnight. Your local cache will be outdated until you refresh.\n\n---\n\n## ❓ FAQ\n\n**Q: Why are some names null?**\nA: `name` is the *Address Book Name*. If you haven't saved the number in Google/Apple Contacts (or the bot's virtual address book), `name` is null. `pushname` is what the user calls themselves.\n\n**Q: Can I add a contact via this API?**\nA: **No.** This is a read-only view. To \"add\" a contact, you technically just need to message them. To \"save\" them with a name, you would need to interact with the host OS's address book, which this API assumes is managed externally or virtually.\n\n**Q: I see duplicates!**\nA: You might get the same human returned as both `@c.us` and `@lid`. This is rare in the list view (we try to merge them), but if it happens, treat the `@c.us` as the master record.\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of contacts to return (1-1000)",
            "schema": {
              "type": "string"
            },
            "example": "50"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of contacts to skip",
            "schema": {
              "type": "string"
            },
            "example": "0"
          },
          {
            "name": "sortBy",
            "in": "query",
            "required": false,
            "description": "Field to sort by (e.g., name)",
            "schema": {
              "type": "string"
            },
            "example": "name"
          },
          {
            "name": "sortOrder",
            "in": "query",
            "required": false,
            "description": "Sort order (ASC or DESC)",
            "schema": {
              "type": "string"
            },
            "example": "ASC"
          }
        ],
        "responses": {
          "200": {
            "description": "List of contacts retrieved successfully",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "1234567890@c.us",
                    "name": "John Doe",
                    "pushname": "John"
                  },
                  {
                    "id": "0987654321@lid",
                    "name": "Business Contact",
                    "pushname": "Business"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/contacts": {
      "get": {
        "operationId": "_v2_contacts_get",
        "summary": "Get Contact Info",
        "description": "Get basic information about a specific contact.\n\n\n# Who is this? Get Contact Details\n\nThe `/v2/contacts/[chatId]` endpoint retrieves the public metadata for any valid WhatsApp user. This is your primary tool for \"enriching\" user profiles in your application.\n\n---\n\n## 🧩 Understanding the Data Fields\n\nWhen you fetch a contact, you receive several fields that might seem redundant but serve very different purposes.\n\n### 1. `id._serialized` (The Key)\n*   **Value**: `15551234567@c.us`\n*   **Usage**: This is the immutable primary key. Always store this in your database. Do not try to parse the phone number manually; treat the whole string as the ID.\n\n### 2. `pushname` (The Public Name)\n*   **Value**: \"Alice\"\n*   **Source**: This is the name the user set for *themselves* in WhatsApp Settings.\n*   **Reliability**: High. It is what the user *wants* to be called.\n*   **Verification**: This name is **NOT** verified. A user can set their pushname to \"Bank of America Support\" to scam people. Never use this for identity verification.\n\n### 3. `name` (The Local Name)\n*   **Value**: \"Alice from Gym\"\n*   **Source**: This is the name *you* saved in your phone's address book for this number.\n*   **Availability**: If you haven't saved the number, this field will be `undefined` or `null`.\n*   **Priority**: In a UI, you should usually display `name` (if available) aliased over `pushname` (fallback), because `name` is your private note.\n\n### 4. `number` (The Clean Phone)\n*   **Value**: `15551234567`\n*   **Usage**: The raw MSISDN without the `@c.us` suffix. Useful if you need to pass the number to an SMS gateway.\n\n---\n\n## 🏢 Business & Enterprise Flags\n\nThe API returns two boolean flags that help you categorize users:\n\n### `isBusiness`\n*   **True**: The user is using the \"WhatsApp Business App\" (SMB).\n*   **Implication**: They might have automated greeting messages or \"Away\" messages. They likely have a catalog.\n\n### `isEnterprise`\n*   **True**: The user is using the \"WhatsApp Business API\" (Cloud API/BSP).\n*   **Implication**: This is likely a bot or a large company.\n    *   *Warning*: Bots talking to bots can create infinite loops. If you detect `isEnterprise: true`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Details',\n            content: 'Fetches stored contact details like Name and Notify Name.'\n        },\n        {\n            type: 'info',\n            title: 'Notify Name',\n            content: 'This is the name the user set for themselves in WhatsApp.'\n        }\n    ],\n  recommendations: [\n        \"Use the 'Notify Name' if the contact is not saved in your address book.\",\n        \"Update your local record if the contact's details change.\"\n    ]\n  \n   you might want to disable your own auto-responders for that chat to prevent a loop.\n\n---\n\n## 🔍 Privacy & \"Ghost\" Data\n\nIf you query a valid number but get limited data:\n*   **Scenario**: You fetch `12345@c.us` and get an ID, but `pushname` is `undefined`.\n*   **Cause**: The user has strict privacy settings.\n*   **Action**: Nothing. The API cannot force the data to appear. You should render a default placeholder (e.g., \"WhatsApp User\").\n\n---\n\n## ⚙️ Usage Patterns\n\n### Pattern A: The \"Welcome\" Personalization\n1.  User sends \"Hi\".\n2.  Bot calls `GET /v2/contacts/[id]`.\n3.  Bot retrieves `pushname: \"Sarah\"`.\n4.  Bot replies: \"Hello Sarah! How can I help?\"\n    *   *Effect*: High perceived personalization.\n\n### Pattern B: The Block Check\n1.  You suspect a user blocked you.\n2.  You call this endpoint.\n3.  If you can see their `pushname` but **cannot** see their `profilePic` or `about` status (via other endpoints), and messages are single-ticking, it is a strong indicator of being blocked. (Note: The API does not have an explicit `isBlockedByMe` flag for privacy reasons).\n\n---\n\n## ⚠️ Notes on Caching\n\nUser profiles change rarely.\n*   **Do Not**: Call this endpoint every time you render a chat message.\n*   **Do**: Cache the result for 24-48 hours.\n*   **Refresh**: Only aggressive fetch if the user interacts with you after a long period of silence.\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "contactId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the contact (e.g., 123456789@c.us)",
            "schema": {
              "type": "string"
            },
            "example": "123456789@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Contact info retrieved successfully",
            "content": {
              "application/json": {
                "example": {
                  "id": "123456789@c.us",
                  "name": "John Doe",
                  "pushname": "John",
                  "isBusiness": false,
                  "isEnterprise": false
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/contacts/check-exists": {
      "get": {
        "operationId": "_v2_contacts_check-exists_get",
        "summary": "Check Phone on WhatsApp",
        "description": "Check if a phone number is registered on WhatsApp.\n\n\n# The Gatekeeper: Validating Phone Numbers\n\nThe `/v2/contacts/check-exists` endpoint is your first line of defense against low-quality data. It queries the WhatsApp Global Directory to verify if a specific MSISDN (phone number) corresponds to an active WhatsApp account.\n\n---\n\n## 🏗️ Why is this Critical?\n\nSending messages to invalid numbers is one of the fastest ways to get your bot banned.\n*   **The Signal**: If you try to message `+12345` and it fails because the user doesn't exist, WhatsApp's spam algorithms flag your account as \"Blindly Broadcasting\".\n*   **The Threshold**: A high failure rate indicates you bought a low-quality lead list.\n*   **The Fix**: Validate **100%** of new numbers using this endpoint before queuing your first message.\n\n---\n\n## 🧹 Input Sanitization\n\nWhatsApp requires a clean format for verification: `[CountryCode][Number]`.\n*   **Supported Input**: `15551234567`\n*   **Supported Input**: `+15551234567` (The API strips the plus)\n*   **Unsupported**: `(555) 123-4567` (You must strip symbols)\n*   **Unsupported**: `0015551234567` (Do not use 00 prefix)\n\n### The Brazil/Mexico Rule\nSome countries have variable number lengths.\n*   **Mexico**: Mobile numbers need a `1` after the country code `+52`.\n*   **Brazil**: Numbers might have an extra `9`.\n*   **Auto-Correction**: The Wawp API attempts to auto-correct common formatting errors for these regions, but it is best if you provide the E.164 standard format.\n\n---\n\n## 🚦 Rate Limits & Safety\n\nThis endpoint performs a real-time network lookup.\n*   **The Limit**: You should not exceed **1 verification per second** per instance.\n*   **The \"Scraping\" Risk**: If you feed a sequential list (e.g., `+15550001`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Validation',\n            content: 'Verifies if a phone number is registered on WhatsApp.'\n        },\n        {\n            type: 'warning',\n            title: 'Anti-Scraping',\n            content: 'Excessive checks on random numbers may flag your account as a scraper.'\n        }\n    ],\n  recommendations: [\n        \"Validate numbers before sending your first message to improve delivery rates.\",\n        \"Do not use this to 'warm up' numbers; use it strictly for verification.\"\n    ]\n  \n   `+15550002`, `+15550003`) into this API, WhatsApp will detect pattern recognition scraping and **permanently ban** your number.\n*   **Best Practice**: Only check numbers that users have explicitly provided to you (e.g., via a signup form). Do not use this to \"clean\" a bought database.\n\n---\n\n## 🔮 Integration Patterns\n\n### Pattern A: The Registration Form\n1.  User signs up on your website.\n2.  Backend calls `/v2/contacts/check-exists`.\n3.  **Result**:\n    *   `exists: true`: Show \"WhatsApp\" logo next to their number on the confirmation page.\n    *   `exists: false`: Disable the \"Send via WhatsApp\" button or fallback to SMS.\n\n### Pattern B: The CRM Cleaner\n1.  You have a list of 10,000 stale leads.\n2.  **Wrong Way**: Loop through all 10,000 now.\n3.  **Right Way**:\n    *   Wait until you *need* to message one.\n    *   Check existence JIT (Just-In-Time) 1 second before sending.\n    *   If invalid, mark as \"Bad Data\" in CRM and skip.\n    *   If valid, send and cache the result.\n\n---\n\n## ❓ FAQ\n\n**Q: Does the user know I checked them?**\nA: **No.** This is a silent directory lookup. It does not trigger a notification, blue tick, or \"online\" status.\n\n**Q: Can I get their profile picture here?**\nA: **No.** This endpoint is purely boolean (Exists/Not Exists) involved with the basic JID. To get the photo, you must first confirm existence, then call `/v2/contacts/profile-picture`.\n\n**Q: What if the API returns false but I know they have WhatsApp?**\nA: Ensure you are using the correct Country Code. In 99% of cases, it's a formatting error (e.g., missing a digit or adding an extra '0' prefix).\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "phone",
            "in": "query",
            "required": true,
            "description": "Phone number to check (digits only)",
            "schema": {
              "type": "string"
            },
            "example": "1234567890"
          }
        ],
        "responses": {
          "200": {
            "description": "Check completed",
            "content": {
              "application/json": {
                "example": {
                  "exists": true,
                  "jid": "1234567890@c.us"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/contacts/profile-picture": {
      "get": {
        "operationId": "_v2_contacts_profile-picture_get",
        "summary": "Get Contact Profile Picture",
        "description": "Get the profile picture URL of a contact.\n\n### Developer Tips\n- **Privacy**: You will get a 404 or placeholder if the user hides their photo.\n- **Caching**: URLs are temporary; download the image immediately.\n\n\n# The Face of the User: Profile Pictures\n\nThe `/v2/contacts/profile-picture` endpoint allows you to retrieve the high-resolution avatar of a WhatsApp user, group, or business.\n\n---\n\n## 🖼️ Image Logic\n\nWhen you request a picture, WhatsApp doesn't send the binary data directly. It provides a signed URL hosted on their CDN (Content Delivery Network).\n\n### The Response Format\n```json\n{\n  \"id\": \"12345@c.us\",\n  \"url\": \"https://pps.whatsapp.net/v/t61.24694-24/...\"\n}\n```\n\n*   **URL Expiry**: These URLs are **temporary**. They expire after a certain period (usually 24-48 hours) or if the user changes their photo.\n*   **Best Practice**: Do not just store the URL string in your database.\n    *   *Option A (Lazy)*: Re-fetch the URL from this API every time you need to display it.\n    *   *Option B (Robust)*: Download the image buffer and store it in your own S3 bucket.\n\n---\n\n## 🛡️ Privacy & \"Missing\" Photos\n\nYou will often get a `404 Not Found` or an empty URL.\n\n### Reason 1: Privacy Settings (Most Common)\nThe user has set \"Profile Photo\" to **\"My Contacts\"** or **\"Nobody\"**.\n*   If you are not saved in their phone's address book, you are not a \"Contact\". Therefore, WhatsApp refuses to serve the image.\n*   **Correction**: There is no workaround. You must respect the user's choice.\n\n### Reason 2: No Photo\nThe user simply hasn't set a photo. They see the default grey silhouette.\n\n### Reason 3: It's You\nYou cannot fetch your *own* profile picture via this endpoint (use `/v2/profile/me` instead).\n\n---\n\n## 🔄 Caching & Refresh\n\nFetch operations are expensive networking calls.\n*   **Default Behavior**: The Wawp API caches the profile picture URL for 24 hours to speed up subsequent requests.\n*   **Forcing a Refresh**: If you suspect the user just changed their photo and you need the new one immediately, pass `refresh=true`.\n    *   *Cost*: This bypasses the local cache and hits WhatsApp servers directly. Use sparingly.\n\n---\n\n## 📸 Resolution & Quality\n\n*   **Standard**: The API attempts to fetch the \"Preview\" size (roughly 96x96 or 640x640 depending on availability).\n*   **Full HD**: WhatsApp only serves the full-resolution uncompressed image (e.g., 1920x1920) if the user is in your contact list or you are in a chat with them.\n*   **Groups**: Group icons work the same way. The `contactId` would be `123456@g.us`.\n\n---\n\n## ❓ FAQ\n\n**Q: Can I set the contact's photo?**\nA: **No.** You cannot change another user's profile picture. You can only change *your* own (via `/v2/profile/picture`) or a Group's icon (if you are an admin).\n\n**Q: Why does the URL stop working after a day?**\nA: All `pps.whatsapp.net` links are signed with a time-limited token for security. If you try to load an old URL, you will get a 403 Forbidden.\n\n**Q: Can I get the photo of a business?**\nA: Yes. Official Business Accounts (OBA) usually have public profile photos visible to everyone, regardless of \"My Contacts\" settings.\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "contactId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the contact",
            "schema": {
              "type": "string"
            },
            "example": "123456789@c.us"
          },
          {
            "name": "refresh",
            "in": "query",
            "required": false,
            "description": "Whether to bypass cache and refresh the picture",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          }
        ],
        "responses": {
          "200": {
            "description": "Profile picture retrieved",
            "content": {
              "application/json": {
                "example": {
                  "id": "123456789@c.us",
                  "url": "https://pps.whatsapp.net/v/t61.24694-24/..."
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/contacts/{chatId}": {
      "put": {
        "operationId": "_v2_contacts_chatId_put",
        "summary": "Create/Update Contact",
        "description": "Create or update a contact in the phone's address book.\n\n### Developer Tips\n- **Local Sync**: Updates the contact name in the phone's address book.\n- **Permissions**: Requires 'Write Contacts' permission on the host device.\n\n\n# Managing Your Digital Rolodex\n\nThe `/v2/contacts/update` endpoint allows you to modify the **local** name of a contact in your WhatsApp address book.\n\n---\n\n## 📖 The Name Game: Private vs Public\n\nIt is vital to distinguish between the two types of names in WhatsApp.\n\n### 1. `pushname` (Public)\n*   **What**: The name Alice chose for herself (\"Alice 🌸\").\n*   **Editable**: **NO**. You cannot change this. Only Alice can.\n\n### 2. `name` (Private)\n*   **What**: The name *you* saved Alice as in your phone (\"Alice from Accounting\").\n*   **Editable**: **YES**. This endpoint changes this value.\n*   **Visibility**: Only *you* (the bot owner) see this. Alice does not know you saved her as \"Alice from Accounting\".\n\n---\n\n## 🛠️ Use Cases\n\n### 1. CRM Synchronization\nIf you have a CRM like Salesforce, you want your WhatsApp chat list to reflect your CRM data.\n*   **Scenario**: A new lead messages you. Their pushname is \"User123\".\n*   **Action**: Your agent asks for their name. They say \"Bob Smith\".\n*   **API Call**: Update contact `123@c.us` with `firstName: \"Bob\", lastName: \"Smith\"`.\n*   **Result**: In your chat list, they now appear as \"Bob Smith\".\n\n### 2. Funnel Tracking\nYou can append tags to names to visualize where a user is in your funnel.\n*   **Example**: \"Bob [Lead]\" -> \"Bob [Customer]\" -> \"Bob [VIP]\".\n*   **Benefit**: Agents can instantly see the user's status just by looking at the chat header.\n\n---\n\n## 🏗️ Technical Nuances\n\n### The Virtual Address Book\nSince Wawp is a cloud-based system, we emulate the behavior of a mobile OS address book.\n*   **Persistence**: Updates are stored in the session's internal database.\n*   **Sync**: If you are using a multi-device session, this change *might* sync to your physical phone (if connected), but it is primarily for the API session's context.\n\n### \"Creating\" a Contact\nThis endpoint is idempotent.\n*   **If the contact exists**: It updates the name.\n*   **If the contact is new**: It \"adds\" them to your address book. This resolves the `name: null` issue when fetching contact details later.\n\n---\n\n## ❓ FAQ\n\n**Q: Will the user see the name I gave them?**\nA: **No.** This is private data on your end.\n\n**Q: Can I update the profile picture too?**\nA: **No.** You cannot change another user's photo.\n\n**Q: What if I only provide a firstName?**\nA: The API will set the full name to just the `firstName`.\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the contact",
            "schema": {
              "type": "string"
            },
            "example": "123456789@c.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "firstName",
            "in": "query",
            "required": false,
            "description": "First name of the contact",
            "schema": {
              "type": "string"
            },
            "example": "John"
          },
          {
            "name": "lastName",
            "in": "query",
            "required": false,
            "description": "Last name of the contact",
            "schema": {
              "type": "string"
            },
            "example": "Doe"
          }
        ],
        "responses": {
          "200": {
            "description": "Contact updated successfully",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/lids": {
      "get": {
        "operationId": "_v2_lids_get",
        "summary": "Get LIDs Mapping",
        "description": "Retrieves all known LID to phone number mappings.\n\n### Developer Tips\n- **Dump**: Returns all LID mappings stored on the device.\n- **Size**: Payload can be large. Parse efficiently.\n\n\n# The Future of Identity: Lookup IDs (LID)\n\nThe `/v2/lids` endpoint exposes the mapping layer between the old world (Phone Numbers) and the new world (Privacy-Preserving IDs).\n\n---\n\n## 🆔 What is an LID?\n\nLID stands for **Lookup ID**.\n*   **Format**: `123456789012345@lid` (A long integer + @lid suffix).\n*   **Purpose**: To allow users to interact **without revealing their phone number**.\n\n### The Shift\n*   **Classic WhatsApp**: Your ID is your phone number (`1555...@c.us`). To talk to you, I need your number.\n*   **Modern WhatsApp**: You might have a username, or you might be in a \"Community\" where your number is hidden. In these cases, WhatsApp uses your **LID** to route messages.\n\n---\n\n## 🗺️ The Mapping Problem\n\nIf a user messages you from a hidden-number community, you will receive a message from `@lid`.\n*   **Challenge**: Your CRM expects a phone number.\n*   **Solution**: You need a translation layer.\n    *   `@lid` -> `@c.us` (If you are authorized to see it).\n    *   `@c.us` -> `@lid` (To find their stable ID).\n\nThis endpoint dumps the entire known cache of these mappings.\n\n---\n\n## 🛡️ Privacy Constraints\n\nYou cannot just \"reverse lookup\" any LID to get a phone number.\n*   **Authorization**: You can only resolve an LID to a phone number if the user has **shared their number with you** or if you are in a specific trust relationship (e.g., mutual contact).\n*   **Community Members**: If you are in a Community Announcement Group, you might see 5,000 members, but their IDs will be LIDs. You **cannot** get their phone numbers via API. This is intentional privacy design by Meta.\n\n---\n\n## 🚀 Use Cases for LIDs\n\n### 1. Stable Identity\n*   **Scenario**: User changes their phone number from `+1...` to `+44...`.\n*   **Old Way**: New JID. New Chat. History lost.\n*   **New Way**: Their `@lid` remains the same. You can link the new phone number to the old account record in your database using the LID as the primary key.\n\n### 2. Hidden Group Participants\n*   **Scenario**: You scrape a group's participant list.\n*   **Result**: You see a mix of `@c.us` (people who don't hide their number) and `@lid` (people who do).\n*   **Action**: Use this endpoint to see if you have the phone number cached for any of those LIDs.\n\n---\n\n## 🚦 Performance\n\n*   **Cache Size**: This list can grow large.\n*   **Pagination**: Always use `limit` and `offset`.\n*   **Refresh**: The mapping is static unless a user re-registers directly.\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Maximum number of mappings to return",
            "schema": {
              "type": "string"
            },
            "example": "100"
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Number of mappings to skip",
            "schema": {
              "type": "string"
            },
            "example": "0"
          }
        ],
        "responses": {
          "200": {
            "description": "LIDs mapped successfully",
            "content": {
              "application/json": {
                "example": [
                  {
                    "lid": "1234567890@lid",
                    "number": "1234567890"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/lids/pn/{number}": {
      "get": {
        "operationId": "_v2_lids_pn_number_get",
        "summary": "Get LID by Phone",
        "description": "Convert a phone number to its corresponding WhatsApp LID.\n\n### Developer Tips\n- **Resolution**: Resolves a Phone Number to its corresponding LID.\n- **Availability**: Not all accounts have LIDs yet; depends on rollout phase.\n\n\n# The Stable Anchor: Phone to LID\n\nThe `/v2/lids/pn/{number}` endpoint performs a forward lookup, converting a traditional phone number into its corresponding privacy-preserving Lookup ID (LID).\n\n---\n\n## 🔮 Why This Matters\n\nIn the modern WhatsApp ecosystem, phone numbers are ephemeral but identities should be persistent.\n*   **The Problem**: A user changes their number from `+1-555-1234` to `+44-7700-900000`.\n*   **Old System**: You lose track of them. Their chat history is orphaned.\n*   **New System**: You query their LID using the old number, store it, then when they message you from the new number, you query the LID again and realize it's the same person.\n\n---\n\n## 🛠️ Implementation Pattern\n\n### The \"Identity Merge\" Workflow\n1.  **User A** messages you from `15551234567@c.us`.\n2.  You call `/v2/lids/pn/15551234567`.\n3.  Response: `{ lid: \"999888777@lid\", number: \"15551234567\" }`.\n4.  You store in DB: `user_id = 999888777@lid, current_phone = 15551234567`.\n5.  **6 months later**: User A changes their number to `447700900000`.\n6.  They message you again from `447700900000@c.us`.\n7.  You call `/v2/lids/pn/447700900000`.\n8.  Response: `{ lid: \"999888777@lid\", number: \"447700900000\" }`.\n9.  **Match Found**: The LID is the same! You update `current_phone` but keep the same `user_id`.\n10. **Result**: Chat history, preferences, and purchase records are preserved.\n\n---\n\n## ⚠️ Availability\n\nNot every phone number has an LID.\n*   **Modern Accounts**: Created after 2023 usually have LIDs.\n*   **Legacy Accounts**: Very old accounts might return `null`.\n*   **Best Practice**: Always handle the case where this endpoint returns no LID. Fall back to using the `@c.us` JID as the primary key if necessary.\n\n---\n\n## 🚦 Performance\n\n*   **Caching**: The mapping is relatively stable. Cache the result for at least 7 days.\n*   **Latency**: ~100-300ms for a fresh lookup.\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "number",
            "in": "query",
            "required": true,
            "description": "The phone number without @c.us (e.g. 447441429009)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/lids/{lid}": {
      "get": {
        "operationId": "_v2_lids_lid_get",
        "summary": "Get Phone by LID",
        "description": "Convert a WhatsApp LID to its corresponding phone number.\n\n### Developer Tips\n- **Architecture**: LID (Ledger ID) is a privacy-preserving identifier.\n- **Usage**: Required for some advanced features like username lookup.\n\n\n# Unmasking the Identity: LID to Phone\n\nThe `/v2/lids/{lid}` endpoint performs a reverse lookup, attempting to find the canonical phone number (`@c.us`) associated with a given Lookup ID.\n\n---\n\n## 🔒 Privacy Barriers\n\nA common misconception is that this endpoint can \"dox\" any user. **It cannot.**\n*   **Success**: The API returns the phone number *only if* your account has **already established a trust relationship** with that user (e.g., they are in your contacts, or you share a group where numbers are visible).\n*   **Failure**: If the user is a stranger in a hidden community, this endpoint will likely return `null` or the same LID, because the phone number is cryptographically sealed from your view.\n\n---\n\n## 🛠️ Use Case: \"One Identity\"\n\nIf you support users moving across phone numbers:\n1.  **Storage**: You store the LID as the user's primary key.\n2.  **Display**: When you need to send an SMS fallback, you call this endpoint.\n3.  **Result**: You get the *current* phone number associated with that LID, ensuring your SMS goes to the right device.\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "lid",
            "in": "query",
            "required": true,
            "description": "The unique LID (@lid)",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@lid"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/lids/count": {
      "get": {
        "operationId": "_v2_lids_count_get",
        "summary": "Get LIDs Count",
        "description": "Returns the number of known LIDs.\n\n### Developer Tips\n- **Stats**: Returns the number of LID-based contacts known to the device.\n- **Health**: Zero count might indicate LIDs are not enabled for this session.\n\n\n# Measuring Your Identity Graph: LID Count\n\nThe `/v2/lids/count` endpoint returns a simple integer: the total number of LID-to-Phone mappings your session has cached.\n\n---\n\n## 📊 What This Number Means\n\nThis is **not** the number of contacts you have. It is the number of **privacy-aware identities** your bot has encountered.\n\n### Interpretation\n*   **Count = 0**: Your account is very new or you only interact with legacy users.\n*   **Count = 50**: You have interacted with 50 users who have modern WhatsApp accounts with LIDs.\n*   **Count = 10,000**: You run a large-scale bot that has processed thousands of unique users.\n\n---\n\n## 🛠️ Use Cases\n\n### 1. Pagination Planning\nBefore calling `/v2/lids` to fetch the full list, check the count.\n*   If `count < 100`: Fetch everything in one call.\n*   If `count > 10,000`: Use aggressive pagination (`limit=1000, offset=0...10000`).\n\n### 2. Analytics Dashboard\nDisplay this metric to your operations team.\n*   **Metric**: \"Unique Privacy-Aware Users\".\n*   **Trend**: If this number grows faster than your total contact count, it means more users are adopting WhatsApp's privacy features.\n\n### 3. Cache Warming\nIf you are migrating to a new server, you can use this count to estimate how long it will take to rebuild your LID cache.\n    ",
        "tags": [
          "Contacts"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Success",
            "content": {
              "application/json": {
                "example": {
                  "count": 42
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/labels": {
      "get": {
        "operationId": "_v2_labels_get",
        "summary": "Get All Labels",
        "description": "Retrieve all WhatsApp labels available in your WhatsApp Business account.\n\n### Developer Tips\n- **Catalog**: Returns a list of all defined labels on the account.\n- **Sync**: Use this on startup to build your local label map.\n\n\n# The Label Directory: Master Inventory Management\n\nThe **Get All Labels** endpoint acts as the central directory for your WhatsApp Business account's organizational metadata. It is the primary tool for auditing your existing taxonomy and synchronizing your external systems with the reality of your WhatsApp environment.\n\n---\n\n## 🏗️ Core Concept: The Source of Truth\n\nThis endpoint provides a snapshot of every label currently configured on your account. Because labels are global resources, this list is common across all agents and automated systems connected to your instance.\n\n### Key Data Architecture\nEach entry in the returned array represents a unique organizational category, defined by a persistent ID and a visual signature (Color Index). While name changes are frequent, the **ID** remains the immutable reference point for your database.\n\n---\n\n## 🚀 Strategic Operational Use Cases\n\n### 1. Global State Synchronization\nThe most common use for this endpoint is \"Directory Hydration.\" On system startup or agent login, your application should fetch the full directory to build a local map of names to IDs. This prevents your system from having to \"guess\" which ID corresponds to \"VIP\" or \"New Lead\" during high-volume operations.\n\n### 2. CRM Taxonomy Mapping\nIf you are integrating WhatsApp with an external CRM (like Salesforce, HubSpot, or a custom ERP), this endpoint allows you to run a \"Taxonomy Audit.\" By comparing your WhatsApp labels with your CRM tags, you can identify naming discrepancies or missing categories and programmatically reconcile them.\n\n### 3. Analytics & Resource Distribution\nBy combining this endpoint with [`Get Chats with Label`](/v2/labels/{id}/chats), you can generate a \"Volume Heatmap.\" This allows management to see exactly how many conversations are sitting in \"Pending\" versus \"In Progress,\" enabling better resource allocation across your agent pool.\n\n---\n\n## ⚡ Performance Engineering: Advanced Caching Strategies\n\nSince labels are established during account setup and rarely change in real-time, fetching the entire list for every message would be inefficient.\n\n### The \"Pulse & Probe\" Caching Pattern\nInstead of high-frequency polling, we recommend a \"Warm Cache\" approach:\n*   **Initial Fetch**: Pull all labels during the \"Warm-up\" phase of your worker or server.\n*   **In-Memory Store**: Keep these labels in a global object or a Redis store.\n*   **Invalidation Hooks**: Instead of a time-based TTL (Time to Live), use **Webhooks**. Your system should only invalidate the cache when it receives a [`label.upsert`](/v2/webhooks/label-upsert) or [`label.deleted`](/v2/webhooks/label-deleted) event. This ensures your data is always 100% current without redundant API overhead.\n\n---\n\n## 🛠️ Integration Patterns: UI & UX Excellence\n\n### Responsive Label Rendering\nWhen building a custom dashboard, use the data from this endpoint to pre-calculate your CSS variables. By mapping the **Color Index (0-19)** to your design system's theme, you ensure that the \"VIP\" badge in your CRM looks identical to the \"VIP\" badge in the official WhatsApp app, providing a seamless multi-channel experience for your agents.\n\n### The \"Smart Dropdown\" Experience\nDon't just show a list of names; use the color metadata to group labels logically in your UI. For example, placing all \"Red\" urgency labels at the top of a selection menu can significantly reduce agent response times during critical escalations.\n\n---\n\n## ⚠️ State Consistency & Error Resilience\n\n### Handling \"The Empty State\"\nIf this endpoint returns an empty array, it indicates a \"Clean Slate\" account. This is a critical trigger for your system to run its \"Bootstrapping\" logic—programmatically creating the default taxonomy (e.g., Marketing, Sales, Support) required for your business logic to function.\n\n### Handling \"The Deleted ID\"\nIf your local database still references a Label ID that no longer appears in this list, your system should proactively \"prune\" those references. Continuing to attempt tagging with a deleted ID will result in API errors and broken workflow automations.\n\n---\n\n## 🎯 Best Practices\n\n1.  **Audits Over Polling**: Run a full directory fetch periodically (e.g., once a day) to catch any manual changes made by agents in the WhatsApp mobile app.\n2.  **Case-Insensitive Searching**: When looking for a label by name in this list, always use case-insensitive matching to prevent duplicate creation errors.\n3.  **Fallback Logic**: If the API is temporarily unreachable, your system should fall back to its last known cached state rather than failing the entire request.\n4.  **Security Scoping**: Limit who can view this full directory in your own application, as label names can sometimes reveal sensitive internal project names or campaign strategies.\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "List of labels retrieved successfully",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "1",
                    "name": "New Customer",
                    "color": 0,
                    "colorHex": "#ff9485"
                  },
                  {
                    "id": "2",
                    "name": "Favorites",
                    "color": 1,
                    "colorHex": "#64c4ff"
                  }
                ]
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/labels/{id}": {
      "get": {
        "operationId": "_v2_labels_id_get",
        "summary": "Get Label",
        "description": "Retrieve details of a specific WhatsApp label.\n\n\n# Precise Discovery: Fetching a Specific Label\n\nWhile fetching all labels is useful for initializing a broad dashboard, the **Get Label by ID** endpoint is designed for high-precision synchronization and real-time state verification. it allows you to retrieve the name, color index, and hex code of a single, specific label using its unique identifier.\n\n---\n\n## 🏗️ Core Concept: High-Precision Verification\n\nThis endpoint acts as a **Single Source of Truth (SSoT)** for a specific piece of your organizational taxonomy. It is primarily used when your system already knows a Label ID (perhaps from a webhook event or a database record) and needs to verify its current properties on the WhatsApp Business account without fetching the entire account directory.\n\n### Key Operational Advantages:\n1.  **Low Latency Discovery**: Fetching a single record is significantly faster and consumes less bandwidth than fetching the entire list of 20 labels, making it ideal for event-driven microservices.\n2.  **State Integrity**: Confirms if a label still exists before your system attempts to apply it to a chat, preventing high-volume API errors during automated tagging cycles.\n3.  **Visual Hydration**: Provides the exact visual metadata (Color Index and Hex) needed to render a specific tag in a contact's profile or a message notification.\n\n---\n\n## 🚀 Strategic Operational Use Case\n\n### The \"Hydration-on-Event\" Strategy\nWhen a new activity occurs (e.g., a [`label.chat.added`](/v2/webhooks/label-chat-added) webhook arrives), Meta only provides the Label ID. For your frontend system to display a meaningful \"Sales\" or \"VIP\" badge, it must \"hydrate\" that ID with its display name and color. This endpoint is the primary bridge for that hydration process.\n\n### Intelligent Resource Allocation\nIn high-volume scenarios, you can use this endpoint to check the \"Urgency Index\" of a label before prioritizing a message. For example, if the color index returned is 0 (Red), your system can immediately route the inquiry to a senior supervisor.\n\n---\n\n## 🛡️ Security & Scalable Access Control\n\nAccess to individual label metadata is protected by the same security layer as your core message history. \n\n*   **Instance Isolation**: You can only fetch labels belonging to the specific `instance_id` provided in the request. Attempting to fetch a Label ID from another instance will return a `404 Not Found`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Lookup',\n            content: 'Retrieves the numeric ID for a given label ID string.'\n        },\n        {\n            type: 'info',\n            title: 'Format',\n            content: 'Useful when mapping between GUIDs and internal IDs.'\n        }\n    ],\n  recommendations: [\n        \"Cache this mapping to avoid redundant calls.\",\n        \"Use this to validate external IDs before processing.\"\n    ]\n  \n   ensuring data privacy between different WhatsApp Business accounts.\n*   **Token-Based Scoping**: Your API access token must have the appropriate permissions to view account metadata. This ensures that even if a Label ID is leaked, it cannot be queried without proper authorization.\n\n---\n\n## ⚡ Performance Engineering: The Hybrid Caching Model\n\nFetching a label ID is lightweight, but repeating it for every message in a busy thread is inefficient. We recommend a \"Demand-Driven Cache\":\n\n1.  **Check Local Store**: Always look for the Label ID in your internal memory or Redis first.\n2.  **Just-In-Time Fetch**: If the ID is missing (potentially because it was recently created), call this endpoint to fetch and store the details.\n3.  **Proactive Refresh**: Update your local record only when a [`label.update`](/v2/webhooks/label-upsert) webhook for that specific ID is received. This minimizes API overhead while maintaining 100% accuracy.\n\n---\n\n## ⚠️ Important Behaviors & Edge Cases\n\n*   **ID Persistence**: A Label ID is a persistent reference. However, if a label is deleted and later recreated with the exact same name, it will receive a **new unique ID**. Your systems should never hardcode ID strings; they should treat them as dynamic variables fetched from the account directory.\n*   **Color Index Stability**: While the `colorHex` might shift slightly across different device themes or Meta updates, the `color` index (0-19) is immutable. Use the index for your internal logic and the hex only for your UI rendering.\n\n---\n\n## 🔍 Debugging & Troubleshooting\n\n### Handling the 404 \"Ghost\" State\nIf this endpoint returns a 404 for a previously known ID, it indicates that the label was deleted—either via the API or manually by an agent in the WhatsApp Business app. Your system should handle this by gracefully removing the ID from its internal store and updating any active UI components to a neutral \"Uncategorized\" state.\n\n---\n\n## 🎯 Best Practices\n\n1.  **Graceful Fallbacks**: If a label fetch fails, default to a neutral grey badge in your UI to avoid breaking the layout.\n2.  **Index-Centric Themes**: Build your custom dashboard themes around the 20 standard indices to ensure a \"native\" feel for agents familiar with the WhatsApp mobile experience.\n3.  **Store Mapping Locally**: Save the returned metadata alongside the ID in your system to avoid redundant fetches during high-traffic periods.\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the label",
            "schema": {
              "type": "string"
            },
            "example": "1"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/labels/create": {
      "post": {
        "operationId": "_v2_labels_create_post",
        "summary": "Create Label",
        "description": "Create a new WhatsApp label with a name and optional color.\n\n\n# Building Your Taxonomy: Creating Labels\n\nEstablishing a robust labeling system is the first step toward transforming your WhatsApp Business account from a simple messaging tool into a structured, metadata-driven customer service platform. The **Create Label** endpoint serves as the fundamental architect for this transformation, allowing you to define the semantic categories that will govern your conversational workflows.\n\n---\n\n## 🏗️ Architectural Philosophy: Designing a Scalable Taxonomy\n\nWhen you create a label, you are not just naming a folder; you are defining a **State** or **Attribute** that a conversation can possess. Because WhatsApp limits each account to **20 labels**, every entry in your taxonomy must be strategic, versatile, and high-impact.\n\n### The \"Label Blueprint\" Strategy\nA well-designed label system should focus on three core pillars:\n1.  **Workflow Stage**: Indicating where the customer is in their journey (e.g., \"New Lead\", \"In Negotiation\").\n2.  **Visual Urgency**: Using the color system to signal the need for immediate action.\n3.  **Ownership & Responsibility**: Defining who or what (e.g., a specific department or bot) is currently managing the thread.\n\n---\n\n## 🎨 The Color System: Visual Intelligence for Agents\n\nThe WhatsApp labeling interface is a highly visual environment. The 20-color palette (indexed 0-19) is designed to minimize cognitive load for agents who are managing dozens of simultaneous threads.\n\n### The Strategic Color Map\n*   **Indices 0 & 13 (High Urgency Reds)**: Reserved for critical escalations, potential churn risks, or time-sensitive breaches.\n*   **Indices 1 & 14 (Operational Blues)**: Ideal for active workstreams, informational updates, or mid-funnel leads that require consistent but not immediate engagement.\n*   **Indices 9 & 15 (Positive Greens)**: Used for \"Closed Won\" status, verified payments, or successfully resolved support tickets.\n*   **Index 2 (Yellow)**: Represents a \"Pending\" or \"Waiting\" state—usually where the ball is in the customer's or a third-party's court.\n*   **Index 4 (Grey)**: Best for \"Cold\" leads, \"Nurture\" campaigns, or archived threads that shouldn't distract the agent's main focus.\n\n> [!IMPORTANT]\n> **Engineering Tip**: While the API returns a `colorHex`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Color',\n            content: 'Supports standard WhatsApp color indices (0-19).'\n        },\n        {\n            type: 'info',\n            title: 'Limits',\n            content: 'You can create up to 20 unique labels per account.'\n        }\n    ],\n  recommendations: [\n        \"Establish a naming convention across your organization.\",\n        \"Use distinct colors for high-priority vs low-priority items.\"\n    ]\n  \n   your system should rely exclusively on the **Color Index (0-19)** for logic. The hex values may shift slightly across different device versions or WhatsApp themes, but the index mapping is the immutable link to Meta's UI.\n\n---\n\n## 📏 Naming Conventions & Standardizations\n\nTo ensure your labels are as effective in the mobile app as they are in your custom CRM, follow these naming standards:\n\n1.  **Character Economy**: WhatsApp enforces a ~25 character limit. Names like \"High Priority Support Request Assigned to Alice\" will be truncated in the UI, rendering them useless. Use \"Urgent: Alice\" instead.\n2.  **Action-Oriented Naming**: Use labels that describe a state or a needed action. \"Invoice\" is a noun; \"Invoice Sent\" or \"Pay Pending\" are actionable states.\n3.  **Semantic Consistency**: Avoid using \"Label\" in the name. \"VIP Label\" is redundant when the UI already places the name in a colored badge.\n\n---\n\n## 🚀 Advanced Operational Use Cases\n\n### 1. Sales Funnel Orchestration\nInstead of manual tracking, use label creation to build a dynamic funnel. You might define stages starting from \"Initial Inquiry\" through \"Discovery Call\" and \"Proposal\" down to \"Closed.\" By programmatically maintaining these labels, your reporting systems can calculate conversion rates simply by counting chat distribution across these IDs.\n\n### 2. Team & Department Routing\nIn large organizations, labels act as the \"Routing Meta\" for incoming threads. You can create specialized labels for \"Technical Support,\" \"Billing,\" and \"Sales.\" When a customer hits a specific branch in your IVR/Bot, your system ensures the correct label exists and applies it, instantly notifying the correct department's monitoring team.\n\n### 3. Campaign & Event Tracking\nFor seasonal events (e.g., \"Black Friday Sale\" or \"Product Launch X\"), temporary labels allow you to isolate performance data. Once the campaign is over, these labels can be archived or deleted to free up space for the next cycle.\n\n---\n\n## ⚠️ Scaling Beyond the 20-Label Limit\n\nThe 20-label limit is a frequent challenge for high-growth businesses. If your system requires more than 20 categories, we recommend the following \"Expansion Patterns\":\n\n*   **The \"Tag Prefix\" Pattern**: Use a single label called \"Campaign\" and store the specific campaign ID in your internal database, linked to the chat ID.\n*   **The \"Rolling Archive\" Pattern**: Implement a cleanup script that deletes labels for campaigns or events that have been inactive for more than 90 days.\n*   **Dynamic Lifecycle**: Only create labels when they are actively needed for the current month's goals, and rotate them as business priorities shift.\n\n---\n\n## 🔄 Idempotency & Conflict Resolution\n\nWhatsApp allows for **Duplicate Label Names**. This can lead to significant confusion if your system creates a new \"New Lead\" label every time a lead arrives.\n\n### The \"Verify-Before-Create\" Pattern\nYour integration should always implement a \"Check and Bridge\" logic. Before attempting to create a label, fetch the current global list. If a label with the target name (case-insensitive) already exists, your system should use that existing ID instead of creating a new one. This preserves the 20-label quota and maintains a single source of truth for each category.\n\n---\n\n## 🛠️ Performance & Integration Principles\n\n### Bootstrapping Your Primary Taxonomy\nWe recommend creating your core \"Mission Critical\" labels during your application's initial setup or \"Warm-up\" phase. Creating labels \"on-the-fly\" during high-traffic message bursts can introduce unnecessary latency and risk hitting Meta's undocumented rate limits for metadata changes.\n\n### Webhook Synergy\nThe creation of a label triggers the [`label.upsert`](/v2/webhooks/label-upsert) webhook. Your backend should listen for this event to keep your local database synchronized with the WhatsApp account, especially if users are also creating labels manually via the mobile app.\n\n---\n\n## 🎯 Best Practices Summary\n\n1.  **Think Statefully**: Labels should represent the current state of a conversation, not just the customer's identity.\n2.  **Optimize Visuals**: Group similar departments into color clusters (e.g., all Sales-related labels use shades of Blue).\n3.  **Store Mapping Locally**: Always save the returned `id` alongside the `name` in your system for high-speed cross-referencing.\n4.  **Audit the Sidebar**: Periodically review your labels in the native WhatsApp app to ensure they remain legible and meaningful for your frontline agents.\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "The name of the new label",
            "schema": {
              "type": "string"
            },
            "example": "Urgent"
          },
          {
            "name": "color",
            "in": "query",
            "required": false,
            "description": "Internal color number (0-19). E.g., 0=#ff9485, 1=#64c4ff, ... 19=#9368cf",
            "schema": {
              "type": "integer"
            },
            "example": "0"
          }
        ],
        "responses": {
          "201": {
            "description": "Label created successfully",
            "content": {
              "application/json": {
                "example": {
                  "id": "3",
                  "name": "Urgent",
                  "color": 0,
                  "colorHex": "#ff9485"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/labels/{labelId}/update": {
      "put": {
        "operationId": "_v2_labels_labelId_update_put",
        "summary": "Update Label",
        "description": "Update an existing WhatsApp label's name or color.\n\n### Developer Tips\n- **Modification**: Allows renaming or changing the color of an existing label.\n- **Consistency**: Updates are pushed to all devices immediately.\n\n\n# Label Evolution: Navigating Taxonomy Changes\n\nAs your business grows and your sales or support funnels mature, your organizational requirements will inevitably shift. The **Update Label** endpoint is designed to facilitate this evolution, allowing you to refine your terminology and visual hierarchy without severing existing conversation links.\n\n---\n\n## 🏗️ Core Concept: Non-Destructive Refinement\n\nUnlike deleting and recreating a category—which would strip all metadata from your active chats—updating a label is a **state-preserving operation**. When you modify a label's name or color, every chat currently tagged with that record is instantly updated across the entire WhatsApp Business ecosystem.\n\n### The Power of Partial Updates\nThis endpoint follows a \"Flexible Schema\" approach. You are not required to provide both the name and the color for every request. \n*   **Terminological Shift**: Use this to rename \"Lead\" to \"Prospect\" across 500+ chats in a single API call.\n*   **Priority Escalation**: Keep the name \"Follow-up\" but change its color from Yellow to Red to instantly signal a high-priority state to your manual agent pool.\n\n---\n\n## 🚀 Strategic Operational Use Cases\n\n### 1. Rebranding & Terminology Alignment\nOrganizations often settle on specific internal buzzwords that eventually change. Whether you are moving from a \"Trial\" based model to \"Freemium\" or simply correcting a typo in a high-visibility tag, the Update endpoint ensures your frontline agents always see the most professional and current terminology.\n\n### 2. Visual Urgency Dynamic\nA label's color is a powerful subconscious trigger. During peak periods (like a holiday sale), you might temporarily update the color of your \"Shipping\" label to a more aggressive index (e.g., Red or Orange) to ensure it stands out in the chat list. Once the peak passes, you can revert it to a more neutral blue or green.\n\n### 3. Funnel Progression & Consolidation\nIf you find that two categories (e.g., \"Web lead\" and \"App lead\") have become redundant, you can rename one to \"Digital Lead\" and begin migrating the other's chats. This ensures a clean transition without losing historical context.\n\n---\n\n## ⚠️ Critical Behaviors & Atomic Logic\n\n### The \"Stable ID\" Principle\nEven when a label's name changes from \"Bug A\" to \"Fixed,\" its underlying **ID** never changes. This is critical for your internal reporting systems and databases. Your backend should always link metadata to the Label ID, allowing the name to remain a flexible \"Display Attribute.\"\n\n### Duplicate Name Tolerance\nWhatsApp allows for multiple labels to share the same name. If you update a label to match the name of an existing one, the system will not prevent the change. While this provides flexibility, it can lead to \"UI Confusion.\"\n*   **Recommendation**: Before executing an update, fetch your global label list and verify that the target name is not already in use by another ID. This maintains a clean and unique sidebar for your agents.\n\n---\n\n## 🛡️ Reliability & Webhook Orchestration\n\nAny change to a label's metadata triggers the [`label.upsert`](/v2/webhooks/label-upsert) webhook. \n\n### Synchronization Strategies\nYour integration should use this webhook as a \"Sync Trigger.\" When an agent renames a label manually in the WhatsApp Business app, your local database will receive the update event. This ensures that your CRM's \"Tag View\" always matches what the agent sees on their mobile device or desktop.\n\n### Managing Rate Limits\nWhile metadata updates are lightweight, we recommend avoiding high-frequency \"flapping\" (e.g., changing a label's color 10 times a minute). Maintain a stable taxonomy to avoid hitting Meta's undocumented rate limits for account-wide metadata modifications.\n\n---\n\n## 🛠️ Integration Patterns: Enterprise Compliance\n\n### The Audit Blueprint\nIn regulated industries (like Finance or Healthcare), changing the meaning of a tag can have legal implications. We recommend logging the \"Before\" and \"After\" state of any update in your own audit logs, capturing the timestamp and the identity of the agent who initiated the change.\n\n### The \"Maintenance Window\" Rollout\nWhen performing a large-scale re-architecture of your labels, perform the updates during low-traffic periods. This allows the changes to propagate through WhatsApp's global servers and ensures your local caches can be refreshed without impacting active conversation flows.\n\n---\n\n## 🎯 Best Practices\n\n1.  **Favor Consistency**: Avoid frequent renames, as agents build \"muscle memory\" based on the text and position of labels in their sidebar.\n2.  **Color Hierarchy**: Reserves Red indices for \"Negative/Urgent\" states and Green for \"Success\" states. Don't flip these meanings during an update.\n3.  **Invalidate Caches**: After a successful update, instantly clear any local or Redis-based label caches to prevent your UI from showing stale terminology.\n4.  **Character Awareness**: Always verify the new name is under the ~25 character limit to prevent truncation in the official WhatsApp app.\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "labelId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the label to update",
            "schema": {
              "type": "string"
            },
            "example": "3"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "name",
            "in": "query",
            "required": false,
            "description": "New name for the label",
            "schema": {
              "type": "string"
            },
            "example": "Very Urgent"
          },
          {
            "name": "color",
            "in": "query",
            "required": false,
            "description": "New internal color number (0-19). E.g., 0=#ff9485, 1=#64c4ff, ... 19=#9368cf",
            "schema": {
              "type": "integer"
            },
            "example": "0"
          }
        ],
        "responses": {
          "200": {
            "description": "Label updated successfully",
            "content": {
              "application/json": {
                "example": {
                  "id": "3",
                  "name": "Very Urgent",
                  "color": 0,
                  "colorHex": "#ff0000"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/labels/{labelId}/delete": {
      "delete": {
        "operationId": "_v2_labels_labelId_delete_delete",
        "summary": "Delete Label",
        "description": "Permanently delete a WhatsApp label.\n\n### Developer Tips\n- **Cascade**: Deleting a label removes it from ALL associated chats.\n- **Irreversibility**: This action cannot be undone.\n\n\n# Lifecycle Management: The Deletion Protocol\n\nThe **Delete Label** endpoint is the final stage in a category's lifecycle. It allows you to prune obsolete categories from your global taxonomy, ensuring that your WhatsApp Business account remains focused and high-performing.\n\n---\n\n## ⚠️ The Gravity of Deletion: Irreversible Consequences\n\nDeleting a label is one of the few truly destructive actions in the WhatsApp ecosystem. It is critical to understand the cascading effects before execution:\n\n*   **Global Taxonomy Removal**: The label is purged from the account's directory. It will no longer appear in the [`Get All Labels`](/v2/labels) response.\n*   **Automatic Untagging (The Cascade)**: Every conversation currently carrying this label will be stripped of it. This happens at the server level; you do not need to manually remove the label from individual chats before deleting the category.\n*   **Zero Recovery**: There is no \"Trash\" or \"Recycle Bin.\" Once a Label ID is deleted, it cannot be recovered. Recreating a label with the same name will result in a **new ID**, and previous chat associations will not be restored.\n\n---\n\n## 🚀 Strategic Operational Use Cases\n\n### 1. Post-Campaign Decommissioning\nMarketing efforts often use high-visibility labels (e.g., \"Holiday Sale 2024\") to track conversion. Once the campaign window closes and follow-ups are completed, deleting the label keeps the agent's sidebar clean and reduces cognitive load during daily operations.\n\n### 2. Taxonomy Consolidation\nAs business processes evolve, you may find that multiple labels (e.g., \"Web-Inquiry\" and \"Form-Inquiry\") are essentially redundant. Deleting the surplus categories encourages agents to use a centralized, standardized \"Digital Lead\" tag instead.\n\n### 3. Cleanup of Experimental Categories\nWhen testing new automation flows or bot behaviors, you may create temporary labels for internal routing. Deleting these once testing is complete prevents your 20-label quota from being exhausted by \"zombie\" tags.\n\n---\n\n## 🛡️ The \"Safe Decommissioning\" Pattern\n\nTo avoid accidental data loss or workflow disruption, the following architectural steps should be taken before calling the Delete endpoint:\n\n1.  **Usage Auditing**: Always query [`Get Chats with Label`](/v2/labels/{id}/chats) to determine the volume of active threads currently relying on the tag.\n2.  **Meta-Migration**: If a label still has active threads, use a batch process to re-tag those chats with a replacement label (e.g., moving \"Old Campaign\" chats to \"Generic Lead\") before deleting the old category.\n3.  **Cross-System Verification**: Ensure that no external CRM filters or automated Slack notifications are exclusively triggered by the ID you are about to remove.\n\n---\n\n## ⚡ Integration Engineering & Webhooks\n\n### Orchestrating the \"Untag\" Flood\nA single deletion event can trigger a massive number of state changes if the label was applied to thousands of chats.\n*   **Webhook Behavior**: WhatsApp will fire the [`label.deleted`](/v2/webhooks/label-deleted) event once. However, your system must be prepared for the fact that those chats no longer possess the metadata.\n*   **UI Reflex**: Your application should immediately invalidate its label cache. If an agent's dashboard shows a \"Deleted Label\" badge, it may lead to confusion when they try to interact with that metadata and receive 404 errors from subsequent API calls.\n\n---\n\n## 🏗️ Enterprise Hygiene: Maximizing the 20-Label Limit\n\nBecause WhatsApp enforces a hard limit of 20 labels, deletion is a vital tool for \"Metadata Grooming.\" \n\n*   **The \"Garbage Collection\" Rule**: Develop a standard operating procedure (SOP) to review your labels every 30-90 days. Labels with zero active associations should be prioritized for deletion to make room for new initiatives.\n*   **Selective Lifecycle**: Instead of creating permanent labels for every small event, reserve your IDs for high-level \"Lifecycle States\" (e.g., Lead, Customer, Escalated). Use deletion to rotate campaign-specific tags in and out of the available 20 slots.\n\n---\n\n## 🎯 Best Practices Summary\n\n1.  **Read-Check-Delete**: Always verify the label exists and check its usage count before pulling the trigger.\n2.  **Inform Your Team**: Deleting a label can be jarring for agents who rely on it for their daily triage. Coordinate with your support or sales leads before making taxonomy changes.\n3.  **Update CRM References**: Ensure your internal database is cleaned of any references to the deleted ID to prevent \"Ghost Metadata\" from appearing in your reports.\n4.  **Favor Renaming (If Unsure)**: If you might need the label again, consider using the [Update](/v2/labels/{id}/update) endpoint to rename it to \"[DEPRECATED] Name\" instead of deleting it immediately. This preserves the chat associations while signaling that the tag is out of rotation.\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "labelId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the label to delete",
            "schema": {
              "type": "string"
            },
            "example": "3"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Label deleted successfully",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/labels/{labelId}/chats": {
      "get": {
        "operationId": "_v2_labels_labelId_chats_get",
        "summary": "Get Chats with Label",
        "description": "Get a list of chats associated with a specific label.\n\n### Developer Tips\n- **Aggregation**: Often used to get a count of chats per label.\n- **Dashboard**: Great for visualizing workload (e.g., 'Pending Support Tickets').\n\n\n# Targeted Retrieval: Mastering Category-Based Filtering\n\nThe **Get Chats with Label** endpoint is the primary bridge between your organizational taxonomy and your communication workflow. It allows you to filter your entire conversation history by a specific Label ID, returning a lean list of chat identifiers and names that belong to that category.\n\n---\n\n## 🏗️ Core Concept: Category-Based Batch Processing\n\nThis endpoint enables high-efficiency retrieval by offloading the filtering logic to Wawp's core servers. Instead of your system iterating through thousands of individual chat logs to identify \"Stale Leads\" or \"VIPs,\" you can retrieve a pre-filtered list in a single, optimized API request.\n\n### Key Strategic Capabilities:\n1.  **Mass Outreach Orchestration**: Instantly identify all participants in a specific marketing campaign or product launch for targeted broadcasts.\n2.  **Workflow Throughput Auditing**: Measure the \"State Density\" of your funnel—such as how many chats are currently bottlenecked in the \"Payment Failure\" or \"Escalated\" states.\n3.  **CRM State Synchronization**: Pull segmented lists of contacts to ensure your external CRM dashboards reflect the real-time visual categorization seen by your WhatsApp agents.\n\n---\n\n## 🚀 Priority Operational Use Cases\n\n### 1. The Proactive Retention Cycle\nBy regularly querying labels like \"Pending Follow-up\" or \"Day 3 Trial,\" your system can identify users who have entered a period of inactivity. This allows you to trigger automated re-engagement messages or move them to a different \"Nurture\" category to prevent lead decay.\n\n### 2. Segmented Sentiment Analysis\nIn high-volume accounts, auditing every message is impossible. This endpoint allows you to focus your analytical resources on the most critical segments. By fetching only the chats tagged \"Dissatisfied\" or \"Urgent,\" you can run targeted sentiment analysis to identify systemic issues before they escalate.\n\n### 3. Queue Management & Load Balancing\nIf you use labels to assign chats to specific departments (e.g., \"Sales Queue,\" \"Support Tier 2\"), this endpoint provides the headcount per queue. This data is essential for dynamic resource allocation, allowing you to move agents between departments based on real-time conversation volume.\n\n---\n\n## ⚖️ Scalability & Big Data Architecture\n\nFor enterprise accounts with tens of thousands of conversations, the management of label lists requires an optimized approach to prevent memory exhaustion and timeout errors.\n\n### Managing High-Volume Lists\nWhile this endpoint is designed for speed, retrieving a list of 5,000+ chats can be tax the CPU of smaller server instances.\n*   **The Cursor-Free Pattern**: This endpoint returns the full current list for a label. To maintain performance, we recommend immediately streaming this data into a background processing queue (such as Redis or RabbitMQ) rather than attempting to process it inside the main HTTP request loop.\n*   **Memory Hygiene**: If you are operating in a resource-constrained environment (like a Lambda function or an Edge Worker), avoid storing the entire array in memory; process the results as a stream of IDs to minimize your memory footprint.\n\n---\n\n## 🛡️ Data Integrity & Compliance\n\n### PII Sensitivity & GDPR\nThe names returned by this endpoint are the contact names as they appear in the WhatsApp account's address book.\n*   **Data Minimization**: Never fetch full chat lists and store them indefinitely. Retrieve the list only when you have an immediate action to perform, and dispose of the identifiers once the operation is complete.\n*   **Real-Time Reflection**: The list is a snapshot of the *current* state. Because agents can add/remove labels in the WhatsApp mobile app at any time, treat the data as highly transient.\n\n---\n\n## 🎯 Best Practices\n\n1.  **Webhook-Triggered Audits**: Avoid high-frequency polling. Instead of checking this endpoint every 5 minutes, use the [`label.chat.added`](/v2/webhooks/label-chat-added) webhook to keep a local, incremental list of chat associations.\n2.  **Verify Label Vitality**: Before querying for chats, ensure the Label ID is still active. Querying a deleted ID will result in an empty list, which your system might incorrectly interpret as \"Zero active leads.\"\n3.  **Hybrid Enrichment**: Use the lean IDs returned here as a \"Filter Key.\" If you need more data (like profile pictures or BIOs), pass these IDs to the [`Get Contact Info`](/v1/get-contact-info) endpoint in small batches to build a rich, visual dashboard.\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "labelId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the label",
            "schema": {
              "type": "string"
            },
            "example": "1"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "List of chats retrieved successfully",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "123456789@c.us",
                    "name": "John Doe"
                  }
                ]
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/labels/{id}/chats/{chatId}": {
      "put": {
        "operationId": "_v2_labels_id_chats_chatId_put",
        "summary": "Link Label to Chat",
        "description": "Assign a specific label to a chat or contact.\n\n### Developer Tips\n- **Capacity**: A chat can have multiple labels (up to 20).\n- **Automation**: Labels are excellent triggers for automated workflows.\n\n\n# Tagging Conversations: Mastering Semantic Orchestration\n\nThe **Link Label to Chat** endpoint is the primary mechanism for attaching strategic metadata to individual or group conversations. This is not merely a \"visual tag\"; it is a programmatic state-marker that allows your CRM, bots, and agents to interact with conversations based on their current business value or urgency.\n\n---\n\n## 🏗️ Core Concept: Metadata at the Conversation Edge\n\nThink of labels as ** dynamic attributes ** that move a chat through your internal processing pipeline. \n\n### Key Architectural Principles:\n*   ** Additive Metadata **: A single chat can carry multiple labels simultaneously(e.g., \"VIP\" + \"Pending Payment\" + \"Assigned to Team A\").This allows for multi - dimensional filtering.\n*   ** Idempotency by Design **: Linking the same label to the same chat multiple times has zero side effects.This makes it safe to include tagging calls in high - frequency event loops without fear of duplication or errors.\n*   ** Silent Context **: Tagging is a purely internal operation.The customer never sees the labels, and no notification is sent to their device.It is a \"Private Channel\" for your organizational logic.\n\n---\n\n## 🚀 Strategic Operational Use Cases\n\n### 1. Funnel State Management\nUse this endpoint to move contacts through your sales funnel.As a user progresses from an \"Inbound Lead\" to a \"Qualified Prospect,\" your system should link the relevant labels to reflect their increasing value.This allows your sales team to instantly prioritize their inbox based on funnel depth.\n\n### 2. Auto - Tagging Intelligence\nBy integrating your messaging history with a sentiment analysis engine or a keyword detector, you can programmatically tag chats. \n*   ** Urgency Detection **: Automatically link an \"Urgent\" label if a user mentions \"ASAP\" or \"Help.\"\n  *   ** Intent Categorization **: Tag conversations as \"Billing,\" \"Support,\" or \"Sales\" based on the initial inbound message, ensuring they are routed to the correct department immediately.\n\n### 3. CRM & System Synchronization\nMirror the state of your external CRM.If a lead's status is updated in Salesforce or HubSpot, use this endpoint to ensure that the agent looking at the WhatsApp app sees the exact same status in real-time. This \"Side-by-Side Synchronization\" prevents data silos and agent confusion.\n\n---\n\n## 🛠️ Integration Patterns: Orchestrating Clean Transitions\n\n### The \"Step-Up\" Transition\nWhen moving a chat to a new state(e.g., from \"Pending\" to \"Approved\"), we recommend a \"Link then Prune\" pattern.First, link the new \"Approved\" label, then use the[Unlink endpoint](/v2/labels / { id } / chats / { chatId }) to remove the old \"Pending\" state.This ensures the chat is never without a category during the transition.\n\n### Event - Driven Tagging\nTrigger tagging based on external business events.For example, when a payment is processed in your billing system, instantly link the \"Paid\" label to the customer's WhatsApp chat. This provides immediate visual confirmation to any agent who might be interacting with that customer.\n\n---\n\n## 🧪 Advanced Operational Safeguards\n\n### Scalability with Groups\nThis endpoint fully supports WhatsApp Group Chats(`@g.us`). This is powerful for B2B workflows where you might tag an entire project room as \"Active\" or \"On Hold.\" \n\n### Handling the \"ID Drift\"\nAlways verify that the Label ID you are attempting to link is active in your global account directory. If a label has been deleted from the account, attempts to link it will result in a 404 error. Your system should listen for [`label.deleted`](/v2/webhooks/label-deleted) events to prevent \"Ghost Tagging\" attempts.\n\n---\n\n## ⚡ Webhook Orchestration\n\nEvery successful link operation triggers a [`label.chat.added`](/v2/webhooks/label-chat-added) event. You can use this to:\n*   **Trigger Notifications**: Push a high-priority browser notification to an agent's dashboard.\n*   **Launch Automations**: Start a specific drip campaign or bot sequence when a \"Warm Lead\" label is applied.\n\n---\n\n## 🎯 Best Practices\n\n1.  **Action-Oriented Taxonomy**: Use names like \"To Follow Up\" or \"Needs Manager\" instead of passive nouns. Labels should imply an action.\n2.  **Visual Consistency**: Leverage the color indices to create an urgency hierarchy. Reserve Reds for high-priority tagging.\n3.  **Batching at Scale**: When tagging a large segment of users (e.g., after a mass broadcast), implement a slight delay or use a background queue to ensure smooth propagation across Meta's servers.\n4.  **Prune Redundancy**: Don't let chats accumulate 10+ labels. Maintain \"Metadata Hygiene\" by removing old stage labels as new ones are added.\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the label",
            "schema": {
              "type": "string"
            },
            "example": "1"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number or group ID (@c.us, @g.us)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "_v2_labels_id_chats_chatId_delete",
        "summary": "Unlink Label from Chat",
        "description": "Remove a specific label from a chat or contact.\n\n### Developer Tips\n- **Cleanup**: Removes a specific label relationship, not the label itself.\n- **Sync**: Changes are reflected instantly across all devices.\n\n\n# Untagging Conversations: Mastering Taxonomy Pruning\n\nThe **Unlink Label from Chat** endpoint is the critical counterpart to the tagging process. It allows you to prune obsolete or resolved metadata from a conversation, ensuring that your agents' inbox remains clutter-free and that your automation engines are operating on the most current state of the relationship.\n\n---\n\n## 🏗️ Core Concept: State De - escalation\n\nRemoving a label is the programmatic equivalent of ** resolving a state ** or ** transitioning a stage **. \n\n### Key Operational Characteristics:\n*   ** Non - Destructive Association **: Unlinking a label from a chat only removes the relationship.The label itself remains untouched in your global account directory, ready to be applied to other conversations.\n*   ** Targeted State Removal **: Unlike a broad \"Clear All,\" this endpoint allows for surgical removal of a specific attribute(e.g., removing \"Urgent\" while keeping \"Assigned to Bob\").\n*   ** Idempotency & Silent Execution **: Attempting to remove a label that isn't currently linked to the chat will result in a success response with no side effects. No notification is ever sent to the customer, maintaining the privacy of your internal organizational logic.\n\n---\n\n## 🚀 Strategic Operational Use Cases\n\n### 1. Funnel Progression Hygiene\nAs a customer moves deeper into your sales or support funnel, their previous stages often become irrelevant.For example, once a \"New Lead\" becomes a \"Qualified Prospect,\" the \"New Lead\" label should be unlinked.This keeps the visual interface focused on the * next required action * rather than the conversation's history.\n\n### 2. Auto - Cleanup of \"Stale\" Metadata\nIn high - volume accounts, labels can accumulate over time, leading to \"Metadata Bloat.\" Use this endpoint in conjunction with a background cron job to automatically unlink \"Temporary\" or \"Inquiry\" labels after a set period of inactivity(e.g., 7 days).This ensures that only active, high - priority conversations carry visual markers.\n\n### 3. User - Triggered Opt - Outs\nIf you use labels to manage internal broadcast segments(e.g., \"Marketing Opt-In\"), use this endpoint to honor customer requests to stop communications.When a user sends a \"Stop\" message, your bot can instantly unlink the marketing label, immediately removing them from any future automated outreach lists.\n\n---\n\n## 🛠️ Integration Patterns: Orchestrating Move Sequences\n\n### The \"Link-then-Prune\" Strategy\nWhen a conversation state changes(e.g., from \"Billing Inquiry\" to \"Resolved\"), we recommend a two - step orchestration:\n1. ** Add the Destination State **: Link the \"Resolved\" label.\n2. ** Remove the Origin State **: Unlink the \"Billing Inquiry\" label.\nThis ensures that the chat always carries at least one visual marker during the transition period, preventing the conversation from \"disappearing\" from filtered views in the agent dashboard.\n\n### Mass Decategorization\nAfter a specific campaign or event(e.g., \"Webinar Q3\") is concluded, you can use this endpoint to clear the campaign markers from thousands of chats.By unlinking the campaign label, you effectively reset those conversations for the next cycle without deleting the record of the interaction itself.\n\n---\n\n## 🛡️ Data Integrity & Reliability\n\n### Handling ID Sensitivity\nAlways ensure that the Label ID you are unlinking is a valid string from your current account directory.If you attempt to unlink an ID that has been globally deleted, the API will return a 404 error.We recommend listening for [`label.deleted`](/v2/webhooks/label-deleted) webhooks to keep your internal ID mappings clean.\n\n---\n\n## 🎯 Best Practices\n\n1.  **Avoid Label Overload**: Maintain a \"Strict Limit\" policy for your chats. If a chat has more than 3 labels, it usually indicates that the previous stage markers haven't been properly unlinked.\n2.  **State-Driven Transitions**: Make unlinking a core part of your bot's logic. If a bot finishes a collection flow, it should unlink the \"Collecting Info\" label as its final act.\n3.  **Real-Time Synchronization**: Ensure your CRM's \"Delete Tag\" event or \"Status Change\" trigger is mapped to this endpoint. This keeps the agent's view in WhatsApp perfectly synchronized with the source of truth in your business database.\n4.  **Audit the Removal**: Log every unlinking operation in your internal audit trails to track how long conversations typically spend in a specific \"Labeled State.\"\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the label",
            "schema": {
              "type": "string"
            },
            "example": "1"
          },
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "Target phone number or group ID (@c.us, @g.us)",
            "schema": {
              "type": "string"
            },
            "example": "447441429009@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/v2/labels/chats/{chatId}": {
      "get": {
        "operationId": "_v2_labels_chats_chatId_get",
        "summary": "Get Chat Labels",
        "description": "Get all labels assigned to a specific chat.\n\n### Developer Tips\n- **Association**: Returns all chats associated with a specific label ID.\n- **Pagination**: Supports cursor-based pagination for large lists.\n\n\n# Reading the Thread Metadata: Fetch All Labels for a Chat\n\nIndividual conversations often wear many hats. A single chat with a customer might simultaneously be a \"VIP,\" have a \"Pending Payment,\" and be \"Assigned to Alice.\" The **Get Chat Labels** endpoint allows you to retrieve the full array of labels currently attached to a specific chat identifier.\n\n---\n\n## 🏗️ Core Concept\n\nThis endpoint is the primary tool for **Conversational Discovery**. It answers the question: \"What is the current business context of this specific thread?\"\n\n### Key Capabilities:\n1.  **UI Hydration**: Populate the \"tags\" or \"labels\" section of your custom agent dashboard when a chat is selected.\n2.  **Conditional Logic**: Trigger different bot responses or agent alerts based on the chat's existing labels.\n3.  **State Audit**: Verify if a chat has correctly transitioned through your workflow stages (e.g., ensuring \"Lead\" was removed before \"Customer\" was added).\n\n---\n\n## 🚀 Priority Use Cases\n\n### 1. Smart Auto-Replies\nAdjust your bot's tone or logic based on the user's current categories.\n```javascript\nconst labels = await api.getLabelsForChat('123456789@c.us');\nconst isVIP = labels.some(l => l.name === 'VIP');\n\nif (isVIP) {\n  await api.sendText(chatId, \"Hello VIP! We've prioritized your request for immediate agent review.\");\n} else {\n  await api.sendText(chatId, \"Thanks for your message. We'll get back to you soon!\");\n}\n```\n\n### 2. CRM \"State Refresh\"\nWhen an agent opens a contact in your CRM, fetch the latest WhatsApp labels to ensure the external CRM state matches the reality of the WhatsApp thread.\n\n### 3. Preventing Duplicate Tags\nBefore adding a label, check if it's already present to avoid redundant API calls (though the add-label operation is idempotent).\n\n---\n\n## 🔄 State Consistency & Synchronization\n\nIn a multi-agent environment, ensuring that every agent sees the same labels at the same time is critical for preventing duplicated work.\n\n### The \"Stale Data\" Challenge\nIf Agent A adds a \"Processing\" label while Agent B is looking at the same chat, Agent B's dashboard may still show \"Unassigned.\" \n*   **The Check-Before-Action Rule**: Before an agent clicks \"Send Invoice,\" your backend should call this endpoint to verify the chat hasn't already been tagged with \"Invoice Sent\" by another automated process or agent.\n*   **Websocket Pushing**: Listen to [`label.chat.added`](/v2/webhooks/label-chat-added) and [`label.chat.removed`](/v2/webhooks/label-chat-removed) webhooks. When they arrive, use this endpoint to fetch the *full current state* and push it via Websockets to all active agent browsers.\n\n---\n\n## 🛡️ Audit Logging & Compliance\n\nLabels are often used to trigger significant business events (e.g., tagging a chat \"Refund Approved\" to trigger a payment gateway).\n\n### Building an Audit Trail\nWhatsApp does not natively store a history of *who* applied a label and *when*. We recommend:\n1.  **Intercepting API Calls**: Every time your system calls [`PUT /v2/labels/{id}/chats/{chatId}`](/v2/labels/{id}/chats/{chatId}), log the user ID of the agent who initiated it.\n2.  **Snapshotting States**: Periodically use this **Get Chat Labels** endpoint to take a snapshot of high-value chats to track their journey through your funnel.\n\n---\n\n## 🛠️ Integration Patterns: Visual Feedback Systems\n\n### The \"Label Badge\" Hydration\n1.  **Fetch List**: Call this endpoint for the active chat.\n2.  **Map Styles**: Cross-reference the `color` index with your local CSS theme.\n3.  **Render**: Display a horizontal list of badges in your sidebar.\n\n```javascript\nasync function renderChatMetadata(chatId) {\n  const currentLabels = await api.getLabelsForChat(chatId);\n  \n  return currentLabels.map(label => ({\n     text: label.name,\n     bgcolor: label.colorHex,\n     isUrgent: label.color === 0 // Red index\n  }));\n}\n```\n\n---\n\n## ⚠️ Important Behaviors & Edge Cases\n\n*   **Multi-Label Support**: WhatsApp supports multiple labels per chat. This endpoint always returns an **array**, which may be empty if no labels are applied.\n*   **Id/Name/Color Trio**: Each label in the response includes its unique ID, name, current color index, and hex code.\n*   **Performance**: This is a lightweight call. However, if building a high-volume dashboard, consider caching the results until a webhook is received.\n\n---\n\n## 🤖 Advanced Integration: Bot Interaction Patterns\n\nWhen building an automated assistant, the labels attached to a chat act as a \"Contextual Memory.\"\n\n### The \"Label-Aware\" Bot\nYour bot can query this endpoint at the start of a session to determine the user's tier or status.\n1.  **Incoming Message**: User says \"Price check.\"\n2.  **Lookup**: Bot calls this endpoint.\n3.  **Branching logic**:\n    *   If label \"Wholesale\" (ID 5) exists → Give bulk pricing.\n    *   If label \"Retail\" (ID 2) exists → Give standard pricing.\n    *   If no labels exist → Ask the user for their customer type.\n\n```javascript\nasync function getBotResponse(chatId, message) {\n  const meta = await api.getLabelsForChat(chatId);\n  const isWholesale = meta.some(l => l.id === '5');\n  \n  if (message.includes('price')) {\n    return isWholesale ? getBulkPriceList() : getStandardPriceList();\n  }\n}\n```\n\n---\n\n## 🎯 Best Practices\n\n1.  **Don't Over-Poll**: Use [Webhooks](/v2/webhooks) to keep your local database in sync instead of calling this every time a message is received.\n2.  **Handle Empty States**: Gracefully render your UI when the response is an empty array `[]`.\n3.  **Cross-Reference with Global Directory**: Use the results here alongside the [`Get All Labels`](/v2/labels) list to provide a full \"Label Picker\" experience for agents.\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the chat (e.g., 123456789@c.us)",
            "schema": {
              "type": "string"
            },
            "example": "123456789@c.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "List of labels for the chat",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "1",
                    "name": "New Customer",
                    "color": 0,
                    "colorHex": "#ff9485"
                  }
                ]
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "_v2_labels_chats_chatId_put",
        "summary": "Set Chat Labels",
        "description": "Overwrite all labels for a specific chat.\n\n### Developer Tips\n- **Overwrite**: This REPLACES all existing labels on the chat with the new set.\n- **Bulk Action**: Efficient for resetting a chat's categorization state.\n\n\n# Decisive State Management: Overwriting All Chat Labels\n\nWhile adding and removing labels individually is useful for incremental updates, the **Set Chat Labels** endpoint is designed for **Atomic State Transitions**. It allows you to define the exact set of labels a chat should have, effectively overwriting any existing tags in a single operation.\n\n---\n\n## 🏗️ Core Concept\n\nThis endpoint is the primary tool for **Full State Sync**. Instead of calling \"Add\" three times and \"Remove\" twice to update a chat's context, you provide an array of all intended Label IDs (e.g., `[\"1\", \"2\"]`). WhatsApp will ensure those specific labels are applied and all others are removed.\n\n### Key Capabilities:\n1.  **Mass Migration**: Instantly move a chat from \"Outdated Campaign\" tags to a new set of \"Retention\" tags.\n2.  **State Synchronization**: Force the WhatsApp thread to match the exact state of your external CRM record.\n3.  **Atomic Updates**: Ensure that a chat is never in an inconsistent state (e.g., having both \"Active\" and \"Closed\" labels at the same time).\n\n---\n\n## 🚀 Priority Use Cases\n\n### 1. The CRM \"Master Sync\"\nEvery time a contact's status changes in your CRM, push the new reality to WhatsApp.\n```javascript\nasync function syncLabelsFromCRM(chatId, crmTags) {\n  // Map CRM tags to WhatsApp Label IDs\n  const labelIds = crmTags.map(tag => tagMap[tag]).filter(Boolean);\n  \n  // Force WhatsApp to match CRM exactly\n  await api.setChatLabels(chatId, labelIds);\n  console.log(`Synchronized labels for ${chatId}: ${labelIds.join(', ')}`);\n}\n```\n\n### 2. Funnel Stage Transitions\nWhen a user graduates from \"Trial\" to \"Paid subscriber,\" you want to clear all \"Trial-related\" metadata and apply \"Subscriber\" metadata.\n```javascript\n// Moving from Trial to Active\nawait api.setChatLabels(chatId, [subscriberLabelId, highValueLabelId]);\n// All previous tags like \"Trial Day 3\", \"Demo Scheduled\" are wiped.\n```\n\n---\n\n## ⚡ Technical Depth: Transactional Safety\n\nBecause this endpoint is **destructive** (it removes anything not mentioned), it should be treated with the same caution as a database `UPDATE` command.\n\n### The \"Get-Modify-Set\" Pattern\nIf you want to add a label while ensuring you strictly control the other labels, use this pattern:\n1.  **Get Current**: Call [`GET /v2/labels/chats/{chatId}`](/v2/labels/chats/{chatId}).\n2.  **Filter**: Locally add/remove the IDs you want.\n3.  **Set**: Call this endpoint with the final array.\n\nThis is safer than incremental calls in high-latency environments where multiple systems might be trying to tag the same chat.\n\n---\n\n## �️ Reliability & Webhook Orchestration\n\nEvery Label ID added or removed during this operation will trigger a corresponding webhook event. \n\n### Webhook Noise Management\nIf your system listens to [`label.chat.added`](/v2/webhooks/label-chat-added), setting 5 labels at once will fire **5 webhooks**. \n*   **Recommendation**: Disable automated logic for a specific chat ID for 5-10 seconds after calling this endpoint to allow the \"dust to settle\" on the remote WhatsApp account.\n*   **Idempotency**: If you set the same labels the chat already has, no webhooks will fire, making this a safe operation to run on a daily sync cron job.\n\n---\n\n## 🛠️ Integration Patterns: Advanced State Sync\n\n### Multi-Agent \"Locking\" System\nUse a specific \"Locked by [Agent Name]\" label. When an agent grabs a chat, use this endpoint to remove \"Unassigned\" and add \"Locked by Agent X\" in one atomic jump.\n\n### The \"Clean Slate\" Pattern\nTo remove **all** labels from a chat without deleting the labels themselves, simply send an empty array:\n```javascript\nawait api.setChatLabels(chatId, []);\n```\n\n---\n\n## ⚠️ Important Behaviors & Edge Cases\n\n*   **Destructive Overwrite**: Any Label ID **not** included in your request will be **removed** from the chat. Use with caution.\n*   **Array Limit**: While you can theoretically send many IDs, keep the array to a reasonable size (<20) as WhatsApp only supports a limited number of labels per account.\n*   **Validation**: If you provide a non-existent Label ID in the array, the entire request may fail with a `400 Bad Request`. Always verify your Label IDs before setting.\n\n---\n\n## � Disaster Recovery & Rollback Strategies\n\nBecause this endpoint is destructive, having a \"safety net\" is a recommended architectural pattern.\n\n### Implementing a \"Soft Delete\" Buffer\nBefore calling this endpoint to clear labels:\n1.  **Snapshot**: Store the current label IDs in a `previousLabels` field in your own database.\n2.  **Delay**: Wait 30 seconds.\n3.  **Rollback Option**: If an agent realized they made a mistake, they can click \"Undo,\" which calls this endpoint again with the `previousLabels` array.\n\n### Visual State Verification\nAfter every set operation, we recommend calling [`GET /v2/labels/chats/{chatId}`](/v2/labels/chats/{chatId}) one last time to verify the WhatsApp server has correctly applied the changes. This ensures your frontend is never out of sync with Meta's actual state.\n\n---\n\n## �🎯 Best Practices\n\n1.  **Read Before Write (If Unsure)**: If you only want to add a label without losing existing ones, use the [`Link Label to Chat`](/v2/labels/{id}/chats/{chatId}) endpoint instead.\n2.  **Webhook Awareness**: This operation will trigger both add and remove events for every change made. Ensure your webhook handlers can handle bursts of events.\n3.  **Use for \"Single View\" Dashboards**: This is the best endpoint for UIs that allow agents to select multiple tags from a list and click \"Save Changes.\"\n    ",
        "tags": [
          "Labels"
        ],
        "parameters": [
          {
            "name": "chatId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the chat (e.g., 123456789@c.us)",
            "schema": {
              "type": "string"
            },
            "example": "123456789@c.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "labels",
            "in": "query",
            "required": true,
            "description": "Array of label IDs to assign (overwrites existing ones)",
            "schema": {
              "type": "string"
            },
            "example": "[\"1\", \"2\"]"
          }
        ],
        "responses": {
          "200": {
            "description": "Labels updated successfully",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups": {
      "get": {
        "operationId": "_v2_groups_get",
        "summary": "Get All List groups",
        "description": "Retrieve a list of all groups the instance is a member of.\n\n### Developer Tips\n- **Performance**: Scanning thousands of groups can be slow. Use filters if available.\n- **Sync**: Use this to bootstrap your local database on startup.\n\n\n# Global Inventory: The Strategic Audit of Your Group Footprint\n\nIn a high-scale WhatsApp deployment, your business account doesn't just manage individual messages; it manages an entire ecosystem of communities. The **Get All Groups** endpoint is your primary tool for **Conversational Resource Management**. It provides a top-down, panoramic view of every shared state—every \"War Room,\" every \"Customer Onboarding Group,\" and every \"Marketing Cohort\"—that your instance is currently a part of. This endpoint is the foundation for ecosystem auditing, bulk state synchronization, and long-term conversational hygiene.\n\nFor developers and architects, \"Listing Groups\" is not just about showing a table of names; it is about **Inventorying Business Assets** and identifying where your automated presence is most active—and where it might be lingering beyond its useful life.\n\n---\n\n## 🏗️ Architectural Philosophy: The Macro-View of Shared State\n\nWhereas the [Get Group](/v2/groups/{id}) endpoint provides high-fidelity depth for a single community, the **Get All Groups** endpoint provides the breadth required for systemic management.\n\n### Key Architectural Objectives:\n*   **Contextual Inventory**: This endpoint returns an array of metadata for every group associated with the instance. This is critical for \"Bootstrapping\" your internal CRM. When you first connect a WhatsApp account to your platform, you use this endpoint to map the pre-existing reality of the account into your database, ensuring that no \"Legacy Group\" is left un-managed.\n*   **Orphaned Flow Detection**: In complex automation environments, a group might be created but, due to a bug or a missing business trigger, it might never be correctly linked to a customer record. By fetching the full list of groups, your system can perform a **\"Reconciliation Audit\"**—comparing the list of active WhatsApp groups against your internal database. Any group found on WhatsApp but not in your database is an \"Orphaned State\" that requires manual review or automated cleanup.\n*   **Permission Census**: This endpoint provides a quick snapshot of the instance's role in each community. By auditing the `participants` array across all groups, your system can identify which communities it still controls as an **Admin** and which ones it has been demoted in. This \"Permission Awareness\" is vital for prioritizing where your bots can execute governance and where they are restricted to mere observation.\n\n---\n\n## 🚀 Strategic Operational patterns: Ecosystem Hygiene\n\nA healthy WhatsApp account is one that is lean and purposeful. The Get All Groups endpoint is the engine behind your **Decommissioning Workflows**.\n\n### 1. The Rolling Archive Protocol\nProfessional enterprises implement a \"Rolling Audit\" every 7 to 30 days. Your system fetches the full list of groups and maps them to their last interaction timestamps. Any group that has had zero activity for more than 90 days—and is not marked as a \"Permanent VIP Channel\" in your CRM—becomes a candidate for the [Delete Group](/v2/groups/delete) endpoint. This \"Conversational Pruning\" keeps your agent's interface focused on active leads and reduces the long-term data footprint on your servers.\n\n### 2. Multi-Instance Load Balancing\nIf your enterprise uses multiple WhatsApp instances to manage a massive community (e.g., thousands of property tenants), the Get All Groups endpoint allows you to track the **Distribution of Responsibility**. By auditing the group counts across different instances, your system can decide which instance has the most \"headroom\" to create the next new group, preventing any single account from hitting Meta's undocumented saturation limits.\n\n### 3. Identity Resolution for Manual Creations\nAgents often create groups manually via the mobile WhatsApp app to handle ad-hoc customer requests. These groups are \"Invisible\" to your automation until identified. By periodically calling Get All Groups, your system can \"Discover\" these manually created communities, parse their names for Project IDs, and automatically import them into your official CRM flow, ensuring that manual agent work is captured in your high-level business analytics.\n\n---\n\n## 🔐 Security & Governance: Auditing the Membership List\n\nGroups are inherently high-trust, but they are also potential data leak points. The Get All Groups endpoint allows for **Global Compliance Auditing**.\n\n### Participant Sentiment & Prohibited Presence\nFor highly regulated industries (such as Banking or Insurance), your system must ensure that no unauthorized JIDs are present in your business groups. By fetching the participant list for all groups in bulk, you can run a \"Compliance Scan\" against your global blacklist. If an instance of an unauthorized number is found in *any* group, your system can trigger an immediate alert to your security team or execute an automated removal.\n\n### Tracking the \"Administrative Footprint\"\nManaging the number of admins in your ecosystem is a critical security task. Too many admins increases the risk of accidental group deletion or unauthorized settings changes. This endpoint allows you to audit the \"Admin Density\" across your entire account. If a regular project member has been promoted to admin without a corresponding approval in your internal HR system, your system can automatically demote them back to member status, maintaining a \"Strict Governance\" posture.\n\n---\n\n## ⚙️ Performance & Scaling: Batching vs. Real-Time Sync\n\nFetching all groups can be a relatively \"Expensive\" operation for accounts that are members of hundreds or thousands of communities. To maintain a high-performance system, follow these principles:\n\n1.  **Avoid Excessive Polling**: Never call this endpoint in a tight loop. Instead, use a scheduled background job (e.g., once every 6-24 hours) to perform the \"Global Reconciliation.\" \n2.  **Rely on Event-Driven Updates**: For real-time changes, always prioritize the [`group.update`](/v2/webhooks/group-update) and [`group.participants.update`](/v2/webhooks/group-participants-update) webhooks. The Get All Groups endpoint should be seen as the \"Self-Correction\" mechanism that runs periodically to catch any events that might have been missed due to network instability.\n3.  **Pagination & Metadata Filtering**: When processing the results, prioritize the `id` and `subject` fields first. Only dig into the full `participants` array for groups that your internal audit has flagged as \"High Priority\" or \"Compliance Vulnerable.\"\n\n---\n\n## 🎯 Conclusion: Mastering the Landscape of Shared State\n\nThe **Get All Groups** endpoint is your primary instrument for architectural discipline. It allows you to move beyond the management of individual threads and start managing the **Total Landscape of Your Presence**. By implementing robust reconciliation, decommissioning, and discovery workflows around this endpoint, you ensure that your WhatsApp infrastructure remains optimized, governed, and perfectly synchronized with your business's strategic objectives. You turn a crowded inbox into a highly structured, metadata-driven community engine.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "List of groups retrieved successfully",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "1234567890@g.us",
                    "name": "Project Team",
                    "participants": []
                  }
                ]
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/create": {
      "post": {
        "operationId": "_v2_groups_create_post",
        "summary": "Create group",
        "description": "Create a new WhatsApp group with specified name and participants.\n\n### Developer Tips\n- **Admin Status**: Your bot automatically becomes a Super Admin of the created group.\n- **Privacy Settings**: Users with strict privacy settings may not be added directly; use Invite Links as a fallback.\n\n\n# Semantic Initialization: The Genesis of Distributed Communities\n\nThe **Create Group** endpoint sits at the very heart of your conversational architecture. It is far more than a simple technical request to allocate a new chat identifier; it is a strategic operation that establishes a **programmatic shared context** between your business and a specific set of participants. By moving the group creation process from the manual efforts of an agent to the precision of an API, you ensure that every new project, every VIP customer onboarding, and every internal coordination team begins its lifecycle with the correct branding, the exact stakeholders, and a strictly defined set of permissions.\n\nIn an enterprise environment, \"Creating a Group\" is the act of **Provisioning a Managed Asset**. This guide explores the architectural nuances and strategic imperatives of building communities through initialization.\n\n---\n\n## 🏗️ Architectural Philosophy: Atomic State Allocation\n\nFrom a system design perspective, creating a group is an **Atomic Operation**. In a single transaction, your system defines both the **Identity** of the community and its **Initial Population**. This synchronicity is critical for maintaining consistency between your backend CRM and the reality of the WhatsApp network.\n\n### The Dynamics of the Global-JID (G-JID)\nWhen a group is born through this endpoint, the WhatsApp network generates a unique, immutable identifier ending in `@g.us`. This \"G-JID\" is the most important piece of metadata your system will ever handle for that community.\n*   **Persistence & Mapping**: Unlike user phone numbers, which can occasionally change or be recycled, the group ID is permanent. Your system must treat this ID as the **Primary Key** in your internal database. All future interactions—sending messages, updating settings, or auditing participants—must be anchored to this specific ID.\n*   **Zero-Latency Inclusion**: The participants you define in the creation call are added to the state immediately. There is no invitation process or \"acceptance window\" required when adding users via this endpoint. They are instantly merged into the shared context, allowing your system to follow up the creation call with a welcome message that is seen by all members the very second they are joined.\n\n---\n\n## 🎭 The Creator’s Mandate: Establishing Permanent Governance\n\nThe most critical strategic outcome of using the Wawp API for group creation is the automatic assignment of **Creator** status to your instances. In the WhatsApp governance hierarchy, the Creator role is unique and powerful.\n\n### Irrevocable Authority\nAs the creator of the group, your instance holds a level of authority that no other admin can challenge. A creator cannot be demoted, and they cannot be removed by other administrators. This provides a \"Steel-Clad Safeguard\" for your business communications. Even if a participant is accidentally promoted to admin and attempts to \"take over\" the group, your system retains absolute control. This allows you to build high-trust collaborative environments while maintaining the peace of mind that your business owns the channel, the data, and the membership list.\n\n---\n\n## 🚀 Strategic Participant Management: Trust and the Privacy Wall\n\nManaging who enters a group is as important as the messages sent within it. Because groups expose the phone numbers of all participants to one another, initialization is a \"High-Sensitivity\" operation that must be balanced with user privacy.\n\n### Navigating the Privacy Shield\nWhatsApp provides robust privacy settings for individual users. If a user has restricted group adds to \"My Contacts Only,\" or if they have blocked your business instance, a direct `add` during the creation process will return a success signal from the API, but the user will **not** actually appear in the group list. \nFor mission-critical communities (like a project team), your system should implement an **\"Invite-as-Fallback\"** strategy. After the group is created, verify the participant list. If a key stakeholder is missing due to privacy restrictions, your system should automatically send a 1:1 message to that user containing the [Group Invite Link](/v2/groups/invite-code). This ensures that participation is both easy and consensual.\n\n### The \"Social Proof\" Requirement\nTo maintain a high account health score, avoid adding large numbers of stranger numbers to a single group. Meta's heuristics look for \"forced interaction.\" We recommend that your system only creates groups with participants who have had at least one 1:1 interaction with your business number in the past. This \"pre-existing relationship\" signals to the WhatsApp network that the group is a legitimate continuation of a business conversation, not a spam vector.\n\n---\n\n## 🎨 Optimizing the Group \"Manifesto\": Subjects, Descriptions, and Icons\n\nThe metadata defined during creation forms the \"First Impression\" for your participants. Every element of the group's visual identity should be optimized for clarity and professional branding.\n\n### The \"Subject Line\" Economy\nWhile technically flexible, group names should be treated like subject lines in a professional email. Use **Serialization and Prefixes** (e.g., `[VIP-2024] - Wawp Onboarding`). This makes it possible for agents to search their inbox effectively and ensures that users know exactly why they have been added to a new chat.\n\n### The Description as a Command Center\nThe group description is the only part of the group's metadata that can hold a significant amount of text. Use it wisely. We recommend using the description field to host:\n*   Standard Operating Procedures (SOPs) for the group.\n*   Links to external customer portals or support documentation.\n*   A list of \"Bot Commands\" that participants can use to interact with your system.\n\n---\n\n## 🛠️ Enterprise Workflow patterns: Automated War Rooms\nThe true power of the Create Group endpoint is realized when it is integrated into your broader business logic.\n\n### Scenario: The Automated Escalation War Room\nWhen your monitoring system detects a \"Severity 1\" incident for a client, it doesn't just send an alert. It instantly calls the Create Group endpoint. It builds a \"War Room\" containing the client's CTO, your assigned account manager, and the lead technical specialist. The group is named `INCIDENT-999 | Critical Alert`. Within seconds, all necessary stakeholders are in a single room, sharing screenshots and logs in real-time, drastically reducing the \"Mean Time to Resolution\" (MTTR).\n\n### Scenario: The Onsite Event Coordination Engine\nFor a physical conference, your system creates a \"Breakout Group\" for each seminar session. As users scan a QR code at the door, they are added to the group. This allows the speaker to share slides instantly and allows attendees to ask questions via the chat, which your bot can then aggregate and present to the speaker at the end of the session.\n\n---\n\n## 🛡️ Operational Guardrails & Rate Management\n\nInitialization is a \"Heavy\" operation on the WhatsApp infrastructure. To ensure long-term reliability and stay within Meta's undocumented rate limits, follow these engineering principles:\n\n1.  **Staggered Creation**: Avoid \"Creation Bursts\" (e.g., 100 groups in 60 seconds). If your system needs to provision many groups for a campaign, use a background worker to stagger the requests. A rate of 5-10 group creations per hour per instance is considered highly safe for enterprise-grade accounts.\n2.  **Social History Priming**: Ensure your instance has an \"Active Profile.\" An account that does nothing but create groups is often flagged for review. Ensure your instance is also sending 1:1 messages and participating in existing threads to maintain a natural \"Account Signature.\"\n3.  **Local Metadata Buffering**: Once a group is created, store the ID, name, and participant list in a high-speed local cache (like Redis). This allows your frontend to display group information instantly without hitting the API for every page load, improving user experience and reducing API overhead.\n\n---\n\n## 🎯 Conclusion: The Foundation of Community\n\nBy mastering the **Create Group** endpoint, you are building the logical foundation of your conversational enterprise. You are moving beyond the era of \"One-Way Alerts\" and into the era of **Collaborative Customer Success**. When used strategically, this endpoint turns WhatsApp into a dynamic, programmable, and highly governed environment where every shared context is an opportunity for a deeper, more meaningful business relationship.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "name",
            "in": "query",
            "required": true,
            "description": "Name of the group",
            "schema": {
              "type": "string"
            },
            "example": "New Project"
          },
          {
            "name": "participants",
            "in": "query",
            "required": true,
            "description": "List of participant JIDs to add to the group",
            "schema": {
              "type": "string"
            },
            "example": "[{\"id\":\"1234567890@c.us\"}]"
          }
        ],
        "responses": {
          "201": {
            "description": "Group created successfully",
            "content": {
              "application/json": {
                "example": {
                  "id": "1234567890@g.us",
                  "name": "New Project"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request - Invalid Parameter Format",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_param",
                  "message": "Invalid format for one or more parameters.",
                  "details": {
                    "param": "text",
                    "value": "too_long",
                    "recommendation": "Refer to the documentation for the allowed format and length of this parameter."
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized - Invalid or Missing Access Token",
            "content": {
              "application/json": {
                "example": {
                  "code": "invalid_access_token",
                  "message": "Invalid or expired access token. Please check your credentials.",
                  "details": {
                    "recommendation": "Ensure you are sending a valid 'access_token' in the request. You can find your token in the dashboard."
                  }
                }
              }
            }
          },
          "500": {
            "description": "Internal Server Error - Unexpected Failure",
            "content": {
              "application/json": {
                "example": {
                  "code": "server_error",
                  "message": "An internal server error occurred. Please try again later.",
                  "details": {
                    "recommendation": "This is likely a temporary issue on our side. Please retry your request in a few seconds or contact support if it persists."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/join": {
      "get": {
        "operationId": "_v2_groups_join_get",
        "summary": "Join group / Get join info",
        "description": "Use GET to fetch information about a group before joining, or POST to join it. Accepts both direct invite codes and full WhatsApp group links.\n\n### Developer Tips\n- **Rate Limits**: Joining too many groups rapidly can flag your account.\n- **Approval**: Some groups require admin approval, which this endpoint does not bypass.\n\n\n# Dynamic Entry: The Strategic Orchestration of Accessible Communities\n\nIn the expansive world of WhatsApp ecosystem management, the **Join Group** endpoint is your primary tool for **Permissionless Scale and Community Self-Onboarding**. While the [Add Participants](/v2/groups/{id}/participants/add) endpoint allows a business to push users into a group, the Join API reverses this logic, allowing your automated instances (or your users' bots) to pull themselves into a conversation using a secure Invite Code. This endpoint is the architectural bridge between a public marketing link and a private, high-trust community space, enabling a seamless transition from discovery to interaction.\n\nFor enterprise architects, managing \"Entry Points\" is about **Scaling Accessibility without Sacrificing Governance**. This guide explores the strategic imperatives of invite-driven growth and the orchestration of dynamic community entry.\n\n---\n\n## 🏗️ Architectural Philosophy: The Bridge from Link to Membership\n\nFrom a technical perspective, the Join Group endpoint is a **State Resolution Engine**. It converts an ephemeral Invite Code into a permanent membership state.\n\n### Key Architectural Objectives:\n*   **The Power of the Invite Code**: The invite code (or the full `chat.whatsapp.com` URL) is a cryptographically secure token that represents a standing invitation to a specific Global-JID. By using this code, your instance can bypass the need for a direct administrator invitation, provided the code is still valid. This is essential for building \"Viral\" growth loops where communities expand through shared links rather than manual admin labor.\n*   **Permissionless Discovery (GET Info)**: A unique feature of this endpoint is the ability to use the `GET` method to **Probe the Group State** before joining. This allows your system to verify the group's name, its current member count, and its profile picture without committing to membership. This \"Pre-flight Verfication\" is critical for avoiding accidental entry into a non-compliant or irrelevant group.\n*   **Global Membership Propagation**: Once the `POST` call is executed, Meta's infrastructure instantly updates the group's membership list across all participant devices. Your instance's JID is now authorized to see the conversation history (from the moment of joining) and participate in active dialogue.\n\n---\n\n## 🚀 Strategic Use Cases: Marketing Funnels and Automated Scaling\n\nThe Join Group endpoint enables a \"Pull-Based\" community strategy that is highly effective for high-volume customer engagement.\n\n### 1. The \"Call-to-Action\" Marketing Funnel\nIn modern marketing, the \"WhatsApp Community\" is the new landing page. Your system can generate thousands of unique landing pages or emails featuring a \"Join our VIP Alert Group\" button. When the user clicks this button, your system can use the **Join Group** endpoint to ensure your official support bot or campaign instance is also present in that specific room to welcome the user. This creates a \"Managed Arrival\" experience where the user enters a room that already has a helpful assistant waiting for them.\n\n### 2. The \"Sub-Agent\" Distribution Model\nFor massive communities that exceed the 1,024-member limit of a single group, your system can use a \"Cellular Expansion\" model. When a group reaches capacity, the system creates a new group, generates an [Invite Code](/v2/groups/invite-code), and then uses the **Join Group** endpoint to move \"Squad Bots\" or specialized support instances into the new room. This allow your automation to scale horizontally across an unlimited number of groups, with each bot \"Joining\" its assigned cell programmatically.\n\n### 3. Cross-Instance Resilience and Recovery\nIf a primary WhatsApp account is lost or restricted, your system needs a way to \"Re-Colonize\" its existing communities with a backup account. By maintaining a database of your groups' Invite Codes, your system can programmatically instruct a new instance to **Join** all existing high-value groups. This \"Automated Recovery\" ensures that your business logic retains its presence in critical conversations even in the face of account-level interruptions.\n\n---\n\n## 🔐 Administrative Mandate: Authority and Permission Management\n\nJoining a group is a high-trust event. Your system must ensure that its entry into a room is both authorized and strategic.\n\n### Managing the \"Invite Code\" Lifecycle\nAn invite code is a permanent vulnerability if handled poorly. Anyone with the code can join the group. Your system should use the [Revoke Invite Code](/v2/groups/invite-code/revoke) endpoint periodically to disable legacy codes and generate new ones. The **Join Group** endpoint will always fail if the code has been revoked, providing a powerful gatekeeping mechanism for your automated communities.\n\n### Visibility and Legal Compliance\nWhen an instance joins a group, it becomes a \"Data Processor\" for that conversation. In regulated industries (like Healthcare or Finance), you must ensure that your system only joins groups where its presence is legally authorized. Use the `GET` probe to verify the group's identity against your internal \"Allowed Groups\" list before performing the `POST` join operation. This \"Sanity Check\" prevents accidental data exposure and ensures your platform remains compliant with privacy standards.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Contextual Arrival\n\n*   **The \"Welcome Greeting\" Pattern**: Upon joining a group, your instance should immediately send a \"Service Identification\" message (e.g., *\"Support Assistant #4 has joined the room. Type /help for assistance.\"*). This prevents your system from appearing as a \"Ghost Participant\" and establishes its role from the first second.\n*   **Monitoring Member Count**: Use the `GET` probe to track the population of the group you are about to join. Joining a nearly-empty group requires a different introductory tone than joining a 500-member community hub.\n*   **Coordinate with CRM Logic**: Your internal database should update the group's status to `active` only after the API returns the confirmed Global-JID (`@g.us`). This JID is the primary key for all future interactions and must be carefully persisted.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Probe Before You Commit**: Always use the `GET` method first to verify the code is valid and the group belongs to your organization. This avoids \"Joining Errors\" and prevents your system from being added to malicious or spam groups.\n2.  **Rate Throttling for Mass Join Operations**: if your system is performing a recovery sequence (joining 100+ groups), stagger the joined calls. Joining too many groups in a single minute can trigger Meta's security heuristics, which might flag the account as a \"Bot Net.\" A rate of 2-5 joins per minute is recommended for large-scale operations.\n3.  **Webhook Integration**: Listen for the [`group.join`](/v2/webhooks/group-join) event. This confirms that the network has accepted your instance as a member. When this event arrives, you can trigger your \"Onboarding Workflow\" for that specific group.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Accessible Community\n\nThe **Join Group** endpoint is the \"Gateway\" of your community architecture. It is your most powerful tool for building scalable, accessible, and resilient conversational networks. By treating the act of joining as a strategic, programmable event, you create a professional environment that is easy for your systems to enter and easy for your users to discover. You move beyond \"Push-Only\" messaging and into the world of **Dynamic Conversational Ecosystems**, where your authority is distributed through secure codes and your presence is always where it's needed most.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "code",
            "in": "query",
            "required": true,
            "description": "Group invite code or full WhatsApp invite URL",
            "schema": {
              "type": "string"
            },
            "example": "FqkbDWXAIzvBwF04luAefz"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "example": {
                  "id": "1234567890@g.us",
                  "subject": "Community Group",
                  "description": "Group for testing"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "post": {
        "operationId": "_v2_groups_join_post",
        "summary": "Join group / Get join info",
        "description": "Use GET to fetch information about a group before joining, or POST to join it. Accepts both direct invite codes and full WhatsApp group links.\n\n### Developer Tips\n- **Rate Limits**: Joining too many groups rapidly can flag your account.\n- **Approval**: Some groups require admin approval, which this endpoint does not bypass.\n\n\n# Dynamic Entry: The Strategic Orchestration of Accessible Communities\n\nIn the expansive world of WhatsApp ecosystem management, the **Join Group** endpoint is your primary tool for **Permissionless Scale and Community Self-Onboarding**. While the [Add Participants](/v2/groups/{id}/participants/add) endpoint allows a business to push users into a group, the Join API reverses this logic, allowing your automated instances (or your users' bots) to pull themselves into a conversation using a secure Invite Code. This endpoint is the architectural bridge between a public marketing link and a private, high-trust community space, enabling a seamless transition from discovery to interaction.\n\nFor enterprise architects, managing \"Entry Points\" is about **Scaling Accessibility without Sacrificing Governance**. This guide explores the strategic imperatives of invite-driven growth and the orchestration of dynamic community entry.\n\n---\n\n## 🏗️ Architectural Philosophy: The Bridge from Link to Membership\n\nFrom a technical perspective, the Join Group endpoint is a **State Resolution Engine**. It converts an ephemeral Invite Code into a permanent membership state.\n\n### Key Architectural Objectives:\n*   **The Power of the Invite Code**: The invite code (or the full `chat.whatsapp.com` URL) is a cryptographically secure token that represents a standing invitation to a specific Global-JID. By using this code, your instance can bypass the need for a direct administrator invitation, provided the code is still valid. This is essential for building \"Viral\" growth loops where communities expand through shared links rather than manual admin labor.\n*   **Permissionless Discovery (GET Info)**: A unique feature of this endpoint is the ability to use the `GET` method to **Probe the Group State** before joining. This allows your system to verify the group's name, its current member count, and its profile picture without committing to membership. This \"Pre-flight Verfication\" is critical for avoiding accidental entry into a non-compliant or irrelevant group.\n*   **Global Membership Propagation**: Once the `POST` call is executed, Meta's infrastructure instantly updates the group's membership list across all participant devices. Your instance's JID is now authorized to see the conversation history (from the moment of joining) and participate in active dialogue.\n\n---\n\n## 🚀 Strategic Use Cases: Marketing Funnels and Automated Scaling\n\nThe Join Group endpoint enables a \"Pull-Based\" community strategy that is highly effective for high-volume customer engagement.\n\n### 1. The \"Call-to-Action\" Marketing Funnel\nIn modern marketing, the \"WhatsApp Community\" is the new landing page. Your system can generate thousands of unique landing pages or emails featuring a \"Join our VIP Alert Group\" button. When the user clicks this button, your system can use the **Join Group** endpoint to ensure your official support bot or campaign instance is also present in that specific room to welcome the user. This creates a \"Managed Arrival\" experience where the user enters a room that already has a helpful assistant waiting for them.\n\n### 2. The \"Sub-Agent\" Distribution Model\nFor massive communities that exceed the 1,024-member limit of a single group, your system can use a \"Cellular Expansion\" model. When a group reaches capacity, the system creates a new group, generates an [Invite Code](/v2/groups/invite-code), and then uses the **Join Group** endpoint to move \"Squad Bots\" or specialized support instances into the new room. This allow your automation to scale horizontally across an unlimited number of groups, with each bot \"Joining\" its assigned cell programmatically.\n\n### 3. Cross-Instance Resilience and Recovery\nIf a primary WhatsApp account is lost or restricted, your system needs a way to \"Re-Colonize\" its existing communities with a backup account. By maintaining a database of your groups' Invite Codes, your system can programmatically instruct a new instance to **Join** all existing high-value groups. This \"Automated Recovery\" ensures that your business logic retains its presence in critical conversations even in the face of account-level interruptions.\n\n---\n\n## 🔐 Administrative Mandate: Authority and Permission Management\n\nJoining a group is a high-trust event. Your system must ensure that its entry into a room is both authorized and strategic.\n\n### Managing the \"Invite Code\" Lifecycle\nAn invite code is a permanent vulnerability if handled poorly. Anyone with the code can join the group. Your system should use the [Revoke Invite Code](/v2/groups/invite-code/revoke) endpoint periodically to disable legacy codes and generate new ones. The **Join Group** endpoint will always fail if the code has been revoked, providing a powerful gatekeeping mechanism for your automated communities.\n\n### Visibility and Legal Compliance\nWhen an instance joins a group, it becomes a \"Data Processor\" for that conversation. In regulated industries (like Healthcare or Finance), you must ensure that your system only joins groups where its presence is legally authorized. Use the `GET` probe to verify the group's identity against your internal \"Allowed Groups\" list before performing the `POST` join operation. This \"Sanity Check\" prevents accidental data exposure and ensures your platform remains compliant with privacy standards.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Contextual Arrival\n\n*   **The \"Welcome Greeting\" Pattern**: Upon joining a group, your instance should immediately send a \"Service Identification\" message (e.g., *\"Support Assistant #4 has joined the room. Type /help for assistance.\"*). This prevents your system from appearing as a \"Ghost Participant\" and establishes its role from the first second.\n*   **Monitoring Member Count**: Use the `GET` probe to track the population of the group you are about to join. Joining a nearly-empty group requires a different introductory tone than joining a 500-member community hub.\n*   **Coordinate with CRM Logic**: Your internal database should update the group's status to `active` only after the API returns the confirmed Global-JID (`@g.us`). This JID is the primary key for all future interactions and must be carefully persisted.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Probe Before You Commit**: Always use the `GET` method first to verify the code is valid and the group belongs to your organization. This avoids \"Joining Errors\" and prevents your system from being added to malicious or spam groups.\n2.  **Rate Throttling for Mass Join Operations**: if your system is performing a recovery sequence (joining 100+ groups), stagger the joined calls. Joining too many groups in a single minute can trigger Meta's security heuristics, which might flag the account as a \"Bot Net.\" A rate of 2-5 joins per minute is recommended for large-scale operations.\n3.  **Webhook Integration**: Listen for the [`group.join`](/v2/webhooks/group-join) event. This confirms that the network has accepted your instance as a member. When this event arrives, you can trigger your \"Onboarding Workflow\" for that specific group.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Accessible Community\n\nThe **Join Group** endpoint is the \"Gateway\" of your community architecture. It is your most powerful tool for building scalable, accessible, and resilient conversational networks. By treating the act of joining as a strategic, programmable event, you create a professional environment that is easy for your systems to enter and easy for your users to discover. You move beyond \"Push-Only\" messaging and into the world of **Dynamic Conversational Ecosystems**, where your authority is distributed through secure codes and your presence is always where it's needed most.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "code",
            "in": "query",
            "required": true,
            "description": "Group invite code or full WhatsApp invite URL",
            "schema": {
              "type": "string"
            },
            "example": "FqkbDWXAIzvBwF04luAefz"
          }
        ],
        "responses": {
          "200": {
            "description": "Successful operation",
            "content": {
              "application/json": {
                "example": {
                  "id": "1234567890@g.us",
                  "subject": "Community Group",
                  "description": "Group for testing"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/count": {
      "get": {
        "operationId": "_v2_groups_count_get",
        "summary": "Get the number of groups",
        "description": "Get the total number of groups the instance is a member of.\n\n### Developer Tips\n- **Caching**: Cache this count locally to avoid frequent API calls.\n- **Monitoring**: Track group count trends to identify suspicious bulk-joining activity.\n\n\n# Quantifying the Ecosystem: The Strategic Power of Demographic Density\n\nIn the world of massive conversational orchestration, your footprint is your reach. The **Get Groups Count** endpoint is your primary tool for **Strategic Portfolio Analysis and Capacity Planning**. It provides a high-level, aggregate view of your instance's presence across the WhatsApp network, returning the total number of communities where your business currently holds a seat. While individual [Group Retrieval](/v2/groups/{id}) provides depth, the Count API provides the \"Aerial View\" required to understand your ecological balance, your resource saturation, and your overall influence within the distributed network.\n\nFor enterprise architects, the group count is the **Primary Barometer of Scalability**. This guide explores the strategic imperatives of numerical auditing and the orchestration of managed growth.\n\n---\n\n## 🏗️ Architectural Philosophy: Aggregate State Retrieval Without Exposure\n\nFrom a technical perspective, the Groups Count endpoint is a **Low-Latency Metadata Aggregator**.\n\n### Key Architectural Objectives:\n*   **High-Speed Portfolio Verification**: Querying the full details of 500 groups via the [List API](/v2/groups) is a data-intensive operation. The Count endpoint provides a \"Fast-Path\" alternative during initialization or health checks. By retrieving a single integer, your system can quickly verify its \"Global Footprint\" without the overhead of parsing extensive JSON objects for every membership.\n*   **Decoupling Presence from Content**: This endpoint operates at the **Mebmership Layer**. It doesn't care about message volume or metadata changes; it simply reconciles the instance's Global-JID (`@g.us`) mapping. This makes it an ideal trigger for high-level dashboarding and operational monitoring.\n*   **Zero-Impact Auditing**: Because it doesn't fetch participant lists or media, the Count API is one of the most resource-efficient endpoints in the Wawp stack. You can call it frequently as part of a \"Warden\" process to detect sudden, unauthorized [Group Leavings](/v2/groups/{id}/leave) or un-tracked [Join Events](/v2/groups/join).\n\n---\n\n## 🚀 Strategic Use Case: Capacity Planning and Viral Load Balancing\n\nThe group count is the foundation of any \"Auto-Scaling\" conversational architecture.\n\n### 1. The \"Horizontal Expansion\" Trigger\nEvery WhatsApp account has practical limits on the number of active conversations it can effectively manage before webhook delivery or storage overhead becomes a concern. Your orchestration engine should monitor the **Get Groups Count** value. When an instance reaches a predefined \"Saturation Threshold\" (e.g., 500 active groups), the system should automatically initialize a **New Instance** to handle future group creations. This \"Cell-Based Growth\" ensures that no single account becomes a bottleneck for your entire organization.\n\n### 2. Viral Campaign Monitoring and Milestone Tracking\nIn marketing scenarios where you are using [Invite Codes](/v2/groups-invite-code) to drive organic growth, the Group Count is your primary KPI. It measures the number of distinct communities that have opted into your branded ecosystem. Rapid spikes in the group count can trigger automated \"Celebration Workflows\" or indicate a successful viral loop, while a plateauing count indicates that your acquisition funnels require strategic adjustment.\n\n### 3. \"Community Bloat\" Detection and Cleanup\nManaging an instance that is a member of 2,000 inactive groups is inefficient and increases the risk of metadata collisions. Your system can use the **Get Groups Count** endpoint as a starting point for its \"Pruning Cycle.\" If the count is significantly higher than your internal CRM's record of \"Active Projects,\" it triggers a deep audit to find and [Leave](/v2/groups/{id}/leave) zombie groups, keeping your instance's presence clean and professional.\n\n---\n\n## 🔐 Administrative Mandate: Visibility and Global Auditing\n\nIn a professional environment, visibility is the first step toward governance.\n\n### Reconciliation and Compliance\nFor businesses in regulated sectors, you must be able to report on your exact footprint at any time. The **Get Groups Count** endpoint provides the raw data for your **Global Compliance Report**. By comparing the API's count with your internal database's count, you can detect \"Shadow Communities\"—groups created by human agents from their phones that have not been registered with your central CRM. Reconciliation ensures that every interaction under your business's name is tracked and governed.\n\n### Identifying \"Instance Saturation\"\nIf your instance is near the service limits (WhatsApp occasionally enforces limits on the number of groups a single account can belong to), this endpoint is your early warning system. By proactively monitoring the count, your platform can gracefully stop new group creations or prompt an admin to decommission legacy projects before a hard network limit is reached, maintaining perfect service continuity.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Performance\n\n*   **Dashboaring for Human Oversight**: Display the group count prominently in your agent's management UI. It provides instant context on the \"Scale of Management\" currently required.\n*   **Event-Driven Verification**: Don't rely solely on counting webhooks. Every 24 hours, perform a \"Hard Sync\" by calling the **Get Groups Count** endpoint to verify your state. This corrects any minor discrepancies caused by missed webhooks or edge-case network partitions.\n*   **Map Count to Resource Allocation**: If your backend processes webhooks differently for groups vs. 1:1 chats, use the count to scale your worker pool. A higher group count generally corresponds to a higher \"Bursty\" message volume during peak hours.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Fast Refresh for UI/UX**: Use this endpoint to provide instant feedback in your application's sidebar. It is much faster than loading a full list and gives the user an immediate sense of the account's scale.\n2.  **Cross-Reference with CRM State**: Your internal database should be the \"Source of Truth\" for what groups *should* exist. The API provides the \"Ground Truth\" of what *actually* exists. A mismatch between these two numbers is an indicator of an operational error or an unauthorized manual change.\n3.  **Synchronization after Batch Operations**: After performing a bulk creation or a bulk deletion, wait for the network to settle and then call the **Get Groups Count** endpoint. This confirms that all operations have been successfully finalized by Meta's infrastructure.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Quantified Community\n\nThe **Get Groups Count** endpoint is the \"Pulse Monitor\" of your community architecture. It is your most direct tool for measuring scale, predicting resource needs, and enforcing compliance across the entire network. By treating the numerical state of your communities as a primary strategic motivator, you build a conversational ecosystem that is resilient to bloat and perfectly optimized for growth. You move beyond \"Managing Individual Chats\" and into the world of **Portfolio Orchestration**, where every group is a number in a well-oiled machine of customer engagement and operational excellence.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Count retrieved",
            "content": {
              "application/json": {
                "example": {
                  "count": 15
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}": {
      "get": {
        "operationId": "_v2_groups_id_get",
        "summary": "Get the group",
        "description": "Retrieve detailed information about a specific group.\n\n### Developer Tips\n- **Metadata**: This returns basic info (Subject, Owner, Creation Time).\n- **No Participants**: This endpoint does NOT return the full participant list. Use '/groups/{id}/participants' for that.\n\n\n# Real-Time Discovery: Mastering the State of Your Communities\n\nIn the dynamic environment of enterprise WhatsApp management, information is your most valuable asset. The **Get Group** endpoint is far more than a simple data retrieval tool; it is your primary mechanism for **Real-Time State Discovery and Verification**. In an ecosystem where a single group can be interacted with by dozens of participants, multiple automation bots, and human agents simultaneously, your internal records can quickly become de-synchronized from the ground truth of the WhatsApp network. This endpoint serves as your \"Source of Truth,\" providing the instantaneous metadata required to drive high-fidelity decision logic.\n\nSuccessful group orchestration requires a \"Verification-First\" mindset. This guide explores how to leverage the Get Group endpoint to build resilient, permission-aware, and metadata-driven workflows.\n\n---\n\n## 🏗️ Architectural Philosophy: The Validation Loop\n\nFrom a system architecture perspective, fetching group information is a **Pre-Conditioning Act**. Before your system attempts a high-sensitivity operation—such as adding a controversial participant, promoting a new admin, or dismantling a group—it must first validate the current configuration of the target community.\n\n### Key Architectural Benefits:\n*   **Permissions & Authority Auditing**: One of the most critical fields returned by this endpoint is the participation list, which includes administrative status indicators. Your system can use this to verify if the Wawp instance still possesses **Admin Rights**. Since admin status can be revoked manually by a human in the WhatsApp app, checking this *before* an automated action prevents downstream failures and ensures your error handling is proactive rather than reactive.\n*   **Metadata Synchronization**: Users have the power to change group subjects and icons at any time (depending on settings). The Get Group endpoint allows your system to \"Re-Synchronize\" its local dashboard with the latest visual identity of the group. This ensures that when an agent looks at your internal CRM, they see the same names and identifiers that the customer sees on their mobile device, minimizing cognitive dissonance and operational errors.\n*   **Structural Health Checks**: This endpoint allows you to verify if a group is still \"Active\" on the network. If a group has been deleted by another admin or if your instance has been \"Kicked,\" the API will return a 404 or 403 error. Incorporating this check into your \"Pre-Flight\" logic ensures that your automation queue doesn't attempt to process interactions for \"Ghost Communities.\"\n\n---\n\n## 🚀 Strategic Operational Patterns: Using Metadata to Drive Logic\n\nThe true power of the Get Group endpoint lies in using the returned metadata to feed your secondary automation engines.\n\n### 1. The Metadata-Driven Routing Engine\nImagine a scenario where your business manages 500 active groups. A user sends a message in a group that your system doesn't immediately recognize as a \"Priority\" channel. By calling the Get Group endpoint, you can pull the current **Group Description**. If your system detects a specific Project ID or Case Code embedded in that description, it can instantly route the incoming message to a specialized support tier. This turns a generic group interaction into a high-context, routed ticket without requiring the user to manually enter an ID.\n\n### 2. Identity Resolution & Naming Volatility\nGroup subjects are volatile; the Global-JID (`@g.us`) is immutable. Your system should never store the name of a group as its primary identifier. Instead, use the Get Group endpoint to maintain a **Mapping Table**. If your system notices that the subject returned by the API is different from the one in your database, it can automatically update the local record and even trigger a \"Name Change Detected\" alert to the project manager. This ensures the integrity of your reporting and archival systems even as the \"Human\" side of the group evolves.\n\n### 3. Verification of Participant Density\nFor compliance-heavy industries (like Finance or Healthcare), it is often a requirement that a group contains exactly one patient and one verified caregiver. This endpoint allows your system to perform a \"census\" of the group. If an unauthorized third party joins via an invite link, your system detects the membership change, verifies the new JID against its whitelist, and can automatically take action (such as an alert or a removal) if the group's \"Security Profile\" has been breached.\n\n---\n\n## 🎭 Administrative Auditing: Tracking the \"Creator\"\n\nAs detailed in the [Groups Overview](/v2/groups-overview), the group creator holds unique, irrevocable power. The Get Group endpoint provides the JID of the owner/creator. In environments where groups might be created by both your API and manually by field agents, tracking the \"Lineage\" of a group is essential for governance.\n*   **Auditing \"Shadow Groups\"**: By periodically scanning for all groups your instance is a member of and checking their source, you can identify \"Shadow Communities\" created by agents that haven't been linked to your official CRM. This allows for top-down governance of your brand's WhatsApp presence.\n\n---\n\n## 🛡️ Reliability & Performance: The Caching Strategy\n\nHitting the WhatsApp network for metadata is a \"Round-trip\" operation that introduces latency. To maintain a high-performance integration, we recommend a **\"Reactive Refresh\" Strategy**.\n\n1.  **Bootstrapping**: Call Get Group when a group is first identified or created to populate your local database.\n2.  **Webhook Synergy**: Instead of polling the endpoint, listen for [`group.update`](/v2/webhooks/group-update) webhooks. Only call the Get Group endpoint when you receive a signal that something has changed.\n3.  **The \"Stale-State\" Buffer**: For non-critical displays (like a list of groups in a footer), use cached data that is 5-10 minutes old. reserve the \"Live\" API call for high-stakes actions like participant management or settings changes.\n\n---\n\n## 🎯 Conclusion: The Intelligence Foundation\n\nThe **Get Group** endpoint is the bridge between the fluid, human-centric reality of WhatsApp and the structured, data-driven needs of your business system. By treating it as a **Validation and Intelligence Layer**, you ensure that your automation is built on a foundation of truth. You move beyond \"Blind Messaging\" and into the era of **Governance-Aware Orchestration**, where every action your system takes is informed by the most current reality of the conversational environment.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group (@g.us)",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Group info retrieved",
            "content": {
              "application/json": {
                "example": {
                  "id": "1234567890@g.us",
                  "name": "Project Alpha",
                  "description": "Main coordination group"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/leave": {
      "post": {
        "operationId": "_v2_groups_id_leave_post",
        "summary": "Leave the group",
        "description": "Leave a specific group.\n\n### Developer Tips\n- **Clean Exit**: You will be removed from the participant list, but the group persists.\n- **History**: You lose access to future messages but often keep local history.\n\n\n# Graceful Withdrawal: The Strategic Lifecycle of Voluntary Presence\n\nIn the dynamic architecture of professional WhatsApp communities, knowing when to arrive is important, but knowing when to depart is critical for operational focus. The **Leave Group** endpoint is your primary tool for **Strategic Offboarding and Resource Reallocation**. Unlike [Deleting a Group](/v2/groups/delete)—which dismantle the shared state for everyone—\"Leaving\" is a graceful resignation of your instance's own participation. It allows the community to persist and continue its internal dialogues while freeing your instance from the \"Noise\" and data overhead of a conversation that has fulfilled its specific business purpose.\n\nFor enterprise architects, managing the \"Exit Phase\" of a bot's participation is a key component of **Inbox Hygiene**. This guide explores the architectural nuances of voluntary resignation and the enforcement of clean conversational lifecycles.\n\n---\n\n## 🏗️ Architectural Philosophy: The Resignation of Shared State\n\nFrom a technical perspective, leaving a group is a **Self-Revocation of Access**. You are severing the link between your instance's JID and the group's Global-JID.\n\n### Key Architectural Objectives:\n*   **Decoupling Without Destruction**: When your instance leaves a group, the group's identity (`@g.us`) remains active for all other participants. The message history, images, and other members are preserved. This is essential for scenarios where a bot provides initial setup (the \"Spark\") and then withdraws to allow human stakeholders to continue the project independently.\n*   **The Power of Autonomy**: Unlike restricted metadata changes, \"Leaving\" is a fundamental right. Any instance can leave any group at any time. There is no \"Lock\" that another admin can put on your instance to prevent you from departing. This ensures that your automation logic always retains absolute control over its own focus and resource consumption.\n*   **Structural Notification**: Every time your instance leaves, a system notification is generated in the chat (e.g., *\"Business Name left\"*). This is a public signal of your system's withdrawal, providing a transparent \"Closing Bracket\" for your automated involvement.\n\n---\n\n## 🚀 Strategic Use Cases: Automated Offboarding and Task Completion\n\nLeaving a group should be the final state in a well-defined state machine.\n\n### 1. The \"Setup and Withdraw\" Implementation Pattern\nIn a technical support or sales environment, your bot's role might be limited to the **Initialization Phase**. The bot creates the group, adds the customer, adds the assigned human expert, and populates the [Description](/v2/groups/{id}/description/set) with relevant case links. Once the human expert sends their first \"Welcome\" message, its work is done. By calling the **Leave Group** endpoint, the bot removes itself from the conversation, ensuring that future customer replies only alert the human agent, not the automation engine.\n\n### 2. The \"Resolution-Driven\" Quiet Exit\nFor a project-based community, the completion of a milestone (e.g., *\"Final Invoice Paid\"*) triggers the offboarding logic. While you might want the customer to keep the group for their own records, your business instance no longer needs to be a member. Leaving the group removes it from your instance's \"Active\" list, which lowers the overhead on your API webhooks and reduces the clutter in your agent's dashboard.\n\n### 3. Subscription Expiry for Support Access\nIf your business provides \"Premium WhatsApp Support\" as part of a subscription, the **Leave Group** endpoint is your primary mechanism for **Access Enforcement**. When a client's subscription expires, your system can automatically trigger a \"Global Resignation\" across all groups associated with that client. This maintains the group's history for the user while formally ending the business's active participation in the service level.\n\n---\n\n## 🔐 Administrative Mandate: Authority and Role Transitions\n\nLeaving a group has specific implications for your administrative authority.\n\n### The \"Transfer of Power\" Requirement\nIf your instance is the **Only Admin** in a group, WhatsApp's network logic will automatically promote another member to admin status upon your departure. This \"Succession Logic\" ensures that the group is never left in an un-governed state. However, to maintain professional control, your system should proactively [Promote](/v2/groups/{id}/admin/promote) a specific trusted human stakeholder before the instance leaves. This ensures that the \"Keys to the Room\" are handed over to the right person, rather than being assigned randomly by the network.\n\n### Preventing \"Zombie Presence\"\nLarge-scale accounts often suffer from \"Community Bloat\"—being a member of thousands of groups that are no longer active. This endpoint is the \"Cleanup Engine\" for this problem. Your system should periodically audit all groups using [Get All Groups](/v2/groups/list). Any group that hasn't seen activity for 180 days should be marked for \"Clean Resignation,\" keeping your instance's footprint lean and optimized.\n\n---\n\n## 🛡️ Operational Best Practices: Professionalism and Graceful Transitions\n\n*   **The \"Final Goodbye\" Pattern**: Never leave a group \"Cold.\" This can feel like a service interruption to the customer. We recommend sending a polite final message (e.g., *\"This case is now handled by our human team. Our automated assistant is leaving to keep the room focused. Thank you!\"*) before calling the endpoint.\n*   **Metadata Finalization**: Before leaving, ensure that the group's [Description](/v2/groups/{id}/description/set) contains any long-term resources the customer might need. Since you won't be able to update it once you've left, this is your last chance to \"Set the Context\" for the group's future.\n*   **Coordinate with CRM State**: Your internal database should mark the relationship for that group as \"Inactive - Withdrawn\" only after the API confirms a successful exit. This prevents \"Orphaned Logic\" where your system thinks it can still send messages to a group it no longer has access to.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Check Membership State**: You cannot leave a group you are not a member of. Attempting to do so will return a 404 or 400 error. Always perform a pre-flight check to ensure your instance is still present in the channel.\n2.  **Handle Re-Join Logic**: Professional systems should always store the group's [Invite Code](/v2/groups/invite-code) before leaving. If a customer manually adds your instance back into the group later, or if your system needs to re-enter for a specific task, having that code or the persistent JID allows for a smooth re-integration.\n3.  **Webhook Synchronization**: Listen for the [`group.leave`](/v2/webhooks/group-leave) event. This is the network's confirmation that your instance has successfully withdrawn. When this event arrives, you can safely purge the group's temporary data from your high-speed caches (like Redis).\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Strategic Exit\n\nThe **Leave Group** endpoint is the \"Closing Bracket\" of your community architecture. It allows you to build sophisticated, multi-phase conversational lifecycles that respect both the customer's need for persistent history and your system's need for operational focus. By treating the withdrawal of your presence as a deliberate, strategic act, you ensure that your WhatsApp infrastructure remains optimized and professional. You turn your business instance into a precise instrument that enters the room when it's needed and departs with grace when its work is done, maintaining a clean, high-fidelity environment for every stakeholder involved.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Left group successfully",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/picture": {
      "get": {
        "operationId": "_v2_groups_id_picture_get",
        "summary": "Get group picture",
        "description": "Retrieve the current profile picture of the group.\n\n### Developer Tips\n- **Caching**: Profile pictures are cached aggressively by WhatsApp.\n- **URL**: Returns a temporary direct URL to the image file.\n\n\n# Visual Discovery: The Strategic Retrieval of Branded Identity\n\nIn the fast-paced world of mobile-first communication, recognition is the currency of trust. The **Get Group Picture** endpoint is your primary tool for **Strategic Visual Discovery and Brand Asset Verification**. It allows your automated systems to programmatically retrieve the current public-facing CDN URL of a specific group's profile image. While the group's subject provides the \"What,\" the picture providing the \"Who\"—the immediate visual anchor that tells a user they are in the right place. By retrieving this asset, your platform can enrich your CRM dashboards, synchronize your internal records, and verify that your communities are projecting the correct, professional image to the world.\n\nFor enterprise architects, the profile picture is the **Visual Signal** of the community's health. This guide explores the strategic imperatives of asset retrieval and the orchestration of visual identity.\n\n---\n\n## 🏗️ Architectural Philosophy: Mapping the CDN Entry Point\n\nFrom a technical perspective, the Get Group Picture endpoint is a **State Proxy for Meta's Content Delivery Network**.\n\n### Key Architectural Objectives:\n*   **Decoupled Asset Management**: The API returns a direct URL to Meta's high-speed image servers. This allows your frontend applications to display the group's icon without forcing your backend to proxy large binary data. This \"URL-First\" approach ensures that your dashboards remain fast and performant, even when managing thousands of distinct communities.\n*   **The Anchor of Real-Time Recognition**: Users navigate their WhatsApp chat list primarily by icon. By retrieving this same icon for your internal agent dashboard, you create a \"Visual Bridge\" between the customer's mobile experience and the agent's CRM experience. This symmetry reduces mental load and prevents mistakes in high-volume support environments.\n*   **Visibility Without Administrative Rights**: Any member of a group can retrieve its profile picture. This allows your monitoring instances to audit the visual state of external groups where your organization is a regular participant, providing a powerful tool for competitive intelligence or vendor management.\n\n---\n\n## 🚀 Strategic Use Case: CRM Enrichment and Monitoring Visual Compliance\n\nVisual data is a critical component of professional relationship management.\n\n### 1. The \"Branded Dashboard\" Enrichment\nA CRM list that only shows phone numbers or group subjects is anemic. By calling the **Get Group Picture** endpoint, your system can populate your internal management UI with the actual group icons. This turns a dry table of data into a rich, intuitive \"Command Center\" where agents can instantly locate the right group purely by its familiar branding. This visual speed is essential for teams handling overlapping project cohorts.\n\n### 2. Automated Brand Compliance Auditing\nIn large-scale franchise or partner operations, you may mandate that all official support groups use a specific, high-resolution brand logo. Your \"Global Warden\" logic can use this endpoint to periodically fetch the icon for every group. By running these images through a simple \"Perceptual Hashing\" algorithm, the system can detect if an unauthorized human admin has changed the group picture to a non-compliant image. The system can then automatically [Reset it](/v2/groups/{id}/picture/set) or alert a brand manager.\n\n### 3. \"Probe-and-Qualify\" Workflows\nWhen your system encounters a new [Invite Link](/v2/groups/join), it should use the `GET` probe (often integrated into the Join Info workflow) to retrieve the group's picture. A group named \"Official Billing\" that has a generic placeholder icon or an unprofessional image is a red flag for a phishing or social engineering attack. By exposing this visual data to your safety logic, you build a \"Visual Firewall\" that protects your agents from entering deceptive environments.\n\n---\n\n## 🔐 Administrative Mandate: Visibility and the Monitoring of Visual Truth\n\nA group without a picture is an incomplete environment. A group with the *wrong* picture is a liability.\n\n### Integrity of the Public Face\nThe group icon is often the first thing a user sees when they receive a [Join Link](/v2/groups/join). If your API retrieves a placeholder or an outdated image, it informs your system that a [Set Picture](/v2/groups/{id}/picture/set) operation is required. This \"Proactive Cleanup\" ensure that your customer's first impression of your organization's digital workspace is always premium and professional.\n\n### Mapping the \"Pulse\" of the Group\nFrequent changes to a group's picture can indicate a highly active—or highly chaotic—community environment. By monitoring the URL returned by this endpoint, your system can detect changes even if the [`group.update`](/v2/webhooks/group-update) webhook is delayed. If the URL changes ten times in a day, your system can flag the group for a human moderator to check for a \"Branding War\" between participants.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency, Cache Management, and Placeholders\n\n*   **The \"Placeholder\" Strategy**: If the API returns a 404 or a null URL (indicating no picture set), your frontend should gracefully fall back to a high-quality, branded placeholder icon. Never show a broken image link or a generic browser error icon; it undermines your system's perceived quality.\n*   **CDN Cache Awareness**: Meta's CDN URLs are typically long-lived but can expire or change if the image is updated. Do not cache these URLs permanently in your own database. Instead, store them with a \"Time-to-Live\" (TTL) of 24 hours or re-fetch them whenever an agent opens the specific group's view.\n*   **Differentiate by Size**: Many implementations of the WhatsApp protocol support different image dimensions. The Wawp API returns the most versatile version for web display. Ensure your UI can handle both square and circular cropping to match the native WhatsApp aesthetics.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Map Logic to Asset Existence**: Your system should treat a \"Missing Picture\" as a \"Metadata Debt\" that needs to be paid. Use the result of this GET call to trigger an automated [Set Picture](/v2/groups/{id}/picture/set) call from your organization's central asset library.\n2.  **Handle Network Timeouts**: Retrieving a picture URL is generally fast, but the underlying network request to Meta's infrastructure can occasionally hang. Implement a sensible timeout (3-5 seconds) and use a local \"Generic Group\" icon if the API doesn't respond in time.\n3.  **Cross-Reference with Group Subject**: A mismatch between a group's name (e.g., `Red Team`) and its icon (e.g., a Blue Logo) can be detected by sophisticated vision-plus-text logic. This provides a deep layer of automated \"Identity Auditing\" for massive portfolios.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Visualized Community\n\nThe **Get Group Picture** endpoint is the \"Lens\" of your community architecture. It is your most powerful tool for ensuring visual continuity, enforcing brand compliance, and enriching the human experience of managing a distributed network. By treating the group icon as a critical piece of operational intelligence to be verified and displayed, you build a conversational ecosystem that is intuitive, professional, and always aligned with your organization's visual standards. You move beyond \"Simple Text Chats\" and into the world of **Rich Asset Orchestration**, where every group has a face and every interaction is anchored in a verified, branded identity.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Picture URL retrieved",
            "content": {
              "application/json": {
                "example": {
                  "url": "https://pps.whatsapp.net/..."
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "_v2_groups_id_picture_put",
        "summary": "Set group picture",
        "description": "Update the group profile picture.\n\n### Developer Tips\n- **Format**: Use SQUARE JPEG or PNG images for best results.\n- **Size**: High-res images may be compressed. Aim for 640x640px.\n\n\n# Visual Branding: The Strategic Psychology of Group Identity\n\nIn the crowded mobile interface, where users often manage dozens of personal and professional chats simultaneously, the **Set Group Picture** endpoint is your primary tool for **Instant Recognition and Brand Affinity**. While the group subject tells the user *what* the group is, its profile picture (also known as its avatar or icon) determines how the user *feels* about the space and how quickly they can locate it in their chat history. By programmatically managing this visual asset, you turn every group into a branded ecosystem that is both professional and easy to navigate.\n\nFor enterprise architects, the group picture is the **Visual Anchor** of the community. This guide explores the strategic imperatives of visual identity management and the psychology of group recognition.\n\n---\n\n## 🏗️ Architectural Philosophy: The Synchronization of Media Metadata\n\nFrom a technical perspective, a group picture is a **High-Density Media Asset** that must be distributed across millions of endpoints.\n\n### Key Architectural Objectives:\n*   **Zero-Latency Visual Recognition**: When a group is created, its default state is often a generic \"Group\" icon. This generic state signals a lack of professional care. By immediately setting a high-quality, branded profile picture via the API, you ensure that the very first time a customer sees the group invitation, it is associated with your official brand colors and logo.\n*   **Authority and Governance**: The ability to set the profile picture is a privileged administrative act. In a professional orchestration, your Wawp instance should maintain [Admin Rights](/v2/groups/{id}/admin/promote) to ensure that only authorized business media is used. This prevents participants from uploading irrelevant or unprofessional photos to your business channels.\n*   **Media Hosting & Proxying**: The Wawp API handles the complex task of taking your external image URL, processing it according to WhatsApp's specific technical requirements, and uploading it to Meta's content delivery network (CDN). This synchronization ensures that a single API call translates into a global push of the new visual identity.\n\n---\n\n## 🚀 Strategic Use Cases: Workflow Branding and Recognition\n\nThe group profile picture should not be static; it can be used as a dynamic indicator of the group's current status or tier.\n\n### 1. Tiered Service Recognition\nIf your business manages different levels of customer support (e.g., Gold, Platinum, VIP), use the profile picture to signal the **Service Level Agreement (SLA)**. A Gold-tier group could have an icon with a gold border, while a VIP group features a distinct \"Platinum\" branding. This visual cue helps both your agents and your customers immediately understand the priority of the conversation without needing to read any meta-text.\n\n### 2. Status-Driven State Visualization\nIn a long-term project lifecycle, the group icon can evolve.\n*   **Active Phase**: A vibrant, colorful logo.\n*   **Milestone Reached**: The logo with a \"Success\" overlay or a green checkmark.\n*   **Archived Phase**: A grayscale or \"Finalized\" version of the logo.\nBy updating the icon programmatically, you provide a visual \"Status Report\" that is visible even when the user isn't looking at the message history.\n\n### 3. Identity Verification and Security\nFor high-security industries like Finance or Legal Services, the profile picture can serve as a \"Trust Signal.\" By using a consistent, high-resolution official company watermark on every group icon, you reassure the customer that the group they have been added to is an official business channel and not a fraudulent or phishing attempt. Visual consistency is the foundation of digital trust.\n\n---\n\n## 🔐 Administrative Mandate: Governance of the Visual Brand\n\nConsistency is the hallmark of enterprise quality. Managing group icons manually across thousands of groups is impossible; automation is the only solution.\n\n### The \"Anti-Tamper\" Protocol\nIf your group settings allow participants to change the profile picture, you risk a user uploading an icon that is inconsistent with your brand guidelines. Your system should listen for the [`group.update`](/v2/webhooks/group-update) webhook. If it detects a picture change that wasn't initiated by your API, it should immediately cross-reference the new media's hash or identifier. If the change is unauthorized, your system can call the **Set Group Picture** endpoint to restore the official branded avatar, maintaining your organization's visual integrity.\n\n### Localization and Culture-Aware Branding\nIf your business operates globally, use the profile picture to provide a **Localized Experience**. A group for Spanish-speaking customers might feature a logo with a subtle cultural variant or a flag-themed element. This \"Dynamic Localization\" through imagery makes the community feel more native and tailored to the specific participant base.\n\n---\n\n## 🛡️ Operational Best Practices: Resolution and Iconography\n\n*   **Aspect Ratio and Centrality**: WhatsApp icons are displayed as circles. When designing your group pictures, ensure that all critical branding (logos, status text) is centered. Any content in the corners will be cropped out.\n*   **Legibility at Scale**: Most users will see the group icon as a tiny 40x40 pixel circle in their chat list. Avoid complex textures or small text. Use bold colors, high-contrast shapes, and iconic symbols that remain recognizable even at a distance.\n*   **File Optimization**: While the Wawp API handles the conversion, the best results come from high-quality square source images (e.g., 640x640 pixels). Using JPEG or PNG formats ensures a clean upload without artifacts.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Verify Admin Status**: Before attempting to change the picture, ensure your instance is a Group Admin. Attempting to set media in a restricted group as a regular member will result in a 403 Forbidden error.\n2.  **Resource URL Accessibility**: Ensure that the URL provided to the API is publicly accessible and has the correct CORS headers if necessary. The Wawp backend needs to be able to fetch the raw image data to perform the upload.\n3.  **Webhook Synchronization**: Listen for the [`group.update`](/v2/webhooks/group-update) event to confirm that the picture was successfully processed by Meta's servers. Once confirmed, you can update your internal CRM's thumbnail for that group to match the reality of the WhatsApp experience.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Visual Community\n\nThe **Set Group Picture** endpoint is the \"Design Engine\" of your community architecture. It is your most powerful tool for establishing instant brand recognition, signaling project status, and building professional trust. By treating the group's visual identity as a dynamic, programmable asset, you create a conversational environment that is both beautiful and highly governed. You move beyond \"Simple Chat Lists\" and into the world of **Branded Conversational Spaces**, where every pixel on the user's screen reinforces your organization's commitment to quality and focus.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "file",
            "in": "query",
            "required": true,
            "description": "Picture file details (url, mimetype, filename)",
            "schema": {
              "type": "string"
            },
            "example": "{\"url\": \"https://example.com/photo.jpg\", \"mimetype\": \"image/jpeg\", \"filename\": \"group_photo.jpg\"}"
          }
        ],
        "responses": {
          "200": {
            "description": "Picture updated successfully",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "delete": {
        "operationId": "_v2_groups_id_picture_delete",
        "summary": "Delete group picture",
        "description": "Remove the group profile picture.\n\n### Developer Tips\n- **Default**: Deleting the picture reverts it to the default WhatsApp placeholder.\n- **Visibility**: All participants will see that the group icon was removed.\n\n\n# Resetting the Visual State: The Strategic Power of the Default\n\nIn the lifecycle of a professional community, the removal of a brand asset is as significant as its creation. The **Delete Group Picture** endpoint is your primary tool for **Visual State Resetting and Media Governance**. It allows you to programmatically strip a group of its custom profile picture, returning its visual identity to the WhatsApp network's default \"Generic Group\" state. This operation is not merely an act of deletion; it is a strategic signal that a community phase has ended, a brand asset has been retired, or a governance standard is being re-enforced.\n\nFor enterprise architects, managing the absence of an image is a critical component of **Conversational Hygiene**. This guide explores the strategic imperatives of resetting group identity at scale.\n\n---\n\n## 🏗️ Architectural Philosophy: The Removal of Media Metadata\n\nFrom a technical perspective, deleting a group picture is a **State Rollback**. You are instructing Meta's infrastructure to purge the associated media hash from the group's metadata and restore the server-side default.\n\n### Key Architectural Objectives:\n*   **Irrevocable Asset Retirement**: When a group picture is deleted, it is removed from the content delivery network (CDN) for all subsequent requests. While participants may retain a local cache of the old icon on their personal devices for a short time, the official \"Pulse\" of the group no longer carries that visual identity.\n*   **The Power of Admin Authority**: Only a Group Admin has the power to delete the group picture (depending on [Group Settings](/v2/groups/{id}/settings/info)). This ensures that the terminal phase of a group's visual identity is a governed act performed by an authorized authority. If your instance is a regular member and attempts this call, it will fail with a 403 Forbidden error.\n*   **Global Sync and Neutrality**: Upon successful deletion, every participant's device is signaled to update. The group instantly loses its custom \"Branding\" and reverts to the standard WhatsApp silhouette. This \"Return to Neutrality\" is a powerful tool for de-escalating the visual prominence of a group in a cluttered inbox.\n\n---\n\n## 🚀 Strategic Use Cases: Lifecycle Termination and Governance Rejection\n\nThe Delete Group Picture endpoint should be integrated into your broader business logic to handle the decommissioning of community assets.\n\n### 1. The \"Archival State\" Transition\nWhen a project moves into a \"Deep Archive\" phase—where the group still exists for historical records but no active interaction is expected—the custom branded logo should be retired. By calling the Delete Group Picture endpoint, your system signals to all participants that the \"Live Project\" has concluded. The transition from a vibrant company logo to a generic default icon is a subtle but effective way to lower the user's focus on that specific channel without needing to delete the group entirely.\n\n### 2. Governance Policy Enforcement and \"Brand Scrubbing\"\nIf your business policy allows participants to edit group metadata, you may encounter scenarios where a user uploads an inappropriate or non-compliant image as the group icon. While the [Set Picture](/v2/groups/{id}/picture/set) endpoint can be used to overwrite it, the **Delete Group Picture** endpoint serves as the \"Immediate Neutralizer.\" If your system detects a compliance violation via a webhook, it can immediately strip the non-compliant image to restore a safe, neutral state while your legal or moderation team reviews the incident.\n\n### 3. Re-branding Preparation and Handover\nProfessional re-branding operations often involve a \"Blank Slate\" phase. Before uploading a new set of high-fidelity community icons during a corporate acquisition or identity shift, your system can use the Delete endpoint to purge the legacy branding across thousands of groups simultaneously. This ensures that there is no \"Visual Conflict\" or lag where some groups show the old logo while others show the new one.\n\n---\n\n## 🔐 Administrative Mandate: Authority and Consistency\n\nIn an enterprise environment, the group icon is a piece of corporate real estate. You cannot allow it to become a vector for unprofessional behavior.\n\n### Tracking the \"Administrative Footprint\"\nManaging who has the power to strip a group of its identity is a security task. Your system should ensure that only its own JIDs (or verified senior staff) possess the ability to execute the Delete endpoint. This prevents a disgruntled admin from maliciously \"Wiping\" the visual branding of your entire customer-facing ecosystem. Periodically auditing the admin list via [Get Group Info](/v2/groups/{id}) is your primary defense against visual tampering.\n\n### Coordination with Webhooks\nSuccessful visual governance requires a \"Reactive\" architecture. Your system should listen for the [`group.update`](/v2/webhooks/group-update) webhook. When the deletion is confirmed by the WhatsApp network, your system should update its internal CRM thumbnail to a placeholder, ensuring that your agent's dashboard matches the reality of the customer's experience.\n\n---\n\n## 🛡️ Operational Best Practices: Professionalism and Visual Grace\n\n*   **The \"Notice of Retirement\" Pattern**: Removing a group's identity can be confusing for users. Before executing the deletion, we recommend sending a final \"Project Closing\" message or a 1:1 notice to key stakeholders. Explain that the group is transitioning to an \"Archived\" status and the branding is being retired to simplify their inbox.\n*   **Rate Management and System Stability**: Like all metadata operations, deleting pictures in bulk should be staggered. While the network call is lightweight, the downstream \"Push\" to thousands of participants' devices is significant. Clearing pictures at a rate of 5-10 groups per minute is recommended for large-scale decommissioning tasks.\n*   **Preserving the Audit Trail**: Before calling the Delete endpoint, your system should \"Snapshot\" the final state of the group's visual identity. If you need to re-verify the branding used during a specific period for compliance reasons, your internal database should have a record of the former media hash or a local archival copy.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Verify Admin Permissions**: Since your instance must be an admin to delete the picture, always perform a pre-flight check of your instance's role in the group. This prevents avoidable 403 errors and ensures your deletion queue remains active and efficient.\n2.  **Idempotency of Removal**: Calling the delete endpoint on a group that already has no profile picture is a safe, no-op operation. It will return a success signal without causing any state issues. This allows you to include the deletion as part of a \"Global Cleanup\" script without needing complex conditional logic for every group.\n3.  **Synchronization with the Source of Truth**: When the metadata is successfully deleted from WhatsApp, ensure your internal media pointers are nullified. This prevents your platform from trying to fetch or display \"Ghost Images\" that no longer exist on Meta's CDN.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Clean State\n\nThe **Delete Group Picture** endpoint is the \"Eraser\" of your community architecture. It allows you to maintain professional standards, enforce governance, and signal the end of a community's active lifecycle with precision. By treating the removal of visual branding as a deliberate, strategic act, you ensure that your WhatsApp ecosystem remains lean, focused, and always aligned with your organization's current identity. A clean, neutral state is often the most professional foundation for an archive, and the ability to programmatically restore that state is what separates a true enterprise platform from a simple messaging tool.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Picture removed successfully",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/description": {
      "put": {
        "operationId": "_v2_groups_id_description_put",
        "summary": "Updates the group description",
        "description": "Update the description text for the group.\n\n### Developer Tips\n- **Visibility**: The description is visible to all participants at the top of the chat.\n- **SEO**: Include keywords and links to your support portal here.\n\n\n# The Semantic Manifesto: Defining Purpose through Persistent Context\n\nIn the landscape of distributed communities, the **Set Description** endpoint is your primary tool for **Strategic Documentation**. While the group subject identifies the conversation, the description defines its boundaries, its rules, and its technical interfaces. Because the group description is a persistent block of text that is accessible to all members at any time, it functions as a \"Shared Source of Truth\" or a \"Group Handbook\" that lives within the WhatsApp interface itself. By programmatically managing this field, you move beyond the era of ephemeral chatting and into the era of **Governance-First Collaborative Workspaces**.\n\nFor architects and product managers, the group description is the **Contextual Foundation** upon which professional interactions are built. This guide explores the strategic imperatives of managing group manifestos at scale.\n\n---\n\n## 🏗️ Architectural Philosophy: The Persistent Context Layer\n\nFrom a technical perspective, the group description is a **Large-Scale Metadata Buffer** that is synchronized globally.\n\n### Key Architectural Objectives:\n*   **Static Resource Discovery**: Users often forget the specific links or command prefixes required to interact with your business bots. By embedding this information in the group description, you provide a \"Lasting Reference\" that doesn't disappear when the chat history is cleared or when new messages arrive. It is the only part of the group state that remains \"Pinned\" to the top of the group info screen.\n*   **The Power of Admin Authority**: Like the subject, the ability to change the description is a privileged act. In professional environments, you should almost always set your group [Settings](/v2/groups/{id}/settings/info) to \"Admins Only\" for metadata changes. This prevents participants from overwriting your official business SOPs or support links with their own text.\n*   **Zero-Latency Propagation**: When your API updates the description, the change is reflected immediately for all participants. Meta's infrastructure handles the complex heavy lifting of ensuring that a user in Tokyo and a user in London see the same \"Manifesto\" simultaneously, providing a unified global context.\n\n---\n\n## 🚀 Strategic Use Cases: The Command Center and Onboarding Handbook\n\nThe group description should be treated as a dynamic asset that evolves during the project lifecycle.\n\n### 1. The Interactive \"Bot Command Desk\"\nIf your WhatsApp group is integrated with an AI agent or a workflow engine (e.g., a group for a field service team), use the description to host a **Documentation of Capabilities**. List the specific keywords that trigger actions, such as:\n*   `/status` - Fetch the current project milestone.\n*   `/upload` - Get a link to the secure document portal.\n*   `/escalate` - Notify a senior manager.\nBy hosting this \"Cheat Sheet\" in the description, you empower participants to interact with your automation without needing to read a separate 20nd-page PDF manual.\n\n### 2. The Dynamic Onboarding & KYC Handbook\nFor financial or medical groups, the first interaction is often the most critical. When a group is created, your system should automatically populate the description with **Legal Disclaimers, Privacy Links, and Resource Identifiers**. As the user moves through the \"KYC\" (Know Your Customer) process, your system can update the description to reflect their current status (e.g., *\"Verification Pending - Please upload your ID via the link below\"*). This turns the group description into a progress tracker that provides constant reassurance to the user.\n\n### 3. Hyperlink Hub for Managed Workflows\nWhatsApp descriptions support clickable URLs. Use this to bridge the gap between the chat and your external business systems. Include links to:\n*   Shared Google Drive folders for the project.\n*   Specific Salesforce Case pages for the assigned agent.\n*   Direct payment links for an outstanding invoice.\nBy centralizing these links in the group description, you ensure they are never \"Lost in the Scroll\" of a busy conversation.\n\n---\n\n## 🔐 Administrative Mandate: Governance of the Group Handbook\n\nIn an enterprise setting, the group description is a branding asset. Consistency across hundreds of groups is essential for professional representation.\n\n### The \"Standard Operating Procedure\" Template\nWe recommend that your system uses a **Templating Engine** to generate group descriptions. A standard template might include:\n1.  **Mission Statement**: A one-sentence summary of why the group exists.\n2.  **Stakeholder Directory**: A list of the JIDs or names of the official business representatives in the room.\n3.  **Governance Policy**: A brief note on expected behavior and response times (SLA).\n4.  **Resource Footer**: Links to help centers or escalation paths.\n\n### Reconciliation and Integrity\nIf you allow humans (like field agents) to edit group descriptions, your system should still perform a \"Compliance Audit.\" Listen for the [`group.update`](/v2/webhooks/group-update) webhook. If a human agent changes the description and removes the mandatory \"Legal Footer\" or \"Compliance Link,\" your system can automatically detect the missing required text and call the **Set Description** endpoint to restore the correct version, maintaining your organization's regulatory posture.\n\n---\n\n## 🛡️ Operational Best Practices: Formatting and Information Density\n\n*   **Brevity and Bullet Points**: While WhatsApp descriptions can hold a significant amount of text, users will only read what they can quickly scan. Use emojis as bullet points and keep your paragraphs short.\n*   **The \"Above the Fold\" Rule**: Only the first few lines of a description are visible in the main group info screen before the user has to tap \"Read more.\" Put your most critical information (like the CASE ID or the URGENT ACTION LINK) at the very top.\n*   **Avoid Over-Updating**: Every time you call this endpoint, a system message is generated in the chat. Limit updates to major state changes to avoid cluttering the conversational flow with administrative notices.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Check Metadata Permissions**: Always verify that your Wawp instance is an admin before attempting to set the description. If the group is restricted and you aren't an admin, your call will fail with a 403.\n2.  **String Sanitization**: Ensure that your description strings are correctly escaped and don't contain prohibited characters that could cause JSON parsing errors in your API calls.\n3.  **Synchronization with Source of Truth**: When the description is updated via the API, your internal database should be updated simultaneously. This ensures that when an agent looks at your internal dashboard, they are seeing the *exact* same handbook that the customer sees in WhatsApp.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Documented Community\n\nThe **Set Description** endpoint is the \"Command Center\" of your community architecture. It is your most powerful tool for establishing long-term context, providing resource discovery, and enforcing behavioral standards. By treating the group description as a living, programmable manifesto, you create a professional environment that is both efficient and highly governed. You move beyond \"Simple Messaging\" and into the world of **Structured Collaborative Workspaces**, where every participant has the information they need to succeed, right at their fingertips.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "description",
            "in": "query",
            "required": true,
            "description": "New group description",
            "schema": {
              "type": "string"
            },
            "example": "This group is for discussing the new project features."
          }
        ],
        "responses": {
          "200": {
            "description": "Description updated",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/subject": {
      "put": {
        "operationId": "_v2_groups_id_subject_put",
        "summary": "Updates the group subject",
        "description": "Update the group subject (name).\n\n\n# The Power of the Label: Naming as Strategic Signaling\n\nIn the high-velocity environment of WhatsApp communication, the **Update Subject** endpoint is your primary tool for **Visual State Management**. It allows you to programmatically change the name of a group, which is the single most visible piece of metadata on a user's mobile device. The group subject is not just a label; it is a real-time status indicator that tells every participant exactly what the current focus of the conversation is. By automating subject changes, you turn the group title into a dynamic signaling mechanism that reflects the progress of your business workflows.\n\nFor enterprise developers, \"Setting the Subject\" is about **Managing the User's Attention**. This guide explores the architectural nuances of identity volatility and the strategic implementation of status-driven naming.\n\n---\n\n## 🏗️ Architectural Philosophy: The Volatility of Visual Identity\n\nFrom a technical perspective, the group subject is a **Mutable Field** mapped to an **Immutable Identifier** (the Global-JID).\n\n### Key Architectural Objectives:\n*   **Decoupling Identity from Presence**: Your internal database must always anchor its logic to the group's JID (`@g.us`), never to its name. Because any admin (human or bot) can change the subject at any time, relying on the name for logic will lead to catastrophic state failure. The Update Subject endpoint allows your system to \"Force\" its preferred naming convention onto the group, ensuring that the visual reality of the chat matches your internal project state.\n*   **The Power of Admin Rights**: Updating the subject is an authorized operation. Depending on the group's [Settings](/v2/groups/{id}/settings/info), this power might be restricted to **Admins Only** or open to all members. To guarantee that your system can always update the name, your Wawp instance should maintain active Admin status.\n*   **Global Sync & Push Notifications**: Every time the subject is updated, Meta's infrastructure pushes a synchronization event to every single member of the group. This often triggers a silent notification or moves the group to the top of the chat list. Use this \"Attention Hook\" strategically to signal major project milestones.\n\n---\n\n## 🚀 Strategic Use Cases: Lifecycle Staging and Status Visibility\n\nThe group subject should evolve alongside the customer's journey. Use it to provide a \"Glanceable\" status report for the user.\n\n### 1. The \"Workflow Staging\" Indicator\nIn a technical support scenario, a group might start with the name `[OPEN] - Case #1234`. As the investigation progresses, your system can automatically update the subject to `[INVESTIGATING] - Case #1234`,\n  tips: [\n        {\n            type: 'info',\n            title: 'Constraints',\n            content: 'Subject has a character limit (approx 100 chars).'\n        },\n        {\n            type: 'warning',\n            title: 'Rate Limit',\n            content: 'Frequent name changes can be flagged as spam.'\n        }\n    ],\n  recommendations: [\n        \"Include a timestamp or status in the subject (e.g., 'Project Alpha [Closed]').\",\n        \"Use consistent naming conventions for easy searching.\",\n        \"Avoid sensitive PII in group subjects as they are visible in notifications.\"\n    ]\n  \n   and finally `[RESOLVED] - Case #1234`. This allows the customer to see the progress of their request just by looking at their chat list, reducing the need for them to send \"Any updates?\" messages and lowering the load on your support team.\n\n### 2. High-Value Serialization for Agent Productivity\nFor businesses managing hundreds of active groups (like a logistics company or an event agency), agents can quickly become overwhelmed by a list of identical-looking names (e.g., \"Customer Support\"). By programmatically injecting **Prefixes and Priority Codes** (e.g., `[PRIO-A] Wawp Corp Delivery`), you allow your human agents to prioritize their responses based on visual cues. The Update Subject endpoint transforms the inbox into a prioritized task list.\n\n### 3. Time-Sensitive Branding for Events\nFor a 3-day conference, the group subject can reflect the **Current Session Name**. By automating the subject change every hour, you turn the group into a \"Live Schedule.\" Attendees don't need to check a PDF or an app; the name of the group they are already in tells them exactly which seminar is currently happening or which room they should be in.\n\n---\n\n## 🔐 Administrative Mandate: Governance of the Group Title\n\nNaming is a component of brand integrity. In an enterprise environment, you cannot allow group names to become chaotic or unprofessional.\n\n### The \"Anti-Tamper\" Reconciliation\nIf your group settings allow participants to change the subject, you risk a user renaming a professional business channel to something inappropriate or confusing. Your system should listen for the [`group.update`](/v2/webhooks/group-update) webhook. If it detects a subject change that wasn't initiated by your API, it should check the new name against a \"Sanity Filter.\" If the change is unauthorized, the system can instantly call the **Update Subject** endpoint to revert the name back to the official business standard.\n\n### Character Limits and Sanitization\nWhatsApp subjects are currently capped at **25 characters**. This \"Subject Line Economy\" requires creative brevity. Your logic should always include a truncation routine to ensure that critical information (like the Case ID) is at the *beginning* of the string, so it isn't cut off on the user's lock screen.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Discoverability\n\n*   **Standardized Prefixes**: Use brackets `[]` or emojis to categorize groups. This creates a visual \"System\" that users can learn to recognize quickly. Use a blue heart for customer success, a red alert for urgent support, and a green check for completed projects.\n*   **Clutter Reduction**: Avoid putting redundant information in the subject. If the user already knows they are talking to \"Brand X,\" don't put \"Brand X\" in every group name. Use that limited character space for specific context (e.g., `Project: Skyline Alpha`).\n*   **Staggered Updates**: While changing a subject is a lightweight operation, avoid doing it \"flicker-style\" (multiple times in a few minutes). Every change generates a system message in the chat history (*\"Business Name changed the subject to...\"*). Too many of these can clutter the conversation and look non-professional.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Check Admin Authority**: Before attempting to set the subject, verify if the group is set to \"Admins Only\" for metadata changes. If it is, and your instance isn't an admin, the call will fail. A proactive audit via [Get Group Info](/v2/groups/{id}) is your best defense against 403 errors.\n2.  **Handle Network Delay**: Subject updates are fast but not instantaneous. Your system should wait for the confirmation webhook before updating its internal \"Display Name\" for that group to ensure your backend state and the network state are perfectly aligned.\n3.  **Cross-Instance Name Management**: If you use multiple WhatsApp accounts, ensure that your naming convention is consistent across all of them so that a VIP customer interacting with different departments sees a unified brand identity.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Brand-Aware Community\n\nThe **Update Subject** endpoint is the \"Face\" of your community architecture. It is your most direct channel for communicating high-level status without sending a single disruptive message. By treating the group name as a dynamic, programmable asset, you create a professional environment that is both informative and highly governed. You move beyond simple chat names and into the world of **Visual Workflow Orchestration**, where every glance at the phone provides the user with meaningful, real-time business context.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "subject",
            "in": "query",
            "required": true,
            "description": "New group subject",
            "schema": {
              "type": "string"
            },
            "example": "Alpha Team Updates"
          }
        ],
        "responses": {
          "200": {
            "description": "Subject updated",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/settings/security/info-admin-only": {
      "get": {
        "operationId": "_v2_groups_id_settings_security_info-admin-only_get",
        "summary": "Get \"info admin only\" settings",
        "description": "Check if only admins can update group info.\n\n### Developer Tips\n- **Permissions**: Checks if 'Edit Group Info' is restricted to admins.\n- **Boolean**: Returns true if restricted (Admins Only), false if open (All Users).\n\n\n# Governance Auditing: The Verification of Metadata Integrity\n\nIn the management of high-sensitivity conversational environments, trust must be verified as much as it is established. The **Get Info Admin Only** endpoint is your primary tool for **Structural Governance Auditing and Compliance Verification**. It allows your automated systems to programmatically query the \"Lock\" state of a group's visual and textual identity. By understanding whether a group is currently restricted to administrators or open to all participants for metadata changes, your system can make informed decisions about its moderation posture, its branding enforcement logic, and its overall risk assessment for that specific community.\n\nFor enterprise architects, this endpoint is the **Pulse Check of Brand Protection**. This guide explores the strategic imperatives of security auditing and the guardianship of shared context.\n\n---\n\n## 🏗️ Architectural Philosophy: Retrieving the Structural Permission Mask\n\nFrom a technical perspective, the Get Info Admin Only endpoint is a **Security State Resolver**.\n\n### Key Architectural Objectives:\n*   **The Baseline of Brand Integrity**: A professional business channel should almost always be \"Locked\" for metadata changes. This endpoint provides the definitive answer to the question: *\"Is our brand identity currently protected from unauthorized changes?\"* By retrieving the current boolean state, your system can identify \"At-Risk Groups\" that have been accidentally or maliciously opened up to participant-led branding.\n*   **Permissionless Verification**: Any member of a group (even if they are not an admin) can query its security settings. This allows your system to monitor groups where it is a regular participant, providing a \"Monitoring-from-Within\" capability that doesn't require elevated privileges to function.\n*   **Low-Overhead State Mapping**: Because only a single boolean flag is retrieved, this API call is extremely lightweight. It is the perfect trigger for a \"Watchdog Utility\" that scans hundreds of groups per minute to ensure they all adhere to your organization's security baseline.\n\n---\n\n## 🚀 Strategic Use Case: Compliance Monitoring and Anti-Tamper Auditing\n\nVisibility into security settings is the foundation of automated correction.\n\n### 1. The \"Governance Watchdog\" Reconciliation\nIn large-scale operations with multiple human admins, it is common for one admin to manually change a group's settings from their phone (e.g., to allow a client to upload a specific photo) and then forget to re-lock the group. Your system should use the **Get Info Admin Only** endpoint to perform a \"Daily Compliance Scan.\" If a group is found to be unlocked (`adminOnly: false`) when your internal policy mandates a lock, the system can automatically flag the group or even [Re-Lock it](/v2/groups/{id}/settings/security/info-admin-only) to restore the authorized posture.\n\n### 2. Risk-Aware Message Orchestration\nBefore sending a message that contains high-value instructions (e.g., a link to an official payment portal), your system should verify the group's \"Integrity State.\" If the group info settings are unlocked, there is a risk that a malicious participant has renamed the group or changed its description to something deceptive. By probing the security state first, your system can decide to refuse to send sensitive information until the group is secured, protecting both your brand and your customers from social engineering.\n\n### 3. Dynamic Moderator Dashboarding\nFor the human agents managing your communities, the security state of a group is a critical piece of context. Displaying the \"Lock Icon\" in your CRM's dashboard—driven by the data from this endpoint—gives the agent instant situational awareness. They know at a glance whether they have absolute control over the group's \"Face\" or whether they need to monitor for unauthorized metadata tampering.\n\n---\n\n## 🔐 Administrative Mandate: The Guardianship of Brand Identity\n\nIn an enterprise setting, the \"About\" section and the Group Icon are corporate assets. Controlling access to them is a regulatory requirement.\n\n### Integrity in Regulated Industries\nFor sectors like Finance or Healthcare, maintaining a static, verifiable group state is essential for audit trails. Auditors must be able to see that your organization maintained a \"Locked\" posture for its entire duration. The **Get Info Admin Only** endpoint provides the raw evidence for your \"Audit Export\"—proving that your system was actively monitoring and verifying the security boundary of its conversational workspaces.\n\n### Protecting the \"Source of Truth\"\nThe group description often hosts critical SOPs and bot commands. If the info settings are unlocked, that \"Document\" is vulnerable. By programmatically verifying the lock state, your system ensures that the information it provide to users remains the definitive, untampered truth. Verification is the final step in the chain of administrative trust.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Periodic Verification\n\n*   **The \"Initialization Audit\"**: Immediately after joining a group or being promoted, your system should call this endpoint to understand its new environment. Don't assume the group is locked; verify it.\n*   **Automated Policy Reporting**: Generate a weekly report for your security team showing the \"Governance Compliance\" percentage across all active groups. This high-level visibility is made possible by the aggregate data retrieved from this endpoint.\n*   **Synchronize with Webhooks**: While [`group.update`](/v2/webhooks/group-update) webhooks tell you when a change *happens*, the **Get Info Admin Only** endpoint tells you what the state *is*. During system recovery or after a network partition, skip the webhook history and call the GET API to reconcile your local state with the network truth.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Map Logic to Boolean States**: Ensure your internal state machine understands that `adminOnly: true` corresponds to a \"Governed\" state and `false` to an \"Expressive\" or \"Collaborative\" state.\n2.  **Handle Network Lag**: Like all metadata reads, the response represents the state at the exact moment of the call. If your system is performing a \"Sync-and-Lock\" loop, wait for a few hundred milliseconds after a [Set](/v2/groups/{id}/settings/security/info-admin-only) call before verifying via the GET API.\n3.  **Cross-Reference with Role Power**: A \"Locked\" group is only secure if your Wawp instance (or a trusted human) is an admin. We recommend a `Get Admin Only -> Get Participant Role` sequence to build a complete picture of the group's current governance posture.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Audited Community\n\nThe **Get Info Admin Only** endpoint is the \"Integrity Monitor\" of your community architecture. It is your most powerful tool for verifying that your brand identity is protected, your compliance mandates are met, and your communities are operating within a structured, professional framework. By treating the \"Lock\" state as a critical metric to be audited rather than assumed, you build a conversational ecosystem that is resilient to tampering and always aligned with your organization's standards of quality. You move beyond \"Passive Presence\" and into the world of **Active Governance Verification**, where every community operates under the watchful, informed eye of your automated business logic.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Setting retrieved",
            "content": {
              "application/json": {
                "example": {
                  "adminOnly": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "_v2_groups_id_settings_security_info-admin-only_put",
        "summary": "Updates \"info admin only\" settings",
        "description": "Set whether only admins can update group info.\n\n\n# Metadata Sovereignty: Enforcing the Integrity of Shared Context\n\nIn the landscape of professional WhatsApp management, the environment is your brand. The **Set Info Admin Only** endpoint is your primary tool for **Metadata Sovereignty and Structural Governance**. It allows you to programmatically toggle the \"Lock\" on a group's visual and textual identity—including its subject, its description, and its profile picture. By restricting these powers to administrators, you ensure that the group remains a professional, business-led workspace, protecting it from the potential chaos of unauthorized changes by regular participants.\n\nFor enterprise architects, managing *who* can change the environment is as important as the environment itself. This guide explores the strategic imperatives of metadata restriction and the enforcement of trusted communication.\n\n---\n\n## 🏗️ Architectural Philosophy: The Locking of Community Attributes\n\nFrom a technical perspective, this endpoint modifies the **Governance Bitmask** of the group's metadata.\n\n### Key Architectural Objectives:\n*   **Protection of the Branding Baseline**: A business group with 500 participants is a high-sensitivity environment. Allowing any one of those 500 users to rename the group to something inappropriate or change the group icon is an unacceptable brand risk. This endpoint allows your system to \"Hard-Lock\" the branding, ensuring that the visual reality of the chat always aligns with your official corporate identity.\n*   **The Power of Admin Authority**: This setting is a \"Privileged Toggle.\" To successfully lock or unlock the group's info settings, your Wawp instance **must be a Group Admin**. This prevents regular members from trying to \"Open Up\" the metadata permissions for themselves.\n*   **Persistent Governance State**: Once the \"Admin Only\" flag is set to `true`,\n  tips: [\n        {\n            type: 'warning',\n            title: 'Admin Only',\n            content: 'You must be an admin to change this setting.'\n        },\n        {\n            type: 'info',\n            title: 'Impact',\n            content: 'Restricting info prevents users from changing the group name/icon.'\n        }\n    ],\n  recommendations: [\n        \"Lock this immediately for branded communities to prevent vandalism.\",\n        \"Unlock temporarily if you want community-driven branding.\"\n    ]\n  \n   the restriction persists until explicitly changed. Even if the group's membership list changes or if new admins are promoted, the structural restriction remains active, providing a \"Steel-Clad Safeguard\" for your conversational real estate.\n\n---\n\n## 🚀 Strategic Use Case: Brand Integrity and Anti-Tamper Orchestration\n\nMetadata sovereignty should be a \"Default-On\" requirement for any professional integration.\n\n### 1. The \"Formal Business Channel\" Posture\nFor high-trust environments (like a Bank-Customer interaction or a Legal War Room), the group must strictly reflect the official case identity. By calling the **Set Info Admin Only** endpoint immediately after [Creating the Group](/v2/groups/create), your system ensures the workspace is professional from its very first second. This prevents \"Vandalism\" where a participant might try to change the group name to something informal, preserving the gravity and professional tone of the channel.\n\n### 2. The \"Campaign-to-Community\" Lifecycle\nImagine a marketing campaign that starts as a tightly controlled, \"Broadcast-First\" environment. Initially, the info settings are locked to Admins Only (`true`). As the campaign matures and the community gains trust, your system might decide to \"Transition\" the channel into a more collaborative space by setting the value to `false`. This allows participants to contribute to the group's identity, fostering a sense of co-ownership as the relationship evolves from \"Alerts\" to \"Engagement.\"\n\n### 3. Anti-Tamper and Reactive Reconciliation\nIn environments where multiple human admins are present, one admin might accidentally \"Unlock\" the group settings. To maintain a strict governance posture, your system should listen for [`group.update`](/v2/webhooks/group-update) webhooks. If your system detects that the `restrict` flag has been flipped to `false` without an authorized API trigger, it can instantly call this endpoint to **Re-Lock the Metadata**, ensuring your brand's visual board remains under automated oversight at all times.\n\n---\n\n## 🔐 Administrative Mandate: The Root of Trusted Communication\n\nControlling the \"Face\" of the group is the first step in controlling the conversation.\n\n### Centralizing the \"Source of Truth\"\nWhen metadata changes are restricted to admins, it allows your business to use the [Group Description](/v2/groups/{id}/description/set) as a **Reliable Resource Catalog**. If any participant could change the description, they could replace your official support links with fraudulent ones. Locking the info settings turns the description into a \"Protected Document,\" ensuring that users can always trust the information hosted in the group's \"About\" section.\n\n### Structural Integrity in Regulated Industries\nFor compliance-heavy sectors, maintaining a fixed group identity is often a legal requirement. Auditors need to know that the \"Case #123\" group they are reviewing was named \"Case #123\" for its entire duration. By leveraging this endpoint, your system provides a \"Governance Lock\" that contributes to your platform's overall auditability and regulatory standing.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Security\n\n*   **Default to Restricted**: unless your use case explicitly requires participant-led branding, we recommend that all enterprise groups be initialized with `value: true`.\n*   **Coordinated Metadata Updates**: When you need to update the group name or icon, do it via the API. Because your API instance is an admin, it will bypass the restriction, allowing you to update the branding while keeping the participants locked out.\n*   **Visual Signaling of the Lock**: Participants see a small notification in the group info when permissions are changed. Use this as a signal of \"Official Handover.\" When the group is locked, it signals to users that they are in a professionally managed, high-trust environment.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Verify Admin Status Before Setting**: You cannot change the security settings of a group if you are not an admin. Attempting to set this value as a regular member will result in a 403 Forbidden error.\n2.  **Idempotent Safety**: Setting the value to `true` when it is already `true` is a safe, no-op operation. This allows you to include the \"Locking Call\" as a mandatory step in your \"Project Refresh\" scripts without needing complex conditional logic.\n3.  **Webhook Integration**: Listen for the [`group.update`](/v2/webhooks/group-update) event to confirm that the network has acknowledged the permission change. Once confirmed, you can update your internal CRM's state to reflect that the group is now in a \"Governed\" posture.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Governed Workspace\n\nThe **Set Info Admin Only** endpoint is the \"Foundation of Integrity\" for your community architecture. It is your primary tool for protecting your brand's visual identity, enforcing administrative trust, and maintaining a structured, professional environment for your participants. By treating the \"Lock\" on a group's metadata as a strategic asset, you build a conversational ecosystem that is resilient to tampering and always aligned with your organization's highest standards of quality and governance. You move beyond simple chat rooms and into the world of **Trusted Business Hubs**, where every participant knows that the context they are in is official, secure, and perfectly managed.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "value",
            "in": "query",
            "required": true,
            "description": "True to restrict to admins, false to allow all",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          }
        ],
        "responses": {
          "200": {
            "description": "Setting updated",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/settings/security/messages-admin-only": {
      "get": {
        "operationId": "_v2_groups_id_settings_security_messages-admin-only_get",
        "summary": "Get settings - who can send messages",
        "description": "Check if only admins can send messages to the group.\n\n### Developer Tips\n- **Announce Mode**: Checks if 'Send Messages' is restricted to admins.\n- **Term**: Often called 'Announcement Group' or 'Broadcast Mode'.\n\n\n# Conversational Auditing: The Strategic Control of Global Dialogue\n\nIn the orchestration of high-volume community networks, the ability to control the \"Microphone\" is as important as the ability to send the message. The **Get Messages Admin Only** endpoint is your primary tool for **Strategic Conversational Auditing and Signal-to-Noise Verification**. It allows your automated systems to programmatically query whether a group is currently in \"Announcement Mode\" (Admins only) or \"Collaboration Mode\" (All participants). By retrieving this boolean state, your platform can make intelligent decisions about its messaging strategy, its moderation load, and its overall posture within the group, ensuring that your organization's voice is always synchronized with the structural permissions of the channel.\n\nFor enterprise architects, this endpoint is the **Pulse Check of Channel Discipline**. This guide explores the strategic imperatives of interaction auditing and the guardianship of community focus.\n\n---\n\n## 🏗️ Architectural Philosophy: Retrieving the Presence of the Interaction Mask\n\nFrom a technical perspective, the Get Messages Admin Only endpoint is a **Low-Latency Permissions Snapshot**.\n\n### Key Architectural Objectives:\n*   **The Foundation of Channel Readiness**: Before initiating a high-priority broadcast, your system needs to know if the channel is \"Clear.\" By retrieving the current message security state, your system can verify that the group is locked to admins-only before sending a critical alert. This ensures that your alert is the first thing a user sees, rather than being buried in a flurry of participant replies.\n*   **Permissionless Monitoring**: Any instance that is a member of the group can query its security settings via this API. This allows you to build a \"Monitoring Grid\"—where a network of instances tracks the conversation state across hundreds of groups—without requiring administrative rights in every single one.\n*   **Real-Time State Mapping**: Webhooks tell you when a change *happens*, but the GET API tells you what the state *is*. During system re-initialization or after a period of instability, this call provides the authoritative \"Ground Truth\" for your internal state machines.\n\n---\n\n## 🚀 Strategic Use Case: Automated Channel Readiness and Alert Verification\n\nUnderstanding the \"Microphone State\" is the first step in sophisticated campaign orchestration.\n\n### 1. The \"Clean Channel\" Pre-Flight Check\nImagine an automated emergency notification system. Before sending an evacuate-and-report order to 1,000 field staff, the system calls the **Get Messages Admin Only** endpoint. If it finds the group is currently unlocked, it first calls the [Set Messages Admin Only](/v2/groups/{id}/settings/security/messages-admin-only) endpoint to \"Clear the Floor,\" and then finally sends the alert. This sequence ensures that the communication is professional, focused, and un-interruptible.\n\n### 2. Forensic Auditing for \"Quiet Hours\" Enforcement\nMany corporate communities have a \"No-Noise\" policy after hours. Your system can use this endpoint to audit its portfolio at 5:00 PM. If a group is still in Collaborative Mode, the system can automatically flag it for moderation. By verifying the state rather than just assuming it, you ensure that your global \"Quiet Hours\" policy is being structuraly enforced by the API, rather than relying on human memory.\n\n### 3. Dynamic Workflow Branching\nYour bot's behavior should change based on whether the group is locked. If your bot is a \"Question-and-Answer\" assistant, its logic can use this endpoint to determine its own availability. If the group is locked to admins, the bot can send a message: *\"The floor is currently closed for official announcements. I will be available for questions once the admins reopen the chat.\"* This provides a premium, context-aware user experience that reflects the actual technical state of the room.\n\n---\n\n## 🔐 Administrative Mandate: The Guardianship of Community Focus\n\nIn a professional environment, noise is a cost. Auditing the \"Microphone\" is a method of cost-control.\n\n### Integrity in High-Stakes Broadcasting\nFor PR and Marketing teams, the ability to confirm that a \"Listen-Only\" environment is active is essential for campaign success. This endpoint provides the raw data for your \"Campaign Governance Report,\" proving that for the duration of a specific product launch, the community was maintained as a high-fidelity broadcast channel with no external interference.\n\n### Protecting the User Experience\nUsers join Groups (vs. Communities) often expecting a high-signal environment. If a group stays in \"Chatty\" mode too long, attrition (leaving) increases. By programmatically auditing the message settings, your system acts as the \"Experience Guardian\"—ensuring that the group returns to a focused, announcement-driven state once a collaborative session has concluded.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Demographic Sensitivity\n\n*   **The \"Initialization Sync\" Pattern**: Always call this endpoint immediately after a successful [Join](/v2/groups/join) or [Create](/v2/groups/create). Understand the structural boundaries of your new home before you start speaking.\n*   **Automated Status Dashboards**: Display the \"Microphone State\" (`Locked` or `Open`) clearly in your agent's UI. It is one of the most important pieces of metadata for an agent tasked with managing hundreds of active conversations.\n*   **Coordinate with Throttling Logic**: If the group is in \"Open\" mode, your system should prepare for a higher volume of incoming webhooks. Use the result of this GET call to dynamically scale your webhook processing workers for that specific instance.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **State-Driven Logic Branching**: Build your bot's command-parsing logic to be \"Governance Aware.\" If the group is in admin-only mode, the bot should only respond to commands from admins, even if its internal logic usually allows regular users to interact.\n2.  **Handle Network Propagation**: When changing the setting via the [Set API](/v2/groups/{id}/settings/security/messages-admin-only), allow for a short network propagation delay (approx. 500ms) before re-verifying the state via the GET API to ensure your local cache reflects the server-side change.\n3.  **Cross-Reference with Admin Authority**: Knowing the group is locked is only useful if you know *who* can speak. Combine the data from this endpoint with the [Get Participants](/v2/groups/{id}/participants) API to build a complete map of authoritative voices in the room.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Focused Community\n\nThe **Get Messages Admin Only** endpoint is the \"Stethoscope\" of your community architecture. It is your most powerful tool for monitoring channel discipline, enforcing focus, and ensuring that your organization's voice is always delivered in the optimal structural environment. By treating the \"Microphone State\" as a critical piece of operational intelligence to be audited and verified, you build a conversational ecosystem that is professional, respectful of its users' attention, and always aligned with your strategic goals. You move beyond \"Simple Messaging\" and into the world of **Structured Dialogue Orchestration**, where every silence is verified and every broadcast is protected by the structural integrity of the network.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Setting retrieved",
            "content": {
              "application/json": {
                "example": {
                  "adminOnly": false
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "put": {
        "operationId": "_v2_groups_id_settings_security_messages-admin-only_put",
        "summary": "Set messages admin only",
        "description": "Set whether only admins can send messages to the group.\n\n\n# The Power of Silence: Mastering the Flow of Community Dialogue\n\nIn the high-velocity environment of distributed messaging, noise is the enemy of clarity. The **Set Messages Admin Only** endpoint (often referred to as **Announcement Mode**) is your primary tool for **Conversational Flow Control and Structural Discipline**. It allows you to programmatically toggle the ability for regular members to send messages in a group. By restricting the channel to administrator-only communication, you transform a potentially chaotic group chat into a high-fidelity broadcast channel, ensuring that your business's critical alerts and information are never \"Lost in the Scroll\" of participant chatter.\n\nFor enterprise architects, managing the \"Noise Level\" of a community is a critical component of **User Experience and Engagement Orchestration**. This guide explores the strategic imperatives of announcement mode and the art of focused conversation.\n\n---\n\n## 🏗️ Architectural Philosophy: The Enforcement of Unidirectional State\n\nFrom a technical perspective, this endpoint modifies the **Interaction Mask** of the group state.\n\n### Key Architectural Objectives:\n*   **The Foundation of Enterprise Clarity**: In large groups (up to 1,024 members), a single off-topic message can trigger a chain reaction of responses that buries important business updates. Announcement Mode provides a \"Noise-Floor\" of zero, allowing your business to use the group as a dedicated notification channel where every message is guaranteed to be from a verified official source.\n*   **The Power of Admin Authority**: This setting is a \"Privileged Toggle.\" To successfully lock or unlock the group's messaging permissions, your Wawp instance **must be a Group Admin**. This ensures that the control of the \"Microphone\" remains in the hands of the business account.\n*   **Seamless Global Enforcement**: Once the setting is flipped to `true`,\n  tips: [\n        {\n            type: 'positive',\n            title: 'Control',\n            content: 'Set to true to silence non-admins (Announcement Mode).'\n        },\n        {\n            type: 'info',\n            title: 'Reversible',\n            content: 'You can toggle this mode on/off as needed (e.g., open for Q&A, closed for night).'\n        }\n    ],\n  recommendations: [\n        \"Use Announcement Mode for official news channels.\",\n        \"Open the group for limited time windows to drive engagement.\",\n        \"Ensure admins are active to moderate if you open the floor.\"\n    ]\n  \n   the \"Message\" input field on every participant's device is instantly replaced by a system notice (*\"Only admins can send messages\"*). Metadata propagation is near-instant, providing a consistent global boundary for the conversation.\n\n---\n\n## 🚀 Strategic Use Cases: High-Impact Alerts and \"Quiet Hours\"\n\nAnnouncement Mode should not be seen as a permanent gag order, but as a dynamic \"Conversational Gearbox\" that your system can shift into depending on the business context.\n\n### 1. The \"Broadcast-First\" Crisis Escalation\nDuring a service outage or a critical incident, you may need to reach hundreds of stakeholders with precise, authoritative updates. By calling the **Set Messages Admin Only** endpoint at the start of the crisis, you ensure that the group remains a \"Clear Channel\" for your incident commanders. This prevents participants from flooding the chat with \"Is it down for you too?\" messages, which would distract the technical teams and obscure the official status reports.\n\n### 2. The \"Event-Driven Interaction\" Cycle\nImagine a daily webinar or a field service coordination group. During the \"Briefing Phase,\" the system locks the group to ensure everyone reads the instructions. Once the briefing is complete, the system calls the endpoint with `value: false`, \"Opening the Floor\" for a 15-minute Q&A session. Finally, at the end of the day, the system re-locks the group to prevent \"Late-Night Noise\" from disturbing participants. This \"Active Duty Cycle\" reflects a professional, time-sensitive management style.\n\n### 3. Automated Throttling During Resource Saturation\nIf your business logic detects that your human agents are being overwhelmed by a burst of incoming messages in a specific group (e.g., during a controversial marketing launch), your system can automatically trigger **Announcement Mode** as a \"Circuit Breaker.\" This provides your team with the \"Breathing Room\" needed to categorize existing requests before opening the floodgates again.\n\n---\n\n## 🔐 Administrative Mandate: Authority and Policy Governance\n\nControlling the \"Voice\" of the group is the ultimate act of moderation.\n\n### Centralizing the \"Source of Truth\"\nWhen a group is in Announcement Mode, every message has the implicit weight of the business's authority. This makes it the perfect state for:\n*   **Policy Updates**: Sharing new terms of service or compliance mandates.\n*   **Logistics Coordination**: Sending bus routes, room numbers, or schedule shifts.\n*   **KYC Reminders**: Informing a cohort of users that they need to complete a verification step.\nBecause participants cannot reply, these messages become \"System Records\" that users can rely on as the definitive truth.\n\n### Structural Integrity in Community Governance\nFor volunteer-led communities, the ability to lock the chat is the primary tool for **Moderation Enforcement**. If a discussion becomes heated or violates group standards, your automated moderator can call this endpoint to initiate a \"Cool-down Period.\" This forces a pause in the interaction, allowing emotions to settle before the channel is reopened.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Engagement Timing\n\n*   **The \"Polite Lock\" Pattern**: Always precede a lock (`value: true`) with an explanatory message (e.g., *\"We are moving into Announcement Mode for the next hour to share project updates. The floor will be reopened at 2:00 PM.\"*). This maintains a positive user experience and prevents users from feeling \"Silenced\" without cause.\n*   **Time-Zone Awareness**: Be mindful of when you unlock a group. Reopening the floor for 500 participants at 3:00 AM in their local time zone can lead to a flood of notifications that disturb their sleep, leading to group exits.\n*   **Admin Participation Strategy**: Remember that all admins can still speak even when the group is locked. This allows you to have a \"Multi-Voice\" broadcast where your primary instance sends the alerts, while human managers provide additional context, all while the general population remains in a \"Listen-Only\" posture.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Verify Admin Permissions**: You cannot change the security settings of a group if you are not an admin. Always perform a pre-flight check via [Get Group Info](/v2/groups/{id}) to ensure your instance has the authority to execute the toggle.\n2.  **Idempotent State Management**: If your system needs to ensure a broadcast-only environment, sending `value: true` repeatedly is a safe, no-op operation. This allows you to tie the \"Locking State\" to your internal cron jobs or alert triggers without complex logic.\n3.  **Webhook Integration**: Listen for [`group.update`](/v2/webhooks/group-update) events. This allows your backend to track the *actual* state of the group's \"Microphone.\" If a human admin unlocks the group manually, your system can detect it and re-lock it if it violates your automated governance policy.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Focused Conversation\n\nThe **Set Messages Admin Only** endpoint is the \"Conductor's Baton\" of your community architecture. It is your primary tool for managing engagement density, enforcing clarity, and ensuring that your organization's voice remains the loudest and clearest in the room. By treating the \"Voice\" of the group as a dynamic, programmable resource, you build a conversational ecosystem that respects your users' attention and guarantees the delivery of your most critical business assets. You move beyond \"Simple Chatting\" and into the world of **High-Fidelity Broadcast Orchestration**, where every word counts and every silence is strategic.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "value",
            "in": "query",
            "required": true,
            "description": "True to restrict to admins, false to allow all",
            "schema": {
              "type": "boolean"
            },
            "example": "true"
          }
        ],
        "responses": {
          "200": {
            "description": "Setting updated",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/invite-code": {
      "get": {
        "operationId": "_v2_groups_id_invite-code_get",
        "summary": "Get the invite code for the group",
        "description": "Get the current invite code for the group.\n\n### Developer Tips\n- **Security**: Anyone with this code can join. Treat it like a password.\n- **Format**: Returns a full URL (https://chat.whatsapp.com/...) and the raw code.\n\n\n# The Key to the Kingdom: Mastering the Distribution of Group Access\n\nIn the landscape of conversational growth, scale is achieved through friction-free entry. The **Get Invite Code** endpoint is your primary tool for **Strategic Access Management and Community Expansion**. While traditional participant management relies on direct \"Add\" operations—which require the business to have the user's contact saved—Invite Codes reverse the onboarding flow. They provide a portable, cryptographically secure token that allows any user to programmatically bridge themselves into your community. By retrieving this code via the API, you turn the \"Closed Gate\" of a private group into an \"Open Door\" that can be integrated into your website, your email campaigns, and your QR codes.\n\nFor enterprise architects, the invite code is the **Growth Engine** of the ecosystem. This guide explores the strategic imperatives of code-driven membership and the stewardship of entry rights.\n\n---\n\n## 🏗️ Architectural Philosophy: The Relationship Between JIDs and Tokens\n\nFrom a technical perspective, an invite code is a **Public Proxy for a Private Identifier**.\n\n### Key Architectural Objectives:\n*   **Decoupling Discovery from Identity**: A Global-JID (`@g.us`) is an internal identifier that is difficult for a regular user to use directly. The invite code provides a user-friendly, textual representation (`chat.whatsapp.com/ABC123...`) that the WhatsApp mobile app can instantly resolve. By retrieving this code, your system creates a \"Portable Link\" that travels through the public internet, ready to be resolved by the first user who clicks it.\n*   **The Power of Admin Stewardship**: Only a Group Admin can retrieve or manage the group's invite code. This ensures that the generation of entry links is a governed act. If your Wawp instance is a regular member, your request for the code will be denied, protecting the group's privacy from unauthorized link extraction.\n*   **Persistence and Volatility**: An invite code is persistent until it is explicitly [Revoked](/v2/groups/invite-code/revoke). This allows you to print a QR code on a billboard or include a link in a monthly newsletter, confident that it will remain functional for the life of the campaign unless you choose to reset it for security reasons.\n\n---\n\n## 🚀 Strategic Use Case: High-Velocity Acquisition and Funnel Integration\n\nThe invite code is the ultimate \"Call to Action\" for modern conversational marketing.\n\n### 1. The \"Zero-Friction\" Landing Page Funnel\nTraditionally, a customer has to \"Message us first\" to start a relationship. With the **Get Invite Code** endpoint, you can place a \"Join our VIP Community\" button directly on your checkout page or in an abandoned cart email. When the user clicks, they are instantly transported into your branded group environment. This eliminates the \"Add to Contacts\" friction, significantly increasing the conversion rate from a lead to a community member.\n\n### 2. Physical-to-Digital Bridge (QR Code Orchestration)\nFor events, retail stores, or packaged goods, the invite code is the primary link to a digital support group. Your system can programmatically retrieve the code for a specific regional group and generate a dynamic QR code for a store display. Customers can scan the code to instantly join a support group for that specific location, creating a \"Hyper-Local\" conversational layer that is centrally managed by your API.\n\n### 3. \"Viral\" Community Expansion\nIn customer loyalty programs, you can encourage existing members to \"Invite a Friend.\" By retrieving the invite code and sharing it with a loyal member, you empower them to act as a growth agent for your brand. Because the invite link is \"Native\" to WhatsApp, it is easily forwarded within the app, creating an organic sharing loop that allows your communities to grow exponentially without increasing your CAC (Customer Acquisition Cost).\n\n---\n\n## 🔐 Administrative Mandate: The Stewardship of Entry Rights\n\nWhile invite codes enable scale, they also introduce a unique security surface area. Anyone with the link can join the room.\n\n### Governance of the \"Open Gate\"\nThe invite code should be treated as a **Dynamic Permission**. We recommend that your system periodically rotates the code using the [Revoke Invite Code](/v2/groups/invite-code/revoke) endpoint. This \"Rotational Security\" ensures that old links found on cached Google pages or in legacy emails eventually stop working, allowing you to maintain control over the \"Cohort\" of users entering your groups at any given time.\n\n### Monitoring the \"Entry Pulse\"\nYour system should listen for the [`group.participants.update`](/v2/webhooks/group-participants-update) webhook. When a user joins via an invite code, the notification often includes a flag indicating the method of entry. By cross-referencing this with the time your API last retrieved the code, you can build \"Channel Analytics\"—measuring exactly which campaigns or websites are driving the most members into your WhatsApp communities.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency, Analytics, and Tracking\n\n*   **URL Prefixing for Professionalism**: When sharing the code, always present it as a full URL: `https://chat.whatsapp.com/{code}`. This ensures that every operating system (Android, iOS, Web) recognizes it as a clickable deep link.\n*   **Metadata Preparation**: Before sharing an invite code publicly, ensure that the group's [Name](/v2/groups/{id}/subject), [Icon](/v2/groups/{id}/picture), and [Description](/v2/groups/{id}/description) are professional and ready for a first-time visitor. The \"Join\" screen is your customer's first impression of your conversational brand.\n*   **Limit the Group Size**: WhatsApp groups have a current limit of 1,024 members. Your system should monitor the member count via [Get Group Info](/v2/groups/{id}). Once a group approaches 90% capacity, your backend should \"Switch\" its landing page links to point to the invite code of a newly created \"Secondary Cell\" group.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Check Admin Permissions**: Your request for the invite code will fail if the Wawp instance is not an admin. Always perform a pre-flight check or implement a retry-after-promotion logic to ensure your link-generation service is always functional.\n2.  **Graceful Handling of Revocation**: If your system has previously stored an invite code in a database and a human admin revokes it manually from their phone, the old code in your database will become dead. Your logic should include a \"Periodic Refresh\" or a \"Check-on-Click\" mechanism to ensure the links you are serving to customers are still active.\n3.  **Cross-Instance Synchronization**: If you use multiple WhatsApp accounts to manage the same group, ensure only the \"Primary Account\" is responsible for managing the invite link to avoid \"Link Conflict\" or accidental revocation by a secondary instance.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Accessible Community\n\nThe **Get Invite Code** endpoint is the \"Marketing Engine\" of your community architecture. It is your most powerful tool for building scalable, friction-free entries into your branded spaces. By treating the invite link as a dynamic, programmable asset, you move beyond \"Manual Onboarding\" and into the world of **Automated Acquisition**, where your communities grow in lockstep with your marketing reach. You bridge the gap between your web presence and your conversational world, ensuring that every customer is only one click away from a high-trust, professional interaction with your brand.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Invite code retrieved",
            "content": {
              "application/json": {
                "example": {
                  "code": "ABC123XYZ"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/invite-code/revoke": {
      "post": {
        "operationId": "_v2_groups_id_invite-code_revoke_post",
        "summary": "Invalidates the current group invite code and generates a new one",
        "description": "Revoke the current invite code and generate a new one.\n\n### Developer Tips\n- **Instant Effect**: The old invite link will stop working immediately.\n- **Auto-Gen**: A new code is automatically generated upon revocation.\n\n\n# Retracting the Welcome: The Strategic Power of Access Revocation\n\nIn the lifecycle of a growing community, the ability to open a door is only half of the governance required; the other half is the ability to change the lock. The **Revoke Invite Code** endpoint is your primary tool for **Strategic Access Nullification and Perimeter Defense**. It allows you to programmatically invalidate the current public-facing invite link (`chat.whatsapp.com/...`) and replace it with a fresh, secure token. This endpoint is the essential counterbalance to the [Get Invite Code](/v2/groups/{id}/invite-code) API, ensuring that your growth remains governed, your cohorts remain isolated, and your group's security perimeter can be rapidly reset in the event of an unauthorized link leak.\n\nFor enterprise architects, revocation is the act of **Reclaiming the Gateway**. This guide explores the strategic imperatives of token rotation and the enforcement of disciplined access lifecycles.\n\n---\n\n## 🏗️ Architectural Philosophy: The Invalidation of Public Tokens\n\nFrom a technical perspective, revoking an invite code is an **Atomically Destructive State Transition**.\n\n### Key Architectural Objectives:\n*   **Immediate Access Severance**: The moment this call is executed, the old invite code is purged from Meta's global resolution directory. Any user who clicks on a legacy link will be met with an \"Invite link has been reset\" or \"This group doesn't exist\" message. This \"Instant Blackhole\" is critical for stopping an influx of unwanted participants who have discovered a link on an unauthorized forum or social media post.\n*   **Mandatory Generation of the New State**: A unique feature of this endpoint is that it doesn't just delete the old code; it **Gives You the New One** in the same response. This ensures that the group always has a functional invite path for your administrative systems, even as you retire the public-facing one.\n*   **The Power of Admin Sovereignty**: Revocation is a high-authority act. Your Wawp instance **must be a Group Admin** to execute this call. This prevents participants from trying to sabotage your growth funnels by maliciously resetting the link.\n\n---\n\n## 🚀 Strategic Use Case: Cohort Isolation and Campaign Discipline\n\nRevocation should be integrated into your \"Campaign Lifecycle\" to handle transition phases and security incidents.\n\n### 1. The \"Campaign Decommissioning\" Protocol\nMarketing campaigns are often time-bound. A \"Join our Black Friday VIP List\" link should not be active in July. By programmatically calling the **Revoke Invite Code** endpoint at the end of a marketing window, you ensure that your \"Black Friday\" group doesn't continue to collect \"Zombie Participants\" who stumble upon the link months later. This allows you to \"Seal the Cohort,\" ensuring that the group remains focused on the specific audience it was created for.\n\n### 2. Rotational Security for High-Value Groups\nFor high-security operations (like a corporate whistleblower group or a high-value transaction hub), an invite link may be shared with a specific stakeholder via email. Once that stakeholder has [Joined](/v2/groups/join), the \"One-Time Use\" policy should be enforced. Your system can listen for the join webhook and immediately call the **Revoke Invite Code** endpoint to invalidate the link. This \"Just-in-Time Revocation\" ensures that the link cannot be forwarded or reused by unauthorized third parties.\n\n### 3. Immediate \"Bot Attack\" Mitigation\nIf your system detects a sudden, rapid influx of unauthorized users (a common sign of a bot attack or a link leak), your \"Breaker Logic\" should trigger an immediate revocation. By resetting the link, you instantly \"Shut the Gate,\" allowing your human moderation team to [Prune](/v2/groups/{id}/participants/remove) the interlopers while your automated backend generates a new, secure link for legitimate distribution.\n\n---\n\n## 🔐 Administrative Mandate: Authority and Boundary Stewardship\n\nIn an enterprise setting, an invite link is a liability that must be actively managed.\n\n### Tracking the \"Token Lineage\"\nYour backend should maintain a history of all invite codes generated for a specific group. This allows you to perform \"Attribution Analysis\"—if an unauthorized user joins, you can check which retired code they attempted to use (if the network permits) or at least know which \"Campaign Window\" was compromised. Revocation is the \"Red Ink\" in the audit log that marks the end of a specific access period.\n\n### Coordination with Physical Assets (Dynamic QRs)\nIf you are using dynamic QR codes in retail locations, ensure your QR generator is \"Aware\" of the revocation. When you rotate the code, your generator must update its target URL to the new code returned by the API. If your QR codes are static (printed on packaging), **Do Not Revoke the Code** unless it is a dire security emergency, as it will render all physical packaging useless. This illustrates the importance of using \"Redirector Links\" for any physical branding.\n\n---\n\n## 🛡️ Operational Best Practices: Professionalism and Graceful Transitions\n\n*   **The \"Notice of Reset\" Pattern**: If you are rotating a link that is currently being used by a legitimate partner or team, send them the new link *before* you revoke the old one to avoid \"Access Gaps.\"\n*   **Internal State Reconciliation**: Upon successful revocation, update your internal database with the new code immediately. Any \"Join Link\" buttons on your website or dashboard must be synchronized to the new token to prevent a \"Broken Link\" experience for your customers.\n*   **Avoid \"Chatter\" Revocation**: Revoking a link multiple times in a few minutes is unnecessary and can lead to synchronization lag across Meta's global CDN. Stick to a \"Schedule-Driven\" or \"Incident-Driven\" rotation policy.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Verify Admin Status**: Like all administrative tools, your request will fail with a 403 if your instance has been demoted. Implement a \"Governance Watchdog\" that ensures your instance's authority is verified before attempting high-security tasks like revocation.\n2.  **Graceful Response Handling**: The API returns the new code in the success object. Ensure your code captures this value and propagates it to your marketing systems. A failure to update the link after a revocation is a self-inflicted \"Denial of Service\" attack on your own funnels.\n3.  **Webhook Integration**: Listen for [`group.update`](/v2/webhooks/group-update) events. This allows your backend to detect if a human admin has revoked the link via the mobile app, ensuring your database and the network's reality are always aligned.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Governed Access\n\nThe **Revoke Invite Code** endpoint is the \"Security Shield\" of your community architecture. It allows you to maintain absolute control over the gateways to your private conversations, enabling you to scale without fear of unauthorized access. By treating the invite link as a temporary, rotating token rather than a permanent asset, you build a conversational environment that is resilient, disciplined, and always aligned with your organization's highest standards of governance. You move beyond \"Open-Door\" policies and into the world of **Managed Access Orchestration**, where every entry is a choice and every link is a controlled instrument of growth.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Invite code revoked and recreated",
            "content": {
              "application/json": {
                "example": {
                  "code": "NEW456DEF"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/participants": {
      "get": {
        "operationId": "_v2_groups_id_participants_get",
        "summary": "Get participants",
        "description": "Retrieve a list of all participants in the group.\n\n### Developer Tips\n- **Scaling**: Large groups return large arrays. Handle pagination or timeouts.\n- **Roles**: The response includes the role (admin, superadmin, participant) of each user.\n\n\n# Demographic Intelligence: The Strategic Audit of Community Membership\n\nIn the orchestration of distributed human networks, understanding *who* is in the room is the foundation of engagement, security, and personalization. The **Get Participants** endpoint is your primary tool for **Strategic Demographic Auditing and Population Mapping**. It allows your automated systems to retrieve a comprehensive census of every JID (`@c.us`) currently associated with a specific WhatsApp group. Beyond a simple list of numbers, this endpoint provides the structural context required to differentiate between influencers (Admins), owners (Creators), and the general population, enabling your platform to tailor its logic to the specific hierarchy of the community.\n\nFor enterprise architects, the participant list is the **Raw Material of Targeting**. This guide explores the strategic imperatives of membership auditing and the governance of group identity.\n\n---\n\n## 🏗️ Architectural Philosophy: Retrieving the Population State\n\nFrom a technical perspective, the Get Participants endpoint is a **State Snapshot of a One-to-Many Mapping**.\n\n### Key Architectural Objectives:\n*   **The Authority Matrix**: Every participant object in the response includes critical boolean flags: `isAdmin` and `isSuperAdmin` (Creator). By retrieving this list, your system builds an \"Authority Map,\" allowing it to know exactly which users have the power to [Add](/v2/groups/{id}/participants/add) or [Remove](/v2/groups/{id}/participants/remove) others. This is essential for building moderated systems that respect the existing human power structure within the chat.\n*   **Real-Time Population Integrity**: WhatsApp groups are fluid; members join and leave constantly. The Get Participants API provides a \"Synchronized Baseline,\" ensuring that your system's internal record of the group's \"Census\" matches the ground truth on Meta's servers. This is critical for preventing \"Ghost Messaging\" to members who have already left or ignoring new members who have just arrived.\n*   **Decoupling Presence from Contacts**: Your instance can see and list all participants in a group even if those users aren't in your official phone contact list. This \"Native Discovery\" is what allows business bots to interact with an unlimited number of customers without the friction of manual contact saving.\n\n---\n\n## 🚀 Strategic Use Case: Target Segmentation and Automated Whitelisting\n\nThe participant list is more than just a registry; it is a signal for automated business logic.\n\n### 1. The \"VIP Tier\" Dynamic Segmentation\nYour system can periodically audit the membership of high-value support groups. If it detects a specific \"Power User\" (identified by their JID in your CRM) is present in multiple groups, the system can automatically flag them for a \"Premium Experience\" or [Promote](/v2/groups/{id}/admin/promote) them to a moderator role. This \"Automated Meritocracy\" ensures that your most important stakeholders are always recognized and empowered within your conversational ecosystem.\n\n### 2. Forensic Auditing and Compliance Verification\nIn regulated sectors (like Healthcare or Finance), knowing who has access to a conversation is a legal requirement. Your system should perform a \"Compliance Audit\" every 24 hours. By calling the **Get Participants** endpoint and comparing the list against your internal \"Authorized Stakeholder Whitelist,\" you can detect \"Unauthorized Observers\"—users who were added manually by a human but who shouldn't have access to sensitive data. The system can then automatically [Remove](/v2/groups/{id}/participants/remove) them, maintaining your organization's regulatory posture.\n\n### 3. Audience Synchronizing for Multi-Channel Orchestration\nIf you are running a combined Email and WhatsApp campaign, the Group Participant list is your \"Source of Truth\" for the WhatsApp segment. Your system can extract the JIDs, map them to email addresses in your CRM, and ensure that a user who receives a \"Group Update\" on WhatsApp also receives the detailed \"Follow-up Report\" via email. This cross-channel synchronization turns a simple chat group into a sophisticated, multi-touch engagement engine.\n\n---\n\n## 🔐 Administrative Mandate: Privacy and the Governance of Identity\n\nManaging a list of human identifiers is a high-responsibility task that requires strict governance.\n\n### Protecting the \"Digital Footprint\"\nGroup participant lists are sensitive data. Your system should ensure that only authorized senior agents or specific automated controllers can access the raw participant data. In your platform's UI, consider masking parts of the phone number for regular agents, while allowing the \"Master Logic\" to use the full JID for routing and personalization. The **Get Participants** endpoint is the \"Secure Feed\" that your platform must protect.\n\n### Handling \"Group Saturation\" (Large Group Logic)\nWhatsApp groups currently support up to 1,024 members. When your system retrieves a participant list for a group nearing this limit, the response can be large. Your backend infrastructure should be optimized to parse these arrays efficiently. We recommend implementing \"Differential Updates\"—comparing the new list with the previous one and only processing the *changes* (joins/leaves)—to minimize the database load and keep your targeting logic responsive.\n\n---\n\n## 🛡️ Operational Best Practices: Consistency and Reconciliation\n\n*   **The \"Welcome Bot\" Trigger**: While the [`group.participants.update`](/v2/webhooks/group-participants-update) webhook is great for real-time events, the **Get Participants** endpoint is your \"Reconciliation Guardrail.\" If your system is unsure about a user's current status, a single GET call provides the definitive answer.\n*   **Staggered Audits**: For organizations managing thousands of groups, avoid auditing every participant list at the same time. Stagger your audits over a 24-hour cycle to distribute the API load and ensure a consistent flow of demographic intelligence.\n*   **Integrity Checks after Migration**: If you move your business logic from one WhatsApp account to another, use the Get Participants API to \"Verify the Handover.\" Ensure that all members from the old groups have been successfully onboarded into the new ecosystem.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Check Instance Membership**: You cannot retrieve the participant list for a group you are not a member of. Attempting to do so will return a 404 or 403 error. Always perform a pre-flight check to ensure your instance is present in the channel.\n2.  **Handle Admin State Mapping**: Remember that `isAdmin` is a state that can change at any time. Your system should not \"Cache and Forget\" this value. The Get Participants call should be treated as a \"Live View\" that expires quickly.\n3.  **Webhook Synchronization**: Professional systems should use a \"Hybrid Model\": listen for webhooks for 99% of updates, and use the **Get Participants** API as the \"Authority\" for 1% of edge cases or system re-initializations.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Populated Community\n\nThe **Get Participants** endpoint is the \"Census Bureau\" of your community architecture. It is your most powerful tool for understanding your audience, enforcing security, and personalizing the conversational experience at scale. By treating the participant list as a dynamic, programmable map of authority and identity, you build a conversational ecosystem that is resilient, compliant, and always perfectly targeted. You move beyond \"Sending Messages into a Void\" and into the world of **Structured Demographic Orchestration**, where every interaction is informed by exactly who is listening and who has the power to lead.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          }
        ],
        "responses": {
          "200": {
            "description": "Participants retrieved",
            "content": {
              "application/json": {
                "example": [
                  {
                    "id": "1234567890@c.us",
                    "isAdmin": true,
                    "isSuperAdmin": false
                  }
                ]
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/participants/add": {
      "post": {
        "operationId": "_v2_groups_id_participants_add_post",
        "summary": "Add participants",
        "description": "Add one or more participants to the group.\n\n### Developer Tips\n- **Privacy**: Users can block being added to groups by strangers.\n- **Failures**: If an add fails, you may need to send an invite link instead.\n\n\n# Expanding the Circle of Trust: The Strategic Orchestration of Participants\n\nIn the architecture of a managed community, the **Add Participants** endpoint is the primary mechanism for scaling interaction and introducing new voices into a shared state. It is not merely a technical bridge to increase a group's headcount; it is a strategic operation that determines who enters your community's \"Trust Zone\" and how your business scales its collaborative reaching. By programmatically managing membership, you shift from the reactive manual addition of users to a proactive, event-driven orchestration model where participants are injected into conversations precisely when their presence is required by the business workflow.\n\nSuccessful community scaling requires a deep understanding of **Governance, Consent, and Systemic Trust**. This guide explores the architectural nuances of participant expansion within the WhatsApp ecosystem.\n\n---\n\n## 🏗️ Architectural Philosophy: The Convergence of Identity and Authority\n\nFrom a system design perspective, adding a participant is an **Authorization Event**. You are granting a specific JID (WhatsApp ID) access to the persistent message history and metadata of a community.\n\n### Key Architectural Objectives:\n*   **The Power of Admin Rights**: Adding participants is a privileged operation. To execute this call, your Wawp instance **must be a Group Admin**. If your instance has been demoted by another admin, the operation will fail with a 403 Forbidden error. Checking your instance's current authority via the [Get Group Info](/v2/groups/{id}) endpoint before attempting a participant expansion is a critical component of a \"Validation-First\" architecture.\n*   **Synchronous State Updates**: When a participant is successfully added, the state change is instantly propagated to every existing member's device. This is often accompanied by a system-generated notice in the chat (e.g., *\"Business Name added [User]\"*). Your system should be prepared to follow this state change with a high-context welcome message, ensuring the new participant is instantly \"Hydrated\" with the group's purpose.\n*   **Multi-Participant Batching**: This endpoint allows for the addition of multiple JIDs in a single request. However, while technologically possible, batching should be used with strategic restraint to maintain a high account reputation score and avoid triggering \"Mass-Spam\" heuristics.\n\n---\n\n## 🚀 Navigating the \"Privacy Shield\": Direct Adds vs. Invite Fallbacks\n\nOne of the most frequent challenges in automated group management is the **WhatsApp Privacy Wall**. WhatsApp provides users with granular control over who can add them to groups.\n\n### The \"Permission Failure\" Scenario\nIf a user has set their privacy settings to \"My Contacts Only\" and your instance is not in their address book, a direct `add` operation will appear to succeed at the API level (returning a 200 OK) but the user will **not** actually appear in the group. This is intentional—it is a security feature designed by Meta to prevent unwanted group participation.\n\n### The \"Invite-as-Fallback\" Strategic Pattern\nTo build a resilient integration that guarantees a path to participation, your system should implement a **Verification and Link sequence**:\n1.  **Initial Add**: Attempt to add the user directly via this endpoint.\n2.  **State Audit**: After a few seconds, verify the group the membership list.\n3.  **Fallback**: If the user is missing from the list, automatically send them a 1:1 message containing the [Group Invite Link](/v2/groups/invite-code). This \"Hybrid Approach\" respects the user's privacy while still empowering them to join the conversation voluntarily.\n\n---\n\n## 🏭 Enterprise Workflow Patterns: Automated Context Injection\n\n### 1. The Dynamic \"Follow-the-Sun\" Support Desk\nIn a 24/7 global support environment, your \"Case Group\" needs to transition between shifts. As the European support lead finishes their day, your system automatically adds the North American shift manager to the group. This ensures that the customer's shared context remains unbroken, and the new expert is brought into the conversation with the full history of the troubleshooting steps already taken.\n\n### 2. The KYC & Verification \"War Room\"\nFor financial services or high-value onboarding, a group might start with just the customer and a bot. Once the bot collects the preliminary documentation, it automatically **Adds a Verification Specialist** to the group to perform a live identity check. This seamless transition from bot-to-human interaction within a single shared state creates a premium, high-fidelity experience for the user.\n\n### 3. The Onsite Event \"Breakout\" Coordination\nFor physical events or workshops, groups can be created for specific breakout sessions. As attendees scan an NFC tag or QR code at their table, the system adds them to the session's group. This allows the facilitator to blast slides, collect real-time polls, and coordinate group activity without requiring manual entry of every attendee's phone number.\n\n---\n\n## 🛡️ Security, Compliance, and the \"Social History\" Mandate\n\nAdding users to groups is a \"High-Sensitivity\" signal for Meta's security heuristics. To protect your business account from being flagged as a spam vector, follow these enterprise-governance principles:\n\n*   **Prioritize Pre-Existing Relationships**: Avoid \"Cold Adds.\" In a professional orchestration model, your system should only add users to a group who have already had at least one 1:1 interaction with your business account within the last 24-48 hours. This \"Social Warm-up\" signals to the WhatsApp network that the group addition is a legitimate continuation of an established dialogue.\n*   **Rate Throttling & Burst Management**: Avoid adding dozens of users to a group simultaneously. We recommend a \"Drip Addition\" approach—adding no more than 5-10 users per minute. This keeps the conversational \"Noise Level\" low for existing members and ensures steady, predictable performance from Meta's infrastructure.\n*   **Administrative Oversight of Members**: Always maintain a clear \"Audit Trail\" of who was added and by which business logic. This is essential for GDPR compliance and for internal security reviews if a participant later engages in prohibited behavior.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Check Group Capacity**: WhatsApp Groups are currently capped at **1,024 participants**. Before calling the Add endpoint, your system should check the current headcount. Attempting to add users to a full group will result in a failure that could have been avoided with a simple pre-flight check.\n2.  **Verify Participant Authenticity**: Ensure that the JIDs you are adding are correctly formatted (`@c.us`). Attempting to add group IDs (`@g.us`) or malformed strings will result in avoidable API errors.\n3.  **Idempotency & Resilience**: Adding a user who is already a member of the group is a safe, idempotent operation. It will not create a duplicate entry or return an error. This allows you to \"Re-Assert\" participation during a recovery workflow without fear of corrupting the group state.\n\n---\n\n## 🎯 Conclusion: Orchestrating the Scalable Human Touch\n\nThe **Add Participants** endpoint is the bridge between your automated logic and your human community. By treating the expansion of a group as a **Strategic Event** rather than a simple data entry task, you build a conversational architecture that is both powerful and governed. When used in conjunction with the [Invite Link API](/v2/groups/invite-code) and the [Roles API](/v2/groups-overview), it becomes a foundational tool for creating dynamic, high-fidelity environments where the right people are in the right room at exactly the right time.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "participants",
            "in": "query",
            "required": true,
            "description": "List of JIDs to add",
            "schema": {
              "type": "string"
            },
            "example": "[{\"id\":\"1234567890@c.us\"}]"
          }
        ],
        "responses": {
          "200": {
            "description": "Participants added",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/participants/remove": {
      "post": {
        "operationId": "_v2_groups_id_participants_remove_post",
        "summary": "Remove participants",
        "description": "Remove one or more participants from the group.\n\n### Developer Tips\n- **Admin Only**: Only group admins can remove participants.\n- **Notification**: The removed user will see a system message that you removed them.\n\n\n# Pruning the State: The Strategic Governance of Participant Removal\n\nIn the lifecycle of a managed community, the ability to selectively withdraw access is as critical as the ability to grant it. The **Remove Participants** endpoint is your primary tool for **Structural Governance and Security Enforcement**. It allows you to programmatically prune the membership list of a group, ensuring that only actively relevant stakeholders maintain access to the shared conversational state. By moving participant removal from a manual agent task to an automated business rule, you ensure that \"Community Drift\" is minimized and that your business remains in absolute control of its collaborative boundaries.\n\nEffective membership management requires a perspective that balances **Security, Professionalism, and Operational Efficiency**. This guide explores the architectural imperatives of governed participant removal.\n\n---\n\n## 🏗️ Architectural Philosophy: The Enforcement of State Boundaries\n\nFrom a technical perspective, removing a participant is a **Revocation of Authorization**. You are severing the link between a specific JID and the persistent group context.\n\n### Key Architectural Objectives:\n*   **Irrevocable Withdrawal of Context**: Once a participant is removed, they instantly lose access to the group's \"Pulse.\" While they may retain a cached history of previous messages on their local device, they can no longer see new messages, view updated metadata, or see the current participant list. This \"Instant Blackout\" is essential for protecting sensitive business information when a project ends or a stakeholder's role changes.\n*   **The Power of Admin Rights**: Removal is an \"Executive Power.\" To successfully execute this call, your Wawp instance **must be a Group Admin**. This ensures that the dismantling of a community's population is a governed act performed by an authorized authority. If your instance is a regular member, the operation will fail with a 403 Forbidden error, preventing unauthorized users from \"Self-Moderating\" the group.\n*   **System-Generated Accountability**: Every removal triggers a system notification in the chat (e.g., *\"Business Name removed [User]\"*). This creates a transparent audit trail for the remaining members, signaling that the community is actively managed and that standards are being enforced.\n\n---\n\n## 🚀 Strategic Use Cases: Workflow Transitions and Rotation\n\nThe Remove Participants endpoint should be integrated into your broader business logic to handle transitions between different phases of a relationship.\n\n### 1. Shift Rotation & Handover Management\nIn global 24/7 support operations, groups often serve as the bridge between time zones. As a support specialist in Asia completes their shift, your system can automatically **Remove them from the group** while simultaneously adding their counterpart in Europe. This keeps the \"Headcount\" of the group low and ensures that the customer is only interacting with the team currently on duty, reducing confusion and preventing \"Off-hours\" messages from reaching sleeping agents.\n\n### 2. The \"Resolved Ticket\" Pruning Protocol\nFor technical troubleshooting groups, once a bug is confirmed as \"Resolved\" in your CRM, the system should automatically remove all secondary technical experts (senior engineers, developers) while leaving only the account manager and the customer. This \"Pruning\" focuses the conversation on the final closure steps and prevents technical staff from being distracted by the social \"Thank you\" messages that follow a successful fix.\n\n### 3. Subscription & Access Expiry\nIf your business manages \"Premium Community Groups\" for paid members, the Remove Participants endpoint is your **Subscription Enforcer**. When a user's subscription expires in your database, the system triggers the removal call. This turns the WhatsApp group into an \"Access-Controlled Asset\" that is perfectly synchronized with your billing engine.\n\n---\n\n## 🔐 Security & Compliance: Revoking Access in Regulated Environments\n\nIn industries like Finance, Healthcare, and Legal Services, controlling who has access to a shared conversation is a regulatory mandate.\n\n### The \"Need-to-Know\" Enforcement\nThe Remove Participants endpoint allows your system to enforce the principle of \"Least Privilege.\" If a staff member leaves your organization or is moved to a different department, your system can perform a **\"Global Access Wipe\"**—scanning all active WhatsApp groups and removing that individual's JID from every shared state. This ensures that no former employee retains a \"Backdoor\" into ongoing customer conversations via their personal WhatsApp device.\n\n### Preventing \"Community Creep\"\nAs a group matures, it is common for the membership list to grow stale. The Get Group Info endpoint should be used to periodically audit the population. If a user has not interacted with the group for 30 days and is not a core stakeholder, your system can proactively remove them to maintain a \"High-Quality, High-Engagement\" environment.\n\n---\n\n## 🛡️ Operational Hygiene and Professionalism\n\nRemoving a user is a socially sensitive act. Your system should handle it with the same level of care as a welcome sequence.\n\n*   **The \"Exit Notice\" Pattern**: Before executing a hard removal, we recommend sending a polite automated message to the group or a 1:1 message to the user explaining why they are being removed (e.g., *\"Our project is now complete, so we are closing out the active working group. Thank you for your collaboration!\"*). This prevents the \"Kicked out\" feeling and maintains your brand's professional reputation.\n*   **Rate Management**: Like adding participants, removing them in bulk should be staggered. Removing 100 users in a single second can trigger security flags. Aim for a \"Drip Removal\" of 5-10 users per minute to ensure system stability and account safety.\n\n---\n\n## ⚙️ Engineering Best Practices: Validation and Resilience\n\n1.  **Verify Member Status Before Removal**: To avoid unnecessary API calls, use the [Get Group Info](/v2/groups/{id}) endpoint to verify that the target JID is actually a member of the group. Attempting to remove someone who isn't there will return an error that could have been avoided with a simple pre-flight check.\n2.  **Handle Creator Immunity**: Remember that the **Creator** of a group cannot be removed by any other admin. If your system attempts to remove the creator (e.g., your primary instance), the operation will fail at the network level. Your logic should always respect this \"Immunity\" to prevent deadlocks in your automation.\n3.  **Event-Driven Synchronization**: Ensure your backend listens for the [`group.participants.update`](/v2/webhooks/group-participants-update) webhook. When a removal is confirmed by the WhatsApp network, your system should update its internal membership cache to ensure that your agent dashboard always displays the accurate population of the room.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Governed Exit\n\nThe **Remove Participants** endpoint is the \"Shield\" of your community architecture. It allows you to maintain the integrity, security, and focus of your shared states. By treating membership pruning as a deliberate, strategic act rather than an afterthought, you build a conversational environment that is both efficient and professional. You ensure that every room your business owns is filled with exactly the right people, and that when their role is finished, they are transitioned out with precision and grace.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "participants",
            "in": "query",
            "required": true,
            "description": "List of JIDs to remove",
            "schema": {
              "type": "string"
            },
            "example": "[{\"id\":\"1234567890@c.us\"}]"
          }
        ],
        "responses": {
          "200": {
            "description": "Participants removed",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/admin/promote": {
      "post": {
        "operationId": "_v2_groups_id_admin_promote_post",
        "summary": "Promote participants to admin users",
        "description": "Promote one or more participants to group admins.\n\n### Developer Tips\n- **Admin Powers**: Admins can edit group info, add/remove users, and promote others.\n- **Trust**: Only promote trusted bots or humans. They can remove you (unless you are Creator).\n\n\n# Delegating Authority: The Strategic Elevation of Community Leaders\n\nIn the complex orchestration of enterprise WhatsApp groups, the **Promote Participants** endpoint is the primary tool for **Distributed Governance**. It allows you to programmatically elevate regular members to the status of Group Administrators, granting them the local authority required to manage the community natively from their own devices. This endpoint is the key to building \"Hybrid Moderation\" models where your Wawp instance provides the high-level automation, while trusted human stakeholders handle the day-to-day interpersonal management of the chat.\n\nFor architects, \"Promotion\" is the act of **Delegating State Control**. This guide explores the strategic implications of admin elevation and how to manage the privilege matrix effectively at scale.\n\n---\n\n## 🏗️ Architectural Philosophy: The Elevation of State Permissions\n\nFrom a technical perspective, promoting a participant is a **Permission Mask Update**. You are transitioning a JID from a \"ReadOnly/Interact\" state to a \"Write-Metadata/Manage-State\" state.\n\n### The Admin Privilege Matrix\nWhen a user is promoted via this endpoint, they gain a suite of local capabilities in their WhatsApp app that are previously restricted. A promoted admin can:\n*   **Modify Global Metadata**: Change the group subject, description, and profile picture (depending on group settings).\n*   **Manage the Population**: Add new members directly or remove existing ones.\n*   **Influence Governance**: Promote other members to admin (though they cannot demote the original [Creator](/v2/groups-overview)).\n*   **Enforce Silence**: Toggle the \"Announcement Mode\" to lock or unlock the group for participant messages.\n\n### The Power of the Super-Admin (API Creator)\nIt is vital to remember that while the API can create many admins, the Wawp instance that initialized the group remains the **Super-Admin/Creator**. This hierarchy ensures that even if a promoted admin attempts to be disruptive, your system maintains the \"Master Override\" capability. Promotion is a delegation of *operational* power, not *absolute* ownership.\n\n---\n\n## 🚀 Strategic Use Case: Hybrid Moderation and Human-in-the-Loop\n\nThe most effective community strategies combine the speed of AI with the nuance of human judgment.\n\n### 1. Enabling Local Autonomy for Field Agents\nIn a large-scale real estate or project management deployment, your system might create hundreds of groups. By automatically **Promoting the assigned field agent** to admin status, you empower them to manage the group \"on the fly\" while they are on-site with a client. They can add a subcontractor or change the group subject to reflect a status update without needing to log into a specialized CRM dashboard. The API handles the creation and initial setup, while the promotion grants the human agent the \"Boots-on-the-Ground\" flexibility they need.\n\n### 2. The \"Community Champion\" Incentive\nFor customer-facing communities (e.g., a fan group or a product feedback cohort), promotion can be used as a reward for high engagement. Your system can track message volume and sentiment; once a user crosses a specific \"Trust Threshold,\" the system automatically promotes them to admin, turning them into a volunteer moderator. This \"Automated Meritocracy\" helps scale community management without increasing your business's headcount.\n\n### 3. Escalation-Based Authority Injection\nIn a standard support group, agents might function as regular members to keep the power centralized. However, if your system detects a \"Critical Escalation\" (via keyword analysis or a sentiment trigger), it can instantly **Promote a Senior Manager** to admin status. This provides the manager with the immediate \"Executive Tools\" needed to lock down the group or remove disruptive parties during a crisis.\n\n---\n\n## 🔐 Security & Trust: Managing the Risk of Decentralized Authority\n\nGranting admin rights is a high-trust event that carries inherent risks. A rogue admin can create significant disruption before your automation can react.\n\n### The \"Governance Audit\" Cycle\nTo mitigate the risk of \"Admin Bloat,\" your system should implement a periodic audit. Using the [Get Group Info](/v2/groups/{id}) endpoint, your system should scan the membership list and compare the current admins against your internal \"Authorized Admin Whitelist.\" Any user found with admin rights who isn't on the whitelist can be automatically [Demoted](/v2/groups/{id}/admin/demote) to restore the governance baseline.\n\n### Participant Visibility and Compliance\nAdmin status grants a user more visibility into group activity. In regulated industries, you must ensure that only verified employees are ever promoted. Your system should cross-reference the JID of any promotion target with your internal HR or Active Directory records to prevent accidental elevation of a customer or a third-party contractor to a position of authority over the group state.\n\n---\n\n## 🛡️ Operational Hygiene and Best Practices\n\n*   **Idempotency of Elevation**: Promoting a user who is already an admin is a safe, no-op operation. This allows your system to \"Re-Assert\" authority during a recovery sequence without fearing errors or duplicate state changes.\n*   **Throttling Bulk Promotions**: While the endpoint allows for multiple JIDs, we recommend promoting individuals one by one or in small batches. Large numbers of simultaneous admin changes can sometimes be flagged by Meta's security heuristics as \"Account Hijacking\" patterns.\n*   **System Notifications & Professionalism**: Every promotion triggers a system notification in the chat (*\"Business Name made [User] an admin\"*). This is a public signal of trust. Your system should often follow this up with a 1:1 message to the newly promoted admin, providing them with a \"Moderator Guide\" or a list of responsibilities.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Verify Admin Status of the Instance**: Your Wawp instance must be a Group Admin to promote others. Always perform a pre-flight check of your own permissions before attempting to change the permissions of others.\n2.  **Verify Membership**: You cannot promote someone who is not currently a member of the group. Attempting to do so will result in an API error. A robust workflow includes an `Add -> Verify -> Promote` sequence for new stakeholders.\n3.  **Webhook Integration**: Ensure your system listens for the [`group.participants.update`](/v2/webhooks/group-participants-update) webhook. When the WhatsApp network confirms the promotion, your system should update its internal \"Authority Map\" so that your UI correctly identifies which users are moderators.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of Delegated Success\n\nThe **Promote Participants** endpoint is the tool that transforms a monolithic bot into a dynamic community ecosystem. By strategically delegating authority to trusted humans and secondary automated instances, you build a conversational architecture that is resilient, scalable, and responsive to the needs of its members. You empower your team to lead, while your system maintains the foundational governance that ensures the community's long-term health and alignment with your business goals.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "participants",
            "in": "query",
            "required": true,
            "description": "List of JIDs to promote",
            "schema": {
              "type": "string"
            },
            "example": "[{\"id\":\"1234567890@c.us\"}]"
          }
        ],
        "responses": {
          "200": {
            "description": "Participants promoted",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/groups/{id}/admin/demote": {
      "post": {
        "operationId": "_v2_groups_id_admin_demote_post",
        "summary": "Demotes participants to regular users",
        "description": "Demote one or more admins to regular participants.\n\n### Developer Tips\n- **Creator Immunity**: You cannot demote the group creator.\n- **Effect**: Demoted users become regular participants but remain in the group.\n\n\n# Restoring Governance: The Strategic Withdrawal of Administrative Authority\n\nIn the lifecycle of a managed community, authority is a fluid asset that must be actively governed. The **Demote Participants** endpoint is your primary tool for **Centralizing Control and Enforcing Procedural Discipline**. It allows you to programmatically revoke the administrative privileges of a user, returning them to the status of a regular member. This endpoint is the critical counterbalance to the [Promote API](/v2/groups/{id}/admin/promote), ensuring that your \"Hybrid Moderation\" model remains focused, secure, and aligned with your business's current operational requirements.\n\nFor enterprise architects, \"Demotion\" is the act of **Permission Reclamation**. This guide explores the strategic imperatives of administrative withdrawal and the enforcement of the hierarchy of trust.\n\n---\n\n## 🏗️ Architectural Philosophy: The Enforcement of Disciplined State\n\nFrom a technical perspective, demoting a participant is a **Restrictive State Transition**. You are narrowing the permission mask of a JID, removing their ability to influence the group's metadata and population.\n\n### Key Architectural Objectives:\n*   **The Power of the Master Admin**: Demotion is a \"Corrective Power.\" To successfully execute this call, your Wawp instance **must be a Group Admin**. This prevents regular members from attempting to \"Overthrow\" an admin. However, because your API instance is typically the [Creator](/v2/groups-overview) of the group, it possesses a unique \"Administrative Immunity\" that secondary admins can never challenge.\n*   **Instant Feature Lockdown**: When a user is demoted, their WhatsApp interface instantly updates. They lose the \"Edit Group Info\" option, the ability to add/remove members, and the ability to lock the group. This \"Instant Revocation\" is essential for mitigating the impact of a rogue moderator or a stakeholder whose role has changed.\n*   **Systemic Transparency**: Every demotion triggers a system notification in the chat (e.g., *\"Business Name removed [User] as an admin\"*). This is a public signal of your system's active governance, reinforcing that the community operates under a structured hierarchy.\n\n---\n\n## 🚀 Strategic Use Cases: Rotating Authority and Managing Compliance\n\nDemotion should be used as a routine component of your \"Governance Cycle\" rather than just a reactive measure.\n\n### 1. The \"Shift Handover\" Protocol\nIn a 24/7 global operations center, many staff members may be added to a VIP case group. To avoid having dozens of active admins (which increases the risk of accidental metadata changes), your system can implement a \"Just-in-Time\" authority model. As a shift ends, the system **Demotes the outgoing manager** while promoting the incoming one. This ensures that only the manager currently on duty has the \"Administrative Tools\" active on their device, minimizing operational clutter and risk.\n\n### 2. Moderation Probation and Meritocratic Governance\nIf your system utilizes volunteer moderators from your customer base, demotion serves as your primary tool for **Quality Enforcement**. If your sentiment analysis engine or a user report detects a moderator engaging in off-topic or disruptive behavior, the system can automatically demote them back to member status. This \"Automated Moderation Guardrail\" protects the group's health without requiring human oversight from your internal team.\n\n### 3. Transitioning from \"Active Project\" to \"Long-term Archival\"\nWhen a project moves from its \"Intensive Phase\" to a \"Maintenance Phase,\" the need for multiple active admins decreases. Your system can automatically demote all stakeholders—except for the primary account manager—to regular member status. This \"State Simplification\" signals to everyone in the group that the primary phase of collaboration has concluded and the channel is now in a monitored, low-activity state.\n\n---\n\n## 🔐 Security and Risk Management: The Rogue Admin Threat\n\nGranting admin status to a third party (like a client or a contractor) is a vulnerability. A rogue admin can maliciously clear the group's participants, change the name to something offensive, or lock out other admins.\n\n### The \"Auto-Correction\" Audit\nWe recommend running a \"Governance Audit\" every 60 minutes for high-value groups. Using the [Get Group Info](/v2/groups/{id}) endpoint, your system should verify the current admin list. If it finds a JID that has been promoted manually (bypassing your API logic) or a JID that should no longer have rights, it should immediately call the **Demote Participants** endpoint to restore the authorized state. This \"Anti-Tamper\" logic ensures your API remains the ultimate arbiter of the group's structure.\n\n### The Hierarchy of Demotion: Creator Immunity\nIn the WhatsApp ecosystem, the **Creator cannot be demoted**. This is a hard-coded security feature of the network. This means that if your Wawp instance created the group, it is physically impossible for any other admin (human or bot) to demote your instance. This \"Steel-Clad Anchor\" ensures that your business system always retains the master key to the conversation, regardless of how many temporary admins you appoint.\n\n---\n\n## 🛡️ Operational Hygiene and Professionalism\n\nDemoting a user is a socially sensitive event. Handled poorly, it can lead to frustration or a sense of being \"Punished.\"\n\n*   **The \"Rotation Notice\" Pattern**: Before executing a demotion for operational reasons (like a shift change), send a polite notice to the group or the individual (e.g., *\"Your moderator shift has concluded. Authority is being transitioned to [New User]. Thank you for your support!\"*).\n*   **Rate Throttling**: Avoid mass-demoting users in a single burst. Like all administrative actions, staggering the calls (5-10 demotions per minute) ensures system stability and reduces the risk of triggering Meta's security heuristics.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Check Admin Status Before Demoting**: Ensure the user you are trying to demote is actually an admin. Attempting to demote a regular member will result in an API error. Use [Get Group Info](/v2/groups/{id}) to perform this pre-flight verification.\n2.  **Verify Presence**: You cannot demote someone who is not a member of the group. If a user leaves the group, their admin status is automatically nullified by the network. Your system should listen for the [`group.participants.update`](/v2/webhooks/group-participants-update) webhook to keep your internal \"Authority Map\" current.\n3.  **Idempotent Recovery**: Demoting someone who is already a member is a safe, no-op operation. Use this to your advantage during system recovery or state reconciliation to ensure your groups are in the correct governance posture.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of Disciplined Management\n\nThe **Demote Participants** endpoint is the \"Check and Balance\" of your conversational architecture. It allows you to reclaim authority, mitigate risk, and maintain a clear hierarchy within your communities. By treating the withdrawal of permissions as a routine, strategic operation, you build a community ecosystem that is both flexible and highly governed. You ensure that power is only held by those who currently need it, and that your business system always remains the definitive source of truth and control.\n    ",
        "tags": [
          "Groups"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "The unique ID of the group",
            "schema": {
              "type": "string"
            },
            "example": "1234567890@g.us"
          },
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "participants",
            "in": "query",
            "required": true,
            "description": "List of JIDs to demote",
            "schema": {
              "type": "string"
            },
            "example": "[{\"id\":\"1234567890@c.us\"}]"
          }
        ],
        "responses": {
          "200": {
            "description": "Participants demoted",
            "content": {
              "application/json": {
                "example": {
                  "ok": true
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/media/convert": {
      "post": {
        "operationId": "_v2_media_convert_post",
        "summary": "Convert Media",
        "description": "Convert media files to WhatsApp-compatible formats (e.g., to OGG/Opus for voice notes).\n\n### Developer Tips\n- **File Limits**: Check file size limits for different media types before uploading.\n- **Mime Types**: Ensure the correct MIME type is specified for the media file.\n\n\n# The Transcoding Gateway: Architecting Format Fidelity for Global Mobile Distribution\n\nIn the heterogeneous world of digital media, \"compatibility\" is a moving target. For an enterprise handling millions of multi-format binary assets, the challenge is not just sending a file, but ensuring that the file is **immediately consumable** on any recipient device, regardless of their operating system or hardware age. The **Media Convert** endpoint is Wawp's specialized **Transcoding Infrastructure**, designed to bridge the gap between your raw business assets and WhatsApp's strict mobile-first requirements. \n\nBy acting as a real-time standardization layer, this endpoint transforms raw audio, video, and image signals into the exact bitrates, codecs, and containers optimized for the Meta network. This guide explores the strategic imperatives of media standardization and the architectural benefits of centralized transcoding.\n\n---\n\n## 🏗️ Architectural Philosophy: The Mandate of Standardization\n\nTo understand the necessity of the Media Convert API, one must first recognize the \"Silent Rejection\" problem in mobile messaging. If a business sends a high-bitrate .AVI file or an unoptimized .WAV through a WhatsApp channel, the recipient may receive the file, but their device may fail to play it natively, or it may appear as a \"Generic Attachment\" rather than an interactive media object.\n\n### 1. Codec Optimization and the \"Play-Ready\" State\nThe Media Convert endpoint ensures that every asset is in a **Play-Ready State**. \n*   **Audio and the Opus Paradox**: Standard MP3 files, while universal on the web, are handled by WhatsApp as \"Audio Files.\" They appear with a generic icon and require the user to download them before playing. However, if that same audio is transcoded into the **OGG container with the Opus codec**, it is recognized by WhatsApp as a \"Voice Note.\" This creates the signature blue-microphone experience, allowing for one-tap listening and variable-speed playback. The Media Convert API makes this transformation programmatic and effortless.\n*   **Video and Bitrate Balancing**: Sending a 4K 60FPS video to a user on a low-end device or a limited data plan on the other side of the world often leads to a poor experience. The Transcoding Gateway applies \"Strategic Compression,\" maintaining visual fidelity while optimizing file size for the rapid transit and display constraints of the mobile ecosystem.\n\n### 2. Centralized vs. Distributed Transcoding\nWhile a developer could manage their own FFmpeg cluster to handle these conversions, doing so introduces significant operational overhead, latency, and technical debt. Wawp's Media Convert API provides a **Serverless Transcoding Layer**. Your application simply provides a URL to the source media, and the API handles the compute-intensive task of re-encoding, returning a new, optimized binary URL ready for delivery. This allows your team to focus on business logic rather than binary mathematics.\n\n---\n\n## 🚀 Strategic Use Cases: Empowering Automated Media Flows\n\nCentralized conversion is the \"Secret Sauce\" of premium automated customer experiences.\n\n### 1. The \"Human Bot\" (Voice Note Automation)\nImagine a customer service bot that handles account inquiries. Instead of a text-only interaction, the bot responds with a voice message: *\"Hello! Your refund has been processed. Is there anything else I can help with today?\"* To achieve this, your system generates raw audio from a Text-to-Speech (TTS) engine, uses the **Media Convert** endpoint to standardize it into OGG/Opus, and delivers it as a native voice note. This adds a layer of empathy and personality to your automation that text alone cannot achieve.\n\n### 2. Cross-Channel Content Synchronization\nYour marketing team may produce high-quality videos for Instagram or YouTube. These videos are often high-resolution and high-bitrate. Before distributing these at scale through a [WhatsApp Channel](/v2/channels) or a broadcast list, the **Media Convert** API can \"Sandwich\" them into a WhatsApp-compatible MP4 format. This ensures that every subscriber, from the latest iPhone user to a legacy Android user, sees the vision exactly as the creative team intended, with zero buffering or playback errors.\n\n### 3. Safety and Sanitization through Transcoding\nMalicious files are often disguised as media. By passing every user-uploaded image or document through a \"Rounding\" transcode process, you effectively \"Sanitize\" the file. The re-encoding process strips away non-essential metadata (EXIF data, potential macro-active code) and regenerates the binary from scratch. This creates a \"Logical Firewall,\" ensuring that the files living in your enterprise storage are clean, standardized, and safe for your internal team to open.\n\n---\n\n## 🛡️ Administrative Mandate: Protecting the User Experience (UX)\n\nConsistency is the cornerstone of brand trust. If your bot's media delivery is inconsistent—sometimes working, sometimes showing \"Format not supported\"—your users will lose confidence in the channel.\n\n### The \"Frictionless Consumption\" Guarantee\nBy religiously using the **Media Convert** endpoint for every outbound asset, you guarantee that your content is frictionless. You move the \"Heavy Lifting\" of compatibility from the user's phone (where battery life and data are precious) to the Wawp cloud. This respect for the user's resources is a subtle but powerful brand signal that separates enterprise-grade platforms from basic implementations.\n\n### Monitoring \"Transcoding Velocity\"\nThe Media Convert API should be integrated into your analytics dashboard. Track how long your average conversion takes. For time-sensitive alerts (like emergency updates or real-time news), use \"Pre-transcoding\"—prepare the WhatsApp-optimized version of an asset the moment it is uploaded to your CMS, so it is ready for instant delivery when the broadcast trigger is pulled.\n\n---\n\n## 🛡️ Operational Best Practices: Optimization and Resource Stewardship\n\n*   **The \"Format First\" Policy**: Always check the source file's metadata before sending. If the file is already in a compatible format, skip the conversion to save time and resources. Use the Media Convert API only for \"Legacy\" or \"High-Fidelity\" sources that require standardization.\n*   **Caching Converted Assets**: Media conversion is a deterministic operation. If you convert \"WelcomeVideo.mov\" into \"WelcomeVideo.mp4\" once, store that MP4 URL in your database. Do not re-convert the same asset for every user; reuse the cached version to minimize latency and costs.\n*   **Managing Aspect Ratios**: WhatsApp favors certain aspect ratios for different UI elements (e.g., 1:1 for profile pictures, 9:16 for status updates). Use the \"Orientation Aware\" logic in your transcoding recipes to ensure your content is never stretched or distorted.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Monitor Target MIME Types**: Ensure you are requesting the correct output format for the intended message type. If you are sending a document, stick to PDF. If you are sending a voice note, always use OGG/Opus. \n2.  **Handle Conversion Errors Gracefully**: If a source file is corrupted or in an unsupported container (like an ancient .FLV), the conversion may fail. Your application should be prepared to \"Fall back\" to a lower-level document attachment or notify an administrator that the asset requires manual intervention.\n3.  **Coordinate with Download Timings**: Since the Media Convert API requires a public URL to the source, ensure your source server (e.g., S3) has granted appropriate \"Read\" permissions to the Wawp service. Use short-lived presigned URLs for security during the conversion transit.\n\n---\n\n## 🎯 Conclusion: Mastery of the Global Media Signal\n\nThe **Media Convert** endpoint is the \"Translator\" of your visual and auditory strategy. It bridge the gap between your enterprise content library and the diverse, global reality of the WhatsApp mobile network. By treating transcoding as a strategic prerequisite for engagement, you ensure that your brand's voice is always clear, your vision is always crisp, and your documents are always accessible. You move beyond \"Hopeful Sending\" and into the world of **Engineered Compatibility**, where every media interaction is a guaranteed win for the user's experience.\n    ",
        "tags": [
          "Media"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "file",
            "in": "query",
            "required": true,
            "description": "File to convert (URL, filename, mimetype)",
            "schema": {
              "type": "string"
            },
            "example": "{\"url\":\"https://example.com/audio.mp3\",\"filename\":\"audio.mp3\",\"mimetype\":\"audio/mpeg\"}"
          },
          {
            "name": "outputFormat",
            "in": "query",
            "required": true,
            "description": "Desired output format (ogg, mp4, etc.)",
            "schema": {
              "type": "string"
            },
            "example": "ogg"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    },
    "/session.status": {
      "post": {
        "operationId": "_session.status_post",
        "summary": "Session Status Change",
        "description": "This event is triggered when the session status changes (e.g., from WORKING to STOPPED).\n\n### Developer Tips\n- **Uptime Monitoring**: Use this event to detect if your WhatsApp instance goes offline so you can alert your support team or trigger an automated restart.\n- **Status Mapping**: The 'status' field returns values like WORKING, STOPPED, and SCAN_QR_CODE.\n\n\n# The Engine Heartbeat: Connectivity Governance and Instance Lifecycle\n\nIn the orchestration of high-scale enterprise messaging, connectivity is not a binary state—it is a dynamic lifecycle. The **Session Status Change** webhook is the definitive signal that informs your infrastructure of the health, availability, and authentication status of your underlying WhatsApp engine. It is the \"Heartbeat Monitor\" of your community and a non-negotiable component of any resilient communication strategy.\n\nThis guide provides a strategic overview of the session lifecycle, exploring how to use status events to build a proactive, self-healing architecture that maximizes uptime and minimizes human intervention.\n\n---\n\n## 🏗️ Architectural Philosophy: Status as a Prerequisite for Action\n\nTo build a reliable WhatsApp integration, your system must operate with \"Connectivity Awareness.\" Attempting to send a high-priority message to a disconnected instance is a waste of compute resources and a risk to business continuity. The [`session.status`] webhook transforms your system from a \"Hopeful Messenger\" into a **Strategic Governor**.\n\n### 1. The State Machine of the WhatsApp Engine\nThe Wawp platform manages a complex state machine for every instance. Each status value represents a specific operational phase:\n*   **WORKING (The Operational Goal)**: This is the only state where the engine can perform full read/write operations. A strategic architecture uses this status as a \"Green Light\" for its outbound message queues. When an instance moves away from this state, your system should automatically \"Pause\" its outbound traffic to prevent delivery failures and quota waste.\n*   **SCAN_QR_CODE (The Gateway to Identity)**: This is a high-priority event signaling that the instance is unauthenticated. By reacting to this webhook, your system can trigger an automated notification to an administrator's internal dashboard or even send a specialized email containing the QR code for instant re-linking.\n*   **DISCONNECTED (The Critical Alert)**: This state indicates that the mobile device has been manually unlinked or has lost its network handshake for a prolonged period. This is an \"Emergency Stop\" signal that requires immediate investigation to ensure customer messages aren't being lost.\n\n### 2. Event-Driven Health Monitoring\nRelying on \"Periodic Heartbeat Checks\" is an inefficient way to monitor connectivity. By using the **Session Status** webhook, you move to a \"Reactive Monitoring\" model. Your server is informed of a failure the moment it happens, allowing for a **Mean Time to Recovery (MTTR)** measured in milliseconds rather than minutes.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Resilient Architectures\n\nMastering the session lifecycle allows you to build systems that are \"Self-Aware\" and robust.\n\n### 1. Proactive Downtime Mitigation and Failover\nIn an enterprise environment managing multiple WhatsApp Business instances, the **Session Status** webhook is the foundation of a \"Failover Strategy.\" If Instance A (Sales-UK) moves to a [`STOPPED`] or [`DISCONNECTED`] state, your central router can detect this event and automatically redirect incoming queries to Instance B (Sales-Global) or escalate the interaction to an email-based support ticket. This ensures that the customer never experiences a \"Dark Chat\" where their messages go unanswered.\n\n### 2. Automated Authentication Workflows\nFor SaaS providers who offer WhatsApp integration to their own customers, managing authentication at scale is a primary challenge. Use the [`SCAN_QR_CODE`] event to trigger a \"Success UI\" on your customer's dashboard. As soon as the webhook arrives, your frontend can automatically display the QR code, wait for the status to transition to [`STARTING`](/v2/webhooks/session-status-starting), and finally show a \"Connected\" checkmark when the status reaches [`WORKING`](/v2/webhooks/session-status-working). This creates a seamless, low-friction \"Onboarding Loop\" that doesn't require the customer to manually refresh their page.\n\n### 3. Engine Integrity and Resource Management\nThe [`STARTING`] and [`STOPPED`] statuses are critical for managing your infrastructure's compute costs. If you are running hundreds of instances, you can use these events to track \"Engine Cold-Starts.\" If an instance remains in a [`STARTING`] state for more than 60 seconds without reaching [`WORKING`], your system can flag this as a \"Stuck Initialization\" and programmatically [Restart](/v2/auth/restart) the instance, maintaining the health of your overall instance fleet without manual human intervention.\n\n---\n\n## 🛡️ Administrative Mandate: The Guardianship of Connectivity\n\nEffective session management is a method of \"Connectivity Insurance.\"\n\n### 1. The \"Working\" State Cache\nEvery message sending function in your application should perform a \"Pre-flight Status Check.\" By caching the most recent status received from the webhook, your system can immediately reject or queue outbound requests if the instance isn't [`WORKING`]. This prevents \"Failed\" message states in your database and allows you to provide immediate feedback to your users: *\"Our WhatsApp connection is temporarily resetting. Your message will be sent in approximately 30 seconds.\"*\n\n### 2. Integrity in Multi-Instance Environments\nWhen managing a fleet of instances, the `session` field in the webhook payload is your primary key. Ensure your monitoring dashboard groups status events by this session ID. A \"Status Heatmap\" can help you identify platform-wide issues (e.g., if multiple instances move to [`DISCONNECTED`] at once, it may indicate a larger network or Meta-side connectivity problem) vs. isolated instance issues (e.g., a specific device's battery died).\n\n---\n\n## 🛡️ Operational Best Practices: Optimizing Lifecycle Awareness\n\n*   **Filter for Change (Deduplication)**: Only trigger your heaviest business logic (like sending an SMS alert to an admin) when the status *changes*. Do not react to repeated heartbeats of the same status unless your specific architecture requires it.\n*   **The \"Human-in-the-Loop\" Escalation**: For [`SCAN_QR_CODE`] events, implement a \"Decaying Alert\" strategy. Send a notification to the manager. If the status hasn't moved to [`WORKING`] within 5 minutes, escalate the alert to the IT department. This balances responsiveness with the need to avoid over-alerting for minor network blips.\n*   **Logging for Post-Mortems**: Store every status transition in a dedicated log table. This allows you to perform \"Uptime Audits\" and identify patterns in connectivity issues (e.g., Instance C always disconnects at 2 AM on Sundays), which is essential for long-term operational optimization.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Coordinate with QR Generation**: When you receive a [`SCAN_QR_CODE`] webhook, do not assume the QR image is ready immediately. There is often a several-hundred-millisecond gap between the status change and the new QR being generated by the engine. We recommend a short \"Wait and Fetch\" strategy before serving the QR image to the user.\n2.  **Graceful Handling of \"Stopped\" States**: A [`STOPPED`] status often indicates a deliberate administrative action. Your system should respect this state and not attempt to \"Force-Restart\" instances that were intentionally shut down for maintenance or billing reasons.\n3.  **Validate Webhook Integrity**: As with all webhooks, ensure you are verifying the source of the status change notification. Malicious actors could attempt to \"Ghost\" your system into thinking an instance is offline, triggering unnecessary failover logic and disrupting your business operations.\n\n## 🎯 Conclusion: Beyond \"Connection\"—The Architecture of Availability\n\nThe **Session Status Change Webhook** is the \"Eye\" of your integration. By building an architecture that listens to the heartbeat of the WhatsApp engine, you move your business from a state of \"Uncertain Connectivity\" to **Guaranteed Availability**. You build systems that detect their own failures, guide users through authentication, and maintain the integrity of the communication channel through any challenge. In the world of Wawp, status is not just a label; it is the strategic signal that ensures your global conversation never skips a beat.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "session.status",
                  "payload": {
                    "name": "default",
                    "status": "STOPPED"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123123@lid",
                    "pushName": "Wawp Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/message": {
      "post": {
        "operationId": "_message_post",
        "summary": "Incoming Message",
        "description": "This event is triggered when a new message is received by your WhatsApp instance.\n\n### Developer Tips\n- **fromMe Field**: The 'fromMe' boolean is crucial. It tells you if the message was sent by YOU (the instance) or by the CONTACT. This prevents infinite bot loops.\n- **Real-time CRM**: Use this event to push WhatsApp messages directly into your support dashboard without the user needing to refresh.\n\n\n# The Atomic Unit of Conversation: Deep Analysis of the Message Webhook\n\nIn the architecture of any conversational application, the **Incoming Message** is the fundamental unit of value. It is the primary signal that initiates business workflows, triggers automated intelligence, and drives customer engagement. Within the Wawp platform, the [`message`] webhook is the most prolific and critical event, acting as the real-time bridge between a user's intent and your system's response. \n\nTo master this webhook is to master the conversation itself. This guide provides an architectural deep-dive into the strategic properties of the message payload and the best practices for building a scalable, context-aware ingestion layer.\n\n---\n\n## 🏗️ Architectural Philosophy: The Anatomy of Intent\n\nA WhatsApp message is far more than just a string of text. It is a rich data object containing identity, source, status, and media metadata. When your server receives a [`message`] webhook, it is being handed a **Moment of Opportunity**.\n\n### 1. The Strategy of Contextual Siloing (`fromMe` and `source`)\nOne of the most common pitfalls in building WhatsApp bots is the \"Infinite Feedback Loop\"—where a bot responds to its own message, triggering another message, and so on. Wawp provides two critical \"Guardrail\" properties to prevent this:\n*   **The `fromMe` Boolean**: This field is the foundation of your logic's \"Self-Awareness.\" It tells you instantly if the message was sent by your own WhatsApp instance (`true`) or by an external contact (`false`). An enterprise-grade integration always filters for `fromMe === false` as the very first step of its ingestion pipeline.\n*   **The `source` Field**: This property provides \"Operational Context.\" It identifies if a message was sent via the Wawp API (`api`) or manually by a human operator using the physical phone or WhatsApp Web (`phone`). This distinction is vital for hybrid support models where bots handle initial triage and humans handle complex escalations. If the source is `phone`, your bot logic can automatically \"Step Back\" and stop interfering with the human conversation.\n\n### 2. High-Fidelity Source Identification (JIDs)\nIn the Wawp ecosystem, every message source is identified by a unique **JID** (WhatsApp ID). The [`from`] property allows your system to instantly determine the context of the conversation:\n*   **Individual Chats (@c.us)**: Messages where [`from`] ends in `@c.us` are 1-on-1 private conversations. This is your primary channel for support and personal engagement.\n*   **Group Chats (@g.us)**: If the [`from`] ends in `@g.us`, the message arrived from a shared group. In this context, the [`author`] property is critical—it identifies the specific individual within the group who sent the message.\n*   **Channels and Newsletters (@newsletter)**: Messages from public broadcasts or channels will carry the `@newsletter` suffix. These are typically read-only or one-way communication streams.\n*   **Lookup IDs (@lid)**: Occasionally, you will see `@lid`. These are privacy-preserving identifiers used by Meta for business discovery or internal routing.\n\nBy correctly parsing these suffixes, your ingestion layer can route messages to different internal modules (e.g., \"Group Bot\" vs. \"Personal Assistant\") without needing to perform expensive database lookups for every event.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Intelligent Workflows\n\nThe message webhook is the \"Sensor\" that feeds your business's central nervous system.\n\n### 1. AI-Augmented Triage and Sentiment Analysis\nAs soon as a message arrives, your system should not just \"Reply.\" It should \"Analyze.\" By routing the `body` of the message to a Large Language Model (LLM) or a sentiment analysis engine, you can determine the customer's emotional state and intent. \n*   **Strategic Routing**: If the sentiment is \"Highly Frustrated\" and the intent is \"Billing Issue,\" the system can skip the standard bot menu and immediately alert a senior billing specialist. \n*   **Data Enrichment**: Use the incoming message to update the \"Last Activity\" field in your CRM, ensuring your sales team always has a real-time view of lead engagement.\n\n### 2. The Visual Evidence Pipeline\nWhen `hasMedia` is `true`, the interaction moves from a text-based query to a \"Proof-based Interaction.\" In field services or insurance, a user sends a photo of a damaged item. The Wawp webhook provides a temporary S3 URL to this media. A strategic architecture immediately downloads this binary and tags it with the customer's JID and the Message ID. This \"Visual Proof\" is then attached to the internal dispatch ticket, providing the field technician with zero-latency visual context before they arrive on-site.\n\n### 3. Cross-Platform Mirroring and Archival\nIn regulated industries, every customer interaction must be archived for 7-10 years. The message webhook provides the raw data required to build a \"Shadow Archive.\" Your system can mirror every WhatsApp interaction into a private, searchable database or an official email archive. Because the webhook includes the `replyTo` metadata, you can perfectly reconstruct threaded conversations, providing a high-fidelity record for legal or compliance audits.\n\n---\n\n## 🛡️ Administrative Mandate: Scaling the Ingestion Layer\n\nWhen your business expands to handling tens of thousands of messages per hour, the efficiency of your webhook handler becomes an infrastructure concern.\n\n### 1. The Strategy of \"Thin Ingestion\"\nDo not perform heavy-duty work within the webhook request-response cycle. If your server receives a message and spends 3 seconds calling an AI API before responding to Wawp, your message queue will back up, and you'll experience \"Retries\" for messages you've already processed. \n**The Professional Pattern**: Your ingestion script should perform minimal validation, push the message object into a fast-access queue (like Redis or NATS), and return a 200 OK Status immediately. A fleet of \"Worker Processes\" then picks up messages from the queue to perform the actual business logic. This decouples \"Delivery\" from \"Processing,\" ensuring your system remains responsive during viral traffic events.\n\n### 2. Global Search and the \"Thread ID\"\nTo build a premium user experience, your system must understand \"Conversation State.\" Use the `id` and `replyTo.id` fields to build a local \"Conversation Graph.\" When a user replies to a specific message, your system can look up that Message ID in your database to understand exactly what the user is referring to. This \"Contextual Awareness\" allows your bot to provide specific, helpful answers rather than generic responses.\n\n---\n\n## 🛡️ Operational Best Practices: Maintaining Conversational Integrity\n\n*   **Idempotency is Key**: Always check the unique `id` of the incoming message against a \"Seen Recently\" cache. Network hiccups can cause the same webhook to be delivered twice. If your system isn't idempotent, you might charge a customer twice or send duplicate bot responses.\n*   **Handle Revocations**: Subscribe to the [Revoked Message](/v2/webhooks/message-revoked) event. If a customer deletes a message after sending it, your system should reflect this in your internal dashboard to ensure your agents aren't responding to \"Ghost\" text that no longer exists in the customer's UI.\n*   **MIME-Type Awareness**: Don't just check if a message `hasMedia`. Check the `media.mimetype`. Treating a 50MB PDF document as if it were a 10KB JPEG image will lead to processing errors and slow performance. Build specialized handlers for each media category (Image, Video, Audio, Document).\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Monitor \"Processing Lag\"**: Track the difference between the `timestamp` provided in the message payload (when the user sent it) and the time your system actually finished processing it. A gap of more than 1-2 seconds indicates that your worker fleet is undersized.\n2.  **Verify Authentication**: Ensure that every webhook request contains the expected security headers or query tokens that you configured in your dashboard. This prevents a \"Flood Attack\" where an external actor could attempt to drain your processing resources by sending fake message payloads.\n3.  **Cross-Instance Siloing**: If your backend manages 50 different WhatsApp instances, the `session` field is your primary filtering key. Ensure your database queries always include the `session` scope to prevent \"Data Leakage\" where a message for Instance A is accidentally processed by the logic for Instance B.\n\n## 🎯 Conclusion: Mastering the Art of the Real-Time Signal\n\nThe **Incoming Message Webhook** is the heartbeat of your WhatsApp integration. By treating it not just as a data packet, but as a \"Strategic Signal,\" you move your organization from passive reception to active conversational orchestration. You build a system that hears the customer's intent, understands their context, and responds with engineered precision. In the world of Wawp, every message is a bridge to a deeper relationship, and every webhook is the first step in a perfectly timed journey.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01aaaaaaaaaaaaaaaaaaaaaaaa",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "message",
                  "payload": {
                    "id": "false_11111111111@c.us_AAAAAAAAAAAAAAAAAAAA",
                    "timestamp": 1666943582,
                    "from": "11111111111@c.us",
                    "fromMe": true,
                    "source": "api",
                    "to": "11111111111@c.us",
                    "participant": null,
                    "body": "Hello, world!",
                    "hasMedia": true,
                    "media": {
                      "url": "https://api.wawp.net/api/files/example.oga",
                      "mimetype": "audio/ogg",
                      "filename": "example.oga",
                      "s3": {
                        "Bucket": "my-bucket",
                        "Key": "default/example.oga"
                      },
                      "error": null
                    },
                    "ack": -1,
                    "ackName": "PENDING",
                    "author": "11111111111@c.us",
                    "location": {
                      "description": "London, UK",
                      "latitude": "51.5074",
                      "longitude": "0.1278"
                    },
                    "vCards": [
                      "BEGIN:VCARD..."
                    ],
                    "_data": {},
                    "replyTo": {
                      "id": "AAAAAAAAAAAAAAAAAAAA",
                      "participant": "11111111111@c.us",
                      "body": "Hello!",
                      "_data": {}
                    }
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123123@lid",
                    "pushName": "Wawp Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/message.reaction": {
      "post": {
        "operationId": "_message.reaction_post",
        "summary": "Message Reaction",
        "description": "Triggered when a user reacts to a message with an emoji.\n\n### Developer Tips\n- **Emoji Removal**: An empty reaction string often indicates that a user has removed their previous reaction.\n\n\n# The Micro-Engagement Signal: Harnessing Message Reactions (Emojis)\n\nIn the evolution of digital discourse, the traditional text reply is no longer the sole unit of engagement. The **Message Reaction**—the ability to attach a single emoji to a message—has become a fundamental method of low-friction, high-nuance communication. Within the Wawp platform, the [`message.reaction`] webhook provides your infrastructure with real-time visibility into these micro-moments of sentiment. \n\nThis guide provides an architectural overview of how to treat reactions as strategic data points, moving beyond \"Simple Emoji Tracking\" into the realm of **Interactive Triage and Sentiment Analysis**.\n\n---\n\n## 🏗️ Architectural Philosophy: Reactions as Low-Friction Content\n\nTo master the Reaction API, one must first recognize the psychology of the interface. A reaction is a \"Zero-Typing\" response. It allows a user to acknowledge, validate, or escalate a conversation without the cognitive effort of composing a sentence.\n\n### 1. The Intent behind the Gesture\nA reaction is a **Contextual Modifier**. It changes the meaning of the message it is attached to. \n*   **The Acknowledgment (Checkmark/Thumbs Up)**: This confirms receipt and agreement. In a task-management or logistical context, this reaction is as binding as a \"Yes\" message.\n*   **The Emotional Nuance (Heart/Fire/Laugh)**: These provide raw sentiment data. They tell your system how the customer *feels* about your support advice or marketing offer, providing a layer of emotional intelligence that text-based NLP (Natural Language Processing) often struggles to capture.\n*   **The Removal Signal**: A reaction event with an empty string or a \"Revoked\" state indicates the user has changed their mind. This \"Correction\" is a critical data point for long-term sentiment tracking, showing where a brand interaction may have moved from positive to neutral.\n\n### 2. The Relationship Between Parent and Child\nA reaction is technically a \"Child Event\" of a parent message. Your architecture must maintain a strong **Referential Integrity** between the [`messageId`] in the reaction payload and the original message stored in your database. This allows you to reconstruct the \"Reaction Profile\" of a specific interaction, identifying which agents or message types are generating the most positive engagement.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Reactive Intelligence\n\nReactions transform passive chat monitoring into an active engine of engagement.\n\n### 1. Interactive Polling and \"Choose Your Own Adventure\"\nInstead of asking users to type \"1\" or \"2\", your bot can present a menu of options and ask users to \"React with an emoji to vote.\" This reduces friction and increases completion rates for surveys or product selections. \n*   **Strategic Workflow**: A travel bot sends three hotel options. The user reacts to the second one with a \"Star\" emoji. The [`message.reaction`] webhook triggers the booking flow for that specific ID. This creates a \"Click-less\" UI that feels modern and intuitive.\n\n### 2. Real-Time Sentiment Triage for Support Teams\nIn a high-intensity support environment, time is of the essence. Your system can monitor the reaction stream in real-time. If a user reacts to a bot's message with a \"Frown\" or an \"Angry\" emoji, the system should treat this as a \"Negative Sentiment Trigger.\" \n**The Actionable Logic**: The system automatically escalates the chat to a human supervisor and tags the interaction as \"At Risk.\" Conversely, a \"Heart\" or \"Thumbs Up\" on a bot's resolution can automatically trigger a \"CSAT\" (Customer Satisfaction) score update in your CRM without the user ever filling out a form.\n\n### 3. \"Reaction-to-Reward\" Marketing Funnels\nConvert micro-engagement into tangible sales. When a user reacts to a broadcast marketing message (e.g., a \"New Collection\" announcement) with a \"Fire\" or \"Heart\" emoji, the [`message.reaction`] webhook can instantly trigger a personalized coupon code: *\"We love that you love the new collection! Here is a 10% discount code just for you.\"* This \"In-the-Moment\" rewards system capitalizes on positive sentiment before it fades.\n\n---\n\n## 🛡️ Administrative Mandate: Scaling the Perception Layer\n\nHandling reactions at scale requires a focus on \"Data Density\" and \"Signal Filtering.\"\n\n### 1. Filtering Noise from Insight\nNot every reaction requires a business action. Your system should implement a **\"Strategic Reaction Map.\"** Decide which emojis are \"Actionable\" (e.g., Thumbs Up = Confirm) and which are \"Informational\" (e.g., Laugh = Neutral Sentiment). This prevents your worker fleet from being overwhelmed by non-essential events while ensuring that every critical signal is processed with high priority.\n\n### 2. The Idempotency of the Gesture\nWhatsApp allows users to change their reaction multiple times. A user might move from a \"Thumbs Up\" to a \"Heart\" to \"Nothing.\" Your architecture should handle this by treating each reaction event as a **\"State Overwrite\"**. Maintain a \"Latest Reaction\" field in your database for each message ID to ensure your UI and reporting always reflect the user's final sentiment.\n\n---\n\n## 🛡️ Operational Best Practices: Optimizing the Interactive Loop\n\n*   **The \"Double Acknowledgement\" Rule**: For critical interactive polling (e.g., \"React to Confirm Appointment\"), your bot should send a follow-up text once the reaction is received: *\"Thanks for the thumbs up! Your appointment is confirmed for Tuesday at 3 PM.\"* This ensures the user that their gesture was \"Heard\" by the automated system.\n*   **Managing Reaction Latency**: For a smooth user experience, your bot's response to a reaction should arrive within 2 seconds. Ensure your reaction webhook handler is optimized for high-speed lookup of the parent `messageId` in your database.\n*   **Privacy and Group Dynamics**: In group chats, multiple users can react to the same message. The [`senderId`] field is vital here. Your system should track the \"Reaction Count\" per emoji per message, allowing you to build \"Consensus Monitoring\" for internal team polls or community engagement.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Monitor \"Reaction-to-Reply\" Ratios**: High numbers of reactions relative to text replies indicate a healthy, frictionless communication channel. If your users are reacting but not replying, it means your bot is providing clear, concise value that requires no further typing from them.\n2.  **Verify Parent Integrity**: Before processing a reaction, verify that the [`messageId`] belongs to an active, non-archived conversation. This prevents \"Orphaned Reactions\" from triggering legacy logic in your system.\n3.  **Coordinate with Revocations**: If the parent message is revoked by the sender, your system should logically decide if the reactions attached to it are still relevant for your historical sentiment analysis or if they should be purged from the dashboard.\n\n## 🎯 Conclusion: Mastering the Art of the Subtle Gesture\n\nThe **Message Reaction Webhook** is the \"Sentiment Sensor\" of your digital brand. By building an architecture that listens to these subtle, high-nuance signals, you move your business from \"Reading Text\" to **Understanding Emotion**. You build systems that respond to gestures, reward engagement, and triage frustration before it escalates. In the world of Wawp, a reaction is not just an emoji; it is the strategic signal that turns a static message into a living, responsive conversation.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "message.reaction",
                  "payload": {
                    "id": "false_11111111111@c.us_...",
                    "reaction": "❤️",
                    "senderId": "11111111111@c.us",
                    "messageId": "false_11111111111@c.us_AAAAA"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/message.any": {
      "post": {
        "operationId": "_message.any_post",
        "summary": "Any Message",
        "description": "Catch-all event for any message activity in the session.\n\n### Developer Tips\n- **High Volume**: This event triggers for every single message. Ensure your server can handle the high traffic frequency.\n\n\n# The Omniscient Listener: Mastering the \"Message Any\" Webhook\n\nIn the architecture of a mission-critical communication platform, data gaps are unacceptable. While specific webhooks like [`message.received`] or [`message.revoked`] provide targeted signals, the **Message Any** event is the global catch-all—the \"Omniscient Listener\" of the Wawp platform. It fires for every single message-related movement within a session, including incoming messages from customers, outgoing messages sent by the API, manual responses made on a physical phone, and even ephemeral system messages.\n\nThis guide provides an architectural deep-dive into the strategic value of global ingestion, moving beyond \"Simple Logging\" into the realm of **Total Auditability, Data Lake Hydration, and Operational Traceability**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Stream of Consciousness\n\nTo master the Message Any API, one must first recognize the shift from \"Event Filtering\" to \"Event Aggregation.\" This webhook represents the raw, unfiltered pulse of the WhatsApp session.\n\n### 1. The Full-Spectrum View\nThe [`message.any`] event collapses the distinction between source and destination.\n*   **The Bidirectional Stream**: It captures both his (`@c.us`/Incoming) and yours (`fromMe: true`/Outgoing). This provides a singular sequence of events, which is essential for reconstructing the \"Conversational Timeline\" in a linear format.\n*   **The Identity Mosaic**: By capturing interactions from Individuals (`@c.us`), Groups (`@g.us`), and Newsletters (`@newsletter`), it creates a holistic view of the instance's total cognitive load and engagement volume.\n\n### 2. The Relationship with Specific Webhooks\nIt is important to understand that [`message.any`] is **Redundant by Design**. Every event it captures is likely also emitted by a more specialized webhook. Its value lies not in *what* it captures, but in its **Consolidated Nature**. A high-performance architecture often uses specialized webhooks for \"Business Logic\" (e.g., triggering a bot response) and [`message.any`] for \"Compliance and Archiving\" (e.g., long-term storage in a Data Lake).\n\n---\n\n## 🚀 Strategic Use Cases: Powering the Auditable Business\n\nThe \"Message Any\" webhook is the engine of technical accountability and historical truth.\n\n### 1. High-Fidelity Audit Trails for Compliance\nIn industries such as Finance, Insurance, and Healthcare, every interaction must be logged for legal review.\n**The Strategic Workflow**: Point your [`message.any`] stream directly at an immutable storage solution (like Amazon S3 or a specialized Audit DB). Because this webhook captures manual phone messages as well as API messages, it provides a \"Complete Truth\" that cannot be bypassed by an agent picking up a physical phone. This ensures your organization remains compliant with non-repudiation and transparency mandates.\n\n### 2. Data Lake Hydration for AI and Analytics\nTo train a custom LLM or to generate \"Sentiment Trends,\" you need the largest possible dataset.\n**The Data Pipeline**: Use [`message.any`] to hydrate your Data Lake. By analyzing the total stream, you can identify \"Peak Activity Hours,\" \"Common Conflict Keywords,\" and \"Customer Effort Scores\" across the entire session. This moves your organization from \"Reactive Support\" to **Proactive Operations**, where business decisions are based on the aggregate signal of every interaction.\n\n### 3. The \"State Reconstruction\" Pattern\nIf your primary database suffers a catastrophic failure, how do you rebuild the conversational state of 10,000 active chats?\n**The Recovery Strategy**: If you have a complete log of [`message.any`] events, you can \"Replay\" the logs to reconstruct the exact state of every chat, including the last message sent, the last reaction, and the last update. This provides a \"High-Availability Safety Net\" that protects your business from data loss in its primary ingestion layers.\n\n---\n\n## 🛡️ Administrative Mandate: Balancing Volume and Value\n\nScaling a \"Global Listener\" requires professional-grade infrastructure.\n\n### 1. Engineering for High-Throughput\nA single Wawp instance can generate thousands of events per hour. If you have 100 instances, the [`message.any`] stream becomes a \"Firehose.\"\n**The Technical Standard**: Do not attempt to process [`message.any`] synchronously within your web server. Instead, use a **Message Broker (like RabbitMQ or Kafka)**. Let your webhook handler do one thing: push the raw payload into the queue and return a `200 OK` instantly. Your \"Archiver Workers\" can then drain the queue at their own pace, ensuring your server never buckles under peak traffic.\n\n### 2. The \"Signal-to-Noise\" Decision\nNot every event in the \"Any\" stream is valuable for your CRM. \n**The Strategic Filter**: Implement a \"Classification Layer.\" Store everything in your raw logs for compliance, but only \"Promote\" specific events from the [`message.any`] stream to your active UI if they meet certain criteria. This prevents your agent dashboard from being cluttered with redundant system messages while still maintaining the integrity of the underlying audit trail.\n\n---\n\n## 🛡️ Operational Best Practices: Optimizing the Global View\n\n*   **De-duplication Logic**: Since [`message.any`] captures events also sent by other webhooks, ensure your database uses the Message ID as a unique constraint. This prevents \"Double Counting\" messages in your analytics.\n*   **The \"Shadow User\" Pattern**: Monitor the [`fromMe: true`] messages to track agent productivity. Since this captures manual phone replies, you can see if an agent is bypassing your official CRM to talk to customers directly. This is a vital tool for quality assurance and \"Shadow IT\" prevention.\n*   **Metadata Enrichment**: The [`message.any`] payload provides basic fields, but can be enriched by cross-referencing with your [Contacts Database](/v2/contacts/all). A premium architecture resolves the JIDs into \"Known Names\" before archiving the event, making the audit logs human-readable.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Idempotent Ingestion**: Always use the Message ID and the Event Type as a combined key. If you receive the same ID via `message.received` and `message.any`, your logic should treat the second arrival as a \"No-Op.\"\n2.  **Verify Payload Integrity**: Ensure you are using the [`engine`] field to handle any subtle differences in payload structure between different Wawp engines (e.g., WEBJS vs. MD).\n3.  **Scoped Resource Allocation**: Dedicate separate compute resources or database instances for your \"Global Ingestion\" pipeline. You don't want a sudden spike in message traffic to slow down your primary \"Reply Logic\" workers.\n\n## 🎯 Conclusion: The Single Source of Truth\n\nThe **Message Any Webhook** is the \"Black Box Recorder\" of your digital brand. By building an architecture that embraces the firehose of data, you move your organization from \"Partial Visibility\" to **Complete Insight**. You build systems that never forget, never miss a signal, and always maintain a high-fidelity record of every word, reaction, and movement. In the world of Wawp, \"Any\" is the signal that ensures your business is always built on the foundation of total, auditable truth.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "message.any",
                  "payload": {
                    "id": "true_11111111111@c.us_...",
                    "body": "Catching everything!",
                    "from": "11111111111@c.us",
                    "to": "22222222222@c.us"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/message.ack": {
      "post": {
        "operationId": "_message.ack_post",
        "summary": "Message Acknowledgement",
        "description": "Track message delivery and read status (sent, delivered, read).\n\n### Developer Tips\n- **ACK Values**: 1 = Sent, 2 = Delivered (Double check), 3 = Read (Blue ticks).\n\n\n# The Lifecycle of a Signal: Mastering Message Acknowledgements (ACK)\n\nIn the high-stakes world of enterprise communication, \"Sending\" is merely the beginning of a message's journey. Truth exists not in the submission of a payload, but in the verification of its receipt and consumption. The **Message Acknowledgement (ACK)** webhook is the definitive feedback loop of the Wawp platform, providing your infrastructure with real-time insight into the \"Transit State\" of every outbound interaction. \n\nThis guide provides an architectural deep-dive into the strategic value of delivery tracking, moving beyond simple state changes into the realm of **Operational Accountability and Sentiment Attribution**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Message as a Continuous Variable\n\nTraditional communication channels, like email or SMS, are often \"Fire and Forget.\" Once the message leaves your server, its status becomes a black box. WhatsApp, via Wawp, transforms this into a **Monitored Transit Lifecycle**.\n\n### 1. The Hierarchy of Verification\nAn ACK event is not a static update; it is a progression through a hierarchy of trust:\n*   **ACK_SENT (Level 1)**: The validation that the message has successfully escaped your instance and reached Meta's global infrastructure. This is the first \"Safety Check,\" confirming that your instance is healthy and your API credentials are valid.\n*   **ACK_DELIVERED (Level 2)**: The \"Double Tick\" moment. This confirms that the recipient's device is online and has successfully downloaded the payload. In a logistical or emergency context, this is the most critical signal—it confirms the bridge has been built.\n*   **ACK_READ (Level 3)**: The \"Blue Tick\" phenomenon. This represents a human event—the recipient has actively opened the chat window. For sales and support teams, this is the \"Moment of Perception,\" the signal that the customer is now consciously engaged with your brand.\n\n### 2. Handling the Asynchronous Nature of ACKs\nAcknowledgements frequently arrive out of order or at significantly different intervals. For example, a message may move from `SENT` to `READ` instantly if the user has the chat open, or it may stay in a `SENT` state for hours if the user is on a plane. A professional architecture handles these events as **Deterministic Idempotent Updates**—your database should only update a message's status to a \"Higher\" level and never revert to a \"Lower\" one, regardless of network retry order.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Data-Driven Operations\n\nMastering the ACK stream allows you to measure and optimize the \"Pulse\" of your business communication.\n\n### 1. SLA Monitoring and \"Last-Mile\" Accountability\nFor customer support organizations, the \"Initial Response Time\" (IRT) is a key metric. By using the **Message ACK** webhook, you can calculate a much more precise metric: the **\"Perceived Response Time\"**. By measuring the gap between when your agent sent the message and when the [`ACK_READ`] webhook arrived, you can identify if your customers are actually consuming your support advice or if your messages are being ignored.\n\n### 2. The \"Automated Second-Chance\" (Failover Logic)\nIf a high-priority notification (e.g., a fraud alert or a delivery update) stays in the [`ACK_SENT`] state for more than 5 minutes without reaching [`ACK_DELIVERED`], your system can trigger a \"Cross-Channel Escalation.\" It can automatically resend the alert via SMS or initiate an automated voice call. This \"Smart Redundancy\" ensures that critical information is never lost due to a user's temporary lack of data connectivity on WhatsApp.\n\n### 3. Attribution and Engagement Scoring\nIn marketing campaigns, a \"Read\" is as valuable as a \"Click.\" By correlating [`ACK_READ`] events with your broadcast lists, you can build an \"Engagement Score\" for every contact in your CRM. Users who consistently \"Blue Tick\" your messages within 60 seconds of receipt are your \"Highly Active\" leads and should be prioritized for your most specialized, human-led sales outreach.\n\n---\n\n## 🛡️ Administrative Mandate: Protecting the \"Trust Chain\"\n\nConsistency in status updates is more than a technical requirement; it is a brand promise.\n\n### 1. The \"Sent-to-Read\" Velocity Metric\nTrack the \"Velocity\" of your acknowledgements. A sudden increase in the time between `SENT` and `DELIVERED` across your entire instance fleet often indicates a regional network issue or a temporary degradation of the Meta API. By monitoring these durations in aggregate, your technical team can act as a \"Early Warning System,\" notifying your support agents of potential delays before they start receiving complaints.\n\n### 2. Privacy and the \"Silent Reader\"\nIt is strategically important to recognize that some WhatsApp users choose to disable \"Read Receipts\" in their privacy settings. In these cases, a message will move to [`ACK_DELIVERED`] but never to [`ACK_READ`]. A sophisticated architecture doesn't treat this as a \"Failure.\" Instead, it looks for \"Implicit Acknowledgements\"—if a user replies to the message, you can logically infer they read it, even if the blue tick never arrived.\n\n---\n\n## 🛡️ Operational Best Practices: Designing for High-Volume Status Updates\n\n*   **Batching Database Writes**: In a high-volume instance sending 100,000 messages per day, you will receive at least 300,000 ACK webhooks (Sent, Delivered, Read). Do not perform a synchronous database write for every single one. Use a message queue and a \"Buffered Writer\" to update your message statuses in batches, significantly reducing the I/O load on your primary database.\n*   **The \"Final State\" Rule**: Once a message reaches [`ACK_READ`], it has reached its terminal state. Any further webhooks for that Message ID (e.g., retries of the `DELIVERED` state) should be discarded immediately at the ingestion layer to save processing power.\n*   **UI Synchronization (WebSockets)**: If you provide a custom chat UI for your agents, use the ACK webhook to trigger a WebSocket push to the agent's browser. This allows the blue ticks to appear in their UI in real-time, providing the \"Snappy,\" responsive feel that users expect from a modern messaging application.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Monitor \"Out-of-Order\" Delivery**: In mobile networking, packets can take unpredictable paths. Your logic should always include a \"Strict Progression\" check: only update `SENT` to `DELIVERED`, and `DELIVERED` to `READ`. \n2.  **Verify Message Ownership**: The ACK payload includes the `chatId`. Ensure this matches the expected recipient in your local records before updating the status, providing a dual-layer of data integrity.\n3.  **Coordinate with Revocations**: If you receive a [Message Revoked](/v2/webhooks/message-revoked) event, any subsequent ACKs for that message ID should be handled with care, as the original \"Read\" sentiment may no longer be relevant to the current conversation state.\n\n## 🎯 Conclusion: Mastering the Art of the Loop-Closure\n\nThe **Message Acknowledgement Webhook** is the \"Eyes and Ears\" of your outbound strategy. By treating every status update as a data point in a continuous lifecycle, you move your business from \"Blind Distribution\" to **Accountable Engagement**. You build systems that understand not just what was said, but what was heard. In the world of Wawp, ACKs are the foundation of trust, the pulse of performance, and the key to a truly \"Reactive\" enterprise.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "message.ack",
                  "payload": {
                    "id": "true_11111111111@c.us_...",
                    "ack": 3,
                    "ackName": "READ",
                    "chatId": "11111111111@c.us"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/message.revoked": {
      "post": {
        "operationId": "_message.revoked_post",
        "summary": "Message Revoked",
        "description": "Triggered when a user deletes a message for everyone.\n\n### Developer Tips\n- **Data Erasure**: Respect the user's wish to delete the message by removing it from your own database/UI as well.\n\n\n# The Erasure Event: Mastering Message Revocations (Delete for Everyone)\n\nIn the dynamic landscape of real-time messaging, data is not always permanent. The \"Delete for Everyone\" feature—technically known as a **Revocation**—allows users to retract a message after it has been sent. Within the Wawp platform, the [`message.revoked`] webhook provides your infrastructure with the immediate notification that a specific interaction has been invalidated by the sender. \n\nHandling revocations is not just a technical requirement for database synchronization; it is a fundamental pillar of **Conversational Integrity and Privacy Compliance**. This guide provides an architectural deep-dive into the strategic management of revoked content, moving beyond \"Simple Deletion\" into the realm of **State Governance and User Trust**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Volatile Nature of Text\n\nTo master the Revocation API, one must first recognize the philosophical shift from \"Archive-First\" to \"User-First\" data priority. A revocation is a user's explicit command to purge a specific data point from the shared conversational record.\n\n### 1. The ID Mapping Strategy\nThe [`message.revoked`] payload does not contain the original message text; it contains the unique **Message ID** of the item being removed and the **JID** of the person who revoked it. \n*   **Individuals (@c.us)**: In 1-on-1 chats, only the sender or the receiver (on their own side) can revoke.\n*   **Groups (@g.us)**: In a group environment, the [`revokedBy`] field is critical. It identifies if the original sender deleted their own message or if a group administrator used their elevated privileges to remove a participant's message for the entire group.\n\n### 2. The Relationship Between Event and Entity\nYour architecture must maintain a robust index of Message IDs. When a revocation arrives, your system must perform a \"Reverse Lookup\" to find the corresponding record in your CRM or database. The speed and accuracy of this lookup define the \"Sync Quality\" of your integration. An enterprise-grade system ensures that the revoked content \"Vanishes\" from the agent's view within milliseconds of the event firing.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Clean Conversational States\n\nWebhooks for revocation ensure your internal systems remain in perfect harmony with the customer's actual experience.\n\n### 1. Maintaining the \"Service Truth\" (Anti-Ghosting)\nThere is nothing more unprofessional than a human agent or an AI bot responding to a message that the user has already deleted.\n**The Strategic Workflow**: When a message arrives, your system starts its processing logic. If the [`message.revoked`] webhook arrives before the bot's response is sent, the system should instantly **abort the response generation**. This prevents \"Ghost Interactions\" where your bot appears to be \"Hearing voices\"—responding to a question that is no longer there.\n\n### 2. Professional Moderation in High-Volume Groups\nIn community management, administrators often need to remove offensive or off-topic content. By listening to the revocation webhook, your central community dashboard can update its state in real-time. If an admin deletes a message on their phone, the central control panel should immediately hide that message for all human moderators, ensuring the \"Moderation State\" is synchronized across the entire organization.\n\n### 3. Compliance and the \"Right to be Forgotten\"\nIn many jurisdictions (such as GDPR in Europe), a user's request to delete data is a legal mandate. While Wawp purges its own temporary caches, your internal database must also respect this signal. \n**The Policy Engine**: Configure your system to treat a [`message.revoked`] event as an **Authorized Deletion Request**. Instead of just hiding the message in the UI, your system should logically \"Scrub\" the original body content from your database, replacing it with a metadata flag: *[Content Revoked by User]*. This ensures you remain compliant with privacy laws while maintaining a valid audit trail of the conversation's structure.\n\n---\n\n## 🛡️ Administrative Mandate: Scaling the Erase Pipeline\n\nScaling revocations requires a focus on \"Transaction Atomicity.\"\n\n### 1. Handling the \"Revoke Before Receipt\" Edge Case\nIn rare high-latency scenarios, your server might receive the [`message.revoked`] event *before* the original [`message`] event (due to different routing paths in a microservice architecture). \n**The Strategic Solution**: Use a **\"Negative Cache\"** or an **\"Out-of-Order Buffer\"**. If you receive a revocation for an ID you don't recognize, store that ID in a temporary \"Pending Revocation\" list for 60 seconds. If the original message arrives within that window, it should be discarded immediately upon ingestion.\n\n### 2. The \"Audit Trail\" vs. \"Privacy\" Balance\nFor sensitive financial or support interactions, you may need a record that a message *did exist* (for auditing) without keeping the *content* of that message (for privacy). \n**The Balance**: Store the metadata (timestamp, sender JID, message ID) but delete the body, media URLs, and attachments associated with the revoked ID. This provides a \"Skeleton History\" that allows you to prove an interaction occurred without violating the user's intent to retract their specific words.\n\n---\n\n## 🛡️ Operational Best Practices: Optimizing the User Experience\n\n*   **UI Visual Cues**: In your custom agent dashboard, don't just delete the row. Replace it with a faded \"Message deleted\" placeholder. This provides the agent with context: \"The customer said something but changed their mind.\" This awareness allows the agent to adjust their tone accordingly.\n*   **Aborting Media Downloads**: If a revocation fires for a media message (image/video) that your system is currently downloading, stop the download process immediately. This saves bandwidth and ensures that sensitive visuals are not stored on your servers.\n*   **Admin Revocation Alerts**: In group management contexts, if an admin (`@c.us`) revokes a message in a group (`@g.us`), your system can tag this event as a \"Moderator Action.\" This data can be used to generate \"Moderation Reports,\" helping you identify which admins are most active in keeping the community clean.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Iterative Indexing**: Ensure your Message ID index is optimized for high-speed \"Delete\" operations. Using a B-Tree or Hash index on the ID field is mandatory for maintaining performance as your database grows.\n2.  **Verify Revoker Authority**: In groups, verify the [`revokedBy`] JID. If your system relies on specific \"Trust Levels,\" you should confirm that the revoker has the necessary permission to delete the target message.\n3.  **Cross-Instance Siloing**: Just like the message webhook, ensure revocation logic is scoped to the specific [`session`]. Never allow a revocation from Instance A to accidentally trigger a lookup in the database for Instance B.\n\n## 🎯 Conclusion: The Power of the Retraction Signal\n\nThe **Message Revoked Webhook** is the \"Eraser\" of your digital brand. By building an architecture that respects these signals, you move your organization from \"Static Archiving\" to **Respectful, Real-Time Synchronization**. You build systems that understand the fluidity of human conversation, respect user privacy, and maintain a high-fidelity \"Single Source of Truth.\" In the world of Wawp, a revocation is not an error; it is a vital conversational signal that ensures your integration remains as human, as private, and as accurate as WhatsApp itself.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "message.revoked",
                  "payload": {
                    "id": "false_11111111111@c.us_...",
                    "revokedBy": "11111111111@c.us"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/message.edited": {
      "post": {
        "operationId": "_message.edited_post",
        "summary": "Message Edited",
        "description": "Triggered when a sent message is modified by the user.\n\n### Developer Tips\n- **Time Window**: Edits can only happen within a short professional window after sending (approx 15 mins).\n\n\n# The Second Chance: Mastering Message Edited Webhooks\n\nIn the fluid world of real-time communication, mistakes are inevitable. A typo, an incorrect price quote, or a misunderstood instruction can lead to significant business friction. The **Message Edited** feature on WhatsApp allows users and bots to correct their errors after the signal has been sent. Within the Wawp platform, the [`message.edited`] webhook is the definitive \"Truth Update\" signal, providing your infrastructure with the immediate notification that an existing interaction has been refined.\n\nHandling edits is not just a technical requirement for UI synchronization; it is a fundamental pillar of **Contextual Accuracy and Data Integrity**. This guide provides an architectural deep-dive into the strategic management of edited content, moving beyond \"Simple Text Updates\" into the realm of **Conversational Governance and Professional Auditing**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Mutable Message\n\nTo master the Message Edited API, one must first recognize the transition from \"Immutable Logs\" to \"Living Conversations.\" A message is no longer a static data point; it is a dynamic entity that can be re-defined within a specific professional window.\n\n### 1. The ID Linkage Strategy\nThe [`message.edited`] payload is structurally tied to the **Original Message ID**. \n*   **The Identifier Map**: Your system must use the [`id`] in the payload to locate the specific record in your CRM or support database. Unlike a new message search, this is a \"Correction Search.\"\n*   **The Body Delta**: The payload provides the [`newBody`] (the current truth) and, where available, the [`prevBody`] (the historical context). \n\n### 2. Contextual Reach (JIDs)\nEdits occur across the entire spectrum of WhatsApp interaction:\n*   **Individual Chats (@c.us)**: Messages where [`from`] ends in `@c.us` represent personal or business-to-customer corrections.\n*   **Group Chats (@g.us)**: In a group environment, an edit by a specific participant updates the shared record for all members. Your ingestion layer must handle this as a \"Group State Update,\" ensuring every agent looking at that group sees the corrected information simultaneously.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Accurate Interactions\n\nThe message edited webhook ensures your internal systems remain in perfect harmony with the customer's intended meaning.\n\n### 1. Zero-Friction Correction in Sales and Quoting\nImagine a sales agent sends a quote: \"The total price is $1,500.\" They immediately realize it should be $1,050 and use the WhatsApp \"Edit\" feature to fix it.\n**The Strategic Workflow**: As soon as the [`message.edited`] webhook fires, your backend updates the Quote record in your CRM. If your system was about to generate an automated invoice based on the $1,500 text, the webhook serves as an **Emergency Correction Trigger**, ensuring the final document matches the user's intended price. This prevents billing errors and preserves customer trust.\n\n### 2. Maintaining the \"Contextual Truth\" for Human Agents\nThere is nothing more confusing for a human support agent than a customer saying \"As I said in the corrected message above...\" if the agent's dashboard still shows the old, incorrect text.\n**The Real-Time Sync**: Use the edited webhook to trigger a WebSocket push to the agent's browser. The text should visually \"Morph\" or update with an \"Edited\" badge in real-time. This ensures the human agent is always looking at the **Current State of the Truth**, eliminating the \"Responsiveness Gap\" caused by outdated message logs.\n\n### 3. AI Intent Re-Analysis\nIf your bot logic uses an LLM to determine customer intent, an edit is a \"Signal of Refinement.\"\n**The Logic**: When a message is edited, your system should re-run its intent analysis on the [`newBody`]. If the original message was \"How do I cancel?\" but the user edited it to \"How do I cancel my *Gold* plan specifically?\", the refined intent allows your bot to provide a much more accurate, high-value response. An enterprise-grade system treats an edit as a **Contextual Re-Trigger** for its intelligent processing layers.\n\n---\n\n## 🛡️ Administrative Mandate: Scaling the Correction Pipeline\n\n### 1. The Audit Trail Discipline\nIn regulated industries (like Legal, Finance, or Healthcare), you cannot simply overwrite data. You must maintain an **\"Edit History\"**.\n**The Strategic Architecture**: When a [`message.edited`] event arrives, do not delete the old text. Instead, move the old text into a `message_versions` table. This provides a \"Transparent History\" of the interaction. If a dispute arises later, your compliance team can see exactly what was said first and how it was corrected. This is the gold standard for **Technical Accountability**.\n\n### 2. Handling the \"Race Condition\" on Ingestion\nIn high-frequency environments, a user might send a message and edit it within 2 seconds. Because webhooks are asynchronous, your server might receive the [`edited`] event before the original [`message`] event is fully written to your primary database.\n**The Robust Solution**: Implement a **\"Staged Update\"**. If your lookup for the original Message ID fails, place the edit payload into a \"Pending Sync\" queue for 5-10 seconds. Once the original message is ingested, the queue processor can then apply the edit. This ensures no correction is lost due to transient networking timing.\n\n---\n\n## 🛡️ Operational Best Practices: Designing for Professional Clarity\n\n*   **The \"Edited\" Badge UI**: Always display a visual indicator (like a small clock icon or the word \"Edited\") next to the corrected text in your custom dashboard. This tells the agent: \"The user changed their mind about what they said here.\"\n*   **MIME-Type Stability**: Note that WhatsApp currently primarily supports editing **Text Messages**. If you receive an edit event for a media message (image/video), it typically signifies a change to the **Caption**. Your system should specifically target the `caption` field in your media records to apply these updates.\n*   **Coordinate with Acknowledgements (ACKs)**: Edits do not reset the delivery status. If a message was already \"Read\" (ACK 3), editing it doesn't turn the ticks back to gray. However, the *corrected* content should be treated as \"Not yet consumed\" by the agent until they look at the screen again.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Deduplicate Edits**: If a user edits the same message three times in a row, you will receive three webhooks. Ensure your database update logic is idempotent and only processes the latest timestamp provided in the event metadata.\n2.  **Verify Edit Authority**: In groups (`@g.us`), only the person who sent the message can edit it. Your system should verify the [`author`] in the edit payload matches the author of the original message to prevent state-injection errors.\n3.  **Cross-Instance Siloing**: Ensure that the edit lookup is strictly scoped to the [`session`]. An edit for a message on Instance A should never attempt to update a message record belonging to Instance B.\n\n## 🎯 Conclusion: Beyond Correction—The Art of the Living Record\n\nThe **Message Edited Webhook** is the \"Living Update\" of your digital brand. By building an architecture that listens, archives, and synchronizes these corrections, you move your organization from \"Static Log Management\" to **Dynamic Conversational Alignment**. You build systems that understand the fluidity of human intent, preserve the history of change, and always present the most accurate version of the truth. In the world of Wawp, an edit is not a failure; it is a vital conversational signal that ensures your integration remains as precise, as professional, and as adaptable as the business it represents.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "message.edited",
                  "payload": {
                    "id": "false_11111111111@c.us_...",
                    "newBody": "Updated message text!",
                    "prevBody": "Old message text"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/group.v2.join": {
      "post": {
        "operationId": "_group.v2.join_post",
        "summary": "Group Join (V2)",
        "description": "Triggered when a new member joins or is added to a group.\n\n### Developer Tips\n- **Auto-Welcome**: Use this to automatically send a welcome message or rule set to new group members.\n\n\n# Community Onboarding: Mastering the Group Join Webhook\n\nIn the high-scale world of community management and enterprise collaboration, the point of entry is the most critical moment of the lifecycle. The [`group.v2.join`] webhook is the primary signal that a new entity has entered a shared conversational space. Whether a user joins via a shared invitation link or is manually added by a community moderator, this event provides your infrastructure with the real-time data required to execute onboarding flows, security audits, and membership tracking.\n\nThis guide provides an architectural deep-dive into the strategic importance of group entry events, moving beyond \"Membership Tracking\" into the realm of **Automated Community Governance and Operational Security**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Gatekeeper Pattern\n\nTo build a premium group experience, one must treat the group join event as a \"Membership Handshake.\" A group in WhatsApp is identified by its unique **Group JID** (ending in `@g.us`), and its members are **Individual JIDs** (ending in `@c.us`).\n\n### 1. The Membership Handshake\nWhen an entry event occurs, your system is handed a two-layer payload: the [`chatId`] (the Group) and a list of [`participants`] (the new members). This allows for **Batch Ingestion**. If a moderator adds five users at once, your system receives a single atomic event containing all five IDs. This efficiency is critical for preventing \"Webhook Flood\" during large community migrations.\n\n### 2. Identifying the Entry Vector\nWhile the current event primarily confirms \"Who Joined,\" a sophisticated architecture correlates this with the **Join Method**. \n*   **The Invitation Link**: If a user joins via a link, your system should treat them as a \"Self-Service Lead.\" \n*   **The Manual Add**: If they were added by an admin, they are an \"Invited Participant.\" \nYour onboarding logic (e.g., the welcome message) should adapt based on this vector to ensure the tone of the interaction matches the user's entry experience.\n\n---\n\n## 🚀 Strategic Use Cases: Powering the Responsive Community\n\nThe group join webhook is the \"Sensor\" that triggers your community's automated greeting and security protocols.\n\n### 1. Zero-Latency Onboarding and Rule Enforcement\nFirst impressions are permanent. As soon as the [`group.v2.join`] webhook fires, your bot can instantly send a personalized welcome message to the group: *\"Welcome to the team, [User Name]! Please read our #rules and introduce yourself.\"* \n**Strategic Value**: By automating this, you ensure every new member is immediately integrated into the community standards without requiring a human moderator to be online 24/7. This creates a sense of \"Active Presence\" for your brand.\n\n### 2. Dynamic CRM Hydration and KYC\nFor subscription-based communities (e.g., \"Premium Trading Groups\"), the join event is a **Verification Trigger**. \n**The Logic**: When a user joins the [`@g.us`] group, your system looks up their [`@c.us`] ID in your payment database. If no active subscription is found, your system can autonomously remove the user and send them a private message explaining how to join legally. This \"Automated Perimeter Defense\" protects your revenue stream from unauthorized link sharing.\n\n### 3. Community Health and Growth Analytics\nTrack \"Join Velocity.\" By logging every entry event, you can build a real-time dashboard showing your community's growth rate. If you see a spike in joins after a specific marketing email, you have direct, high-fidelity attribution of that campaign's success. This data allows you to move from \"Managing Chats\" to **Managing a Growing Ecosystem**.\n\n---\n\n## 🛡️ Administrative Mandate: Designing for Community Security\n\n### 1. The \"Shadow Directory\" Strategy\nWhatsApp groups do not naturally sync with external CRMs. You must build a **\"Shadow Directory\"**—a local database that mirrors every group's membership. The [`group.v2.join`] and [`group.v2.leave`] webhooks are the \"Sync Sentinels\" that keep this directory accurate. \n**Benefit**: When an agent needs to send a broadcast to all \"Active Community Members,\" they don't have to query WhatsApp; they query your fast, local directory.\n\n### 2. Guarding against \"Number Scraping\"\nMalicious actors often join groups solely to harvest the phone numbers of other participants. By monitoring the join stream, your system can cross-reference new IDs against a global \"Blacklist\" of known scrapers. If a flagged ID joins, the system can autonomously eject them within seconds, protecting the privacy of your genuine community members.\n\n---\n\n## 🛡️ Operational Best Practices: Optimizing the Onboarding Loop\n\n*   **The \"Welcome Debounce\" Rule**: If three users join within 5 seconds, don't send three separate welcome messages. Your system should \"Debounce\" the event—wait 10 seconds, then send a single message: *\"Welcome to our new members: [User 1], [User 2], and [User 3]!\"* This keeps the chat history clean and professional.\n*   **Private vs. Public Greetings**: For high-privacy groups, consider having the bot send the \"Rules\" message to the new user's **Private Chat (@c.us)** instead of the main group. This provides a personal, 1-on-1 welcome while keeping the group chat focused on its primary topic.\n*   **Handling the \"me\" Identity**: Note that if *your* instance ID (the [`me`] field in the metadata) is added to a new group, this webhook will also fire. Your system should detect this \"Self-Join\" event to automatically initialize the group's metadata and settings in your local records.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Deduplicate Participants**: Always iterate through the [`participants`] array and treat each ID as a separate transactional update in your database. Ensure your \"Member Count\" logic is idempotent to handle potential event retries.\n2.  **Verify Group Integrity**: Before sending a welcome message, verify that the [`chatId`] is still an active, non-archived group in your logic.\n3.  **Coordinate with Presence**: If a user joins but their presence state is \"Invisible\" or has no status, your system might wait for their first message before triggering a complex onboarding flow to ensure they are actually seen by the bot.\n\n## 🎯 Conclusion: Beyond Membership—Building the Conversational Perimeter\n\nThe **Group Join Webhook** is the \"Front Door\" of your digital community. By building an architecture that listens, verifies, and greets, you move your organization from \"Hosting a Chat\" to **Governing an Interface**. You build systems that reward genuine interest, enforce community standards, and protect user privacy with engineered precision. In the world of Wawp, an entry event is not just a log entry; it is the strategic signal that turns a stranger into a member of your conversational ecosystem.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "group.v2.join",
                  "payload": {
                    "chatId": "1234567890@g.us",
                    "participants": [
                      "11111111111@c.us"
                    ]
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/group.v2.leave": {
      "post": {
        "operationId": "_group.v2.leave_post",
        "summary": "Group Leave (V2)",
        "description": "Triggered when a member leaves or is removed from a group.\n\n### Developer Tips\n- **Retention Logic**: Use this to track churn or automatically follow up with members who leave (if appropriate).\n\n\n# Group Leaving\n\nTriggered whenever someone is no longer part of the group.\n\n### Fields\n*   **chatId**: The group ID.\n*   **participants**: Array of IDs that left.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "group.v2.leave",
                  "payload": {
                    "chatId": "1234567890@g.us",
                    "participants": [
                      "11111111111@c.us"
                    ]
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/group.v2.update": {
      "post": {
        "operationId": "_group.v2.update_post",
        "summary": "Group Updated (V2)",
        "description": "Triggered when group settings like title, description, or icon are changed.\n\n### Developer Tips\n- **Synchronization**: Keep your mirrored group metadata up to date using this event.\n\n\n# The Living Community: Mastering Group Update Webhooks (V2)\n\nIn the architecture of large-scale community management and B2B communication, a group is more than just a chat—it is a digital entity with its own identity, rules, and visibility. The **Group Updated (V2)** webhook is the primary signal that the metadata or configuration of a shared workspace has changed. Whether a title is renamed for a new project phase or a group is \"Locked\" by an administrator, the [`group.v2.update`] event provides your infrastructure with the real-time data required to maintain a high-fidelity **Mirror Directory** of your organizational chats.\n\nThis guide provides an architectural deep-dive into the strategic importance of group metadata tracking, moving beyond \"Logging Changes\" into the realm of **Brand Consistency, Operational Governance, and Community Health**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Metadata Mirror\n\nTo build a premium enterprise experience, your system must treat group settings as \"States of Truth.\" A group is identified by its unique **Group JID** (ending in `@g.us`), and its current configuration (Title, Description, Permissions) defines the \"Interface Rules\" for all participants.\n\n### 1. The Mirror Directory Strategy\nWhatsApp does not provide a \"Push Sync\" for group settings until a change occurs. Therefore, your architecture must maintain a local database that mirrors every active group.\n*   **The Ingestion Loop**: When a [`group.v2.update`] fires, your system performs an \"Upsert\" operation. If the Group ID is already in your CRM, update the relevant field (e.g., `subject`). If it doesn't exist, this event acts as a \"Discovery Trigger\" to initialize the group record.\n*   **Field-Level Atomicity**: The payload identifies exactly what changed—be it the [`subject`] (title), [`description`], or [`restrictMode`] (who can send messages).\n\n### 2. Identifying the Actor\nWhile the payload focuses on \"What Changed,\" correlation with the sender JID (if available in the metadata) allows your system to identify **Who** initiated the change. This is critical for auditing accountability in multi-admin environments.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Dynamic Community Governance\n\nGroup updates are the \"Control Signals\" that allow your bot logic to adapt to the changing environment of a live chat.\n\n### 1. Brand Consistency and \"Subject Protection\"\nFor official brand communities, the Group Title (Subject) is a critical asset.\n**The Strategic Workflow**: If a non-authorized user (someone not flagged as a \"Brand Manager\" in your CRM) changes the group's subject to something unprofessional, your system can detect this [`group.v2.update`] immediately. It can then programmatically [Update the Subject](/v2/groups/update) back to the official name and send a warning message: *\"Hi! Only authorized admins are permitted to change the group title. Reverting to 'Official Branding'...\"* This automated protection ensures your brand remains professional 24/7 without manual supervision.\n\n### 2. Operational Pivoting (Announcement Mode)\nMany communities transition between \"Open Discussion\" and \"Announcement Only\" modes (where only admins can post). \n**The Logic**: When you receive a [`group.v2.update`] indicating that [`announceMode`] has been enabled, your bot should immediately \"Step Back.\" It should stop processing user messages (which are now impossible anyway) and perhaps update its internal state to \"Broadcast Mode.\" Conversely, when the group is \"Opened,\" the bot can send a summary of what was missed during the locked period. This creates a \"Smooth Handover\" between different community configurations.\n\n### 3. CRM Information Enrichment\nThe \"Description\" field of a WhatsApp group is often used for #rules, links to external FAQs, or project IDs. \n**The Insight**: By parsing the [`description`] in every update event, your system can automatically extract metadata. If a project manager adds `ProjectID: #9921` to the group description, your Wawp-powered CRM can automatically link this WhatsApp Group JID to the corresponding entry in your Project Management software. This is **Automated Contextual Mapping** at its finest.\n\n---\n\n## 🛡️ Administrative Mandate: Designing for Community Security\n\n### 1. The \"Audit Trail\" for Accountability\nIn sensitive corporate communications, knowing when a group's purpose shifted is vital.\n**The Policy Engine**: store a full \"History of Settings\" for every group. This allows a compliance officer to look back and see: *\"The group was renamed from 'Confidential R&D' to 'Public Beta' at 14:00 by John Doe.\"* This transparency is a requirement for SOC2 and other enterprise compliance frameworks.\n\n### 2. Monitoring \"Description Spam\"\nMalicious actors often join open groups and edit the description to include phishing links. By monitoring the [`description`] update stream, your system can automatically scan for \"Blacklisted URLs.\" If a malicious link is detected in an update, the system can autonomously delete the description or notify an admin within seconds of the edit.\n\n---\n\n## 🛡️ Operational Best Practices: Optimizing the Update Loop\n\n*   **The \"Icon Refresh\" Trigger**: If the group's profile picture changes, the [`group.v2.update`] event (or a companion `profile_picture` event) should trigger your system to fetch the new image URL. This ensures that the avatars in your agent dashboard always match the reality of the WhatsApp client, preventing agent confusion.\n*   **The \"Silent Onboarding\" Rule**: If a group's subject changes from \"New Chat\" to a recognized project name, your bot can use this as a trigger to send a \"Welcome to the Project\" packet, even if the bot was already a member of the group.\n*   **Coordinate with Participants**: Often, a group update happens alongside a participant change (e.g., someone is promoted to Admin). Your system should cross-reference `group.v2.update` with [Group Participant Change](/v2/webhooks/group-v2-participants) events to build a complete picture of the \"Power Dynamics\" within the chat.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Strict State Synchronization**: Use a \"Version Counter\" or a strict timestamp comparison. Do not apply a group update if your database already contains a \"Newer\" update for that specific [`chatId`]. This prevents \"Update Flip-Flopping\" in high-latency network scenarios.\n2.  **Verify Asset Accessibility**: If a description update contains a link, your system should perform a \"Head Request\" to verify the link's safety before allowing it to be indexed in your searchable records.\n3.  **Scoped Logic by ID**: Groups ending in `@g.us` are the only valid targets for this webhook. Ensure your ingestion layer ignores any Malformed/Test IDs to prevent database pollution.\n\n## 🎯 Conclusion: Beyond Settings—The Architecture of Context\n\nThe **Group Updated Webhook** is the \"Registry of Purpose\" for your digital communities. By building an architecture that listens, protects, and synchronizes these metadata shifts, you move your organization from \"Generic Messaging\" to **Context-Aware Governance**. You build systems that protect brand integrity, automate administrative tasks, and maintain a perfect \"Mirror of Reality\" for your human agents. In the world of Wawp, an update is more than a change—it is the strategic signal that keeps your conversational ecosystem aligned with your business objectives.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "group.v2.update",
                  "payload": {
                    "chatId": "1234567890@g.us",
                    "subject": "New Group Name",
                    "description": "Updated description text"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/group.v2.participants": {
      "post": {
        "operationId": "_group.v2.participants_post",
        "summary": "Group Participants Change",
        "description": "Triggered when participants are promoted to admin or demoted.\n\n### Developer Tips\n- **Admin Rights**: Be aware of admin status changes if your bot depends on admin permissions to execute certain commands.\n\n\n# Participant Role Changes\n\nThis event tracks promotions and demotions within a group.\n\n### Fields\n*   **action**: Either `promote` or `demote`.\n*   **participants**: Array of WhatsApp IDs whose roles were changed.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "group.v2.participants",
                  "payload": {
                    "chatId": "1234567890@g.us",
                    "action": "promote",
                    "participants": [
                      "11111111111@c.us"
                    ]
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/presence.update": {
      "post": {
        "operationId": "_presence.update_post",
        "summary": "Presence Updated",
        "description": "Triggered when a contact starts typing, recording audio, or changes their online status.\n\n### Developer Tips\n- **Online Privacy**: Note that many users have 'Last Seen' and 'Online' status disabled in their privacy settings.\n\n\n# The Digital Pulse: Mastering Presence and Activity Webhooks\n\nIn the architecture of a high-performance messaging system, text is only half of the conversation. The other half is **Presence**—the subtle, high-frequency signals that indicate when a human is looking at their screen, composing a thought, or recording a voice note. The [`presence.update`] webhook is the \"Social Sensor\" of the Wawp platform. It provides your infrastructure with real-time insight into the intentions of your contacts before they ever press the \"Send\" button.\n\nThis guide provides an architectural deep-dive into the strategic value of presence monitoring, moving beyond \"Activity Tracking\" into the realm of **Social Intelligence and Conversational Flow Management**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Social Contract of Availability\n\nTo master the Presence API, one must recognize the psychological weight of the \"Typing...\" indicator. It represents active focus. Within Wawp, presence is usually scoped to an **Individual JID** (`@c.us`) within a specific chat context.\n\n### 1. The Hierarchy of Activity\nThe presence event captures the progression of human-device interaction:\n*   **Composing (Typing)**: The user is actively entering text into the input field. This is the strongest signal of \"Pending Input.\"\n*   **Recording**: The user is holding the microphone button to record a voice note. This provides a \"Media Warning\"—your system should expect an audio payload shortly.\n*   **Paused**: The user has stopped typing but still has the chat window open. This is a state of \"Deliberation\" or \"Interruption.\"\n*   **Available / Unavailable**: The global \"Online\" or \"Last Seen\" status. (Note: These are only available if the user's privacy settings allow it).\n\n### 2. The Relationship Between Presence and Priority\nA presence event is a **Temporary State Mutation**. Unlike a message, which is a permanent record, presence is a fleeting signal. Your architecture should treat these events as \"Volatile Data.\" They are primarily used to update a Live UI or to pause bot logic, rather than being archived in a long-term data warehouse.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Socially Intelligent Bots\n\nPresence and activity signals transform a static bot into a \"Conversational Orchestrator\" that respects human rhythms.\n\n### 1. The \"Respectful AI\" Bot (Collision Avoidance)\nOne of the most frustrating user experiences is when a bot sends a long answer *while the user is still typing* their next question. \n**The Strategic Workflow**: When your bot generates a response, it first checks the current \"Activity State\" of the [`chatId`]. If a [`presence.update`] event of type `composing` has arrived in the last 10 seconds, the bot **pauses its output**. It waits for the user to finish typing and send their message before delivering its own answer. This creates a \"Natural Turn-Taking\" flow that mimics human conversation.\n\n### 2. Real-Time Dashboard Synchronicity\nFor human-led support teams, the presence webhook is the engine of the \"Agent Awareness\" feature. When an agent sees \"Customer is typing...\" on their dashboard, they know to wait rather than asking \"Are you there?\". This simple visual cue reduces redundant messages, lowers agent fatigue, and gives the customer the space they need to compose complex queries.\n\n### 3. Presence as a \"Sentiment Warm-up\"\nTrack the \"Time-to-Reply\" starting from the first `composing` event rather than the final `message` timestamp. A user who types for 3 minutes for a 2-word message is likely frustrated or struggling with your interface. Your system can detect this prolonged \"Composing State\" and proactively suggest human assistance before the user even finishes their message.\n\n---\n\n## 🛡️ Administrative Mandate: Balancing Intelligence and Privacy\n\n### 1. The \"Subscribed vs. Unsubscribed\" State\nPresence updates on WhatsApp are typically **Contextual**. You receive typing indicators for users you are currently interacting with. For global \"Online\" status, you may need to call the [`/presence/subscribe`](/presence) endpoint. \n**The Strategic Rule**: Only subscribe to presence for \"Active Leads\" or \"High-Priority Support Tickets.\" Maintaining 10,000 active presence subscriptions simultaneously is an architectural anti-pattern that can lead to backend throttling and unnecessary bandwidth costs.\n\n### 2. Respecting the \"Invisible\" User\nPrivacy is a core pillar of the WhatsApp ecosystem. If a user has disabled \"Read Receipts\" or \"Online Status,\" your system will not receive these webhooks. A premium architecture must fail gracefully. If presence data is missing, your system should default to \"Passive Mode\"—treating every message as if it were sent without warning. Never attempt to \"Infer\" presence via invasive polling, as this can lead to account flags or user complaints.\n\n---\n\n## 🛡️ Operational Best Practices: Handling the High-Frequency Signal\n\n*   **The \"Debounce\" Strategy**: Presence updates can fire every few seconds. Do not trigger a database write for every \"User is typing\" packet. Instead, use an **In-Memory Cache (like Redis)** to store the \"Current State\" of a chat. Only push an update to your frontend UI if the state *actually changes* (e.g., from `paused` to `composing`).\n*   **Visual State Lifespan**: Typing indicators should have a \"Time-to-Live\" (TTL) on your dashboard. If you don't receive a fresh [`presence.update`] within 15 seconds, your UI should automatically hide the \"Typing...\" indicator. This prevents a \"Stuck UI\" if a user closes their app without the `paused` event firing correctly.\n*   **Presence in Groups (@g.us)**: In a group context, you will receive presence updates for multiple different [`from`] JIDs simultaneously. Your system must correctly map these activities to the specific user's avatar within the group UI, allowing agents to see exactly which participant is currently responding.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Low-Latency Ingestion**: Unlike a message, a presence signal loses 90% of its value if it is delayed by more than 2 seconds. Ensure your presence webhook handler is hosted on a high-availability, low-latency node.\n2.  **Verify Event Ordering**: Use the [`timestamp`] in the event metadata to ensure you aren't processing an old \"Typing\" packet after a newer \"Paused\" packet.\n3.  **Coordinate with \"Start Typing\"**: If your bot is about to reply, call the [`/v2/send/start-typing`](/v2/send/start-typing) endpoint yourself. This closes the \"Symmetry Loop\"—the user sees that the bot is \"Thinking,\" and the bot sees that the user is \"Waiting.\"\n\n## 🎯 Conclusion: Beyond Text—The Reactive Pulse of Engagement\n\nThe **Presence Update Webhook** is the \"Peripheral Vision\" of your WhatsApp integration. By building an architecture that listens to these subtle, high-frequency signals, you move your business from \"Reading Logs\" to **Understanding Human Momentum**. You build systems that respect silence, wait for input, and provide reassurance through live visual feedback. In the world of Wawp, presence is the signal that turns a cold interaction into a living, breathing conversation.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "presence.update",
                  "payload": {
                    "chatId": "11111111111@c.us",
                    "type": "composing",
                    "from": "11111111111@c.us"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/poll.vote.failed": {
      "post": {
        "operationId": "_poll.vote.failed_post",
        "summary": "Poll Vote Failed",
        "description": "Triggered if a vote on a poll fails to process correctly.\n\n### Developer Tips\n- **Error Handling**: Use this to notify admins if a voting session is being interrupted by technical errors.\n\n\n# Poll Voting Errors\n\nOccurs when a user attempts to vote but the WhatsApp engine or server cannot register it.\n\n### Common Reasons\n*   **Stale Message**: The poll has been deleted or expired.\n*   **Network Timeout**: Connection issues preventing synchronization.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "poll.vote.failed",
                  "payload": {
                    "pollId": "true_11111111111@c.us_...",
                    "voter": "11111111111@c.us",
                    "reason": "MSG_NOT_FOUND"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/chat.archive": {
      "post": {
        "operationId": "_chat.archive_post",
        "summary": "Chat Archived/Unarchived",
        "description": "Triggered when a chat's archive status changes.\n\n### Developer Tips\n- **Folder Logic**: Use this to organize chats in your custom dashboard similar to the official WhatsApp app.\n\n\n# Archive Management\n\nFired whenever you or a sync action moves a chat into/out of the archived folder.\n\n### Key Fields\n*   **chatId**: The individual or group ID.\n*   **archived**: `true` if moved to archive, `false` if moved back to active.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "chat.archive",
                  "payload": {
                    "chatId": "11111111111@c.us",
                    "archived": true
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/call.received": {
      "post": {
        "operationId": "_call.received_post",
        "summary": "Call Received",
        "description": "Triggered when an incoming Voice or Video call is detected.\n\n### Developer Tips\n- **Calling Limitation**: Wawp currently does not support ANSWERING calls via API. This is for NOTIFICATION purposes only.\n\n\n# The Voice-to-Text Bridge: Mastering Call Received Webhooks\n\nIn a digital-first support ecosystem, the incoming call is often a signal of high urgency or user frustration. While the Wawp platform is primarily an asynchronous messaging engine and does not support the ingestion of raw VoIP audio streams, the [`call.received`] webhook is a critical diagnostic and operational event. It allows your infrastructure to \"Hear\" the incoming ringing state, providing your system with the metadata required to bridge the gap between a voice request and a text-based resolution.\n\nThis guide provides an architectural deep-dive into the strategic value of call monitoring, moving beyond \"Notification\" into the realm of **Automated Redirection and High-Urgency Triage**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Call as an Escalation Signal\n\nTo master the Call Received API, one must recognize that a WhatsApp call (identified by the [`from`] JID, usually `@c.us`) is a \"Request for Synchronous Interaction.\" In the context of a bot-led flow, this is often a signal that the user is finding the text-based menu insufficient for their current needs.\n\n### 1. The Metadata of the Attempt\nThe [`call.received`] event provides the core identifiers of the interaction:\n*   **The Identity (from)**: The [`@c.us`] JID of the caller. This allows for instant CRM lookup.\n*   **The Vector (isVideo)**: Distinguishing between an Audio and Video call. A video call attempt often indicates a desire to \"Show\" a problem (e.g., a broken product) rather than just \"Tell\" it.\n*   **The Session (me)**: Which of your many WhatsApp instances is receiving the call.\n\n### 2. The Operational Boundary\nIt is architecturally vital to communicate to your stakeholders that Wawp acts as a **Sensor, not a Receiver**. Your system cannot \"Answer\" the call or \"Record\" the audio. Instead, your system should treat the call event as a **Trigger for an Automated Fallback Workflow**.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Automated Call Failovers\n\nCall monitoring allows you to build a sophisticated \"Safety Net\" that ensures no customer is left in the \"Ringing\" void.\n\n### 1. The \"Call-to-Chat\" Redirection Strategy\nThe most powerful use of this webhook is the **Instant Redirect**. \n**The Strategic Workflow**: As soon as the [`call.received`] event fires, your bot can immediately send a private message to the caller: *\"Hi there! We saw you trying to call. We currently only offer support via chat to ensure we can handle all requests efficiently. How can I help you today?\"* \n**Strategic Value**: This moves the user from a frustrated \"No Answer\" state to an active \"Chat Ingestion\" state within seconds. It manages expectations and keeps the conversation within your manageable support pipeline.\n\n### 2. High-Urgency Agent Alerting\nFor premium or VIP accounts, an incoming call should bypass the standard bot and trigger an internal alert for a human agent. \n**The Logic**: When the webhook fires for a VIP JID, your system can trigger a desktop notification or a Slack alert: *\"VIP Customer [Name] is currently calling the WhatsApp line! Please reach out to them via chat immediately.\"* Even if the agent doesn't answer the call (which they can't via API), they can initiate a proactive chat while the user still has their phone in their hand.\n\n### 3. Calculating the \"Frustration Quotient\"\nBy logging the frequency of incoming calls for a specific [`chatId`], you can calculate an \"Engagement Stress\" metric. A user who calls 5 times in 10 minutes is in a high-stress state. Your system can detect this pattern and automatically escalate the next text message from that user to a \"Priority 1\" status, ensuring they receive the fastest possible human response.\n\n---\n\n## 🛡️ Administrative Mandate: Scaling the Notification Layer\n\n### 1. The \"Ghost Call\" and Bot Loops\nAvoid sending a \"Why are you calling?\" message for every single ring event. WhatsApp sometimes emits multiple events for a single long-ringing session. \n**The Strategy**: Implement a **Call Debounce**. If you receive a call event for User A, do not trigger your \"Redirect Bot\" again for the same user within the next 2 minutes. This prevented your system from spamming the user with multiple redirect messages for a single call attempt.\n\n### 2. Respecting the \"No-Voice\" Perimeter\nClearly state in your business profile and your \"Welcome\" messages that you do not support voice calls. Use the [`call.received`] webhook only as a **Secondary Defense**. The primary defense is setting the right expectations in your text-based UI. If a user calls despite the warnings, your system should respond with firm but polite redirection logic.\n\n---\n\n## 🛡️ Operational Best Practices: Designing for Missed Connections\n\n*   **Differentiating Between Ringing and Missed**: Ensure you coordinate this event with the [Call Rejected](/v2/webhooks/call-rejected) event. A [`call.received`] without a rejection often means the call timed out. You should treat \"Missed Calls\" differently than \"Rejected Calls\" in your CRM logging.\n*   **Syncing with Physical Devices**: If you have a physical phone linked to the Wawp instance, that phone *will* ring. This webhook allows your digital backend to \"Know\" what the human holding that phone is seeing, enabling a unified view of the customer across digital and physical touchpoints.\n*   **VCard and Identity Correlation**: If the caller is not in your CRM, use the [`from`] JID to initiate a [Contact Lookup](/v2/contacts/about). You can often retrieve the user's \"Push Name\" or \"About\" info even if they just called for the first time, allowing your \"Redirect Message\" to be personalized (e.g., \"Hi John, we saw you calling...\").\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Low-Latency Routing**: Call events are time-sensitive. If your redirect message arrives 5 minutes after the call ended, it looks unprofessional. Your handler should aim for sub-500ms processing.\n2.  **Verify the Session Scope**: In a multi-instance environment, ensure the [`session`] ID is used to filter the redirection logic. You don't want Instance A sending a \"We don't support calls\" message to a user who called Instance B.\n3.  **Coordinate with Revocations**: Calls do not have \"Revocations\" in the same way messages do, but they do have \"Timeouts.\" Your system should automatically clear any \"Active Call\" flag in your dashboard after 60 seconds if no further status is received.\n\n## 🎯 Conclusion: Turning Silence into Conversation\n\nThe **Call Received Webhook** is the \"Emergency Beacon\" of your integration. By building an architecture that listens to voice attempts and converts them into chat opportunities, you move your organization from \"Missing Connections\" to **Intelligent Redirection**. You build systems that catch every signal, manage every frustration, and bridge every channel gap with engineered precision. In the world of Wawp, a call is not an impossibility; it is a high-priority invitation to a better conversation.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "call.received",
                  "payload": {
                    "id": "call_12345",
                    "from": "11111111111@c.us",
                    "isVideo": false
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/call.accepted": {
      "post": {
        "operationId": "_call.accepted_post",
        "summary": "Call Accepted",
        "description": "Triggered when a received call is picked up on another device.\n\n### Developer Tips\n- **Multi-device Sync**: Shows the status shift when you answer the call using your physical phone.\n\n\n# Call Acceptance\n\nFired when a call lifecycle moves from `ringing` to `active`.\n\n### Fields\n*   **id**: Match this with the ID from `call.received`.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "call.accepted",
                  "payload": {
                    "id": "call_12345"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/call.rejected": {
      "post": {
        "operationId": "_call.rejected_post",
        "summary": "Call Rejected",
        "description": "Triggered when an incoming call is declined.\n\n### Developer Tips\n- **Sync Status**: Useful for accurate logging of missed or ignored calls.\n\n\n# Closing the Voice Loop: Mastering Call Rejected Webhooks\n\nIn the ecosystem of digital communication, the termination of an interaction is as significant as its initiation. The [`call.rejected`] webhook is the definitive \"End of Signal\" event for a voice or video attempt within the Wawp platform. Whether a call is manually declined by a human operator using a physical device or automatically terminated due to system policy, this event provides your infrastructure with the closure required to maintain an accurate, real-time audit trail of customer engagement.\n\nThis guide provides an architectural deep-dive into the strategic value of call termination monitoring, moving beyond \"Status Logging\" into the realm of **Operational Accountability and Customer Experience Synchronization**.\n\n---\n\n## 🏗️ Architectural Philosophy: The Call as a Finite Session\n\nA WhatsApp call is a synchronous state that consumes resources and attention. The [`call.rejected`] event serves as the \"Garbage Collector\" for your communication logic.\n\n### 1. The Termination Vector\nA rejection event can occur due to several distinct triggers, and a premium architecture must account for all of them:\n*   **Manual Decline**: A human agent taps \"Decline\" on the physical phone or WhatsApp Web.\n*   **Automated Policy**: Your backend logic or a third-party app terminates the call.\n*   **User Cancellation**: The caller hangs up before the call is answered (though this sometimes results in a \"Missed\" state, Wawp often emits the rejection signal to clear the socket).\n\n### 2. Identifying the Call Session\nThe only field in the payload is the [`id`] of the call. This is by design. The Call ID is the **Primary Key** that connects the [`call.received`] event with the [`call.rejected`] event. Your system must use this ID to \"Reconcile\" the interaction, moving the call record in your database from `RINGING` to `TERMINATED`.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Accountable Support Flows\n\nCall rejection monitoring allows you to measure the \"Response Gap\" and automate the next step in the customer journey.\n\n### 1. The \"Immediate Proactive Chat\" Strategy\nIf a call is rejected, the user is likely at their phone *right now*. This is the perfect moment for a text-based follow-up.\n**The Strategic Workflow**: As soon as [`call.rejected`] is received, your system checks if it was preceded by a [`call.received`] event. If so, it instantly sends a message: *\"Sorry we couldn't take your call right now! We're currently assisting other customers via chat. How can we help you here?\"* \n**Strategic Value**: This turns a \"Negative Interaction\" (a rejected call) into a \"Positive Engagement\" (a proactive chat). It demonstrates that your brand is aware, responsive, and ready to assist through alternate channels.\n\n### 2. Agent Performance and Accountability Mining\nIn a support center where agents have physical phones, the rejection rate is a key performance indicator (KPI). \n**The Logic**: By correlating the [`call.rejected`] event with the agent assigned to that WhatsApp instance, you can identify patterns of avoided interactions. If an instance consistently rejects 80% of incoming calls during business hours, it indicates a training or staffing issue. This data allows for **Evidence-Based Management**, moving away from \"Feelings\" about agent performance toward hard, technical proof of interaction avoidance.\n\n### 3. CRM History and \"Audit of Intent\"\nA complete CRM record should not just show messages; it should show every attempt at contact. \n**The Data Pattern**: When the rejection webhook fires, update the user's timeline with a specialized \"Missed/Rejected Call\" entry. This gives the next agent to handle the customer a full view of the context: *\"Customer tried to call 3 times this morning and was declined each time.\"* This allows the agent to apologize for the missed connection, significantly improving the \"Personalization Score\" of the next interaction.\n\n---\n\n## 🛡️ Administrative Mandate: Balancing Physical and Digital Reality\n\n### 1. The \"Physical Sync\" Problem\nWhen you use Wawp, you are often using a real WhatsApp account that exists on a physical smartphone. If a human picks up that phone and hits \"Decline,\" the Wawp API receives the [`call.rejected`] webhook. \n**The Strategic Insight**: This webhook is your backend's only way of knowing what the physical human operator did. Use it to keep your digital dashboard \"In Sync\" with the physical reality of the office. If the phone user is declining calls, your digital bot should probably \"Sleep\" for a few minutes to avoid conflicting with the human's manual workflow.\n\n### 2. Guarding against \"Zombie Calls\"\nWithout a rejection signal, your custom dashboard might show a \"Call in Progress\" banner forever if the network drops during the ringing phase. \n**The Strategy**: Use the [`call.rejected`] event as a **Global Clear Command**. When this event fires, it should forcibly remove any \"Active Call\" UI elements for that specific [`session`], ensuring your agents always have an accurate view of the instance's state.\n\n---\n\n## 🛡️ Operational Best Practices: Designing for Professional Closure\n\n*   **Handling the \"Busy\" Signal**: If your system rejects a call because the agent is already in a chat, use the [`call.rejected`] event to trigger a \"Wait\" message. This explains *why* the call was declined, preventing the user from feeling ignored.\n*   **Coordinate with Call Received**: Always index your calls by ID. If you receive a [`call.rejected`] for an ID that you never received a [`call.received`] for, log it as a \"Network Anomaly.\" This helps your technical team identify stability issues with the WhatsApp WebSocket or your server's ingestion lag.\n*   **The \"Zero-Latency\" Rule**: Like all call events, rejection is extremely time-sensitive. If your follow-up message arrives 10 minutes late, the customer has already moved on to a competitor. Host your rejection handler on your fastest, most reliable infrastructure.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Strict ID Mapping**: Ensure your database uses the Call ID as a primary key for call-related records. This prevents \"ID Collision\" and ensures that state updates are applied to the correct interaction.\n2.  **Verify the Session Scope**: In a multi-instance setup, Ensure that the [`session`] ID provided in the webhook metadata is used to gate your follow-up logic. You don't want a \"Sorry we missed you\" message being sent from the wrong business line.\n3.  **Clean up In-Memory States**: If you use a cache (like Redis) to track \"Active Calls,\" use the [`call.rejected`] event to immediately purge the entry for that Call ID. This keeps your cache lean and prevents memory leaks.\n\n## 🎯 Conclusion: Mastering the Art of the End-Point\n\nThe **Call Rejected Webhook** is the \"Final Chapter\" of a voice interaction. By building an architecture that listens to this termination signal and converts it into a proactive opportunity, you move your organization from \"Abrupt Disconnects\" to **Seamless Redirection**. You build systems that respect human decisions, capture interaction data, and maintain a high-fidelity conversational history with engineered precision. In the world of Wawp, a rejection is not the end of the relationship; it is the strategic trigger for a better, more focused conversation.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "call.rejected",
                  "payload": {
                    "id": "call_12345"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/label.upsert": {
      "post": {
        "operationId": "_label.upsert_post",
        "summary": "Label Created/Updated",
        "description": "Triggered when a WhatsApp Business label is added or modified.\n\n### Developer Tips\n- **Business Feature**: Labels are exclusive to WhatsApp Business accounts. Personal accounts will not fire this event.\n\n\n# The Taxonomy of Engagement: Mastering Label Upsert Webhooks\n\nIn the sophisticated world of WhatsApp Business management, organization is the engine of efficiency. Labels are the native categorization tool of the WhatsApp Business ecosystem, allowing agents to visually prioritize and segment their conversations. The **Label Created/Updated (Upsert)** webhook is the primary signal that your organization's taxonomy has evolved. Whether a new \"Priority Sales\" label is created or an existing \"In Review\" label is renamed, the [`label.upsert`] event provides your infrastructure with the real-time data required to maintain a perfect synchronization between your WhatsApp interface and your central CRM.\n\nThis guide provides an architectural deep-dive into the strategic importance of label metadata management, moving beyond \"Tag Tracking\" into the realm of **Operational Categorization and Visual Workflow Orchestration**.\n\n---\n\n## 🏗️ Architectural Philosophy: Labels as Structural Metadata\n\nTo build a premium enterprise integration, your system must treat labels as the \"Primary Keys of Segmentation.\" A label consists of three core properties: a unique **ID**, a **Name** (the category title), and a **Color** (the visual priority).\n\n### 1. The Taxonomy Bridge\nA Label Upsert event should be treated as a **Configuration Update**. \n*   **CRM Synchronization**: Your system should mirror these labels as \"Tags\" or \"Status Folders\" within your internal CRM. When a label name changes on WhatsApp, your CRM must update its display name instantly to ensure agents don't experience \"Contextual Mismatch\"—where the phone says \"Lead\" but the CRM says \"Prospect.\"\n*   **The Idempotent Upsert**: Because the payload contains the full label object, your ingestion layer can use an \"Upsert\" (Update-or-Insert) logic. If the Label ID is new, branch it into your taxonomy; if it exists, update its metadata.\n\n### 2. The Visual Pulse (Colors as Priority)\nWhatsApp labels use hex color codes to denote priority. A high-performance architecture maps these colors to internal priority levels. For example, a \"Red\" label might trigger a higher-priority alert in your internal Slack channel than a \"Blue\" label. The [`label.upsert`] webhook is the signal that these priority assignments have shifted.\n\n---\n\n## 🚀 Strategic Use Cases: Powering Categorized Communication\n\nLabels are the \"Sorters\" of your conversational pipeline. Mastering the upsert event allows you to build a system that understands the *meaning* of a chat before an agent even opens it.\n\n### 1. Automated CRM Tag Migration\nFor businesses scaling from manual phone usage to automated Wawp-powered workflows, the label upsert event is the \"Historical Bridge.\" \n**The Strategic Workflow**: As agents create labels on their physical phones, your backend listens to the [`label.upsert`] stream. It automatically creates corresponding \"Segments\" in your email marketing or lead-tracking software. This ensures that the efforts of the \"Front-line\" agents (who organize the chats) are immediately visible to the \"Back-office\" analytical teams.\n\n### 2. Visual Consistency Across Custom Dashboards\nIf you are building a custom multi-agent dashboard using Wawp, you must replicate the \"Look and Feel\" of the WhatsApp Business app. \n**The Real-Time Update**: Use the color and name data from the upsert webhook to dynamically style your dashboard. When an admin changes the \"Urgent\" label from Orange to Red on their phone, the entire team's dashboard should update its CSS in real-time. This visual synchronicity builds a sense of a \"Unified Workspace\" across all devices and platforms.\n\n### 3. Dynamic Routing based on Taxonomy\nCombine the [`label.upsert`] event with the [Label Chat Added](/v2/webhooks/label-chat-added) event to build a \"Category-Based Router.\" \n**The Logic**: If a label [`VIP`] is created/updated, your system updates its routing tables. Any chat that is subsequently tagged with this label can be programmatically moved to the \"Senior Account Manager\" queue. By listening to the upsert, your system stays aware of *what* the labels mean, allowing for more flexible, human-readable routing logic.\n\n---\n\n## 🛡️ Administrative Mandate: Scaling the Organizational Layer\n\nEffective label management is a method of \"Structural Integrity.\"\n\n### 1. The \"Single Source of Truth\" Governance\nDecide who is the master of your taxonomy. \n*   **Hybrid Management**: If you allow agents to create labels on their phones, the [`label.upsert`] webhook is your \"Compliance Sentinel.\" You can use it to monitor the creation of \"Off-brand\" or \"Duplicate\" labels and programmatically [Delete](/v2/labels/delete) them if they violate your organizational policy.\n*   **Wawp-Led Management**: If your CRM is the master, you use the [Create Label](/v2/labels/create) API to push tags to WhatsApp. In this scenario, the webhook acts as a **Confirmation Signal**, letting you know the platform has successfully ingested your new tag.\n\n### 2. High-Fidelity Audit Logs for Business Strategy\nA change in a label name often signals a change in business process. \n**The Data Insight**: By logging the history of label upserts, you can track the evolution of your sales funnel. *\"We changed 'Interested' to 'Qualified' on March 1st\"*—having this technical timestamp in your logs allows you to accurately measure the performance of your marketing campaigns across different procedural eras.\n\n---\n\n## 🛡️ Operational Best Practices: Optimizing the Categorization Loop\n\n*   **Color-to-Severity Mapping**: Maintain an internal mapping table: `#DFE5E7` (Light Gray) = `Archived`, `#FFD700` (Gold) = `Premium`. When an upsert event carries one of these colors, the system should automatically apply the corresponding severity level to any associated support tickets.\n*   **The \"Special Characters\" Warning**: WhatsApp labels support emojis. Ensure your database and ingestion layer use full UTF-8 encoding so that a label named \"🚀 Sales\" doesn't become \"? Sales\" in your CRM.\n*   **Coordinate with label.deleted**: An upsert event updates the label, but it does not tell you if the label was removed from a specific chat. Always coordinate this webhook with [`label-chat-deleted`] to maintain an accurate count of how many users are currently in each \"Live Category.\"\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Deduplicate Rapid Updates**: If an agent is indecisive and renames a label three times in a minute, your system will receive three webhooks. Use the event [`timestamp`] to ensure you only apply the \"Final\" state to your database.\n2.  **Verify Business Engine Compatibility**: Labels are a premium feature of the WhatsApp Business engine. If your instance is downgraded or the engine is swapped to a non-business version, your system should handle the absence of these webhooks gracefully by falling back to \"Generic Text Tags.\"\n3.  **Scoped ID Lookups**: Label IDs are typically small integers (e.g., \"1\", \"2\"). Ensure your lookup logic doesn't confuse a Label ID with a Message ID or a JID, as they exist in different namespaces.\n\n## 🎯 Conclusion: Beyond Tags—The Architecture of Priority\n\nThe **Label Upsert Webhook** is the \"Registry of Categories\" for your conversational brand. By building an architecture that listens, synchronizes, and acts upon these metadata shifts, you move your organization from \"Generic Chat Management\" to **Engineered Prioritization**. You build systems that understand the visual language of the agent, respect the evolution of the sales funnel, and maintain a perfect synchronization between the front-office and the back-office. In the world of Wawp, an upsert is more than a change—it is the strategic signal that keeps your organizational structure aligned with your real-time engagement.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "label.upsert",
                  "payload": {
                    "label": {
                      "id": "1",
                      "name": "New Customer",
                      "color": "#DFE5E7"
                    }
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/label.deleted": {
      "post": {
        "operationId": "_label.deleted_post",
        "summary": "Label Deleted",
        "description": "Triggered when a label is completely removed from the account.\n\n### Developer Tips\n- **Cascading Deletion**: When a label is deleted, it is automatically removed from all chats. You should cleanup your local associations as well.\n\n\n# Label Deletion\n\nSignals that a specific business label no longer exists.\n\n### Fields\n*   **labelId**: The ID of the removed label.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "label.deleted",
                  "payload": {
                    "labelId": "1"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/label.chat.added": {
      "post": {
        "operationId": "_label.chat.added_post",
        "summary": "Label Added to Chat",
        "description": "Triggered when a label is assigned to a specific conversation.\n\n### Developer Tips\n- **Lead Status**: Perfect for moving leads through your custom kanban or pipeline based on tags applied in WhatsApp.\n\n\n# The Signal of Conversion: Mastering the Label-to-Chat Webhook\n\nIn the architecture of a high-performance sales and support engine, a tag is not just a label—it is a **State Transition**. The **Label Added to Chat** webhook is the primary signal that a human agent or an automated system has categorized a conversation into a specific operational phase. Whether a chat is marked as \"Interested,\" \"Payment Pending,\" or \"VIP Support,\" the [`label.chat.added`] event provides your infrastructure with the real-time trigger required to move the customer through your internal Kanban or CRM pipeline.\n\nThis guide provides an architectural deep-dive into the strategic value of dynamic chat labeling, moving beyond \"Tagging\" into the realm of **Automated Pipeline Orchestration and Lead-Scoring Logic**.\n\n---\n\n## 🏗️ Architectural Philosophy: Labels as Pipeline Gates\n\nTo master the Label-to-Chat API, one must recognize that applying a label is an act of **Intentional Classification**.\n\n### 1. The Interaction Identity (JIDs)\nThe mapping of a label to a chat is agnostic of the chat type:\n*   **Individuals (@c.us)**: Tagging a 1-on-1 chat creates a personalized lead profile in your CRM.\n*   **Groups (@g.us)**: Tagging a group chat categorizes the entire community (e.g., \"Project Delta\" or \"Priority Partners\").\nYour system must use the [`chatId`] in the payload to locate the target entity and the [`labelId`] to determine which specific \"Bucket\" the entity now belongs to.\n\n### 2. The Relationship Between Meta and State\nWhile the [Label Upsert](/v2/webhooks/label-upsert) event defines *what* the label is (name/color), the [`label.chat.added`] event defines *where* the label is. A robust architecture treats the Upsert as a \"Schema Update\" and the Added event as a \"Data Mutation.\" \n\n---\n\n## 🚀 Strategic Use Cases: Powering Automated Conversion Funnels\n\nThe Label-to-Chat webhook is the \"Glue\" that connects the human interaction on a phone with the automated processes in your backend.\n\n### 1. Building the \"WhatsApp Kanban\" (Automated Pipeline Sync)\nMany organizations use external tools like Trello, Pipedrive, or custom Kanban boards to track leads.\n**The Strategic Workflow**: When an agent on a physical phone applies the \"Qualified\" label to a chat, Wawp fires the [`label.chat.added`] webhook. Your backend catches this and programmatically moves the corresponding card in your CRM from the \"Lead\" column to the \"Opportunity\" column. This ensures your sales dashboard is **Always in Sync** with the real-time actions of the front-line team, eliminating manual data entry.\n\n### 2. Automated Drip-Sequence Triggers\nLabels can act as \"Switches\" for automated marketing campaigns.\n**The Logic**: If your system detects that a chat has been tagged with \"Send Catalog,\" it can automatically trigger the [`send-pdf`](/v2/send/pdf) endpoint to deliver your latest product brochure to that [`chatId`]. This \"Label-Triggered Automation\" allows human agents to initiate complex bot flows with a single tap of a tag on their phone screen.\n\n### 3. Escalation and Priority Routing\nUse labels to denote \"Escalated\" status.\n**The Use Case**: When a support supervisor tags a chat as \"High Priority,\" your system detects the change via the webhook and updates the metadata in your internal ticketing system. It can also trigger a Slack notification to the engineering team: *\"Urgent assistance required for [Contact Name]—tagged as High Priority.\"* This turns a simple WhatsApp feature into a **Cross-Platform Alerting Engine**.\n\n---\n\n## 🛡️ Administrative Mandate: Scaling the Attribution Layer\n\nScaling labeling logic requires a focus on \"Categorical Integrity.\"\n\n### 1. The \"Single Label\" Policy vs. Multi-Tagging\nWhatsApp allows multiple labels to be applied to a single chat. \n**The Strategic Rule**: Decide how your CRM handles \"Tag Overlap.\" Does your system treat the *latest* label as the primary status, or does it accumulate labels into an array of tags? We recommend an **\"Accumulative Model\"** for marketing segments and a **\"Single-Truth Model\"** for pipeline stages. The [`label.chat.added`] event provides the IDs you need to maintain whichever model fits your business logic.\n\n### 2. Monitoring Agent Productivity and Accuracy\nBy logging every [`label.chat.added`] event with its timestamp, you can measure the \"Time-to-Label\"—the gap between the first message and the moment the lead was qualified. \n**The Data Insight**: If an agent takes 4 hours to label a lead, it indicates a bottleneck in your triage process. If they label 50 chats as \"Spam\" in 5 minutes, it may indicate a data-quality issue or a need for better automated filtering. This webhook is a vital tool for **Operational Quality Control**.\n\n---\n\n## 🛡️ Operational Best Practices: Optimizing the State Loop\n\n*   **Coordinate with label.chat.deleted**: A chat can move out of a category by having the label removed. To maintain an accurate count of \"Live Leads\" in your CRM, your system *must* listen to the [Label Deleted from Chat](/v2/webhooks/label-chat-deleted) event to clear the corresponding tag in your database.\n*   **The \"Shadow State\" Warning**: Note that labels are sometimes applied *before* the first message is received (e.g., from a prior contact). Your system should be prepared to handle a [`label.chat.added`] event for a [`chatId`] that doesn't yet have a message history in your logs.\n*   **Visual Reassurance**: If your custom dashboard has its own tagging UI, ensure that any label added via the Wawp API also triggers the same \"Success\" visuals as a manual tag. This keeps the experience consistent for the user.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Strict ID Mapping**: Always resolve the [`labelId`] using your latest cached data from the [label.upsert](/v2/webhooks/label-upsert) stream. Never hardcode label IDs, as they can change between different WhatsApp Business instances.\n2.  **Verify Asset Consistency**: If a label is added to a Group (`@g.us`), ensure your code updates the metadata for the *Group Entity* rather than a specific individual.\n3.  **Handle \"Mass Tagging\" Scenarios**: Some WhatsApp engines allow \"Bulk Labeling\" (tagging 10 chats at once). Your webhook handler should be designed to receive and process these as atomic, high-speed events.\n\n## 🎯 Conclusion: The Rhythm of Classification\n\nThe **Label Added to Chat Webhook** is the \"Pulse of Progress\" for your digital brand. By building an architecture that listens, automates, and synchronizes these categorical shifts, you move your organization from \"Reactive Chatting\" to **Structured Revenue Management**. You build systems that understand the stage of every lead, automate the delivery of resources, and maintain a high-fidelity pipeline between the WhatsApp interface and your corporate brain. In the world of Wawp, a label is not just a tag—it is the strategic signal that drives your business forward.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "label.chat.added",
                  "payload": {
                    "chatId": "11111111111@c.us",
                    "labelId": "1"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/label.chat.deleted": {
      "post": {
        "operationId": "_label.chat.deleted_post",
        "summary": "Label Removed from Chat",
        "description": "Triggered when a label is unassigned from a conversation.\n\n### Developer Tips\n- **Pipeline Movement**: Use this to detect when a lead is cleared from a specific stage in your sales funnel.\n\n\n# Chat Label Removal\n\nSignals that a tag has been disconnected from a chat.\n\n### Fields\n*   **chatId**: ID of the conversation.\n*   **labelId**: The ID of the label that was removed.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "label.chat.deleted",
                  "payload": {
                    "chatId": "11111111111@c.us",
                    "labelId": "1"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/event.response": {
      "post": {
        "operationId": "_event.response_post",
        "summary": "Event Success Response",
        "description": "Triggered when an asynchronous event completes successfully.\n\n### Developer Tips\n- **Async Tracking**: Essential for tracking the completion of bulk tasks or long-running operations.\n\n\n# Asynchronous Success\n\nThis event confirms that a previously requested async operation has finished without errors.\n\n### Fields\n*   **requestId**: The unique ID you received when making the initial request.\n*   **data**: The successful result or confirmation data.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "event.response",
                  "payload": {
                    "requestId": "req_001",
                    "data": {
                      "status": "completed"
                    }
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/event.response.failed": {
      "post": {
        "operationId": "_event.response.failed_post",
        "summary": "Event Failure Response",
        "description": "Triggered when an asynchronous event fails to complete.\n\n### Developer Tips\n- **Error Recovery**: Always listen for this event to implement retry logic or alert users of a failed task.\n\n\n# Asynchronous Failure\n\nIndicates that an async operation could not be completed.\n\n### Fields\n*   **requestId**: The ID of the failed request.\n*   **error**: Error details describing what went wrong.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "event.response.failed",
                  "payload": {
                    "requestId": "req_002",
                    "error": "TIMEOUT_ERROR"
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/engine.event": {
      "post": {
        "operationId": "_engine.event_post",
        "summary": "Raw Engine Event",
        "description": "Catch-all for low-level system events directly from the WhatsApp engine.\n\n### Developer Tips\n- **Advanced Use**: This is primarily for developers needing raw access to internal engine movements not covered by high-level events.\n\n\n# Raw Engine Access\n\nThis event exposes internal movements of the underlying engine (`WEBJS`, etc.).\n\n### Usage\nUseful for tracking internal connection retries or low-level protocol debugging.\n    ",
        "tags": [
          "Webhooks"
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Webhook Payload Example",
            "content": {
              "application/json": {
                "example": {
                  "id": "evt_01...",
                  "timestamp": 1634567890123,
                  "session": "default",
                  "metadata": {
                    "user.id": "123",
                    "user.email": "email@example.com"
                  },
                  "engine": "WEBJS",
                  "event": "engine.event",
                  "payload": {
                    "raw": {
                      "event": "internal_movement",
                      "data": {}
                    }
                  },
                  "me": {
                    "id": "11111111111@c.us",
                    "lid": "123@lid",
                    "pushName": "Instance"
                  }
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v2/calls/reject": {
      "post": {
        "operationId": "_v2_calls_reject_post",
        "summary": "Reject Call",
        "description": "Reject an incoming call for a specific session.\n\n### Developer Tips\n- **Webhook Events**: Listen to call.* webhooks to handle incoming calls in real-time.\n- **Outbound Calls**: WhatsApp API does not support programmatic outbound calls. Use links instead.\n\n\n# Strategic Declinism: The Power of Programmatic Call Termination\n\nIn the orchestration of high-volume digital business environments, the ability to say \"No\" is as critical as the ability to respond. The **Reject Call** endpoint is your primary tool for **Strategic Boundary Enforcement and Conversational Routing**. It allows your automated systems to programmatically terminate an incoming voice or video signal based on real-time business logic, ensuring that your organization's human and technical resources are always focused on the highest-priority interactions. Beyond a simple \"Dismiss\" action, this endpoint is the foundation of a managed voice perimeter that protects your agents from noise and your customers from a substandard conversational experience.\n\nFor enterprise architects, rejection is the **First Step of Redirection**. This guide explores the strategic imperatives of call termination and the governance of real-time presence.\n\n---\n\n## 🏗️ Architectural Philosophy: Signal Termination vs. Passive Silence\n\nFrom a technical perspective, the Reject Call endpoint is a **Signaling Command** that instructs Meta's infrastructure to send a \"Busy\" or \"Call Declined\" packet back to the caller.\n\n### Key Architectural Objectives:\n*   **Active vs. Passive Denial**: If your instance simply ignores a call, the caller's phone will continue to ring for 30-45 seconds until it times out. This creates a perception of unresponsiveness or technical failure. By calling the **Reject Call** API, your system provides an immediate, authoritative signal. This \"Active Rejection\" is a professional courtesy that allows the caller to immediately seek an alternative path of resolution.\n*   **Interrupt Management**: Real-time calls are high-intensity events that occupy the device's audio and networking hardware. Programmatic rejection ensures that these resources are cleared as quickly as possible, maintaining the performance and stability of your WhatsApp Business instance for other concurrent tasks, such as sending high-priority alerts or [Broadcasting](/v2/messaging).\n*   **Idempotency and Traceability**: Every rejection is tied to a unique `callId` retrieved from the [`call.received`](/v2/webhooks/call-received) webhook. This ensures that your system never terminates the wrong interaction and provides a clear audit trail for your compliance and performance monitoring engines.\n\n---\n\n## 🚀 Strategic Use Case: Enforcing Operational Boundaries\n\nReal-time voice communication is expensive. Utilizing programmatic rejection allows you to manage this cost while maintaining a premium brand image.\n\n### 1. The \"VIP-Only\" Calling Perimeter\nYour organization may choose to offer live voice support only to high-value stakeholders (e.g., Enterprise Tier clients or VIP partners). When a call arrives, your system performs a \"Call-Sign Verification\" against your CRM. If the caller is a \"Regular Tier\" user, the system instantly rejects the call and initiates a text-based redirection: *\"We see you are trying to call. Live voice support is a feature of our Premium plan. Please continue your request here via text or click this link to upgrade your account.\"* This turns a rejected call into a targeted \"Upsell Opportunity.\"\n\n### 2. Global \"Quiet Hours\" Enforcement\nFor businesses operating across multiple time zones, enforcing local business hours is a logistical challenge. By integrating the **Reject Call** endpoint with a \"Time-Zone aware Scheduler,\" your system can automatically reject calls arriving outside of a specific region's working hours. The system can then provide context-aware feedback: *\"Greetings! Our London office is currently closed. We will be back online at 09:00 GMT. In the meantime, you can leave a voice note or use our automated FAQ bot.\"*\n\n### 3. Combatting the \"Robocall\" Epidemic\nWhatsApp accounts are not immune to automated spam callers. Your system can implement \"Frequency Throttling.\" If a specific JID calls three times in 60 seconds without a prior 1:1 conversation history, the system identifies this as a \"Bot Signature\" and automatically rejects all subsequent attempts, potentially triggering a temporary [Block](/v2/contacts/block) of the identifier to protect your internal infrastructure.\n\n---\n\n## 🔐 Administrative Mandate: The Guardianship of Operational Focus\n\nIn a professional call center or a distributed agent environment, distraction is a measurable cost. Strategic rejection is a method of \"Focus Insurance.\"\n\n### Protecting the \"Deep Work\" State\nYour agents are most productive when they can focus on resolving complex issues without being interrupted by random incoming rings. By using the **Reject Call** endpoint as a \"Gatekeeper,\" you ensure that the only calls that reach a human agent are those that have been \"Qualified\" through a prior text-based interaction. This \"Qualified-Voice-Only\" policy significantly increases agent throughput and reduces the mental fatigue associated with unmanaged conversational noise.\n\n### Integrity in Compliance and Recording\nIn regulated industries (like Finance or Law), every voice call must be recorded for compliance purposes. If your secondary SIP/VoIP bridge is currently down or at capacity, your system should use the **Reject Call** API as a \"Safety Valve.\" It prevents any call from being established that cannot be properly audited, ensuring that your organization remains within its legal and regulatory guardrails at all times.\n\n---\n\n## 🛡️ Operational Best Practices: The \"Rules of the Graceful Exit\"\n\n*   **The \"Contextual Follow-up\" Mandate**: A programmatic rejection should **never** be a standalone event. The strategic objective is to move the user from a synchronous (High-Cost) channel to an asynchronous (Low-Cost) one. Your system must always send a 1:1 text message within 500ms of the rejection, acknowledging the call and providing the next step.\n*   **Latency-Optimized Processing**: The window for a professional rejection is narrow. If your system takes more than 500-1000ms to process the webhook and send the rejection command, the user will experience one or two rings, creating a \"Glitchy\" impression. Ensure your webhook handler is optimized for high-speed decision-making.\n*   **Monitoring \"Rejection Attrition\"**: Track how many users leave your ecosystem after their calls are rejected. If you find a high drop-off rate, it indicates that your redirection messages are not empathetic or helpful enough. Continuous AB testing of your \"Redirect Copy\" is essential for long-term retention.\n\n---\n\n## ⚙️ Engineering Best Practices: The Validation Loop\n\n1.  **Map JIDs to Session Integrity**: Ensure the `from` JID matches your known context for that specific `callId`. This prevents \"Cross-Talk\" errors where your system might accidentally try to terminate a call on a different session.\n2.  **Handle \"Signal Already Terminated\" States**: In high-latency networking scenarios, a user might hang up right as your system is sending the rejection command. Your code should gracefully handle [`400 Bad Request`] or [`404 Not Found`] responses from the API, treating them as successful \"Race Condition\" resolutions.\n3.  **Coordinate with Presence Awareness**: Before rejecting a call from a high-value customer, perform a quick check of your [Presence State](/v2/presence). If the system detects that *no* agents are currently online, the rejection is justified. If agents are online but \"Busy,\" consider a \"Queueing Message\" rather than a hard rejection.\n\n---\n\n## 🎯 Conclusion: Mastering the Art of the Governed Perimeter\n\nThe **Reject Call** endpoint is the \"Shield\" of your community and interaction architecture. It is your most powerful tool for enforcing discipline, protecting resources, and ensuring that every voice interaction is an intentional, high-value event. By treating rejection as a strategic lever rather than a technical necessity, you build a conversational ecosystem that is professional, respectful of both your agents' and your customers' time, and always perfectly aligned with your business objectives. You move beyond \"Simple Signal Handling\" and into the world of **Advanced Presence Governance**, where the boundary of your business is defined by automated intelligence and architectural precision.\n    ",
        "tags": [
          "Calls"
        ],
        "parameters": [
          {
            "name": "instance_id",
            "in": "query",
            "required": true,
            "description": "Your unique WhatsApp Instance ID",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "access_token",
            "in": "query",
            "required": true,
            "description": "Your API Access Token",
            "schema": {
              "type": "string"
            },
            "example": "123456789"
          },
          {
            "name": "callId",
            "in": "query",
            "required": true,
            "description": "The unique ID of the incoming call (from call.received webhook)",
            "schema": {
              "type": "string"
            },
            "example": "call_123456789"
          },
          {
            "name": "from",
            "in": "query",
            "required": true,
            "description": "The WhatsApp ID (JID) of the caller (from call.received webhook)",
            "schema": {
              "type": "string"
            },
            "example": "123456789@c.us"
          }
        ],
        "responses": {
          "200": {
            "description": "Success (Plain Text)",
            "content": {
              "application/json": {
                "example": "Success: Operation completed successfully."
              }
            }
          },
          "400": {
            "description": "Bad Request (Plain Text)",
            "content": {
              "application/json": {
                "example": "Error: missing_param. Missing required parameter: {parameterName}. Please check your request parameters and try again."
              }
            }
          },
          "401": {
            "description": "Unauthorized (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_access_token</code>\n    <message>Invalid or expired access token.</message>\n    <details>\n        <recommendation>Ensure you are sending a valid 'access_token' in the request.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "404": {
            "description": "Not Found (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>invalid_session</code>\n    <message>Session not found.</message>\n    <details>\n        <recommendation>Check if the instance exists and is active.</recommendation>\n    </details>\n</error>"
              }
            }
          },
          "500": {
            "description": "Internal Server Error (HTML)",
            "content": {
              "application/json": {
                "example": "<!DOCTYPE html>\n<html>\n<head><title>500 Internal Server Error</title></head>\n<body>\n    <h1>Internal Server Error</h1>\n    <p>The server encountered an internal error. Please try again later.</p>\n    <p><em>Recommendation: Check the API dashboard for service status updates.</em></p>\n</body>\n</html>"
              }
            }
          },
          "502": {
            "description": "Bad Gateway (XML Format)",
            "content": {
              "application/json": {
                "example": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<error>\n    <code>proxy_error</code>\n    <message>Failed to connect to WhatsApp server.</message>\n    <details>\n        <recommendation>Check if the instance is online and connected.</recommendation>\n    </details>\n</error>"
              }
            }
          }
        }
      }
    }
  }
}