Agent skill

GREEN-API Webhooks Skill

Receive and verify GREEN-API (green-api.com WhatsApp API gateway) webhooks. Use when setting up a GREEN-API Webhook Endpoint, validating the webhookUrlToken Authorization header, or handling typeWebhook notifications like incomingMessageReceived, outgoingMessageStatus, outgoingAPIMessageReceived, and stateInstanceChanged.

Install this skill

npx skills add hookdeck/webhook-skills --skill green-api-webhooks


GREEN-API is a WhatsApp API gateway. With the Webhook Endpoint technology, the GREEN-API server POSTs a JSON notification to your webhookUrl for every incoming message, outgoing message status, instance state change, call, and so on. The notification type is in the body's typeWebhook field.

When to Use This Skill

  • How do I receive GREEN-API WhatsApp webhooks?
  • How do I verify GREEN-API webhooks / check the webhookUrlToken?
  • How do I handle incomingMessageReceived or outgoingMessageStatus notifications?
  • Why does my GREEN-API webhook get 401 when I set a Webhook URL Token?
  • Why am I receiving the same GREEN-API notification more than once?

Verification (core)

GREEN-API webhooks have no signature: there is no HMAC, no timestamp, and no Standard Webhooks headers. The only authentication is the optional webhookUrlToken instance setting.

Caveat: when webhookUrlToken is set, GREEN-API sends it as the full Authorization header value, including the scheme: Bearer <token> (default) or Basic <token>. Compare the whole header value, scheme included, with a constant-time compare. Don't strip Bearer and compare only the token.

const crypto = require('crypto');

// webhookUrlToken as entered in GREEN-API: "Bearer abc", "Basic abc", or bare "abc" (sent as "Bearer abc")
function expectedAuthorization(token) {
  return /^(Bearer|Basic) /.test(token) ? token : `Bearer ${token}`;
}

function verifyGreenApiAuthorization(header, token) {
  if (!header || !token) return false;
  const a = Buffer.from(header);
  const b = Buffer.from(expectedAuthorization(token));
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

Return 401 on a mismatch. Return 200 quickly on success: GREEN-API retries undelivered notifications every minute for up to 24 hours, so make handlers idempotent (dedupe on idMessage where present).

For complete handlers with tests, see examples/express/, examples/nextjs/, examples/fastapi/.

Common Event Types

Dispatch on the body's typeWebhook field:

typeWebhookDescription
incomingMessageReceivedIncoming message or file (messageData.typeMessage gives the kind: textMessage, imageMessage, ...)
outgoingMessageReceivedMessage sent from the phone
outgoingAPIMessageReceivedMessage sent via the API
outgoingMessageStatusStatus of a sent message (sent, delivered, read, failed, noAccount, ...)
stateInstanceChangedInstance authorization state (authorized, notAuthorized, blocked, ...)
statusInstanceChangedInstance socket state (online, offline)
incomingCallIncoming call

For the full list, see GREEN-API incoming webhook types.

Environment Variables

# Exactly what you entered as webhookUrlToken, e.g. "Bearer my-secret" or "Basic dXNlcjpwYXNz".
# A bare token without a scheme is treated as "Bearer <token>".
GREEN_API_WEBHOOK_URL_TOKEN=Bearer your-long-random-secret

Local Development

# Start tunnel (no account needed)
npx hookdeck-cli listen 3000 green-api --path /webhooks/green-api

Reference Materials


Repository

hookdeck/webhook-skills

v0.1.0 · MIT · Updated Oct 28, 2026

View on GitHub →