Schnellstart
1 · Prüfen Sie Ihren Schlüssel
Der erste Aufruf kostet nichts, ändert nichts und sagt Ihnen, was Ihr Schlüssel darf und wie viel davon Sie verbraucht haben. Antwortet er mit 200, steht Ihnen alles Weitere in diesem Dokument offen.
curl https://api.xsignalfeed.com/v1/account \ -H "Authorization: Bearer xsf_your_key"
import httpx r = httpx.get("https://api.xsignalfeed.com/v1/account", headers={"Authorization": "Bearer xsf_your_key"}) print(r.json())
const r = await fetch("https://api.xsignalfeed.com/v1/account", { headers: { Authorization: "Bearer xsf_your_key" } }); console.log(await r.json());
req, _ := http.NewRequest("GET", "https://api.xsignalfeed.com/v1/account", nil) req.Header.Set("Authorization", "Bearer xsf_your_key") res, err := http.DefaultClient.Do(req)
{
"name": "acme-trading",
"plan": "pro",
"key_id": "3f9a1c2b7d4e",
"scopes": [
"targets:read",
"targets:write",
"stream",
"replay",
"reads",
"webhook",
"keywords:read",
"keywords:write"
],
"event_types": [],
"event_types_all": true,
"limits": {
"max_targets": 200,
"max_conns": 5,
"max_keywords": 20,
"requests_per_minute": 600
},
"usage": {
"targets": 12,
"keywords": 3
}
}2 · Ein Konto überwachen
Benennen Sie das Konto per Handle, ohne das @. Haben wir es noch nie gesehen, lösen wir es gegen X auf und aktivieren die Zustellung – das dauert unter einer Minute und braucht nichts von Ihnen. Die Antwort sagt Ihnen, welcher der beiden Fälle eingetreten ist.
curl -X POST https://api.xsignalfeed.com/v1/monitor/targets \ -H "Authorization: Bearer xsf_your_key" -H "Content-Type: application/json" \ -d '{"screen_name": "elonmusk", "event_types": ["followers.verified.add"]}'
{
"status": "subscribed",
"state": "subscribed",
"id": "44196397",
"screen_name": "elonmusk",
"name": "Elon Musk",
"event_types": [
"followers.verified.add"
],
"event_types_all": false
}
{
"status": "queued",
"state": "queued",
"screen_name": "newaccount",
"user_id": null,
"event_types": [],
"event_types_all": true,
"note": "target will be resolved and placed shortly; poll GET /v1/monitor/targets/{screen_name}"
}Ein Konto, das wir bereits kennen, wird sofort abonniert (201; 200, wenn Sie es schon abonniert hatten). Ein nie gesehenes Konto ergibt 202: Prüfen Sie GET /v1/monitor/targets/{target}, bis state gleich subscribed ist, oder lesen Sie eine 404, deren details.state gleich failed ist und deren details.reason den Grund nennt: user_not_found, user_suspended oder user_protected. Hat X uns das in den letzten zehn Minuten mitgeteilt, antwortet bereits der POST selbst mit dieser 404. Standardmäßig wird jeder Ereignistyp zugestellt, den Ihr Schlüssel erlaubt; senden Sie event_types, um nur einige zu erhalten, etwa nur followers.verified.add (so geht’s). Viele auf einmal? Nutzen Sie den Batch-Endpunkt.
3 · Den Stream öffnen
Verbinden Sie sich, und die Ereignisse kommen als einzeilige JSON-Objekte an. Mehr ist nicht nötig – keine Subscribe-Nachricht, keine Channels.
import asyncio, json, websockets async def main(): url = "wss://ws.xsignalfeed.com/v1/stream?api_key=xsf_your_key" async with websockets.connect(url) as ws: async for raw in ws: ev = json.loads(raw) if ev["t"].startswith("system."): continue print(ev["t"], ev["target"]["screen_name"], ev["d"].get("text", "")[:60]) asyncio.run(main())
import WebSocket from "ws"; const ws = new WebSocket("wss://ws.xsignalfeed.com/v1/stream?api_key=xsf_your_key"); ws.on("message", (raw) => { const ev = JSON.parse(raw); if (ev.t.startsWith("system.")) return; console.log(ev.t, ev.target.screen_name, (ev.d.text ?? "").slice(0, 60)); });
c, _, err := websocket.DefaultDialer.Dial("wss://ws.xsignalfeed.com/v1/stream?api_key=xsf_your_key", nil) for { _, raw, err := c.ReadMessage() if err != nil { break } var ev Event json.Unmarshal(raw, &ev) if strings.HasPrefix(ev.T, "system.") { continue } log.Println(ev.T, ev.Target.ScreenName) }
4 · Ihr erstes Ereignis lesen
Der erste Frame ist immer system.hello. Danach kommt das Eigentliche:
{
"v": 1,
"t": "tweet.create",
"op": "create",
"id": "tweet:2097879002992070835",
"ts": 1789012345678,
"sid": "1789012346012-0",
"target": {
"id": "1652541",
"screen_name": "Reuters",
"name": "Reuters"
},
"d": {
"tweet_id": "2097879002992070835",
"kind": "tweet",
"text": "Ash-covered shoes and a president in crisis…",
"lang": "en",
"author": {
"id": "1652541",
"screen_name": "Reuters",
"name": "Reuters",
"bio": "Top and breaking news, pictures and videos from Reuters.",
"avatar": "https://pbs.twimg.com/profile_images/1874154135869616128/nJDmubGJ_normal.jpg",
"banner": "https://pbs.twimg.com/profile_banners/1652541/1573687397",
"followers": 25900000,
"following": 1150,
"tweets": 1080000,
"location": "Around the world",
"url": "https://www.reuters.com",
"verified": true,
"verified_type": "Business",
"protected": false,
"created_at": "2007-03-20T17:46:05Z",
"category": null
},
"reply_to": null,
"retweet_of": null,
"quoted": null,
"media": [
"https://pbs.twimg.com/media/….jpg"
],
"media_items": [
{
"type": "photo",
"url": "https://pbs.twimg.com/media/….jpg",
"expanded_url": "https://x.com/Reuters/status/2097879002992070835/photo/1",
"width": 1200,
"height": 675
}
],
"urls": [
"https://reut.rs/…"
],
"counts": {
"reply": 12,
"rt": 40,
"like": 131,
"quote": 3,
"bookmark": 9
},
"views": 20411,
"url": "https://x.com/Reuters/status/2097879002992070835",
"full": true,
"kind_final": true
}
}