Wchat API

Authentication

Create a key in Settings → API keys (up to 5 keys, each one can be revoked at any time). The key is shown only once: store it safely, on your server. Never put it in a web page or a mobile app.

Send it in every request:

Authorization: Bearer wchat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Endpoints

Create a link

POST /links with these fields:

curl

curl -X POST https://wchat.info/api/v1/links \
  -H "Authorization: Bearer $WCHAT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type":"whatsapp","phone_code":"39","phone_number":"3331234567","message":"Hello, I would like some information"}'

PHP

$ch = curl_init('https://wchat.info/api/v1/links');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('WCHAT_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'type' => 'shortlink',
        'url' => 'https://example.com/offer',
    ]),
]);
$link = json_decode(curl_exec($ch), true)['data'];
echo $link['short_url'];

JavaScript (Node.js 18+)

const res = await fetch('https://wchat.info/api/v1/links', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.WCHAT_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ type: 'whatsapp', phone_code: '39', phone_number: '3331234567', message: 'Hi!' }),
});
const { data } = await res.json();
console.log(data.short_url, data.qr_code_url);

Response

{
    "data": {
        "id": 1234,
        "slug": "MYSHOP",
        "short_url": "https://wchat.info/MYSHOP",
        "type": "whatsapp",
        "phone_code": "39",
        "phone_number": "3331234567",
        "message": "Hello, I would like some information",
        "url": null,
        "destination": "https://api.whatsapp.com/send?phone=393331234567&text=Hello%2C%20I%20would%20like%20some%20information",
        "clicks": 42,
        "qr_code_url": "https://wchat.info/qrcode/MYSHOP",
        "qr_code_download_url": "https://wchat.info/qrcode/MYSHOP/save",
        "created_at": "2026-10-25T10:30:00+02:00",
        "updated_at": "2026-10-25T10:30:00+02:00"
    }
}

qr_code_url is a PNG image of the QR code, ready to print or show.

List links

GET /links?page=1&per_page=25&type=whatsapp&q=shop

All parameters are optional. per_page is at most 100, q searches in slug, phone number and URL. Newest links first.

{
    "data": [
        "…"
    ],
    "meta": {
        "page": 1,
        "per_page": 25,
        "total": 57,
        "total_pages": 3
    }
}

Change or delete a link

curl -X PATCH https://wchat.info/api/v1/links/MYSHOP \
  -H "Authorization: Bearer $WCHAT_API_KEY" -H "Content-Type: application/json" \
  -d '{"message":"New pre-filled message"}'

curl -X DELETE https://wchat.info/api/v1/links/MYSHOP -H "Authorization: Bearer $WCHAT_API_KEY"

The type of a link cannot be changed. DELETE answers 204 No Content; the link and its statistics are deleted forever, printed QR codes stop working.

Statistics

GET /links/MYSHOP/stats?days=30
GET /links/MYSHOP/stats?from=2026-01-01&to=2026-03-31
GET /stats?days=7

Default: last 30 days. History up to 3 years. Dates use the server time zone (UTC).

{
    "data": {
        "slug": "MYSHOP",
        "from": "2026-09-26",
        "to": "2026-10-25",
        "total_clicks": 128,
        "days": [
            {
                "date": "2026-09-26",
                "clicks": 3
            },
            "…"
        ],
        "countries": [
            {
                "country": "IT",
                "clicks": 97
            },
            {
                "country": "ES",
                "clicks": 21
            }
        ],
        "regions": [
            {
                "country": "IT",
                "region": "Lombardy",
                "clicks": 40
            }
        ],
        "cities": [
            {
                "country": "IT",
                "city": "Milan",
                "clicks": 31
            }
        ],
        "referrers": [
            {
                "referrer": "https://www.instagram.com/",
                "clicks": 60
            },
            {
                "referrer": null,
                "clicks": 41
            }
        ],
        "devices": [
            {
                "device": "mobile",
                "clicks": 110
            }
        ],
        "platforms": [
            {
                "platform": "AndroidOS",
                "clicks": 70
            }
        ],
        "browsers": [
            {
                "browser": "Chrome",
                "clicks": 80
            }
        ]
    }
}

null means unknown (for referrers: direct visit). Countries are ISO 3166-1 alpha-2 codes. IP geolocation by DB-IP.

Errors and limits

{
    "error": {
        "code": "validation_failed",
        "message": "The phone number field is required.",
        "fields": {
            "phone_number": "The phone number field is required."
        }
    }
}

Up to 60 requests per minute per key. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix time).

If the Pro plan ends, the keys stop working (403) but are kept: they work again when the plan is renewed. Your links keep redirecting in any case.

Terms of use

Using the API means accepting the Terms and Conditions, including the rules on acceptable use. Keys that are abused (spam, phishing, malware, attempts to get around the limits) are revoked.