Appearance
Automation tools: n8n, Zapier and Make
Connect Kiwire to n8n, Zapier, Make or any tool that can receive a webhook, so that something happening on your WiFi starts a workflow elsewhere — a new guest added to your CRM, a sales channel told about a payment, a reminder sent to an ISP subscriber whose payment is due.
It works in both directions:
| Direction | How | Use it for |
|---|---|---|
| Kiwire → your workflow | Events on a Webhook connector | Reacting to sign-ins, registrations, vouchers, payments and subscriber due dates |
| Your workflow → Kiwire | The public API | Creating vouchers or accounts, looking up a guest, changing a profile |
Sending events from Kiwire
- In your automation tool, create a step that receives a webhook and copy its URL (the tool-specific steps are below).
- In Kiwire, open Connectors, add (or open) a Webhook connector and paste the URL into Webhook URL.
- Under Events for automation tools, tick the events you want. Save.
- Open the connector again and click Send test event. Kiwire sends a
webhook.testevent straight away and tells you whether your tool accepted it.
A connector can send any number of events, and you can have several connectors — for example one per workflow. The connector's HTTP Method and Headers keep working for Portal Rules as before; event deliveries are always a POST with a JSON body, and any headers you entered (such as an Authorization header your tool asks for) are sent with them.
n8n
- Add a Webhook node. Set HTTP Method to
POSTand Respond to Immediately. - Copy the Production URL (use the Test URL only while the workflow is in "listen for test event" mode).
- Paste it into the Kiwire connector, tick your events, save, and click Send test event.
- Activate the workflow. The event's fields are under
body— for example{{ $json.body.event }}and{{ $json.body.data.username }}.
Zapier
- Create a Zap whose trigger is Webhooks by Zapier → Catch Hook. Webhooks by Zapier is available on Zapier's paid plans.
- Copy the webhook URL Zapier shows.
- Paste it into the Kiwire connector, tick your events, save, and click Send test event.
- Back in Zapier, click Test trigger. Zapier shows the test event's fields (
event,data__…) to map into the next steps. Use a Filter step oneventif one connector sends several kinds of event.
Make
Use a Webhooks → Custom webhook module, copy its address into the Kiwire connector, and click Send test event while Make is waiting for data so it learns the structure.
What Kiwire sends
Every event is one JSON POST:
json
{
"id": "evt_01k7d4p0m6x8c3q9w2e5r7t1y4",
"event": "guest.login",
"created_at": "2026-10-08T04:03:50+00:00",
"tenant": "your-tenant-id",
"data": {
"username": "jane@example.com",
"fullname": "Jane Tan",
"email": "jane@example.com",
"phone": "60123456789",
"user_type": "account",
"profile": "Standard 1 Day",
"mac": "aa:bb:cc:dd:ee:ff",
"ip": "10.10.0.25",
"zone": "Lobby",
"login_method": "email",
"nas_id": "HOTEL-AP-01"
}
}id identifies the event and stays the same if the delivery is retried or re-sent, so your workflow can ignore an id it has already handled. Times are in UTC (ISO 8601). Fields Kiwire doesn't know are null.
| Event | When | data fields |
|---|---|---|
guest.login | A guest or user signs in to the WiFi — through the portal or directly (802.1X, PAP) | username, fullname, email, phone, user_type, profile, mac, ip, zone, login_method, nas_id |
guest.registered | A new account is created from the portal's sign-up | username, fullname, email, profile_id, valid_days, mac, ip, zone, login_method |
voucher.redeemed | A voucher code is used for the first time | code, batch, profile_id, price, expires_at, remark, redeemed_at |
payment.paid | An online payment completes — buy panel, captive portal or a subscriber's renewal | reference, provider, gateway_ref, amount, tax_amount, currency, plan, username, mac, paid_at |
subscriber.due | An ISP subscriber's paid-until date is 3 days away (sent once per due date) | username, account_no, fullname, email, phone, plan, status, paid_until |
subscriber.expired | An ISP subscriber's paid-until date has passed (sent once per due date) | same as subscriber.due |
webhook.test | You click Send test event | message, webhook, sent_by |
The subscriber events need the ISP module switched on. They are checked every hour, so they arrive within the hour of the subscriber reaching the date.
Checking that an event came from Kiwire
Each connector that sends events has a signing secret (whsec_…), created when you first save it with an event ticked. On the connector, Show reveals it and New replaces it — the old secret stops working at once, so update your tool straight after.
Every delivery carries these headers:
| Header | Value |
|---|---|
X-Kiwire-Event | The event name, e.g. payment.paid |
X-Kiwire-Delivery | The event id |
X-Kiwire-Signature | t=<unix time>,v1=<signature> |
The signature is the HMAC-SHA256, in hex, of the time, a full stop and the exact request body, keyed with the signing secret. To check it, compute the same value and compare; reject the request if it differs or if the time is more than a few minutes old.
In an n8n Code node (set the Webhook node's Raw Body option so the original body is available):
js
const crypto = require('crypto');
const secret = 'whsec_…'; // the connector's signing secret
const [t, v1] = $json.headers['x-kiwire-signature'].split(',').map(p => p.split('=')[1]);
const body = Buffer.from($binary.data.data, 'base64').toString('utf8');
const expected = crypto.createHmac('sha256', secret).update(`${t}.${body}`).digest('hex');
if (expected !== v1 || Date.now() / 1000 - Number(t) > 300) throw new Error('Not from Kiwire');
return [{ json: JSON.parse(body) }];In Python:
python
import hmac, hashlib, time
def from_kiwire(raw_body: bytes, header: str, secret: str) -> bool:
parts = dict(p.split("=", 1) for p in header.split(","))
expected = hmac.new(secret.encode(), f"{parts['t']}.".encode() + raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, parts["v1"]) and time.time() - int(parts["t"]) < 300Zapier's Catch Hook does not expose the raw body, so on Zapier rely on the secrecy of the webhook URL, or put a token in the connector's Headers and check it in a Filter step.
Deliveries, retries and the log
- Kiwire waits up to 10 seconds for your tool to answer. Any
2xxanswer counts as delivered. - Anything else — an error status, a timeout, the tool being offline — is retried after 1, 5 and 30 minutes. After the fourth try the delivery is marked Failed.
- The connector shows its 20 most recent deliveries with the result, the HTTP status and the number of tries. Resend sends a delivered or failed event again, with the same
id. - The log keeps 30 days.
- Switching the connector off stops new events at once; deliveries already waiting are dropped.
- URLs on private or internal addresses are refused, as for every Kiwire connector.
Acting on Kiwire from a workflow
Workflows call the public API with two headers, X-Tenant-ID and X-Api-Key (create a key under My Profile › API Keys):
- n8n: an HTTP Request node with the two headers, for example
POST https://<your Kiwire address>/api/v1/voucherto create a voucher after a payment in another system. - Zapier: Webhooks by Zapier → Custom Request with the same headers and a JSON body.
- Make: the HTTP → Make a request module.
API keys are limited to 25 requests a minute by default, which suits event-driven workflows; for bulk jobs, ask Synchroweb about a higher limit for your licence. The full list of endpoints is in the Swagger reference.