Docs/Core concepts/Publishing

Publishing

How a trusted server publishes signed events to the gateway, and what the gateway does before fan-out.

Concept· 6 min read

The publish path

Publishing always originates from a trusted server. The server SDK signs the request and POSTs it to the publish endpoint at /apps/{appId}/events. EmitWave then verifies the HMAC signature, rate-limits, validates, scopes the channel to your application, and fans the event out to subscribers over their WebSocket.

Browsers never publish. The public application key and end-user token only authorize connecting and subscribing — see Authentication.

The trigger method

Every server SDK exposes the same method signature: trigger(channel, event, data). It publishes to any external channel type — the gateway scopes the name to your app and subscriber authorization is evaluated separately.

publish.ts
import { Client } from '@emitwave/node'

const emitwave = new Client({
  appId: process.env.EMITWAVE_APP_ID,
  key: process.env.EMITWAVE_KEY,
  secret: process.env.EMITWAVE_SECRET,
  // gatewayUrl defaults to https://api.emitwave.com
})

await emitwave.trigger('orders', 'order.created', {
  id: 'ord_123',
  total: 4900,
})

See the Node, Go, PHP, and Laravel SDK pages for language-specific usage.

Request signing

For every request the SDK hashes the exact JSON body and HMAC-signs the HTTP method, path, canonical query, and body hash with HMAC-SHA256 using your server secret. The gateway rejects unknown app keys, revoked credentials, stale timestamps, and invalid signatures. The SDK never includes the secret in an error message.

Because the signature covers the exact serialized body, do not re-serialize or reorder the payload between signing and sending. Let the SDK own serialization.

Rate limits & size limits

The gateway rate-limits publishing and enforces a maximum payload size. Exceeding either returns a stable error code (RATE_LIMITED or PAYLOAD_TOO_LARGE) rather than silently dropping the event.

Error handling

Each SDK surfaces a dedicated error type for non-2xx gateway responses (e.g. EmitwaveError in Node), while network and configuration problems remain ordinary transport errors.

errors.ts
import { Client, EmitwaveError } from '@emitwave/node'

try {
  await emitwave.trigger('orders', 'order.created', { id: 'ord_123' })
} catch (error) {
  if (error instanceof EmitwaveError) {
    console.error('rejected', error.status, error.body)
  } else {
    console.error('transport or config error', error)
  }
}

The full list of stable codes is on the Errors page.