Every dashboard feature, explained in full.
Not a FAQ — a full reference. Every group in your dashboard sidebar, the ISN website itself, and the guest captive portal your visitors actually see, each explained field by field, screen by screen. If you want the short version of common questions instead, see our Help Center.
Jump to a section
Documentation covers three layers: your dashboard, organized exactly like its sidebar — Overview, Clients, Branding, Messaging, Billing & plan, Vouchers, Free access, Network, Insights, Team & access, and Account — plus the ISN website itself and the guest captive portal your visitors actually see. On a wider screen, use the sidebar on the left to jump straight to any single item without scrolling.
Overview
The landing view every dashboard session opens on — a live rollup of the same numbers that drive your bill and your capacity limit, so you never have to dig for them.
Dashboard home
Your "at a glance" screen. Portal state reads "Portal live" once you've clicked Publish, or "Setup in progress" before then — this is a confirmation flag you control, not an access gate: your captive is reachable to real guests the moment a router points at it, published or not. Domain shows your active address (free subdomain or verified custom domain). Active now (this month's peak) / limit and Estimated monthly cost are pulled live from the same numbers detailed under Plan & pricing below. SMS credits, Routers online, Vouchers redeemed (7d), and Ad views (7d) round out the top row, followed by a 7-day guest-traffic chart, a 7-day peak-concurrent-devices chart, and a router fleet table (name, location, online status, device count, last seen) — empty until you add your first router under Network → Routers.
Portal preview
The real thing, not a mockup — this loads your actual live captive portal, with your real logo, colors, and brand name, inside the dashboard so you can check it without leaving. Save a change under Branding & colors and this refreshes automatically. An "Open in new tab" link sits next to it for when you'd rather test on a full screen or a phone.
Post ads & more ↗
This ISN Portal — everything documented on this page: your account, branding, billing, vouchers, network, and team — lives at https://isnfreewifi.co.za/dashboard, reached by logging in at https://isnfreewifi.co.za/login with your ISN Free WiFi email and password. That is a completely different address and a completely different dashboard from your own captive's own domain — a second, separate dashboard lives THERE instead, reachable at your live captive address with /dashboard on the end (e.g. https://yourbrand.isnfreewifi.co.za/dashboard, note it's on YOUR domain, not isnfreewifi.co.za) — that one is only for ad campaigns, ad-performance tracking, and a few captive-specific tools (see Captive Dashboard below); it does not have vouchers, billing, branding, or any of the settings documented on this page. "Post ads & more" opens that second one for you in a new tab, already pointed at your own captive, using the exact same email and password you use here — no separate login to remember. It stays visible the moment your account exists, whether or not you've published yet.
Clients
Built for agencies, resellers, and ISPs running WiFi for more than one site under one login.
My clients
Every branded location tied to your account — name, domain, publish status, and router count — all reachable without a second login. Each client is a fully separate, isolated captive: its own branding, its own routers, its own vouchers, its own guest data. Nothing about one client's setup or guest list is visible from another. Add a new one with just a business name (no separate email/password — you're already verified); one click on any row in the table switches your whole dashboard session into that client, the same mechanism as Switch captive. One limit worth knowing: an account that has never made a real subscription payment is capped at 2 captives total, so a free/trial account can't be used to spin up unlimited draft portals — the cap lifts permanently the moment any one of your captives completes its first real payment.
Branding
What your guests see, and the address they see it at.
Branding & colors
Everything that makes your captive portal look like your business instead of a generic template: brand name, short name, logo upload, four colors (primary, accent, background, text), tagline and summary copy, your login page's own description and "how it works" steps, support email and WhatsApp number, Facebook/Instagram/TikTok links (any left blank simply don't show — nothing appears by default), and your own terms-of-service text (falls back to ISN's default if you leave it blank). A live phone-mockup preview sits alongside the form on tablet and desktop, with Login/Home/Business tabs, updating as you type — on phones this becomes a "Preview" button that opens the real portal in a new tab instead, since a side-by-side mockup doesn't fit usefully on a small screen. Changes apply immediately on save; there's no separate publish step for branding itself. Everything you set here is exactly what loads on the real guest screens documented under The captive portal further down this page — Captive Login, Home, and Marketing Page all pull their logo, colors, and copy from this one place.
Custom domain
Every account starts with a free working address the moment you sign up — you can be live before you ever touch this section. Add your own domain when you're ready and guests never see ours again. Type the domain you own (e.g. yourbusiness.com, no "www." or "captive." needed) and ISN sets up captive.yourbusiness.com as your guests' WiFi login page — the rest of your domain, your website, your email, is completely untouched. You'll then get one DNS record to add at your domain provider: a CNAME (or, if your provider can't do CNAME on a subdomain, a fallback A record). Verification is a real, live DNS lookup against exactly that captive. subdomain — never your bare root domain, never "www" — so it only goes active once it's genuinely resolving correctly, not a box you get to tick yourself. Your router's own External Login URL updates automatically to your new domain once verified, though you'll still need to update that setting on each physical router (or use Remote CLI) to actually switch it over. Keep your free subdomain active until your custom domain is verified — turning it off any earlier takes your portal offline for anyone still using the old address.
Messaging
SMS is built into the platform itself for guest and account verification codes and account notifications — there's no separate provider or API key for you to configure. Every one-time code sent, to a guest or to your own team, uses one credit from your balance.
SMS balance
Your current credit balance, front and center. A banner appears once you hit zero credits, since that's the point OTP codes stop sending to guests trying to sign up or verify a new device — the exact verification step described under Captive Login below.
Buy credits
Type either a Rand amount or a number of credits — the other side calculates itself automatically, so you never have to do the conversion by hand. Pay by card (instant) or by EFT (you'll get banking details; credits land once payment is confirmed). Minimum purchase is 200 credits.
Two settings live alongside this, under Notifications: "Alert me at (credits)" sends you a low-balance email once your balance drops to a threshold you set. Auto top-up optionally buys more automatically the moment that threshold is hit — instantly on a saved card if you have one on file (from a trial or subscription payment), or as a pending EFT request if you don't. "Do not exceed this spend per month (R)" is the safety net on auto top-up specifically: once your automatic top-ups for the calendar month reach that Rand figure, auto top-up pauses itself (you still get the low-balance email, and can always top up manually) rather than continuing to spend without limit. That cap resets at midnight South African time on the 1st of every month.
Credit history
Every credit purchase you've made — manual card, manual EFT, or auto top-up — with date, amount, credits, and status. Each settled purchase generates a proper invoice with a PDF receipt emailed to you automatically, the same invoicing your subscription billing uses, so SMS spend is tracked exactly as accountably as everything else you're billed for.
Sent messages
The full send log — every OTP and notification actually sent, filterable by status (delivered, failed, and so on), so you can see exactly where your credits are going and confirm a specific guest's code really did go out.
Email settings
Connect your own email address so invites, password resets, and ad-campaign notifications sent to the businesses/advertisers on your platform come from you, not a shared ISN address. Enter your email and password (Gmail/Google Workspace app-password by default; open "Advanced" to point at a different provider's mail server, host/port/SSL) plus an optional display name, then Save & verify. For your own security, once saved the password can never be viewed again in the dashboard — only replaced with a new one or removed entirely. Only the account owner or an "IT" team role can configure this. This is also the address your Marketing Page advertiser-inquiry form emails to, once set.
Billing & plan
Your own subscription for running this captive on ISN Free WiFi — a 14-day free trial (one per account, card-verified up front), then billed monthly.
Subscription
Status, your next trial/billing date, and the card on file, plus controls to update your payment method, suspend your captive (unpublish — takes your guest-facing URL offline immediately without cancelling the subscription itself; republish any time before your next billing date at no extra cost), or cancel outright. Miss a payment and you get a 5-day grace period: your dashboard flags the account as past due, but your captive keeps serving guests normally throughout. Only if the balance stays unsettled past those 5 days do portal-facing features get suspended — nothing is ever deleted, your configuration and history stay exactly as they were.
Plan & pricing
R1,500/month includes 300 concurrent users, with unlimited routers and locations at no extra cost — extra concurrent users beyond 300 bill at R5/user. This is the same plan described on the public Pricing page; nothing changes between what's quoted there and what you're billed here. "Concurrent user limit" is the ceiling you set (or that auto-scale raised for you); "Peak concurrent users this month" is your real high-water mark for the current calendar month, tracked continuously as guests actually connect. Your estimated monthly cost is based on whichever of those two numbers is higher — so lowering your limit after a busy period doesn't retroactively lower what you're billed for the users you genuinely had; it only affects what happens going forward. Auto-scale when at capacity, if switched on, raises your limit automatically by a fixed increment every time it's reached, instead of turning new guests away — configure the increment and an optional ceiling ("never auto-scale above") separately. A limit auto-scale raised can't be lowered below that point until the next billing month, but a limit you set yourself here stays exactly as you left it. Capacity monitoring is a separate early-warning email, sent once usage crosses a percentage you choose — before anyone is actually turned away, distinct from the "at capacity" notification that fires once the real limit is hit.
Invoices
Every charge against your own subscription — invoice number, date, amount, status. Only ever your own; never visible across tenants.
Vouchers
Codes and plans your guests redeem or buy directly on the captive portal — you decide how they're sold (cash, front desk, your own booking system), the platform just tracks issuance and redemption. You create and manage every voucher right here, in this ISN Portal at https://isnfreewifi.co.za/dashboard (log in at https://isnfreewifi.co.za/login) — not on your captive's own subdomain (yourbrand.isnfreewifi.co.za/dashboard), which is a separate, ads-only dashboard with no voucher tools of its own (see Post ads & more).
Generate vouchers
Print or hand out a batch of one-off codes. Set how many to generate, the data bundle (MB), duration (in hours, or in days if that's easier — the days field just converts for you), a price for your own records, a batch label, an optional expiry, and max redemptions per code (1 by default for single-use; set higher for a shared code, like a 10-use event code). "Allow adding extra devices" makes a multi-redemption code share one data pool across devices instead of granting a separate bundle each time. Newly generated codes are shown once, with a CSV download — copy them down immediately, since every code's live status stays visible afterward under All vouchers regardless. Three toggles above this section control what end users actually see on the connect screen (Captive Login): ad-supported bundles, voucher redemption, and (once ads and vouchers are both off) direct card-paid data plans — turn on any combination, at least one must stay on.
Voucher presets
Your own reusable pricing menu — e.g. "500MB – R1", "1GB – R1.50" — each with a label, bundle, duration, price, a validity rule (expires N days after issuing, pinned to an exact date set per-voucher, or never expires), max redemptions, and the same "allow extra devices" option as a one-off voucher. This is what makes the API safe to expose to your own systems: a booking or point-of-sale integration references a preset by its ID, and the bundle/price/duration always come from the preset you defined here — never from whatever the calling system happens to send.
All vouchers
Every voucher you've ever generated or issued via the API, filterable by status (unused, redeemed, void), with code, bundle, duration, price, redemption count, and who redeemed it and when. Downloadable as CSV for your own records.
Data plans
Sell internet access directly by card, no voucher code needed — a guest picks a plan on the connect screen and pays with their own card through your connected payment gateway (see Billing & plan). Set a name, price, duration, and data bundle per plan; default is one device per purchase, treated as a standalone guest account, raised per-plan if you want to allow more sharing one purchase. An optional per-plan download/upload speed cap (Mbps) lets a cheaper plan come with a lower speed than a pricier one — see Bandwidth & speed caps for how this sits alongside the platform's other speed limits.
Free access
Everything about letting specific people online without ads, a voucher, or a card — from your own instant login, to blanket free access for every guest, to named accounts you provision yourself.
Your own bypass (owner login)
The instant, no-voucher-no-ads access you get the moment you log in with your own dashboard credentials on your own captive portal. Choose unlimited data or a set MB cap, and a duration (2 hours, 24 hours, 2 months, 1 year, or never expires).
Open access for all guests
Extends that same instant access to every guest who logs in or registers — no voucher, no ad-watch, full internet the moment they arrive. A good fit for venues like student accommodations where you'd rather bill a flat rate than gate individual guests one at a time. Configure unlimited data or a cap, a duration, and how often the same physical device can claim a fresh free grant: once ever, daily, weekly, or monthly. "Once ever" is enforced by device fingerprint, not just the email or phone number someone signs up with — registering again on the same phone under a new identity doesn't get around it.
Internal accounts (named users)
Accounts you provision yourself for students, staff, or residents — a real, permanent alternative to a shared network password that inevitably leaks to outsiders. Each one bypasses ads and vouchers entirely, with its own data cap (or unlimited), its own duration (a rolling preset, or an exact custom expiry date), and its own device limit so one login can't quietly become the whole building's free WiFi. Duration presets match the owner bypass above: 2 hours, 24 hours, 2 months, 1 year, or never expires; "exact date & time" pins it to a real calendar deadline instead (e.g. a lease end date) — once that date passes, the account is permanently and automatically shut out, no manual cleanup needed. Its own download/upload speed cap (Mbps) is optional too — leave at 0 to just inherit the tenant-wide default described under Bandwidth & speed caps.
Guest vouchers from residents
The answer to "my tenant's friend needs internet for the afternoon" without reopening the whole network to strangers. When switched on, any internal account can generate a voucher from their own My Usage panel and hand it to a real visitor — a random signup with no connection to a resident gets nothing at all. Configure the data cap per voucher (or unlimited), how many of the visitor's own devices can share one voucher (their phone and laptop, not a stack of unrelated guests), how many vouchers one resident can create per day, a download/upload speed cap for visitors specifically (separate from the general guest default), and curfew hours. Set both a start and end time and the voucher only works inside that window — outside it, residents can't create new ones, visitors can't redeem existing ones, and anyone already connected through one is disconnected the instant curfew starts. The same code can't be reused once curfew reopens the next day; a fresh one has to be issued.
Fair usage policy
Stops resident-issued guest vouchers from quietly turning into unlimited free WiFi for a rotating cast of visitors — on by default. Once a resident's guest vouchers move more than your monthly limit (in GB) of data combined, or one visiting device moves that much data across any resident's vouchers, your chosen policy kicks in. Soft mode throttles the resident's vouchers, and any visitor already connected through one, down to a speed you set — live, immediately, without waiting for anyone to reconnect. Hard mode stops that resident issuing any new vouchers, and blocks that specific visiting device from redeeming any resident's voucher at all, until the policy resets on the 1st of the next calendar month. The device-level check exists specifically because the account-level one alone would be trivial to dodge: FUP is tied to the visitor's physical device, not the identity they signed up with, so logging out and registering again doesn't reset anything, and trying a different, not-yet-limited resident's voucher just gets caught by the same device check on that voucher too. Every guest visiting an already-limited resident is affected the same way, not just the one who tripped the limit, until the next month begins.
Network
Your actual hardware — adding it, controlling it remotely, and filtering what it can reach — all from the dashboard, with no vendor RMS portal or SSH session required for everyday changes.
Routers
Add a router with a name, a location, and an optional router ID (auto-generated if you leave it blank). You'll get a one-time SSH command to run on the physical device — it needs to be OpenWRT-based (Teltonika RutOS, GL.iNet, or similar) — plus the External Login URL to set in that router's own Hotspot settings so it knows where to send guests, pointed straight at your Captive Login. From there, every router in your fleet shows online/offline status, connected device count, and last-seen time, and an "Auto-config" wizard walks through vendor-specific setup for Teltonika, GL.iNet, generic OpenWRT, MikroTik (fully supported for access control and content filtering; still marked beta since it's newer and WiFi/bandwidth settings on MikroTik still need configuring on the router itself), Cisco, or "Other" (guided manual instructions, no automation). Click into any router to set its WiFi name/password (or run it as an open network), speed caps (see Bandwidth & speed caps next), restart it remotely, or deactivate it without losing its history.
Bandwidth & speed caps
Several separate speed caps exist across the dashboard, each governing a different scope — worth having in one place, since it's easy to set one expecting it to cover a case a different one actually governs. Default guest speed cap (Free access → Owner & guest access, Mbps down/up) applies to every regular guest at this location unless something more specific below overrides it — 0 means uncapped, no hidden platform ceiling underneath. Speed limit for each guest device, set from any router's own management page but — despite living there — applied account-wide across every router you run, not just that one, is the everyday version of the same idea: you pay your ISP for 150 Mbps but only want to hand each individual guest device 10 Mbps of it. Guests always get full speed while watching an ad to unlock access, and again automatically the moment they're earning more data — the cap only bites during actual unlocked browsing time, and your own owner-login session is never capped by it. This router's total line speed, on that same router page, is a different and rarely-needed thing: a cap on that one specific router's own total incoming connection, for reserving bandwidth on a particular line rather than limiting individual guests.
Four more caps override the defaults above for a specific case: a data plan's own speed (sold at a certain price point, capped to match it), an internal account's own cap (0 falls back to the tenant default), a resident-issued guest voucher's visitor speed cap, and the fair usage policy's throttle speed once a resident's vouchers cross their monthly threshold. In every case, 0 (or an empty field) means uncapped at that level, falling through to whichever broader default applies above it.
Remote CLI & restart
Direct command access to a paired router for diagnostics and one-off fixes, without needing physical or SSH access to the hardware yourself. Re-enter your dashboard password to unlock it, choosing how long the unlock should last (2, 5, 15, or 30 minutes) — after that it locks again automatically. Every command you run is logged with a timestamp, the router, the command itself, its status, and its output, kept as a permanent audit trail against your account, since this is the kind of tool that can take a whole site's WiFi offline if used carelessly. Restarting a router is a separate one-click action elsewhere (no CLI unlock needed) — expect it to be briefly unreachable, about a minute, while it comes back up.
Content filtering
Block specific websites on your WiFi. Nothing is blocked until you add something yourself — there's no preset list to opt out of. Type the domains you want blocked, one per line, re-enter your password the same way as Remote CLI, and save; the rule pushes automatically to every router in your fleet that supports it, applying as soon as each one next checks in. Routers that aren't yet automated for filtering get a manual instruction instead: add a DNS blackhole entry for each domain, and drop the relevant ports at the firewall if you also want VPN mitigation. Speaking of which, an optional "VPN mitigation" toggle blocks common VPN ports and known public DNS-over-HTTPS providers — a genuine deterrent against casual VPN use, not an absolute guarantee; a sufficiently determined, technical user can still find a way around any network-level filter, true of every vendor's product, not just this one.
Insights
Everything you need to understand who's using your WiFi and how — from the big-picture trend line down to a single guest's history.
Analytics & reports
The aggregate picture over a range you choose (7/30/90 days): guest connections, peak concurrent devices, ad views and clicks by campaign, vouchers redeemed, and SMS sent — with a downloadable CSV report. Guest connections count real portal activity (every ad-unlock, voucher redemption, data-plan purchase, or free-access grant), so it stays accurate even for a location whose router isn't yet reporting live telemetry. Peak concurrent devices prefers real router-reported device counts for its daily trend; if a router hasn't reported any data for the period, the summary figure falls back to your accurate monthly peak (the same number shown in Plan & pricing) rather than showing a misleading zero next to genuinely non-zero activity elsewhere on the page.
Guest activity
The individual event log, for when you need to trace one specific guest or incident rather than the aggregate trend: registered users (name, email/phone, bundle and remaining data, status, when they registered), recent bundle-grant transactions (identifier, bundle size, router, when granted), and domain visits — POPIA-compliant, daily anonymised snapshots aggregated by domain only, never a per-guest browsing history.
Notifications
Everything that needs your attention, surfaced by email in one place instead of you having to notice it yourself in the dashboard: low SMS credits (and, if you've set one, your monthly auto-topup spend cap being reached), capacity approaching and capacity-reached warnings, and billing reminders sent a few days ahead of a trial converting to paid or a subscription renewing, so a charge is never a surprise. Each type can be switched off individually if you'd rather not receive it. Every one of these is sent to your own account's registered email — never anyone else's, and never shared across tenants.
Team & access
Invite staff with exactly the access they need instead of sharing one login, and let your own systems talk to ISN Free WiFi directly.
Team members
Invite someone by name, email, and role — they get an email with an activation link to set their own password, never yours. Five roles are available: IT Department (full access, both this dashboard and your captive's own dashboard), Full Admin (full access, captive dashboard only), Ads/Marketing Manager (ads, vouchers, branding, and routers, on the captive dashboard), Financial (billing and invoices only), and View Only (read-only everywhere it can see; any attempted change is blocked). Every role is enforced on the server, not just hidden in the menu — a Financial-role login genuinely cannot reach voucher generation even by guessing a URL, and a View Only login genuinely cannot save anything. By default an invite only covers this one captive; check "Give access to every captive I own" (owner-only) to extend it across every client you run. Only the account owner and IT-role members can manage the team roster itself — the owner's own role can never be changed or removed by anyone.
API & integrations
Generate an API key here to issue and reschedule vouchers programmatically from your own booking system or point-of-sale — always against a voucher preset you've already defined, so bundle, price, and duration stay under your control no matter what the calling system sends. Every key is shown to you once at creation; only a hash is stored afterward, so losing it means generating a new one, not recovering the old. Never call this API from browser or front-end code — a page's JavaScript, a Wix page, or a WordPress theme's front-end script is visible to every visitor, and a key is a live credential worth money, not "sort of secret" like a session ID. Always call it from a server you control.
Base URL & authentication — send your key on every request as the x-api-key header (it starts with isn_live_). The key alone determines which of your captives a request belongs to; the hostname you call doesn't need to match that captive's own domain.
POST /api/partner/vouchers/issue | Issues one new voucher against a preset. Safe to retry: calling it twice with the same externalReference never issues a second voucher — it returns the same one again. |
|---|---|
POST /api/partner/vouchers/reschedule | Changes the expiry date of a voucher you've already issued that hasn't been redeemed yet, identified by that same externalReference. |
externalReference is the idempotency key for issuing — derive it from something already unique in your own system (an order or booking ID), never a random value per attempt, so a retry after a network timeout safely returns the original voucher (HTTP 200) instead of risking a duplicate (HTTP 201, which only fires the first time).
Node.js 18+ (built-in fetch, no extra dependency). Keep ISN_API_KEY in an environment variable, never hard-coded.
const ISN_API_KEY = process.env.ISN_API_KEY; // isn_live_...
const ISN_BASE_URL = 'https://yourbrand.isnfreewifi.co.za';
async function issueVoucher(presetId, externalReference, ticketDate) {
const res = await fetch(`${ISN_BASE_URL}/api/partner/vouchers/issue`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-api-key': ISN_API_KEY },
body: JSON.stringify({ presetId, externalReference, ticketDate })
});
const data = await res.json();
if (!data.ok) throw new Error(data.message);
return data; // { code, bundleMB, durationHours, price, expiresAt, ... }
}
// Example: issue a voucher right after a booking is confirmed
issueVoucher(12, 'BOOKING-90142', '2026-08-10')
.then(v => console.log('Voucher code:', v.code))
.catch(err => console.error('Issue failed:', err.message));
Python 3 with requests (pip install requests). Keep ISN_API_KEY in an environment variable, never hard-coded.
import os
import requests
ISN_API_KEY = os.environ["ISN_API_KEY"] # isn_live_...
ISN_BASE_URL = "https://yourbrand.isnfreewifi.co.za"
def issue_voucher(preset_id, external_reference, ticket_date=None):
response = requests.post(
f"{ISN_BASE_URL}/api/partner/vouchers/issue",
headers={"Content-Type": "application/json", "x-api-key": ISN_API_KEY},
json={"presetId": preset_id, "externalReference": external_reference, "ticketDate": ticket_date},
timeout=15,
)
data = response.json()
if not data.get("ok"):
raise RuntimeError(data.get("message", "Unable to issue voucher"))
return data # {"code": "AB12-CD34", "bundleMB": 1000, ...}
# Example: issue a voucher right after a booking is confirmed
voucher = issue_voucher(12, "BOOKING-90142", "2026-08-10")
print("Voucher code:", voucher["code"])
Plain PHP with the built-in curl extension — for a non-WordPress backend. Running WordPress instead? Use the WordPress tab, which uses wp_remote_post and hooks into your site the WordPress way.
<?php
$ISN_API_KEY = getenv('ISN_API_KEY'); // isn_live_...
$ISN_BASE_URL = 'https://yourbrand.isnfreewifi.co.za';
function isn_partner_api_call($url, $apiKey, $body) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => ['Content-Type: application/json', 'x-api-key: ' . $apiKey],
CURLOPT_POSTFIELDS => json_encode($body),
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
$voucher = isn_partner_api_call($ISN_BASE_URL . '/api/partner/vouchers/issue', $ISN_API_KEY, [
'presetId' => 12,
'externalReference' => 'BOOKING-90142',
'ticketDate' => '2026-08-10',
]);
if (empty($voucher['ok'])) {
throw new Exception($voucher['message'] ?? 'Unable to issue voucher');
}
echo 'Voucher code: ' . $voucher['code'];
Handy for a quick manual test from a terminal before wiring up real code.
curl -X POST https://yourbrand.isnfreewifi.co.za/api/partner/vouchers/issue \
-H "Content-Type: application/json" \
-H "x-api-key: isn_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{
"presetId": 12,
"externalReference": "BOOKING-90142",
"ticketDate": "2026-08-10"
}'
curl -X POST https://yourbrand.isnfreewifi.co.za/api/partner/vouchers/reschedule \
-H "Content-Type: application/json" \
-H "x-api-key: isn_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{
"externalReference": "BOOKING-90142",
"ticketDate": "2026-08-14"
}'
Add to your theme's functions.php (or a small custom plugin — safer, survives theme updates). Define the key once in wp-config.php, outside the web root's publicly-served files.
// wp-config.php
define( 'ISN_API_KEY', 'isn_live_xxxxxxxxxxxxxxxxxxxxxxxx' );
// functions.php
function isn_issue_wifi_voucher( $preset_id, $external_reference, $ticket_date = null ) {
$response = wp_remote_post( 'https://yourbrand.isnfreewifi.co.za/api/partner/vouchers/issue', array(
'headers' => array(
'Content-Type' => 'application/json',
'x-api-key' => ISN_API_KEY,
),
'body' => wp_json_encode( array(
'presetId' => $preset_id,
'externalReference' => $external_reference,
'ticketDate' => $ticket_date,
) ),
'timeout' => 15,
) );
if ( is_wp_error( $response ) ) {
error_log( 'ISN voucher issue failed: ' . $response->get_error_message() );
return null;
}
$body = json_decode( wp_remote_retrieve_body( $response ), true );
if ( empty( $body['ok'] ) ) {
error_log( 'ISN voucher issue rejected: ' . ( $body['message'] ?? 'unknown error' ) );
return null;
}
return $body; // ['code' => 'AB12-CD34', 'bundleMB' => 1000, ...]
}
// Example: issue a voucher when a WooCommerce order is marked completed
add_action( 'woocommerce_order_status_completed', function ( $order_id ) {
$order = wc_get_order( $order_id );
$voucher = isn_issue_wifi_voucher( 12, 'ORDER-' . $order_id );
if ( $voucher ) {
$order->add_order_note( 'Wi-Fi voucher issued: ' . $voucher['code'] );
}
} );
No WooCommerce? Hook isn_issue_wifi_voucher() into whatever action your booking plugin fires on confirmation (Bookly, Amelia, Gravity Forms' gform_after_submission, etc.) the same way.
Wix page code runs in the visitor's browser, so the key must live in a Velo backend file (backend/isnWifi.jsw) instead, ideally pulled from the Wix Secrets Manager rather than hard-coded even there.
// backend/isnWifi.jsw
import { fetch } from 'wix-fetch';
import { getSecret } from 'wix-secrets-backend';
export async function issueWifiVoucher(presetId, externalReference, ticketDate) {
const apiKey = await getSecret('ISN_API_KEY'); // stored in Secrets Manager
const response = await fetch('https://yourbrand.isnfreewifi.co.za/api/partner/vouchers/issue', {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey },
body: JSON.stringify({ presetId, externalReference, ticketDate })
});
const data = await response.json();
if (!data.ok) throw new Error(data.message);
return data;
}
// e.g. Bookings page code, on a "booking confirmed" event — never call the
// API straight from page code with the key inline, always via this backend file.
// import { issueWifiVoucher } from 'backend/isnWifi.jsw';
// issueWifiVoucher(12, 'BOOKING-' + booking._id)
// .then((voucher) => console.log('Voucher issued:', voucher.code))
// .catch((err) => console.error('Voucher issue failed:', err.message));
| 400 | Missing/invalid presetId, externalReference, or ticketDate. |
|---|---|
| 401 | Missing, malformed, or unknown API key. |
| 403 | Key revoked, or the account is suspended for billing. |
| 404 | Preset not found/inactive, or (reschedule) no matching unused voucher for that reference. |
| 409 | That reference was already issued against a different preset. |
| 429 | Rate limit or daily issuance cap reached — back off and retry later. |
Every response includes {"ok": false, "message": "..."} on failure — always check ok rather than assuming a 200-range status means success. The Integration guide button inside the dashboard opens this same reference with your own domain already filled in, plus a live key-generation form.
Account
Your own login and identity — separate from any single captive's branding, and shared across every captive you run.
My profile
Your login email (display-only here — changing it goes through a separate, security-question-gated recovery flow, not this form), your full name, phone number, company name, and a "person responsible" contact if that's someone other than you — used for billing contact and support, never shown to your guests. A separate section changes your password (current password required), and an optional but recommended "security questions" section lets you set at least 3 questions so, if you ever lose access to your own email and can't sign in, ISN support can verify it's really you before changing your login email — support never asks for or uses your password to do this.
Switch captive
Every branded location on your login, one click away — the same list shown in the account menu in the header, just easier to find here. Click any other captive in the list and your session switches into it instantly, no re-entering a password. "Add another captive" starts a brand-new one under this same login without leaving your current session (subject to the same 2-captives-until-first-payment limit described under My clients).
The ISN website
Everything above this line documents what happens after you've signed up. This section documents the site you're on right now — isnfreewifi.co.za itself — for anyone trying to understand what each part of it is for, whether that's a prospect evaluating the platform or an existing tenant trying to find where something lives.
Home
The homepage (isnfreewifi.co.za, no path) is the pitch, aimed at whoever's evaluating whether to run their guest WiFi on ISN instead of a vendor's stock hotspot app or nothing at all. It opens on what the platform actually is — a SaaS company you subscribe to and keep getting updates from, not a box you buy once and are stuck with — then walks through what running a captive on ISN gets you: real router management instead of a vendor-locked app, monetization options so guest WiFi can pay for itself instead of only costing money, and the infrastructure and scale claims behind that. If you've read this far into the documentation, you already know the platform in more depth than the homepage goes into — it's written for people who haven't signed up yet, not as a reference for people who have.
Features
Where the homepage sells the idea, Features is the technical follow-through for someone doing real evaluation: router fleet management that isn't just a read-only status page but real, audited shell access to your own hardware (the same capability documented in depth under Network → Remote CLI & restart above); the monetization options in more depth (Vouchers); custom domains (Branding → Custom domain); named accounts sitting alongside open guest access (Free access); SMS built into the platform with no separate provider account to configure (Messaging); and strict tenant isolation. Every claim on this page is something this documentation covers in full once you're actually running a captive, not marketing exaggeration.
Solutions
A by-industry version of the same pitch, because "guest WiFi platform" means something different to an airport than it does to a 40-bed student residence. Each industry — Airports, Education, Hotels and Hospitality, ISPs, Marina, Public spaces, Restaurants and Cafes, Retail, and Transport — gets its own anchored section (e.g. /solutions#education) written around what that kind of venue actually needs from guest WiFi, closing on the same point every section makes: it's the same platform underneath for all of them, just configured differently — the same dashboard and features this documentation covers apply regardless of which industry brought you here.
Resources
The catch-all for everything that isn't a sales pitch: About Us (the company itself), the Help Center (short answers to the questions people actually ask), this Documentation page (the full reference), News & Updates (a running changelog of what's shipped), and System Status (see below). The footer's Resources column adds a few more: a head-to-head comparison page against alternatives like Powerlynx and MikroTik's own hotspot tooling, and the legal set — Terms & Conditions, Service Level Agreement, Privacy Policy, and Security — covering the contractual, uptime, data-handling, and security commitments behind the platform, respectively.
Pricing
One plan, not a tiered ladder to climb — R1,500/month covers 300 concurrent connected guests, unlimited routers and locations at no extra cost, with extra concurrent users beyond 300 billed at R5 each. An interactive calculator on the page lets you estimate your own monthly cost by entering an expected concurrent-guest number before you ever sign up. These are the exact same figures — and the exact same "peak concurrent users this month decides what you pay" logic — documented in full once you're a tenant under Billing & plan → Plan & pricing; nothing changes between what's quoted here and what you're actually billed.
ISN status
Not a static "all good" badge — this page calls the platform's own status API live to show what's actually running right now, any scheduled maintenance, active incidents, and a rolling uptime history per monitored component. It reports on ISN's own infrastructure — the platform every tenant runs on — not any individual tenant's own router or captive uptime, which is what that tenant's own Status Page page (covered below) is for.
Login & signup
The header's Login and Get started buttons are for becoming or managing an ISN tenant account, not for a guest joining someone's WiFi — an important distinction, since the platform also has a completely separate login screen guests see on the captive itself (covered below), and the two are never interchangeable. Signup collects a business name, an owner name and email, then a short set-up flow — confirm your email and set a password, then brand it with a logo, colors, and your first router — before you land in the dashboard this documentation spends most of its time on.
The captive portal
Everything from here documents what your own guests — not you — actually see and click through when they join your WiFi. Understanding this flow makes the dashboard settings above easier to reason about, since most of them (branding, vouchers, free access, content filtering) are really just configuring what happens at these exact screens. A guest's device gets redirected here automatically by your router the moment it joins the network and tries to browse; none of these pages are something a guest goes looking for by URL.
Captive Login
The actual WiFi login/signup screen (login.html) — your router's External Login URL (set under Network → Routers) points here, and it's what actually loads your branding & colors rather than a generic template. A guest enters a South African phone number or email, verifies with a one-time SMS/email code (drawn from your SMS balance), and picks how they're getting online — watching an ad, redeeming a voucher, or paying for a data plan, depending on which of those you've switched on under Vouchers. An "already connected on another device?" option lets a guest link a second device to the same active data grant instead of starting a fresh one from zero.
Home
The screen a guest lands on once they're actually online (home.html) — not a dead end, but their ongoing hub for the rest of the session. This is where the My Usage panel lives: remaining data, remaining time, and (for ad-supported access) a live-updating ad-watch counter for topping up with more. A My Account area alongside it lets a guest check their own connection details without needing to contact you. Everything a guest does after their first successful login — watching another ad, checking how much data is left, seeing when access expires, or (for internal accounts) generating a guest voucher — happens on this one page, not a series of separate screens.
Marketing Page
A separate pitch page (business.html), this one aimed at local businesses who might want to advertise on your captive rather than at guests joining your WiFi — reachable at your live address with /business on the end. It lays out your ad packages and pricing, how the ad-watch flow actually works for the businesses buying into it, and an inquiry form; submissions email straight to your own support address (the one configured under Email settings), not a shared ISN inbox. You control everything here through your branding settings the same way you do the guest-facing pages — logo, colors, and brand name all carry through.
Status Page
Your own service-health page (status.html), at /status on your live address — not to be confused with ISN's own platform status page, which reports on the infrastructure every tenant runs on, not any one tenant's own router or portal uptime specifically. This page reports on your location: whether your router and portal are actually reachable right now, and any maintenance windows or incidents you or ISN support have logged against your account specifically. Worth linking to from your own support channels if guests or your own staff ever ask "is the WiFi down for everyone, or just me?"
Captive Dashboard
Not the dashboard you're reading documentation for right now — this is the captive's own separate dashboard (business-dashboard.html), gated behind its own login, for whoever actually manages your ad campaigns day to day (an Admin or Ads/Marketing Manager team role, per Team members). It opens on a live analytics view — filterable by time range, granularity, and campaign — with active-campaign stat tiles, a top-campaigns chart, and a full results table, plus its own settings area. Reach it from Overview → Post ads & more in this dashboard, which signs you straight in with the same email and password, no second login to remember.
Still stuck on something?
This page is the full reference — for quick answers to the questions we hear most, see the Help Center. For anything neither page covers, email info@isnfreewifi.co.za with your tenant slug, domain, and router model so support can confirm what still needs attention before replying.
