Docs
API and webhook
You pull watches and events with an API key. We push a signed POST when a threshold fires. Two separate surfaces — same account.
API
Public REST under /api/v1. You call us. Create a key in Integrations → API keys. Keys start with spk_.
Auth
The key sees every watch and event on the account. Watches belong to a project; the key does not.
Authorization: Bearer spk_live_...
Create a watch
POST /api/v1/watches
channel accepts a UC id, @handle, or YouTube URL. thresholdViews is 1–999,999,999. windowHours is 1–720 (30 days). projectId is optional — otherwise we use the current dashboard project.
POST /api/v1/watches
Authorization: Bearer spk_live_...
Content-Type: application/json
{
"channel": "https://www.youtube.com/@handle",
"thresholdViews": 3000,
"windowHours": 1,
"projectId": 1
}Response 201:
{
"watch": {
"id": 12,
"userId": 1,
"projectId": 1,
"channelId": 44,
"youtubeChannelId": "UCxxxxxxxxxxxxxxxxxxxxxx",
"channelTitle": "MrBeast",
"channelThumbnailUrl": "https://yt3.googleusercontent.com/…",
"triggerDefinitionId": 3,
"thresholdViews": 3000,
"windowHours": 1,
"status": "active",
"createdAt": "2026-09-02T00:18:11.000Z"
}
}409 if the unique-channel limit is reached ({ "code": "CHANNEL_LIMIT", "channelLimit" }). Extra watches on a channel you already track do not consume the limit. 400 for a bad channel or condition. 403 if the trial or subscription is not live.
List watches
GET /api/v1/watches
Every watch on the account, all projects, newest first.
GET /api/v1/watches
Authorization: Bearer spk_live_...
{
"watches": [
{
"id": 12,
"userId": 1,
"projectId": 1,
"channelId": 44,
"youtubeChannelId": "UCxxxxxxxxxxxxxxxxxxxxxx",
"channelTitle": "MrBeast",
"channelThumbnailUrl": "https://yt3.googleusercontent.com/…",
"triggerDefinitionId": 3,
"thresholdViews": 3000,
"windowHours": 1,
"status": "active",
"createdAt": "2026-09-02T00:18:11.000Z"
}
]
}Get a watch
GET /api/v1/watches/:id
Response { "watch": { ... } }. 404 if the id is not yours.
Delete a watch
DELETE /api/v1/watches/:id
Stops that condition. Past events stay. Response { "ok": true }.
List events
GET /api/v1/events?limit=50
Threshold hits, newest first. limit is 1–100, default 50. Same JSON we POST to a webhook. Events exist even when no endpoint is configured. Delivery status is not on this route — use the dashboard log.
GET /api/v1/events?limit=50
Authorization: Bearer spk_live_...
{
"events": [
{
"id": 1842,
"type": "video.threshold_reached",
"created": "2026-09-02T00:18:11Z",
"data": {
"watchId": 12,
"projectId": 1,
"projectName": "Main",
"channelId": "UCxxxxxxxxxxxxxxxxxxxxxx",
"channelTitle": "MrBeast",
"videoId": "dQw4w9WgXcQ",
"videoTitle": "Why this hook is printing views",
"videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
"publishedAt": "2026-09-01T23:18:00Z",
"viewCount": 3280,
"lastHourAdded": 3210,
"threshold": 3000,
"windowHours": 1
}
}
]
}Example
curl -X POST /api/v1/watches \
-H "Authorization: Bearer spk_live_…" \
-H "Content-Type: application/json" \
-d '{"channel":"@handle","thresholdViews":3000,"windowHours":1}'