Descriptions are in English
private-order.task.{orderId}
Events for a single order. Someone else's order is out of reach: subscription auth returns 403.
Spec fixes · 1
orderIdin the channel name is a UUID, not a numberIn the AsyncAPI document the channel parameter
orderIdis declared asinteger, while its own description and every example show the order UUID — the one returned asdata.idbyPOST /orders. Subscribe with the string:private-order.task.c7d8e9f0-1a2b-4c3d-8e4f-5a6b7c8d9e0f. The numericuserIdin the other channel really is a number.
Channel parameters
Fill in your values — they appear in the channel name, in the code below and in the console. They are sent nowhere and never end up in the page URL.
is the UUID from the POST /orders response.
Channel name to subscribe to
private-order.task.{orderId}
The name still contains placeholders in braces. You cannot subscribe with it: the server authorizes channels by exact name.
import Pusher from 'pusher-js';
const pusher = new Pusher('7c4dd881d8116ac76fe89aff71d8c2ff', {
wsHost: 'ws.lumean.app',
wsPort: 443, wssPort: 443,
forceTLS: true,
enabledTransports: ['ws', 'wss'],
cluster: '',
channelAuthorization: {
endpoint: 'https://api.lumean.app/api/public/broadcasting/auth',
headers: { 'X-API-KEY': 'YOUR_API_KEY' },
},
});
const channel = pusher.subscribe('private-order.task.{orderId}');
channel.bind('paragraph_regenerate.completed', (data) => {
console.log(data);
});import Echo from 'laravel-echo';
import Pusher from 'pusher-js';
window.Pusher = Pusher;
const echo = new Echo({
broadcaster: 'pusher',
key: '7c4dd881d8116ac76fe89aff71d8c2ff',
wsHost: 'ws.lumean.app',
wsPort: 443, wssPort: 443,
forceTLS: true,
enabledTransports: ['ws', 'wss'],
cluster: '',
authEndpoint: 'https://api.lumean.app/api/public/broadcasting/auth',
auth: { headers: { 'X-API-KEY': 'YOUR_API_KEY' } },
});
echo.private('order.task.{orderId}')
// the leading dot is for Laravel Echo; pusher-js has none
.listen('.paragraph_regenerate.completed', (e) => {
console.log(e);
});# pip install websocket-client requests
import json, requests, websocket
APP_KEY = "7c4dd881d8116ac76fe89aff71d8c2ff"
WS_URL = "wss://ws.lumean.app:443/app/" + APP_KEY + "?protocol=7&client=python&version=1.0"
CHANNEL = "private-order.task.{orderId}"
ws = websocket.create_connection(WS_URL)
# 1. grab socket_id from the pusher:connection_established event
hello = json.loads(ws.recv())
socket_id = json.loads(hello["data"])["socket_id"]
# 2. authorize the private subscription with your API key
auth = requests.post("https://api.lumean.app/api/public/broadcasting/auth",
headers={"X-API-KEY": "YOUR_API_KEY"},
data={"socket_id": socket_id, "channel_name": CHANNEL},
).json()["auth"]
# 3. subscribe and listen for events
ws.send(json.dumps({"event": "pusher:subscribe",
"data": {"auth": auth, "channel": CHANNEL}}))
while True:
print(ws.recv())Payload example
Channel: private-order.task.{orderId}
This is an example from the spec. There is no connection and none is simulated: subscribing for real needs your API key.
.paragraph_regenerate.completed
{
"order_id": "01a0d8c6-86d3-70b5-a86e-5a12b1d860df",
"paragraph_index": 1,
"created_count": 1,
"failed_count": 1
}Channel events: 8
Every event has its own anchor, a full payload table with descriptions and enums, and a sample shape. Names are shown in Laravel Echo notation — with the leading dot.
.paragraph_regenerate.completed
Echo: .paragraph_regenerate.completed · pusher-js: paragraph_regenerate.completed
Payload fields
Payload example
{
"order_id": "01a0d8c6-86d3-70b5-a86e-5a12b1d860df",
"paragraph_index": 1,
"created_count": 1,
"failed_count": 1
}Values come from the spec where the spec has them; the rest are type-based placeholders. This is the shape of the event, not a recording of a real one.
.voice_search.queue.updated
Echo: .voice_search.queue.updated · pusher-js: voice_search.queue.updated
Payload fields
Payload example
{
"order_id": "example",
"queue_position": 1,
"queue_wait_seconds": 1
}Values come from the spec where the spec has them; the rest are type-based placeholders. This is the shape of the event, not a recording of a real one.
.bulk_retry.completed
Echo: .bulk_retry.completed · pusher-js: bulk_retry.completed
Payload fields
Payload example
{
"order_id": "01a0d8c6-86b5-706a-958a-a626ddb3ba3d",
"created_count": 1,
"failed_count": 1
}Values come from the spec where the spec has them; the rest are type-based placeholders. This is the shape of the event, not a recording of a real one.
.renamed
Echo: .renamed · pusher-js: renamed
Payload fields
orderrequiredobject
templaterequiredobject
May arrive as null.
May arrive as null.
currency_assetrequiredobject
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
retentionrequiredobject
chunksrequiredobject
May arrive as null.
filesrequiredobject
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
May arrive as null.
Payload example
{
"order": {
"id": "01a12b4f-ddef-71a8-ae98-c8ec656c2886",
"user_id": 70,
"name": "example",
"template": {
"id": "01a12b4f-dded-706a-91d6-0f86a632230d",
"user_id": 71,
"slug": "a80eab29-6508-36cb-b8e8-3e85029e97b3",
"name": "consequatur",
"service_key": "example",
"service": "string",
"config": [],
"is_public": false,
"folder_id": "string",
"created_at": "2026-10-11T14:13:36+00:00",
"updated_at": "2026-10-11T14:13:36+00:00"
},
"template_id": "01a12b4f-dded-706a-91d6-0f86a632230d",
"task_type": "tts",
"status": "created",
"price_units": 97.05,
"price_formatted": 0.97,
"currency_asset": {
"id": "string",
"code": "LUMC",
"kind": "string",
"precision": 2,
"name": "string",
"deleted_at": "<date-time>",
"created_at": "<date-time>",
"updated_at": "<date-time>"
},
"total_tokens": "string",
"total_duration_ms": "string",
"tokens_from_quota": "string",
"tokens_from_payg": "string",
"tokens_spent": "string",
"task_data": "string",
"result": "string",
"created_at": "2026-10-11T14:13:36+00:00",
"updated_at": "2026-10-11T14:13:36+00:00",
"files_expire_at": "<date-time>",
"files_expired": false,
"retention": {
"chunks": {
"expires_at": "<date-time>",
"expired": false,
"expires_early": false,
"reason": "string"
},
"files": {
"expires_at": "<date-time>",
"expired": false
}
},
"eta_seconds": "string",
"eta_at": "<date-time>",
"completed_chunks": "string",
"total_chunks": "string",
"progress_percent": "string",
"stitching": false,
"paragraphs": "string"
}
}Values come from the spec where the spec has them; the rest are type-based placeholders. This is the shape of the event, not a recording of a real one.
.status.changed
Echo: .status.changed · pusher-js: status.changed
The order changed status.
Payload fields
A snapshot of the order without the chunk list — per-chunk changes arrive as separate item.status.changed events.
items_summaryrequiredA summary of the order's chunks instead of the full list.
object
A summary of the order's chunks instead of the full list.
How many chunks are in each status: pending, processing, completed, failed, policy_flagged.
Payload example
{
"order": {},
"items_summary": {
"total": 12,
"by_status": {
"completed": 10,
"failed": 2
}
},
"previous_status": "created",
"new_status": "created"
}Values come from the spec where the spec has them; the rest are type-based placeholders. This is the shape of the event, not a recording of a real one.
.item.status.changed
Echo: .item.status.changed · pusher-js: item.status.changed
An order chunk changed status.
Payload fields
itemrequiredThe chunk index, its status, the result file path and the audio duration.
object
The chunk index, its status, the result file path and the audio duration.
Whether the order's audio is being stitched. The last finished chunk of a multi-chunk order means stitching has started, not that the order is done: while true the result is not final.
Payload example
{
"item": {
"id": "<uuid>",
"chunk_index": 3,
"status": "pending",
"result_file": {},
"duration_ms": 12480
},
"previous_status": "string",
"new_status": "string",
"completed_chunks": 3,
"total_chunks": 7,
"progress_percent": 43,
"stitching": false
}Values come from the spec where the spec has them; the rest are type-based placeholders. This is the shape of the event, not a recording of a real one.
.stitch.changed
Echo: .stitch.changed · pusher-js: stitch.changed
Payload fields
stitchrequiredobject
May arrive as null.
Payload example
{
"order_id": "01a12b4f-d2ba-70ef-b1a8-14aff97d1da2",
"order_status": "created",
"stitching": false,
"stitch": {
"id": "01a12b4f-d2bc-7117-83c6-a16f11eac8f4",
"status": "pending",
"paragraph_index": "string",
"restitch": false
}
}Values come from the spec where the spec has them; the rest are type-based placeholders. This is the shape of the event, not a recording of a real one.
.progress
Echo: .progress · pusher-js: progress
Live progress of the order.
Payload fields
The order UUID — the same value as the channel's {orderId}.
Kept for compatibility and does not reflect progress — rely on the progress events of the orders channel, or on eta_seconds.
Kept for compatibility and does not reflect how many parts are done — count completion from item.status.changed events.
Total number of parts in the order.
How many seconds the task has been running. This is elapsed time, not remaining.
Estimated time remaining, in seconds. Computed by the API from service statistics.
How much to trust the estimate: high — statistics for chunks of the same size, medium — for the service overall, low — little data, so show it with a «≈».
Payload example
{
"task_id": "<uuid>",
"progress": 42.5,
"chunks_done": 0,
"chunks_total": 0,
"duration_seconds": 0,
"eta_seconds": 95,
"eta_confidence": "high",
"timestamp": "<date-time>"
}Values come from the spec where the spec has them; the rest are type-based placeholders. This is the shape of the event, not a recording of a real one.
All channels and connection parameters·POST /broadcasting/auth
Feed this page to an AI
spec 0.0.1