POST to the engine’s HTTP plane,
which is what your own server code does. That request carries five query
parameters — auth_key, auth_timestamp, auth_version, body_md5 and
auth_signature — and the engine rejects it if the signature does not match.
This page documents how to build that request by hand, and what the
queued result on the API response card means.
The publish endpoint and its query parameters
<ws-host> and <app_id> are filled in for you in the cURL card — the app id
is also shown in the pill next to the page title.
Content-Type is application/json. Only auth_signature is excluded from the
material that gets signed; every other parameter above is part of it.
Request body and encoding the data field
The body is a JSON object with three fields:name— the event name. This is the name subscribers bind to.channels— an array of channel names. The Event Creator publishes to one channel at a time, so the card emits a single-element array.data— a JSON-encoded string, not a nested object. The Data textarea in the console holds a JSON object; the card serialises that object and puts the resulting string indata. Client-side, the payload is parsed back out of that string.
JSON.stringify(payload) for the data field, then JSON.stringify again
for the whole envelope.
Computing body_md5
body_md5 is the lowercase hex MD5 digest of the serialised request body — the
same bytes you pass to -d. Compute it after you have finished building the
body; any whitespace or key-order change invalidates it.
Building the sign-string and the auth_signature HMAC
The sign-string is three lines joined with a single\n (no trailing newline):
- The HTTP method, uppercase:
POST. - The request path only — no scheme, no host, no query string.
- The query parameters, excluding
auth_signature, sorted by parameter name and joined with&. Use the raw values here, not URL-encoded ones.
auth_key, auth_timestamp, auth_version, body_md5. If you add any other
query parameter, it has to be folded into the same sorted list.
auth_signature is then the lowercase hex HMAC-SHA256 of that sign-string,
keyed with your app secret:
body string you hashed:
Channel and event name rules
The console validates the same shapes the control plane enforces, so a name that the Event Creator rejects will not work over REST either:- Channel name — required, at most 164 characters, and may contain only
letters, digits and
_ - = @ , . ;. This is the realtime protocol’s channel grammar: a stock client refuses to subscribe to anything outside it, so publishing to such a name publishes into the void. - Event name — required, at most 200 characters.
private- and
presence- channels are legitimate publish targets, because a signed REST
caller (or the console’s control plane) is an authorized publisher. The prefix
governs who may subscribe, not who may publish.
Response codes and error bodies
A successful publish returns a 2xx and the console shows the green ok pill with the event and channel name. When the engine rejects the publish, the control plane surfaces the engine’s HTTP status and its response body unchanged. On the API response card that appears as a warning pill carrying the status code, the linePublish failed (HTTP <status>), and the raw response body rendered as JSON
underneath. Read that body — it is the engine’s own error, not a control-plane
wrapper, so it is the same text your server SDK would see from a direct signed
call.
Two failure modes never reach the engine at all:
- Invalid JSON in the Data field. The console parses the textarea before
sending and reports
Invalid JSON: <message>inline. The Data field’svalid JSON/invalidindicator tracks this as you type. - Shape validation. An empty or malformed channel or event name is reported under the field and the request is not sent.
Accepted-but-queued delivery semantics
Publishes issued from the console do not go over the signed HTTP plane. The control plane pushes the publish body onto the engine’s generic ring buffer —clutchcall:realtime:ring, the same bus the presence and assist bridges
ride. That is why console publishing needs no per-deployment HTTP
configuration: the publisher is always reachable, even when the engine is not.
The consequence is a third outcome besides success and failure. The response
carries a wired flag:
queued is an acceptance, not an error: the card reads “Queued — engine
offline; will deliver when the engine reconnects.” The event sits on the ring
and is delivered when an engine comes back and drains it. Subscribers that are
connected at that later moment receive it then; the publish is not replayed to
clients that were subscribed at the original publish time and have since gone
away.
Treat queued as a signal to check engine health before you interpret a silent
client as a publishing bug. If you see queued for a publish that you expected
to be live, the event is not lost — the engine link is down.
Publishing from the console instead of signing
For one-off tests, the Event Creator is the shorter path: it publishes through the control plane with your org credentials, so there is noauth_key,
body_md5 or HMAC to build, and private- / presence- channels work without
extra setup. Use the signed REST endpoint when the publisher is your own
backend, and reach for the Equivalent cURL card to get a copy-paste
starting point that already mirrors the channel, event and payload you typed
into the form.
Related
- Authentication — where app keys and secrets sit relative to client tokens
- Telemetry — the metric and trace streams that cover publishes

