Skip to content

Realtime

Realtime tokens, channels, publish and presence.

1. Overview

Base path: https://api.infrai.cc/v1/realtime
Auth header: Authorization: Bearer $INFRAI_API_KEY
bash
# Call any /v1/realtime capability over raw HTTP — no SDK to install.
# curl:
curl https://api.infrai.cc/v1/realtime/... \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json"

2. Methods (11)

2.1realtime.publish

POST /v1/realtime/publish

Publish an event to a channel.

Parameters

NameTypeRequiredDescription
channelstring
Required
Channel name.
eventstring
Required
Event name.
default: "message"
dataunknown
Required
Event payload to publish.
idempotency_keystringOptionalOptional dedup key; identical retries return the same result.

Returns

{ message_id }
NameTypeDescription
event_idstringUnique identifier for this event
channelstringChannel name or identifier
published_atstringISO 8601 timestamp when the event was published
format: date-time
vendorstringVendor that handled or will handle this request

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/realtime/publish \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"channel": "sample"}'

2.2realtime.token.issue

POST /v1/realtime/token/issue

Issue a client token scoped to channels and capabilities.

Parameters

NameTypeRequiredDescription
user_idstringOptionalId of the connecting user.
channelsstring[]OptionalChannels the token may access.
ttl_secondsnumberOptionalLifetime in seconds before expiry.
≥ 1

Returns

RealtimeToken { token, client_id, expires_at, endpoint }
NameTypeDescription
tokenstringAuthentication or verification token
jtistringJWT ID; used for server-side revocation.
channelsstring[]List of channel names the token grants access to
capabilities("subscribe" | "publish" | "presence" | "history")[]List of capability permissions (publish, subscribe)
expires_atstringISO 8601 timestamp when this resource or token expires
format: date-time

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/realtime/token/issue \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"client_id": "sample"}'

2.3realtime.channel.create

POST /v1/realtime/channel/create

Create a realtime channel.

Parameters

NameTypeRequiredDescription
namestring
Required
Channel name.
type"public" | "private" | "presence"OptionalChannel visibility type.
default: "public"

Returns

{ channel_id, name, type }
NameTypeDescription
channel_idstringUnique identifier for this channel
namestringHuman-readable name for this resource
type"public" | "private" | "presence"Type discriminator for this resource
vendorstringVendor that handled or will handle this request
created_atstringISO 8601 timestamp when this resource was created
format: date-time
member_countinteger | nullNumber of members in the channel
≥ 0
last_published_atstring | nullISO 8601 timestamp of the last published event
format: date-time

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/realtime/channel/create \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"channel": "sample"}'

2.4realtime.presence.get

GET /v1/realtime/presence/get/{channel}

Get the members currently present on a channel.

Parameters

NameTypeRequiredDescription
channelstring
Required
Channel name.

Returns

{ members: Array<{ client_id, user_id? }> }
NameTypeDescription
channelstringChannel name or identifier
membersobject[]List of presence members in the channel
members[].client_idstringClient identifier for the connected user
members[].joined_atstringISO 8601 timestamp when this member joined
format: date-time
members[].user_dataobject | nullCustom data associated with the presence member
next_cursorstring | nullPass back into presence.get() to fetch the next page; null on last page.

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/realtime/presence/get/CHANNEL \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.5realtime.channel.get

GET /v1/realtime/channel/get/{channel}

获取单个实时频道的详情,包括类型、厂商、在线人数等。

Parameters

NameTypeRequiredDescription
channelstring
Required
要查询的频道名。

Returns

Channel { channel_id, name, type, vendor, created_at, member_count?, last_published_at? }
NameTypeDescription
channel_idstringUnique identifier for this channel
namestringHuman-readable name for this resource
type"public" | "private" | "presence"Type discriminator for this resource
vendorstringVendor that handled or will handle this request
created_atstringISO 8601 timestamp when this resource was created
format: date-time
member_countinteger | nullNumber of members in the channel
≥ 0
last_published_atstring | nullISO 8601 timestamp of the last published event
format: date-time

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/realtime/channel/get/CHANNEL \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.6realtime.channel.delete

DELETE /v1/realtime/channel/delete/{channel}

删除一个实时频道并断开其订阅者。

Parameters

NameTypeRequiredDescription
channelstring
Required
要删除的频道名。
idempotency_keystringOptional幂等键,用于安全重试。

Returns

ChannelDeleteResult { channel, deleted, status }
NameTypeDescription
channelstringChannel name or identifier
deletedbooleanWhether the resource was successfully deleted
status"deleted" | "not_found"Current status of this resource

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X DELETE https://api.infrai.cc/v1/realtime/channel/delete/CHANNEL \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.7realtime.channel.list

GET /v1/realtime/channel/list

分页列出当前账户下的实时频道。

Parameters

NameTypeRequiredDescription
cursorstringOptional翻页游标,传入上一页返回的 next_cursor。
limitnumberOptional单页返回的最大条数。

Returns

ChannelListResult { channels: Channel[], next_cursor? }
NameTypeDescription
channelsobject[]List of channel names the token grants access to
channels[].channel_idstringUnique identifier for this channel
channels[].namestringHuman-readable name for this resource
channels[].type"public" | "private" | "presence"Type discriminator for this resource
channels[].vendorstringVendor that handled or will handle this request
channels[].created_atstringISO 8601 timestamp when this resource was created
format: date-time
channels[].member_countinteger | nullNumber of members in the channel
≥ 0
channels[].last_published_atstring | nullISO 8601 timestamp of the last published event
format: date-time
next_cursorstring | nullPass back into channel.list() to fetch the next page; null on last page.

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/realtime/channel/list \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.8realtime.event.types

GET /v1/realtime/event/types

列出可订阅的实时事件类型封闭集合。

Returns

EventTypesResult { types: string[] }
NameTypeDescription
types("channel.opened" | "channel.closed" | "message.published" | "presence.join" | "presence.leave")[]List of available event types

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X GET https://api.infrai.cc/v1/realtime/event/types \
  -H "Authorization: Bearer $INFRAI_API_KEY"

2.9realtime.publish.batch

POST /v1/realtime/publish/batch

在一次调用中向多个频道批量发布消息。

Parameters

NameTypeRequiredDescription
messagesArray<{ channel: string; event: string; data: unknown }>
Required
要发布的消息列表,每条含 channel、event 和 data。
≥ 1 item
idempotency_keystringOptional幂等键,用于安全重试,避免重复发布。

Returns

PublishBatchResult { published }
NameTypeDescription
publishedintegerNumber of messages accepted for delivery.
≥ 0

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/realtime/publish/batch \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"messages": [{"channel": "sample", "event": "sample", "data": "sample"}]}'

2.10realtime.token.revoke

POST /v1/realtime/token/revoke

吊销先前签发的订阅令牌(登出或封禁时使用)。

Parameters

NameTypeRequiredDescription
token_or_jtistring
Required
完整令牌或其 jti 标识。
≥ 1 chars
idempotency_keystringOptional幂等键,用于安全重试。

Returns

TokenRevokeResult { revoked }
NameTypeDescription
revokedbooleanWhether the token was successfully revoked

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/realtime/token/revoke \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"token_or_jti": "sample"}'

2.11realtime.user.disconnect

POST /v1/realtime/user/disconnect

强制将某客户端踢下线,可选限定到单个频道。

Parameters

NameTypeRequiredDescription
client_idstring
Required
要断开连接的客户端身份标识。
≥ 1 chars
channelstringOptional将断开限定到此频道;省略则全部断开。
idempotency_keystringOptional幂等键,用于安全重试。

Returns

UserDisconnectResult { disconnected }
NameTypeDescription
disconnectedbooleanWhether the user was successfully disconnected

Example

一次性前置(每个范例都假定已完成):

bash
# No SDK to install — every call is a plain HTTPS request.
# Get a project key by signing in at https://infrai.cc/login (Google/GitHub gives
# you $2 free credit; email sign-in starts at $0). On 402 INSUFFICIENT_CREDIT, add
# funds at https://infrai.cc/billing (or POST /v1/account/topup and open the
# returned checkout_url).
export INFRAI_API_KEY="ifr_..."
bash
curl -X POST https://api.infrai.cc/v1/realtime/user/disconnect \
  -H "Authorization: Bearer $INFRAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"client_id": "sample"}'
Advanced: pin a vendor

By default infrai routes each call to the best available provider — you do not pick a vendor. As an escape hatch, this capability accepts an optional vendor parameter to pin one specific provider. Every live vendor for this capability is available in real time from the discovery endpoint for the capability id — see the discovery API.

GET /v1/discovery/{capability}

realtime.channel.create

3. All capabilities

Every routed capability in this module — the complete public REST contract. The methods above are the guided walkthrough; this index is the full reference.

realtime.channel.createPOST /v1/realtime/channel/create

Create a realtime pub/sub channel; idempotent.

Parameters (4)
NameTypeRequiredDescription
channelstringRequiredChannel name to create.
typestringOptionalChannel type (e.g. public, private, presence).
default: "public"
vendorstring | nullOptionalPin to a specific fan-out vendor; falls back to the registry default.
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
realtime.channel.deleteDELETE /v1/realtime/channel/delete/{channel}

Delete a realtime channel and disconnect its subscribers.

Parameters (1)
NameTypeRequiredDescription
channelstringRequiredPath parameter.
realtime.channel.getGET /v1/realtime/channel/get/{channel}

Get a single realtime channel's details (type, vendor, online count, etc.).

Parameters (1)
NameTypeRequiredDescription
channelstringRequiredPath parameter.
realtime.channel.listGET /v1/realtime/channel/list

List the account's realtime channels with pagination.

No request parameters.

realtime.event.typesGET /v1/realtime/event/types

List the closed set of subscribable realtime event types.

No request parameters.

realtime.presence.getGET /v1/realtime/presence/get/{channel}

Get the current presence state of members online in a channel.

Parameters (1)
NameTypeRequiredDescription
channelstringRequiredPath parameter.
realtime.publishPOST /v1/realtime/publish

Publish an event message to a realtime pub/sub channel.

Parameters (5)
NameTypeRequiredDescription
channelstringRequiredChannel to publish to.
eventstringOptionalEvent name.
default: "message"
dataanyOptionalEvent payload (any JSON value).
account_idstring | nullOptionalAccount identifier that owns this resource
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
realtime.publish.batchPOST /v1/realtime/publish/batch

Publish messages to multiple channels in a single batch call.

Parameters (2)
NameTypeRequiredDescription
messagesobject[]RequiredList of messages to publish or process
≥ 1 item
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
realtime.token.issuePOST /v1/realtime/token/issue

Issue a short-lived infrai-HMAC client auth token for pub/sub realtime channels (NOT for AI voice sessions — see ai.voice.session).

Parameters (5)
NameTypeRequiredDescription
client_idstringRequiredIdentity the issued token is bound to.
≥ 1 chars
channelsstring[] | nullOptionalChannels the token may attach to; omit for an account-scoped token.
capabilities("subscribe" | "publish" | "presence" | "history")[] | nullOptionalCapability bits; constrained to the RealtimeCapability closed set. Defaults to subscribe.
ttl_secondsinteger | nullOptionalRequested lifetime; clamped to MAX_TTL_SECONDS (<=0 or invalid -> REALTIME_TOKEN_TTL_INVALID 400).
≥ 1
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
realtime.token.revokePOST /v1/realtime/token/revoke

Revoke a previously issued subscription token (e.g., on logout or ban).

Parameters (2)
NameTypeRequiredDescription
token_or_jtistringRequiredEither the full token or its jti.
≥ 1 chars
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry
realtime.user.disconnectPOST /v1/realtime/user/disconnect

Forcibly disconnect a client, optionally scoped to a single channel.

Parameters (3)
NameTypeRequiredDescription
client_idstringRequiredClient identifier for the connected user
≥ 1 chars
channelstring | nullOptionalRestrict the disconnect to this channel; omit for all.
idempotency_keystring | nullOptionalClient-provided idempotency key; prevents duplicate execution on retry

4. End-to-end example

A production-style walkthrough of this module: configure once, then run the flow. It exercises most of the module's APIs.

A copy-paste-runnable single-file Python program (stdlib only, no SDK): set your INFRAI_API_KEY, run it, and walk this module's core flow with REAL billed calls — later steps reuse real fields returned by earlier ones. The 12-line helper is the entire integration.

python
#!/usr/bin/env python3
"""Infrai · realtime — runnable real-app example (single file, zero deps).

Copy this file, set your key, run it: every step is a REAL call to
api.infrai.cc, billed at the real (tiny) per-call price, printing the
live JSON response. Get a key at https://infrai.cc/login (Google/
GitHub sign-in grants $2 free credit); add funds at
https://infrai.cc/billing. No SDK — the 12-line helper below is the
entire integration."""
import json
import os
from urllib import error, request

KEY = os.environ.get("INFRAI_API_KEY") or "ifr_..."  # <- your key
BASE = "https://api.infrai.cc"


# Same raw HTTPS POST/GET as every per-method example on this page —
# wrapped once for reuse. There is nothing else to it: no SDK.
def infrai(method, path, body=None):
    req = request.Request(
        BASE + path, method=method,
        data=json.dumps(body).encode() if body is not None else None,
        headers={"Authorization": f"Bearer {KEY}",
                 "Content-Type": "application/json"})
    try:
        with request.urlopen(req, timeout=60) as r:
            return json.loads(r.read())
    except error.HTTPError as e:
        return json.loads(e.read())


def show(label, resp):
    print(f"\n== {label} ==")
    print(json.dumps(resp, indent=2, ensure_ascii=False))
    return resp


# 1) realtime.publish — POST /v1/realtime/publish · Publish an event message to a realtime pub/sub channel.
r1 = show("realtime.publish", infrai("POST", "/v1/realtime/publish", {"channel":"room-42","event":"message","data":{"text":"hi"}}))

# 2) realtime.token.issue — POST /v1/realtime/token/issue · Issue a short-lived infrai-HMAC client auth token for pub/sub realtime channels (NOT for AI voice sessions — see ai.voice.session).
r2 = show("realtime.token.issue", infrai("POST", "/v1/realtime/token/issue", {"client_id":"user_42","channels":["room-42"],"capabilities":["subscribe","presence"],"ttl_seconds":3600}))

# 3) realtime.channel.create — POST /v1/realtime/channel/create · Create a realtime pub/sub channel; idempotent.
r3 = show("realtime.channel.create", infrai("POST", "/v1/realtime/channel/create", {"name":"room-42","type":"presence"}))

# 4) realtime.channel.list — GET /v1/realtime/channel/list · List the account's realtime channels with pagination.
r4 = show("realtime.channel.list", infrai("GET", "/v1/realtime/channel/list"))