WhatsApp Webhooks: V2

Webhooks provide real-time delivery updates for messages sent via messages sent by using Netcore APIs. Each time a message’s state changes (e.g., sent, delivered, read), Netcore triggers a webhook to your configured endpoint with a standardized JSON payload.

These events help you:

  • Track the message lifecycle accurately
  • Improve reporting and analytics
  • Trigger workflows based on message status
  • Ensure billing accuracy

Webhook Structure

All webhook events follow a consistent format:

{
  "delivery_status": [
    {
      "ncmessage_id": "string",
      "phoneNumber": "string",
      "pricing": {
        "billable": boolean,
        "category": "string",
        "pricing_model": "string",
        "type": "string"
      },
      "received_at": "epoch_timestamp",
      "recipient": "string",
      "source": "string",
      "status": "string",
      "status_remark": "string",
      "x-apiheader": "string"
    }
  ]
}

Fields

Refer to the given table to know the descriptions for the webhook fields.

FieldTypeDescription
delivery_statusarrayAn array of webhook event objects. Multiple events may be sent in a single webhook batch.
ncmessage_idstringUnique message identifier generated by Netcore.
phoneNumberstringSender’s phone number or virtual number used to send the message.
recipientstringDestination number to which the message was sent.
received_atinteger(epoch)Timestamp when the event was generated.
sourcestringInternal routing or originating source (e.g., partner, app system).
statusstringCurrent delivery stage (e.g., sent, delivered, read).
status_remarkstringAdditional remarks from the operator/carrier (may be empty).
x-apiheaderstringCustom header passed during API request—echoed back for correlation.

Pricing Object

Refer to the given table to know the descriptions for the pricing object fields.

FieldValuesDescription
billabletrue / falseIndicates whether the event is billable.
categorymarketing/utility/marketing_liteClassifies the message type.
pricing_modelPMP / otherPricing model applied.
typeregular / otherType of message.

Webhook Event Examples

Read Event

Triggered when the recipient reads the message.

{
  "delivery_status": [
    {
      "ncmessage_id": "3694d58b-fc29-4563-b0d4-923c2ae43555",
      "phoneNumber": "919867644673",
      "pricing": {
        "billable": true,
        "category": "marketing",
        "pricing_model": "PMP",
        "type": "regular"
      },
      "received_at": "1764693401",
      "recipient": "916361467892",
      "source": "kiran",
      "status": "read",
      "status_remark": "",
      "x-apiheader": "kiran"
    }
  ]
}

Delivered Event

Triggered when the operator/carrier confirms delivery.

{
  "delivery_status": [
    {
      "ncmessage_id": "bab1e073-51c9-4566-8008-30d33b6bedfd",
      "phoneNumber": "912249757556",
      "pricing": {
        "billable": false,
        "category": "utility",
        "pricing_model": "PMP",
        "type": "regular"
      },
      "received_at": "1764585432",
      "recipient": "918657856504",
      "source": "",
      "status": "delivered",
      "status_remark": "",
      "x-apiheader": ""
    }
  ]
}

Sent Event

Triggered when the message is accepted and sent to the carrier.

{
  "delivery_status": [
    {
      "ncmessage_id": "859c535b-8d46-46ed-9afb-9082262a8dfb",
      "phoneNumber": "912249757556",
      "pricing": {
        "billable": true,
        "category": "marketing_lite",
        "pricing_model": "PMP",
        "type": "regular"
      },
      "received_at": "1764585991",
      "recipient": "918657856504",
      "source": "",
      "status": "sent",
      "status_remark": "",
      "x-apiheader": ""
    }
  ]
}

Failed Event

Triggered when the operator fails to deliver the message. Note: The pricing object is not included because failed messages are not billable.

{
  "delivery_status": [
    {
      "ncmessage_id": "f12a9c22-8b37-4b75-bd1d-12ab45c90877",
      "phoneNumber": "912249757556",
      "received_at": "1764587102",
      "recipient": "918657856504",
      "source": "",
      "status": "failed",
      "status_remark": "Operator rejected the message",
      "x-apiheader": ""
    }
  ]
}

Note:

  • status_remark may include operator-specific error codes.
  • Messages may transition from sent → failed.

Clicked Event

Triggered when a recipient clicks a URL in the message. Note: The structure remains unchanged from Webhooks v1.

Status Lifecycle

A message may pass through the following stages:

  • sent – Submitted to the operator.
  • delivered – Operator confirms handset delivery.
  • read – Message is opened by the user.
  • failed – Operator fails to deliver the message.

Not all operators support all statuses.

Security and Verification

Recommended Practices

  • Validate request signatures (HMAC-based).
  • Verify source IPs (Netcore-provided).
  • Use HTTPS-only endpoints.
  • Implement retry logic with idempotent processing.

Recommended Response

Respond with HTTP 200 OK within 2–3 seconds. If not acknowledged, Netcore retries as per the retry policy.

Error Handling

If your system rejects a webhook:

  • Log the payload.
  • Respond with appropriate HTTP status codes (4xx/5xx).
  • Use dead-letter queues for delayed or duplicate events.