IllyVoIPdevelopers Back to IllyVoIP

WhatsApp

Record actual recipient consent or an opt-out

Record actual recipient consent or an opt-out

Try in API Playground ↗Sign in to prepare and run this request.
POST/api/v1/whatsapp/consent

Before you start

Connect your business and number in Portal → WhatsApp → Numbers & accounts first. Use an account-owner Production API key. Create templates in the Portal.

Result

Read current state first and send its version as expected_version. The evidence note is encrypted. Idempotency-Key identifies this immutable decision: retry with the exact body. Replaying an earlier consent grant never overrides a newer opt-out; current contains the latest state. New grants require an enabled, verified account and ready sender. Authorized opt-outs remain recordable while sending is disabled. Does not send or recall messages.

Charges and safe retries

Inspect uncertain operations before retrying. A queued message is not delivered. IllyVoIP reserves its fee at queue admission and charges only delivered outbound messages; incoming messages are free.

Authentication

Send your account API key in the X-Api-Key header. Keep it on your server; never embed it in browser code.

Request examples

Replace the example values with your own inputs. Examples do not run on this page. Production requests can change your account or incur charges.

cURL

cURL
curl -X POST "https://app.illyvoip.com/api/v1/whatsapp/consent" \
  -H "X-Api-Key: ${ILLYVOIP_API_KEY:?Set ILLYVOIP_API_KEY}" \
  -H "Idempotency-Key: YOUR_UNIQUE_IDEMPOTENCY_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "number_id": "YOUR_NUMBER_ID",
    "to": "YOUR_TO",
    "consented": false,
    "note": "YOUR_ACTUAL_CONSENT_OR_OPTOUT_EVIDENCE",
    "expected_version": 0
}'

Node.js

Node.js
const response = await fetch("https://app.illyvoip.com/api/v1/whatsapp/consent", {
  method: "POST",
  headers: {
    "X-Api-Key": process.env.ILLYVOIP_API_KEY,
    "Idempotency-Key": "YOUR_UNIQUE_IDEMPOTENCY_KEY",
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    "number_id": "YOUR_NUMBER_ID",
    "to": "YOUR_TO",
    "consented": false,
    "note": "YOUR_ACTUAL_CONSENT_OR_OPTOUT_EVIDENCE",
    "expected_version": 0
})
});

const data = await response.json();
console.log(response.status, data);

PHP

PHP
<?php
$ch = curl_init('https://app.illyvoip.com/api/v1/whatsapp/consent');
curl_setopt_array($ch, [
    CURLOPT_CUSTOMREQUEST => 'POST',
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'X-Api-Key: ' . getenv('ILLYVOIP_API_KEY'),
        'Idempotency-Key: YOUR_UNIQUE_IDEMPOTENCY_KEY',
        'Content-Type: application/json'
    ],
    CURLOPT_POSTFIELDS => '{
    "number_id": "YOUR_NUMBER_ID",
    "to": "YOUR_TO",
    "consented": false,
    "note": "YOUR_ACTUAL_CONSENT_OR_OPTOUT_EVIDENCE",
    "expected_version": 0
}',
]);

$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

echo $status . PHP_EOL;
echo $response;

Python

Python
import os
import json
import requests

response = requests.request(
    "POST",
    "https://app.illyvoip.com/api/v1/whatsapp/consent",
    headers={
        "X-Api-Key": os.environ["ILLYVOIP_API_KEY"],
        "Idempotency-Key": "YOUR_UNIQUE_IDEMPOTENCY_KEY",
        'Content-Type': 'application/json'
    },
    json=json.loads("{\n    \"number_id\": \"YOUR_NUMBER_ID\",\n    \"to\": \"YOUR_TO\",\n    \"consented\": false,\n    \"note\": \"YOUR_ACTUAL_CONSENT_OR_OPTOUT_EVIDENCE\",\n    \"expected_version\": 0\n}"),
)

print(response.status_code)
print(response.json())

Node.js examples run on the server (Node.js 22.17+). Python examples require requests; PHP examples require cURL. Set the environment variables referenced in each example.

Request parameters

Header parameters

Idempotency-Keystringrequired
pattern "^[A-Za-z0-9._:-]{8,128}$"

Request body

application/json

Body required.

number_idintegerrequired
minimum 1
tostringrequired
pattern "^\\+[1-9][0-9]{7,14}$"
consentedbooleanrequired
notestringrequired
minLength 1maxLength 2000
expected_versionintegerrequired
minimum 0

Additional properties: not allowed.

Full schema
Schema
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "number_id",
    "to",
    "consented",
    "note",
    "expected_version"
  ],
  "properties": {
    "number_id": {
      "type": "integer",
      "minimum": 1
    },
    "to": {
      "type": "string",
      "pattern": "^\\+[1-9][0-9]{7,14}$"
    },
    "consented": {
      "type": "boolean"
    },
    "note": {
      "type": "string",
      "minLength": 1,
      "maxLength": 2000
    },
    "expected_version": {
      "type": "integer",
      "minimum": 0
    }
  }
}

Request behavior

Read current state first and send its version as expected_version. The evidence note is encrypted. Idempotency-Key identifies this immutable decision: retry with the exact body. Replaying an earlier consent grant never overrides a newer opt-out; current contains the latest state. New grants require an enabled, verified account and ready sender. Authorized opt-outs remain recordable while sending is disabled. Does not send or recall messages.

Conditions and examples

Production only; no WhatsApp Sandbox is available. Replace placeholders with your own account data. Response examples are abbreviated; use the OpenAPI schemas for the full contract. Meta bills its charges separately.

Response fields

  • data: Endpoint-specific result object. Its nested fields are shown in the sample response.

HTTP responses

Expand a status to inspect its documented response format and examples. Example prices, IDs and timestamps are illustrative values, not quotes or account records.

200 Current owner-recorded permission state; not independent verification of consent.

application/json

successbooleanrequired
dataobjectrequired
Full schema
Schema
{
  "type": "object",
  "required": [
    "success",
    "data"
  ],
  "properties": {
    "success": {
      "type": "boolean"
    },
    "data": {
      "type": "object"
    }
  }
}
400 Invalid request.
401 Invalid API credential.
403 Insufficient account permissions.
409 Record changed, idempotency conflict or action unavailable. Fetch current state before starting a new decision.
503 Outcome unconfirmed. Retry the same request identity and body or inspect current state.

Production only

This operation is not available in Sandbox. Use an enabled Production account and review its effects before executing.

Search API operations, parameters, SDK and webhooks.