Documentation

Reference Guide

Everything you need to integrate real-time features with Apinator: channels, events, presence, server API, and SDKs for 7 platforms.

Getting Started

Apinator provides WebSocket infrastructure for adding real-time features to any application. Publish events from your server, receive them instantly on connected clients.

The architecture is simple: your backend publishes events through the REST API using HMAC-signed requests, and clients subscribe to channels over WebSocket connections. Apinator handles fan-out, reconnection, and presence tracking.

Installation

Install the client SDK in your frontend application and a server SDK in your backend. The client SDK connects via WebSocket; server SDKs sign API requests with HMAC.

Client (Browser)
npm install @apinator/js
Server (Node.js)
npm install @apinator/server
Server (Python)
pip install apinator-server
Server (Go)
go get github.com/apinator-io/apinator-go

Quick Example

Here is a minimal example: the client subscribes to a channel and binds to an event, then the server publishes a message to that channel.

Client
import { RealtimeClient } from '@apinator/js'

const client = new RealtimeClient({
  appKey: 'your-app-key',
  cluster: 'us'
})

client.connect()

const channel = client.subscribe('notifications')
channel.bind('new-alert', (data) => {
  console.log('Received:', data)
})
Server (Node.js)
import { Apinator } from '@apinator/server'

const apinator = new Apinator({
  appId: 'your-app-id',
  key: 'your-key',
  secret: 'your-secret',
  cluster: 'us'
})

await apinator.trigger('notifications', 'new-alert', {
  title: 'New message',
  body: 'You have a new notification'
})

Channels

Channels are the primary mechanism for organizing real-time messages. Clients subscribe to channels, and servers publish events to them. There are three channel types, each with different authorization and features.

Channel names can contain alphanumeric characters, hyphens, underscores, and dots. The maximum length is 200 characters. The channel type is determined by the name prefix.

TypePrefixAuth RequiredUse Case
Public(none)NoBroadcast data visible to all users
Privateprivate-YesRestricted data for authorized users
Presencepresence-YesTrack who is online in a channel

Public Channels

Public channels require no authorization. Any connected client can subscribe. Use them for broadcasting publicly visible data such as live scores, stock tickers, or site-wide notifications.

Subscribe
const channel = client.subscribe('live-scores')
channel.bind('score-update', (data) => {
  console.log(data.team, data.score)
})

Private Channels

Private channels require server-side authorization before a client can subscribe. The client SDK sends an authorization request to your auth endpoint, which returns an HMAC signature if the user is permitted.

Prefix the channel name with private- to create a private channel.

Client
const client = new RealtimeClient({
  appKey: 'your-app-key',
  cluster: 'us',
  authEndpoint: '/api/realtime/auth'
})

const channel = client.subscribe('private-user-123')
Auth Endpoint (Node.js)
// POST /api/realtime/auth
const auth = apinator.authorizeChannel(
  req.body.socket_id,
  req.body.channel_name
)
res.json(auth)

Presence Channels

Presence channels extend private channels with member tracking. When a user subscribes, their identity is shared with other members. Presence channels track who is currently online and fire events when members join or leave.

Prefix the channel name with presence-. The auth endpoint must include channel_data containing the user's identity.

Auth Endpoint (Node.js)
const auth = apinator.authorizeChannel(
  req.body.socket_id,
  req.body.channel_name,
  {
    user_id: 'user-123',
    user_info: { name: 'Alice' }
  }
)

Events

Events are the messages delivered through channels. Each event has a name and a data payload (JSON string). There are three categories of events: server events (published by your backend), client events (sent between clients), and system events (emitted by Apinator).

Server Events

Server events are published from your backend via the REST API. They can have any name that does not start with realtime: or client-. The data payload is a JSON string with a maximum size of 10 KB.

Publish (Node.js)
await apinator.trigger('chat-room', 'new-message', {
  user: 'Alice',
  text: 'Hello, world!'
})
Receive (Client)
channel.bind('new-message', (data) => {
  console.log(data.user, data.text)
})

Client Events

Client events are sent directly from one client to others on the same channel, without going through your server. They must be on private or presence channels, and the event name must start with client-.

Client events are useful for features like typing indicators where server round-trips add unnecessary latency.

Client events are not delivered to the sender, only to other subscribers on the channel.

Send
channel.trigger('client-typing', {
  user: 'Alice'
})

System Events

System events are emitted by Apinator and prefixed with realtime:. They cannot be published manually. Use them to react to connection state and subscription lifecycle changes.

EventDescription
realtime:subscription_succeededSubscription to a channel was authorized and completed
realtime:subscription_errorSubscription to a channel failed (auth rejected)
realtime:member_addedA new member joined a presence channel
realtime:member_removedA member left a presence channel
realtime:connection_establishedWebSocket connection was established and authenticated

Presence

Presence lets you track which users are currently subscribed to a channel. It is built on top of presence channels and provides member lists, join/leave events, and multi-tab deduplication.

Subscribing

Subscribe to a presence channel the same way as a private channel. The auth endpoint must return channel_data with a unique user_id and optional user_info.

Subscribe
const channel = client.subscribe('presence-room')

channel.bind('realtime:subscription_succeeded', (members) => {
  console.log('Online:', members.count)
  members.each((member) => {
    console.log(member.id, member.info)
  })
})

Member Tracking

The member list is available after the realtime:subscription_succeeded event fires. Each member has an id (from user_id) and info (from user_info).

Apinator handles multi-tab deduplication automatically. If a user opens multiple tabs, they appear as a single member. The member_removed event only fires when all of a user's connections leave.

Presence Events

Presence channels emit join and leave events so you can update your UI in real time.

Member Events
channel.bind('realtime:member_added', (member) => {
  console.log('Joined:', member.info.name)
})

channel.bind('realtime:member_removed', (member) => {
  console.log('Left:', member.info.name)
})

Server API

The Apinator server API is a REST API authenticated with HMAC-SHA256 signed requests. All requests must include the X-Realtime-Key, X-Realtime-Timestamp, and X-Realtime-Signature headers. The server SDKs handle signing automatically.

The base URL is https://api-{cluster}.apinator.io, where {cluster} is your region (e.g., us, eu).

Publish Events

Publish an event to one or more channels. The data payload is a JSON string with a maximum size of 10 KB.

FieldTypeDescription
channelstringTarget channel name
eventstringEvent name (no realtime: or client- prefix)
datastringJSON-encoded payload (max 10 KB)
channelsstring[]Multiple channels (alternative to channel, max 10)
socket_idstringOptional: exclude this connection from receiving the event
HTTP Request
POST /apps/{app_id}/events
Content-Type: application/json

{
  "channel": "notifications",
  "event": "new-alert",
  "data": "{\"title\":\"Hello\"}"
}

Channel Queries

Query active channels and their subscriber counts. Useful for building admin dashboards or monitoring.

HTTP Request
GET /apps/{app_id}/channels

# Response
{
  "channels": {
    "chat-room": { "subscription_count": 42 },
    "notifications": { "subscription_count": 156 }
  }
}
Single Channel
GET /apps/{app_id}/channels/{channel_name}

# Response
{
  "occupied": true,
  "subscription_count": 42
}

Batch Events

Send up to 10 events in a single request. Each item in the batch array follows the same schema as a single publish request.

HTTP Request
POST /apps/{app_id}/batch
Content-Type: application/json

{
  "batch": [
    { "channel": "room-1", "event": "msg", "data": "..." },
    { "channel": "room-2", "event": "msg", "data": "..." }
  ]
}

JavaScript SDK

The JavaScript client SDK connects to Apinator via WebSocket from browsers. It handles automatic reconnection with exponential backoff, channel subscription management, and auth token negotiation.

Installation

Install via npm, yarn, or pnpm. Works with any bundler (webpack, Vite, esbuild, Rollup).

npm
npm install @apinator/js
Script Tag
<script src="https://cdn.apinator.io/js/latest/apinator.min.js">script>

Usage

Create a client instance, connect, then subscribe to channels and bind event handlers.

OptionTypeDescription
appKeystringYour application key (required)
clusterstringRegion cluster: us, eu (required)
authEndpointstringURL for private/presence channel auth
authHeadersobjectExtra headers sent with auth requests
forceTLSbooleanForce TLS connection (default: true)
Full Example
import { RealtimeClient } from '@apinator/js'

const client = new RealtimeClient({
  appKey: 'your-app-key',
  cluster: 'us',
  authEndpoint: '/api/realtime/auth'
})

client.connect()

// Public channel
const alerts = client.subscribe('alerts')
alerts.bind('new-alert', (data) => showAlert(data))

// Private channel
const inbox = client.subscribe('private-inbox-123')

// Presence channel
const room = client.subscribe('presence-room')
room.bind('realtime:member_added', (m) => addUser(m))

// Disconnect
client.disconnect()

Node.js SDK

The Node.js server SDK provides event publishing, channel authorization, channel queries, and webhook verification. Zero dependencies — uses Node.js built-in crypto and fetch (Node 18+).

Installation

Requires Node.js 18 or later.

Install
npm install @apinator/server

Usage

Initialize with your credentials, then use the client to publish events and sign channel auth.

Publish & Auth
import { Apinator } from '@apinator/server'

const apinator = new Apinator({
  appId: 'your-app-id',
  key: 'your-key',
  secret: 'your-secret',
  cluster: 'us'
})

// Publish an event
await apinator.trigger('chat', 'message', { text: 'Hello' })

// Authorize a private channel
const auth = apinator.authorizeChannel(socketId, channelName)

// Query channels
const channels = await apinator.getChannels()

// Verify a webhook
const valid = apinator.verifyWebhook(signature, timestamp, body)

Python SDK

The Python server SDK provides event publishing, channel authorization, and webhook verification. Zero dependencies — uses only the standard library. Requires Python 3.9+.

Installation

Install from PyPI.

Install
pip install apinator-server

Usage

Initialize the client and use it to publish events or authorize channels.

Usage
from apinator import Apinator

apinator = Apinator(
    app_id='your-app-id',
    key='your-key',
    secret='your-secret',
    cluster='us'
)

# Publish an event
apinator.trigger('chat', 'message', {'text': 'Hello'})

# Authorize a private channel
auth = apinator.authorize_channel(socket_id, channel_name)

# Verify a webhook
valid = apinator.verify_webhook(signature, timestamp, body)

Go SDK

The Go server SDK provides event publishing, channel authorization, and webhook verification. Zero dependencies — uses only the standard library. Requires Go 1.21+ and uses the functional options pattern.

Installation

Install with go get.

Install
go get github.com/apinator-io/apinator-go

Usage

Create a client with functional options and use it to publish events.

Usage
import "github.com/apinator-io/apinator-go"

client, err := apinator.New(
    apinator.WithAppID("your-app-id"),
    apinator.WithKey("your-key"),
    apinator.WithSecret("your-secret"),
    apinator.WithCluster("us"),
)

// Publish an event
err = client.Trigger(ctx, "chat", "message", map[string]string{
    "text": "Hello",
})

// Authorize a channel
auth, err := client.AuthorizeChannel(socketID, channelName)

PHP SDK

The PHP server SDK provides event publishing, channel authorization, and webhook verification. Zero dependencies, PHP 8.1+, with PSR-4 autoloading.

Installation

Install via Composer.

Install
composer require apinator/apinator-php

Usage

Create a client instance and use it to publish events.

Usage
use Apinator\\Apinator;

$apinator = new Apinator([
    'app_id' => 'your-app-id',
    'key' => 'your-key',
    'secret' => 'your-secret',
    'cluster' => 'us'
]);

// Publish an event
$apinator->trigger('chat', 'message', ['text' => 'Hello']);

// Authorize a channel
$auth = $apinator->authorizeChannel($socketId, $channelName);

Swift SDK

The Swift client SDK connects to Apinator via WebSocket from iOS and macOS apps. It uses URLSessionWebSocketTask and supports iOS 13+ / macOS 10.15+. Distributed via Swift Package Manager.

Installation

Add the package via SPM in Xcode or your Package.swift.

Package.swift
.package(url: "https://github.com/apinator-io/apinator-swift", from: "1.0.0")

Usage

Create a client, connect, then subscribe to channels.

Usage
import ApinatorSDK

let client = RealtimeClient(
    appKey: "your-app-key",
    cluster: "us",
    authEndpoint: "https://your-server.com/api/realtime/auth"
)

client.connect()

let channel = client.subscribe("notifications")
channel.bind("new-alert") { data in
    print("Received: \(data)")
}

Kotlin SDK

The Kotlin client SDK connects to Apinator via WebSocket from Android and JVM apps. Built on OkHttp WebSocket. Distributed via Gradle.

Installation

Add the dependency to your build.gradle.kts.

build.gradle.kts
implementation("com.apinator:sdk:1.0.0")

Usage

Create a client, connect, then subscribe and bind events.

Usage
import com.apinator.sdk.RealtimeClient

val client = RealtimeClient(
    appKey = "your-app-key",
    cluster = "us",
    authEndpoint = "https://your-server.com/api/realtime/auth"
)

client.connect()

val channel = client.subscribe("notifications")
channel.bind("new-alert") { data ->
    println("Received: $data")
}

Authentication

Apinator uses HMAC-SHA256 for all authentication. There are two authentication contexts: API request signing (server-to-Apinator) and channel authorization (client subscription to private/presence channels).

API Request Signing

Every API request from your server must include three headers. The server SDKs generate these automatically.

The signature is computed over a string containing the timestamp, HTTP method, path, and an MD5 hash of the request body.

HeaderDescription
X-Realtime-KeyYour application API key
X-Realtime-TimestampUnix timestamp (seconds). Must be within 300s of server time.
X-Realtime-SignatureHMAC-SHA256 hex digest of the signature string
Signature Algorithm
body_md5 = len(body) == 0 ? "" : hex(md5(body))
sig_string = "{timestamp}\n{METHOD}\n{path}\n{body_md5}"
signature = hex(hmac_sha256(secret, sig_string))

Channel Authorization

When a client subscribes to a private or presence channel, it sends an auth request to your endpoint. Your server validates the user and returns an HMAC signature.

For private channels, the signature input is {socket_id}:{channel_name}. For presence channels, append :{channel_data} where channel_data is a JSON string with user_id and optional user_info.

The channel_data field is only required for presence channels. Omit it for private channels.

Auth Response Format
{
  "auth": "app-key:hmac-signature",
  "channel_data": "{\"user_id\":\"123\",\"user_info\":{\"name\":\"Alice\"}}"
}

Webhooks

Webhooks notify your server when events occur in your Apinator application, such as channel occupancy changes or client events. Webhooks are delivered via HTTP POST with HMAC-SHA256 signed payloads.

Configuration

Configure webhooks in the Apinator dashboard under your app settings. Provide a URL and select which events to receive. Each webhook has a unique secret used for signature verification.

Webhooks are delivered with exponential backoff. Failed deliveries are retried up to 5 times.

Webhook Events

The following webhook event types are available.

EventDescription
channel_occupiedFirst client subscribed to a channel
channel_vacatedLast client unsubscribed from a channel
member_addedA user joined a presence channel
member_removedA user left a presence channel
client_eventA client event was triggered on a channel
Webhook Payload
{
  "event": "channel_occupied",
  "channel": "chat-room",
  "timestamp": 1700000000
}

Signature Verification

Every webhook request includes an X-Webhook-Signature header. Verify this signature to ensure the request originated from Apinator.

The signature is computed as sha256={hmac_sha256(webhook_secret, "{timestamp}.{body}")}.

Verification (Node.js)
const valid = apinator.verifyWebhook(
  req.headers['x-webhook-signature'],
  req.headers['x-webhook-timestamp'],
  req.body
)

if (!valid) {
  return res.status(401).send('Invalid signature')
}

Rate Limits

Apinator enforces rate limits on API requests, WebSocket messages, and concurrent connections. Limits vary by plan and are applied per-application using a sliding window counter.

Plan Limits

The following limits apply per application.

ResourceFreeProBusiness
Concurrent connections10010,000500,000
Messages per day200,00020,000,000Unlimited
API requests per second10100500
Max message size10 KB10 KB256 KB
Max channels10010,000Unlimited

Response Headers

API responses include rate limit headers so you can monitor your usage.

When a rate limit is exceeded, the API returns HTTP 429 Too Many Requests with a Retry-After header.

HeaderDescription
X-RateLimit-LimitMaximum requests per window
X-RateLimit-RemainingRemaining requests in current window
X-RateLimit-ResetUnix timestamp when the window resets