xapi-to 0.1.17 → 0.1.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +60 -10
- package/dist/index.js +493 -44
- package/package.json +9 -2
- package/skills/xapi/SKILL.md +485 -0
- package/skills/xapi/guides/ai.md +200 -0
- package/skills/xapi/guides/ai_gateway.md +263 -0
- package/skills/xapi/guides/crypto.md +197 -0
- package/skills/xapi/guides/douyin.md +297 -0
- package/skills/xapi/guides/google_search.md +194 -0
- package/skills/xapi/guides/linkedin.md +198 -0
- package/skills/xapi/guides/reddit.md +312 -0
- package/skills/xapi/guides/sms.md +186 -0
- package/skills/xapi/guides/tiktok.md +322 -0
- package/skills/xapi/guides/twitter.md +276 -0
- package/skills/xapi/guides/weibo.md +301 -0
- package/skills/xapi/guides/ws_gateway.md +206 -0
- package/skills/xapi/guides/xiaohongshu.md +315 -0
- package/skills/xapi/scripts/download_tweet_videos.sh +125 -0
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# Weibo Guide
|
|
2
|
+
|
|
3
|
+
Complete guide for Weibo operations via xAPI — hot search, content search, user profiles, posts, comments, and media.
|
|
4
|
+
|
|
5
|
+
> **Dynamic catalog:** These are database-registered third-party APIs under the `weibo-app` service. Exact action IDs, HTTP methods, parameters, and response fields can change. Run `search` and `get` before calling; the current schema wins. Examples below reflect one known GET-based version and keep `"method":"GET"` in the input for compatibility.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Hot search](#hot-search-热搜)
|
|
10
|
+
- [Search](#search-搜索)
|
|
11
|
+
- [User data](#user-data-用户)
|
|
12
|
+
- [Post data](#post-data-博文)
|
|
13
|
+
- [Media](#media-多媒体)
|
|
14
|
+
- [Feed](#feed-信息流)
|
|
15
|
+
- [Common workflows](#common-workflows)
|
|
16
|
+
- [API reference](#api-reference)
|
|
17
|
+
- [Error handling](#error-handling)
|
|
18
|
+
|
|
19
|
+
## Hot Search (热搜)
|
|
20
|
+
|
|
21
|
+
### Get trending hot search
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__hot__search \
|
|
25
|
+
--input '{"method":"GET","params":{"category":"realtimehot"}}'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The `category` parameter selects which trending list to fetch:
|
|
29
|
+
|
|
30
|
+
| Value | Category |
|
|
31
|
+
|-------|----------|
|
|
32
|
+
| `realtimehot` | 热搜(default) |
|
|
33
|
+
| `social` | 社会 |
|
|
34
|
+
| `fun` | 文娱 |
|
|
35
|
+
| `technologynav` | 科技 |
|
|
36
|
+
| `lifenav` | 生活 |
|
|
37
|
+
| `region` | 同城 |
|
|
38
|
+
| `sportnav` | 体育 |
|
|
39
|
+
| `gamenav` | ACG |
|
|
40
|
+
|
|
41
|
+
Results are in `data.data.items[]`, which contains multiple groups. Filter for the group with `type: "vertical"` and ~50 sub-items — this is the main hot search list. Each entry has `data.desc` (topic title) and `data.scheme` (deep link). A separate "实时上升热点" group (preceded by a text label) lists ~20 rapidly rising topics.
|
|
42
|
+
|
|
43
|
+
**Note:** The `count` and `page` parameters are accepted (count max 50) but do not affect the number of results — the full list is always returned.
|
|
44
|
+
|
|
45
|
+
### Get hot search categories
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__hot__search__categories \
|
|
49
|
+
--input '{"method":"GET"}'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
No parameters needed. Returns available trending category metadata.
|
|
53
|
+
|
|
54
|
+
## Search (搜索)
|
|
55
|
+
|
|
56
|
+
### Comprehensive search
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__search__all \
|
|
60
|
+
--input '{"method":"GET","params":{"query":"AI","search_type":1,"page":1}}'
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Pagination: `page` is an integer.
|
|
64
|
+
|
|
65
|
+
The `search_type` parameter controls what to search for:
|
|
66
|
+
|
|
67
|
+
| Value | Type |
|
|
68
|
+
|-------|------|
|
|
69
|
+
| `1` | Comprehensive (综合) |
|
|
70
|
+
| `61` | Real-time (实时) |
|
|
71
|
+
| `3` | Users (用户) |
|
|
72
|
+
| `64` | Videos (视频) |
|
|
73
|
+
| `63` | Images (图片) |
|
|
74
|
+
| `62` | Followed (关注) |
|
|
75
|
+
| `60` | Trending (热门) |
|
|
76
|
+
| `21` | All platforms (全站) |
|
|
77
|
+
| `38` | Topics (话题) |
|
|
78
|
+
| `98` | Super topics (超话) |
|
|
79
|
+
| `92` | Locations (地点) |
|
|
80
|
+
| `97` | Products (商品) |
|
|
81
|
+
|
|
82
|
+
Results are in `data.data.items[]`, which mixes different `category` types. Filter for items with `category: "feed"` to get posts — their data is in the `.data` sub-object with fields: `text` (HTML), `user`, `created_at`, `reposts_count`, `comments_count`, `attitudes_count`. Items with `category: "group"` are UI elements (e.g. user cards, topic cards) and can be skipped.
|
|
83
|
+
|
|
84
|
+
### AI smart search
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__ai__smart__search \
|
|
88
|
+
--input '{"method":"GET","params":{"query":"人工智能","page":1}}'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
AI-powered search that returns curated results. Supports pagination via `page`.
|
|
92
|
+
|
|
93
|
+
## User Data (用户)
|
|
94
|
+
|
|
95
|
+
### Get user profile
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__info \
|
|
99
|
+
--input '{"method":"GET","params":{"uid":"1669879400"}}'
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The `uid` is the numeric Weibo user ID. Returns user info at `data.data.header.data.userInfo` with fields including `screen_name`, `description`, `domain`, `lang`, `status`, and more.
|
|
103
|
+
|
|
104
|
+
**How to find a uid:** Use `fetch_search_all` with `search_type: 3` (user search) to look up a user by name, then extract `uid` from the results.
|
|
105
|
+
|
|
106
|
+
### Get user detailed profile
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__info__detail \
|
|
110
|
+
--input '{"method":"GET","params":{"uid":"1669879400"}}'
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Returns extended profile at `data.data.userInfo` with additional fields beyond `fetch_user_info`: verification details, badge info, credit score, `urank`, `mbrank`, etc. Also includes `items` sections with structured profile details (education, work history).
|
|
114
|
+
|
|
115
|
+
### Get user timeline (博文列表)
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__timeline \
|
|
119
|
+
--input '{"method":"GET","params":{"uid":"1669879400","page":1}}'
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Results are in `data.data.items[]`, which mixes different `category` types. Filter for items with `category: "feed"` to get posts — their data is in the `.data` sub-object with fields: `mid` (post ID), `text` (HTML), `created_at`, `reposts_count`, `comments_count`, `attitudes_count`, `user`. Items with `category: "card"` are UI elements and can be skipped.
|
|
123
|
+
|
|
124
|
+
Optional parameters:
|
|
125
|
+
- `page` — page number, integer (default 1)
|
|
126
|
+
- `filter_type` — filter type, e.g. `"all"`
|
|
127
|
+
- `month` — time filter in YYYYMM format (e.g. `"202604"`)
|
|
128
|
+
|
|
129
|
+
### Get user articles (头条文章)
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__articles \
|
|
133
|
+
--input '{"method":"GET","params":{"uid":"1669879400"}}'
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Paginate with `since_id` (cursor from previous response).
|
|
137
|
+
|
|
138
|
+
### Get user super topics (超话)
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__super__topics \
|
|
142
|
+
--input '{"method":"GET","params":{"uid":"1669879400","page":1}}'
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Post Data (博文)
|
|
146
|
+
|
|
147
|
+
### Get post detail
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__status__detail \
|
|
151
|
+
--input '{"method":"GET","params":{"status_id":"5284850937629474"}}'
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The `status_id` is the numeric post ID (same as `mid`). Returns post data at `data.data.detailInfo.status` with: `id`, `mid`, `text`, `created_at`, `source`, `reposts_count`, `comments_count`, `attitudes_count`, `user`.
|
|
155
|
+
|
|
156
|
+
### Get post comments (评论)
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__status__comments \
|
|
160
|
+
--input '{"method":"GET","params":{"status_id":"5284850937629474","sort_type":"0"}}'
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`sort_type`: `"0"` = sort by popularity, `"1"` = sort by time. Paginate with `max_id` cursor.
|
|
164
|
+
|
|
165
|
+
### Get post reposts (转发)
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__status__reposts \
|
|
169
|
+
--input '{"method":"GET","params":{"status_id":"5284850937629474"}}'
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Paginate with `max_id` cursor.
|
|
173
|
+
|
|
174
|
+
### Get post likes (点赞)
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__status__likes \
|
|
178
|
+
--input '{"method":"GET","params":{"status_id":"5284850937629474","attitude_type":"0"}}'
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`attitude_type` values: `"0"` = all, `"1"` = like, `"2"` = happy, `"3"` = surprised, `"4"` = sad, `"5"` = angry, `"6"` = tip, `"8"` = hug.
|
|
182
|
+
|
|
183
|
+
## Media (多媒体)
|
|
184
|
+
|
|
185
|
+
### Get user photos (相册)
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__album \
|
|
189
|
+
--input '{"method":"GET","params":{"uid":"1669879400"}}'
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Paginate with `since_id`.
|
|
193
|
+
|
|
194
|
+
### Get user videos
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__videos \
|
|
198
|
+
--input '{"method":"GET","params":{"uid":"1669879400"}}'
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Paginate with `since_id`.
|
|
202
|
+
|
|
203
|
+
### Get user audio
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__audios \
|
|
207
|
+
--input '{"method":"GET","params":{"uid":"1669879400"}}'
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Paginate with `since_id`.
|
|
211
|
+
|
|
212
|
+
### Get video detail
|
|
213
|
+
|
|
214
|
+
```bash
|
|
215
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__video__detail \
|
|
216
|
+
--input '{"method":"GET","params":{"mid":"5284850937629474"}}'
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Returns video post data at `data.data.status`.
|
|
220
|
+
|
|
221
|
+
### Get featured video feed
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__video__featured__feed \
|
|
225
|
+
--input '{"method":"GET","params":{}}'
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
For page 2+, pass `"page": "2"` (**string**, not integer). First page should omit the `page` param.
|
|
229
|
+
|
|
230
|
+
## Feed (信息流)
|
|
231
|
+
|
|
232
|
+
### Get home recommend feed
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__home__recommend__feed \
|
|
236
|
+
--input '{"method":"GET","params":{"count":15}}'
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Returns recommended posts from the Weibo homepage feed. For page 2+, pass `"page": "2"` (**string**, not integer). First page should omit `page`.
|
|
240
|
+
|
|
241
|
+
### Get user homepage feed
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
npx xapi-to call weibo-app.api_v1_weibo_app_fetch__user__profile__feed \
|
|
245
|
+
--input '{"method":"GET","params":{"uid":"1669879400"}}'
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Returns the user's profile page feed (UI-oriented). For post data, prefer `fetch_user_timeline`. Paginate with `since_id`.
|
|
249
|
+
|
|
250
|
+
## Common Workflows
|
|
251
|
+
|
|
252
|
+
### Monitor trending topics
|
|
253
|
+
|
|
254
|
+
1. Fetch hot search: `weibo-app.api_v1_weibo_app_fetch__hot__search` with `category: "realtimehot"` → get top 50 topics
|
|
255
|
+
2. Search a topic: `weibo-app.api_v1_weibo_app_fetch__search__all` with `query: "<topic>"` → find relevant posts
|
|
256
|
+
3. Get post details: `weibo-app.api_v1_weibo_app_fetch__status__detail` → read full content and engagement
|
|
257
|
+
|
|
258
|
+
### Research a Weibo user
|
|
259
|
+
|
|
260
|
+
1. Search user: `weibo-app.api_v1_weibo_app_fetch__search__all` with `search_type: 3` and `query: "<name>"` → find uid
|
|
261
|
+
2. Get profile: `weibo-app.api_v1_weibo_app_fetch__user__info` → basic info (followers, bio, verification)
|
|
262
|
+
3. Get timeline: `weibo-app.api_v1_weibo_app_fetch__user__timeline` → recent posts with engagement stats
|
|
263
|
+
4. Get media: `weibo-app.api_v1_weibo_app_fetch__user__album` / `weibo-app.api_v1_weibo_app_fetch__user__videos` → photos and videos
|
|
264
|
+
|
|
265
|
+
### Analyze post engagement
|
|
266
|
+
|
|
267
|
+
1. Get post: `weibo-app.api_v1_weibo_app_fetch__status__detail` → reposts_count, comments_count, attitudes_count
|
|
268
|
+
2. Read comments: `weibo-app.api_v1_weibo_app_fetch__status__comments` with `sort_type: "0"` → top comments
|
|
269
|
+
3. Check reposts: `weibo-app.api_v1_weibo_app_fetch__status__reposts` → who reposted
|
|
270
|
+
4. Check likes: `weibo-app.api_v1_weibo_app_fetch__status__likes` → who liked
|
|
271
|
+
|
|
272
|
+
## API Reference
|
|
273
|
+
|
|
274
|
+
| API | Description | Key Params |
|
|
275
|
+
|-----|-------------|------------|
|
|
276
|
+
| `weibo-app.api_v1_weibo_app_fetch__hot__search` | Hot search trending list | `category` |
|
|
277
|
+
| `weibo-app.api_v1_weibo_app_fetch__hot__search__categories` | Hot search categories | — |
|
|
278
|
+
| `weibo-app.api_v1_weibo_app_fetch__search__all` | Comprehensive search | `query`, `search_type`, `page` |
|
|
279
|
+
| `weibo-app.api_v1_weibo_app_fetch__ai__smart__search` | AI smart search | `query`, `page` |
|
|
280
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__info` | User basic profile | `uid` |
|
|
281
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__info__detail` | User extended profile | `uid` |
|
|
282
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__timeline` | User's posts | `uid`, `page` |
|
|
283
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__profile__feed` | User homepage feed | `uid`, `since_id` |
|
|
284
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__articles` | User's articles | `uid`, `since_id` |
|
|
285
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__super__topics` | User's super topics | `uid`, `page` |
|
|
286
|
+
| `weibo-app.api_v1_weibo_app_fetch__status__detail` | Post detail | `status_id` |
|
|
287
|
+
| `weibo-app.api_v1_weibo_app_fetch__status__comments` | Post comments | `status_id`, `sort_type` |
|
|
288
|
+
| `weibo-app.api_v1_weibo_app_fetch__status__reposts` | Post reposts | `status_id`, `max_id` |
|
|
289
|
+
| `weibo-app.api_v1_weibo_app_fetch__status__likes` | Post likes | `status_id`, `attitude_type` |
|
|
290
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__album` | User photos | `uid`, `since_id` |
|
|
291
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__videos` | User videos | `uid`, `since_id` |
|
|
292
|
+
| `weibo-app.api_v1_weibo_app_fetch__user__audios` | User audio | `uid`, `since_id` |
|
|
293
|
+
| `weibo-app.api_v1_weibo_app_fetch__video__detail` | Video detail | `mid` |
|
|
294
|
+
| `weibo-app.api_v1_weibo_app_fetch__video__featured__feed` | Featured videos | `page` |
|
|
295
|
+
| `weibo-app.api_v1_weibo_app_fetch__home__recommend__feed` | Home recommend feed | `count`, `page` |
|
|
296
|
+
|
|
297
|
+
## Error Handling
|
|
298
|
+
|
|
299
|
+
- **422 Validation Error** → Check parameter types and ranges (e.g. `count` must be 1–50)
|
|
300
|
+
- **Empty results** → Verify `uid` or `status_id` is correct; use search to find valid IDs
|
|
301
|
+
- **Pagination** → Use `since_id` (cursor) or `page` depending on the endpoint; check response for next cursor value
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
# WebSocket Gateway Guide
|
|
2
|
+
|
|
3
|
+
Use xAPI's WebSocket Gateway for full-duplex, low-latency sessions such as OpenAI Realtime, streaming speech recognition, bidirectional text-to-speech, simultaneous interpretation, and podcast generation.
|
|
4
|
+
|
|
5
|
+
The WebSocket Gateway shares the public `ai.xapi.to` host with the HTTP AI Gateway, but it is a separate protocol surface. An HTTP request continues to use the AI Gateway; a valid WebSocket Upgrade request is routed to the WebSocket Gateway.
|
|
6
|
+
|
|
7
|
+
## Contents
|
|
8
|
+
|
|
9
|
+
- [Choose the right interface](#choose-the-right-interface)
|
|
10
|
+
- [Public URLs and routing](#public-urls-and-routing)
|
|
11
|
+
- [Authentication](#authentication)
|
|
12
|
+
- [OpenAI Realtime example](#openai-realtime-example)
|
|
13
|
+
- [Browser connections](#browser-connections)
|
|
14
|
+
- [Native protocol endpoints](#native-protocol-endpoints)
|
|
15
|
+
- [Volcengine ASR options](#volcengine-asr-options)
|
|
16
|
+
- [Connection behavior and billing](#connection-behavior-and-billing)
|
|
17
|
+
- [Errors and reconnects](#errors-and-reconnects)
|
|
18
|
+
- [Security](#security)
|
|
19
|
+
|
|
20
|
+
## Choose the right interface
|
|
21
|
+
|
|
22
|
+
Use:
|
|
23
|
+
|
|
24
|
+
- `npx xapi-to call ai.*` for one-off CLI calls with JSON input and output;
|
|
25
|
+
- the HTTP AI Gateway in `guides/ai_gateway.md` for Anthropic/OpenAI-compatible request-response APIs and SSE streaming;
|
|
26
|
+
- the WebSocket Gateway for a persistent, bidirectional session with text, audio, or provider-native binary frames.
|
|
27
|
+
|
|
28
|
+
Do not send a WebSocket request through `npx xapi-to call`. The CLI action envelope (`action_id` / `input`) and HTTP Gateway request bodies do not apply after a WebSocket connection is established.
|
|
29
|
+
|
|
30
|
+
## Public URLs and routing
|
|
31
|
+
|
|
32
|
+
Preferred unified form:
|
|
33
|
+
|
|
34
|
+
```text
|
|
35
|
+
wss://ai.xapi.to/<endpoint-path>
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Current curated production paths include:
|
|
39
|
+
|
|
40
|
+
| Path | Protocol | Typical use |
|
|
41
|
+
|---|---|---|
|
|
42
|
+
| `/v1/realtime` | OpenAI Realtime GA JSON events | Realtime text and voice |
|
|
43
|
+
| `/v1/asr` | Volcengine ASR binary frames | Streaming speech recognition |
|
|
44
|
+
| `/v1/tts` | Doubao bidirectional TTS binary frames | Streaming text-to-speech |
|
|
45
|
+
| `/v1/ast` | Doubao AST v4 protobuf frames | Simultaneous interpretation |
|
|
46
|
+
| `/v1/podcast` | Doubao podcast binary frames | Long-form podcast generation |
|
|
47
|
+
|
|
48
|
+
The catalog is dynamic. Confirm the path and wire protocol shown by the current xAPI service before building against it.
|
|
49
|
+
|
|
50
|
+
The unified host resolves a connection by exact path. A unique active endpoint is selected directly. If several endpoints share `/v1/realtime`, the unified route prefers the native `openai-realtime` endpoint. It does not currently use `?model=` to select another realtime provider.
|
|
51
|
+
|
|
52
|
+
For a specific third-party service, use its service host when provided:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
wss://<service-slug>.p.xapi.to/<endpoint-path>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This avoids shared-path ambiguity and is required when the desired service uses a provider-native protocol that is not selected by the unified path. Console Try-It and review workflows can also address an endpoint exactly with `?endpoint=<endpoint-id>`.
|
|
59
|
+
|
|
60
|
+
## Authentication
|
|
61
|
+
|
|
62
|
+
Use the same xAPI key as the CLI and HTTP Gateway. Server-side clients should send one of these handshake headers:
|
|
63
|
+
|
|
64
|
+
```text
|
|
65
|
+
XAPI-Key: <XAPI_KEY>
|
|
66
|
+
Authorization: Bearer <XAPI_KEY>
|
|
67
|
+
x-api-key: <XAPI_KEY>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Example with `wscat`:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
wscat -c "wss://ai.xapi.to/v1/realtime" \
|
|
74
|
+
-H "XAPI-Key: $XAPI_KEY"
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The Gateway also accepts `?token=<XAPI_KEY>` or `?xapi-key=<XAPI_KEY>` for clients that cannot set headers. Avoid query authentication for long-lived keys: URLs are commonly retained in browser history, access logs, error reports, and monitoring systems.
|
|
78
|
+
|
|
79
|
+
Authentication is checked before the WebSocket upgrade. Invalid handshakes therefore return an HTTP status instead of opening and immediately closing a socket.
|
|
80
|
+
|
|
81
|
+
## OpenAI Realtime example
|
|
82
|
+
|
|
83
|
+
The unified `/v1/realtime` route speaks the OpenAI Realtime GA JSON event protocol. It is native passthrough: send the same events you would send to the upstream Realtime API, but authenticate with the xAPI key.
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
import WebSocket from "ws";
|
|
87
|
+
|
|
88
|
+
const ws = new WebSocket("wss://ai.xapi.to/v1/realtime", {
|
|
89
|
+
headers: { "XAPI-Key": process.env.XAPI_KEY },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
ws.on("message", (raw, isBinary) => {
|
|
93
|
+
if (isBinary) return;
|
|
94
|
+
const event = JSON.parse(raw.toString());
|
|
95
|
+
|
|
96
|
+
if (event.type === "session.created") {
|
|
97
|
+
ws.send(JSON.stringify({
|
|
98
|
+
type: "conversation.item.create",
|
|
99
|
+
item: {
|
|
100
|
+
type: "message",
|
|
101
|
+
role: "user",
|
|
102
|
+
content: [{ type: "input_text", text: "Say hello in one sentence." }],
|
|
103
|
+
},
|
|
104
|
+
}));
|
|
105
|
+
ws.send(JSON.stringify({ type: "response.create" }));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (event.type === "response.done") {
|
|
109
|
+
console.log(event.response);
|
|
110
|
+
ws.close(1000, "done");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (event.type === "error") console.error(event.error);
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Do not send the retired `OpenAI-Beta: realtime=v1` header. Session settings, audio buffers, tool calls, and response events follow the current OpenAI Realtime GA shape.
|
|
118
|
+
|
|
119
|
+
## Browser connections
|
|
120
|
+
|
|
121
|
+
The browser `WebSocket` API cannot set arbitrary handshake headers. The Gateway accepts an xAPI key or temporary token through a subprotocol entry:
|
|
122
|
+
|
|
123
|
+
```javascript
|
|
124
|
+
const temporaryToken = await getTemporaryTokenFromYourBackend();
|
|
125
|
+
const ws = new WebSocket(
|
|
126
|
+
"wss://ai.xapi.to/v1/realtime",
|
|
127
|
+
[`xapi-key.${temporaryToken}`],
|
|
128
|
+
);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Never embed a long-lived xAPI key in frontend JavaScript. Use the authenticated xAPI Console Try-It flow or your backend to obtain a short-lived token, then pass only that token to the browser. The Console's `POST /api/keys/ws-token` flow mints a temporary token for a WebSocket endpoint; it requires a logged-in entity account and an endpoint ID, and is not authenticated with a normal xAPI key.
|
|
132
|
+
|
|
133
|
+
If a browser integration must use `?token=`, use only a short-lived token and avoid logging the complete URL.
|
|
134
|
+
|
|
135
|
+
## Native protocol endpoints
|
|
136
|
+
|
|
137
|
+
The Gateway forwards frames without translating the application protocol. The selected adapter extracts usage for billing and observability, but the client still has to speak the endpoint's native wire format.
|
|
138
|
+
|
|
139
|
+
| Adapter | Client frames | Important client requirement |
|
|
140
|
+
|---|---|---|
|
|
141
|
+
| `openai-realtime` | UTF-8 JSON text | Use OpenAI Realtime GA events. |
|
|
142
|
+
| `volcengine-asr` | Binary | Send the Volcengine ASR header/config/audio frame sequence; PCM configuration must match the audio bytes. |
|
|
143
|
+
| `doubao-realtime` | Binary | Use the Doubao end-to-end realtime dialogue protocol through its service host or exact endpoint. |
|
|
144
|
+
| `doubao-tts` | Binary | Use the bidirectional TTS event sequence; audio responses are provider-native frames. |
|
|
145
|
+
| `doubao-ast` | Binary protobuf | Each message follows Doubao AST v4 protobuf framing. |
|
|
146
|
+
| `doubao-podcast` | Binary | Use the Doubao podcast event protocol and complete input metadata. |
|
|
147
|
+
|
|
148
|
+
Do not send JSON copied from the OpenAI Realtime API to a Doubao binary endpoint. The shared `ai.xapi.to` hostname does not imply a shared event schema, and the Gateway does not currently translate OpenAI Realtime events into Doubao events.
|
|
149
|
+
|
|
150
|
+
For binary services, prefer the service's xAPI Try-It client or the provider protocol documentation. `wscat` can prove that a handshake succeeds, but it is not sufficient for a functional ASR, TTS, AST, or podcast test.
|
|
151
|
+
|
|
152
|
+
## Volcengine ASR options
|
|
153
|
+
|
|
154
|
+
The `/v1/asr` adapter exposes these per-session fields in the native config frame's `request` object:
|
|
155
|
+
|
|
156
|
+
| Field | Default | Meaning |
|
|
157
|
+
|---|---:|---|
|
|
158
|
+
| `enable_punc` | `true` | Insert punctuation. |
|
|
159
|
+
| `enable_itn` | `true` | Normalize spoken numbers, dates, and amounts. |
|
|
160
|
+
| `enable_ddc` | `false` | Remove filler words and repeated speech. |
|
|
161
|
+
| `show_utterances` | `false` | Return utterance boundaries and timestamps. |
|
|
162
|
+
| `result_type` | `full` | Use `full` for cumulative text or `single` for incremental fragments. |
|
|
163
|
+
|
|
164
|
+
Audio must be raw PCM, 16-bit, mono, at 16 kHz (default) or 8 kHz. The rate declared in the config frame must exactly match the bytes sent. The ASR `model_name` is fixed by the selected endpoint and is not a caller-selectable option.
|
|
165
|
+
|
|
166
|
+
## Connection behavior and billing
|
|
167
|
+
|
|
168
|
+
- Frames are forwarded as text or binary without changing their order. The maximum accepted WebSocket message payload is currently 4 MiB.
|
|
169
|
+
- The default idle timeout is 120 seconds, but an endpoint can override it. Send valid application traffic and let the WebSocket library answer ping frames automatically.
|
|
170
|
+
- Maximum session duration is endpoint-specific. Reconnect when the application needs a longer conversation.
|
|
171
|
+
- The default per-key limits are 10 concurrent connections and 60 connection attempts per minute; an endpoint can configure lower or higher values.
|
|
172
|
+
- Billing is endpoint-specific: duration, realtime token usage, or input characters. The Gateway can reserve balance at handshake and settles usage when the connection closes.
|
|
173
|
+
- Unlike HTTP AI Gateway routing, a WebSocket session is pinned to one resolved endpoint and upstream. There is no transparent mid-session provider fallback.
|
|
174
|
+
|
|
175
|
+
## Errors and reconnects
|
|
176
|
+
|
|
177
|
+
Handshake failures:
|
|
178
|
+
|
|
179
|
+
| HTTP status | Meaning |
|
|
180
|
+
|---|---|
|
|
181
|
+
| `400` | The selected endpoint is not a valid WebSocket endpoint or its upstream is unavailable by policy. |
|
|
182
|
+
| `401` | API key is missing, invalid, or expired. |
|
|
183
|
+
| `402` | Balance is insufficient for the initial reservation. |
|
|
184
|
+
| `404` | No active endpoint matches the host, path, or explicit endpoint ID. |
|
|
185
|
+
| `429` | Per-key concurrency or connection-rate limit was exceeded. |
|
|
186
|
+
|
|
187
|
+
After upgrade, important close codes include:
|
|
188
|
+
|
|
189
|
+
| Close code | Meaning |
|
|
190
|
+
|---|---|
|
|
191
|
+
| `1000` | Normal close, idle timeout, or configured maximum duration. |
|
|
192
|
+
| `1001` | Gateway is updating or draining; reconnect after a delay. |
|
|
193
|
+
| `1011` | Upstream connection, timeout, backpressure, or internal gateway failure. |
|
|
194
|
+
| `4401` | The key expired or was revoked while the session was open. |
|
|
195
|
+
| `4402` | Available balance was exhausted during the session. |
|
|
196
|
+
|
|
197
|
+
Reconnect only for recoverable conditions such as `1001`, transient `1011`, or a failed handshake caused by rate limiting. Use exponential backoff with jitter, cap the delay, and stop retrying on authentication, balance, or endpoint errors until the underlying problem is corrected. Recreate session state after reconnect; the Gateway does not resume prior provider sessions.
|
|
198
|
+
|
|
199
|
+
Use a real WebSocket client to test connectivity. A hand-written `curl` Upgrade request can be changed by an intermediary and produce a misleading HTTP response.
|
|
200
|
+
|
|
201
|
+
## Security
|
|
202
|
+
|
|
203
|
+
- Send xAPI credentials only to `*.xapi.to` hosts.
|
|
204
|
+
- Prefer handshake headers for server-side clients and short-lived tokens for browsers.
|
|
205
|
+
- Never put a long-lived key in source code, frontend bundles, query strings, screenshots, or logs.
|
|
206
|
+
- Treat endpoint-specific audio, transcripts, prompts, and generated media as sensitive application data.
|