IllyVoIPdevelopers Back to IllyVoIP

WhatsApp

Upload a WhatsApp attachment

Upload a WhatsApp attachment

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

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

Upload one multipart file with number_id and Idempotency-Key. IllyVoIP validates and scans the file, stores it privately and uploads it to Meta internally. Use the returned data.id as media_id only when status is ready. If failed or unknown, inspect the saved media status and resolve it in the Portal; do not blindly reupload an uncertain operation. Retry the same file, filename, number and idempotency key to recover its original identity. No message is sent and no messaging fee is charged by uploading.

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/media" \
  -H "X-Api-Key: ${ILLYVOIP_API_KEY:?Set ILLYVOIP_API_KEY}" \
  -H "Idempotency-Key: YOUR_UNIQUE_IDEMPOTENCY_KEY" \
  -F "file=@sample.wav" \
  -F "number_id=YOUR_NUMBER_ID"

Node.js

Node.js
import { openAsBlob } from 'node:fs';
const response = await fetch("https://app.illyvoip.com/api/v1/whatsapp/media", {
  method: "POST",
  headers: {
    "X-Api-Key": process.env.ILLYVOIP_API_KEY,
    "Idempotency-Key": "YOUR_UNIQUE_IDEMPOTENCY_KEY"
  },
  body: await (async () => {
    const form = new FormData();
    form.append("file", await openAsBlob("sample.wav"));
    form.append("number_id", "YOUR_NUMBER_ID");
    return form;
  })()
});

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

PHP

PHP
<?php
$ch = curl_init('https://app.illyvoip.com/api/v1/whatsapp/media');
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'
    ],
    CURLOPT_POSTFIELDS => [
        'file' => new CURLFile('sample.wav'),
        'number_id' => 'YOUR_NUMBER_ID'
    ],
]);

$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/media",
    headers={
        "X-Api-Key": os.environ["ILLYVOIP_API_KEY"],
        "Idempotency-Key": "YOUR_UNIQUE_IDEMPOTENCY_KEY"
    },
    files={
        "file": open("sample.wav", 'rb')
    },
    data={"number_id": "YOUR_NUMBER_ID"},
)

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
minLength 8maxLength 128

Request body

multipart/form-data

Body required.

number_idintegerrequired
minimum 1
filestringrequired
format "binary"

Additional properties: not allowed.

Full schema
Schema
{
  "type": "object",
  "additionalProperties": false,
  "required": [
    "number_id",
    "file"
  ],
  "properties": {
    "number_id": {
      "type": "integer",
      "minimum": 1
    },
    "file": {
      "type": "string",
      "format": "binary"
    }
  }
}

Request behavior

Upload one multipart file with number_id and Idempotency-Key. IllyVoIP validates and scans the file, stores it privately and uploads it to Meta internally. Use the returned data.id as media_id only when status is ready. If failed or unknown, inspect the saved media status and resolve it in the Portal; do not blindly reupload an uncertain operation. Retry the same file, filename, number and idempotency key to recover its original identity. No message is sent and no messaging fee is charged by uploading.

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 Owner-scoped result. Uploading a file does not send a message or confirm delivery.

application/json

successbooleanrequired
dataobjectrequired
View nested fields
statusstringrequired

ready, failed, unknown or another current media state; only ready may be sent.

idstringrequired
pattern "^[a-f0-9]{48}$"
number_idintegeroptional
typestringoptional
mime_typestringoptional
filenamestringoptional
byte_sizeintegeroptional
Full schema
Schema
{
  "type": "object",
  "required": [
    "success",
    "data"
  ],
  "properties": {
    "success": {
      "type": "boolean"
    },
    "data": {
      "type": "object",
      "properties": {
        "status": {
          "type": "string",
          "description": "ready, failed, unknown or another current media state; only ready may be sent."
        },
        "id": {
          "type": "string",
          "pattern": "^[a-f0-9]{48}$"
        },
        "number_id": {
          "type": "integer"
        },
        "type": {
          "type": "string"
        },
        "mime_type": {
          "type": "string"
        },
        "filename": {
          "type": "string"
        },
        "byte_size": {
          "type": "integer"
        }
      },
      "required": [
        "id",
        "status"
      ]
    }
  }
}
400 Invalid request.
401 Invalid API credential.
403 Account or action not authorized.
409 Unavailable operation, idempotency conflict, in-progress operation or recovery required.
503 Temporarily unavailable; do not repeat with a new identity when the previous outcome is unknown.

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.