Beta
Manage / Channels

Channels

Manage delivery channels and verification.

Delivery channels carry your briefings: email, telegram, and webhook. (Web push exists in the product but is not addable through the API.)

List channels

GET/manage/channelsapi.daily-tube.com/v1

Complete list, newest first, no pagination. GET /manage/channels/{id} returns one (404 channel.not_found for foreign or unknown ids).

Response

The projection depends on the type — emails are masked, webhooks show the URL:

{
"data": {
"items": [
{
"id": "c91d…",
"type": "email",
"status": "pending_verification",
"added_at": "2026-10-26T10:00:00Z",
"identifier": "a***@example.com",
"stage": "code_sent",
"expires_at": "2026-10-26T11:00:00Z"
}
]
},
"request_id": "5f0c…"
}

status runs pending_verification → active / disabled. Telegram channels carry identifier (@username, once known) and bot_username; pending channels also carry stage and expires_at.

Add a channel

POST/manage/channelsapi.daily-tube.com/v1

Request body

A type discriminator plus a nested object of the same name:

TypeBodyBorn asVerification
email{ "type": "email", "email": { "address": "[email protected]" } }pending_verificationA code arrives by email — submit it with the verify action
telegram{ "type": "telegram", "telegram": {} }pending_verificationThe response carries a verification_code and bot_username — send the code to the bot in Telegram, then reply YES
webhook{ "type": "webhook", "webhook": { "url": "https://…" } }pending_verificationtest action: DailyTube POSTs a sample payload; any 2xx verifies

Request

curl -X POST https://api.daily-tube.com/v1/manage/channels \
-H "Authorization: Bearer dtk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"type":"webhook","webhook":{"url":"https://example.com/hooks/dailytube"}}'

Response

201 with the pending channel. A telegram add returns the fresh verification_code alongside the projection — that code is the caller's own handshake secret; keep it only long enough to send it to the bot. Adding a webhook when one already exists replaces it (a 200 instead of 201).

Webhook URLs must be https, credential-free, and ≤ 2048 characters, and must resolve to a public address — private/reserved ranges and single-label hostnames are rejected (SSRF-guarded).

Channel actions

POST/manage/channels/{id}api.daily-tube.com/v1

Request body

ActionBodyEffectResponse
verify{ "action": "verify", "code": "…" }Email: code is the token from the emailed link — verifies and returns the channel. Telegram: code is the DT-code — accepted codes still return 400 channel.verification_pending with guidance, because the YES-reply happens in Telegram; poll the channel until active. Already-verified channels return their current state200 channel
resend-verification{ "action": "resend-verification" }Email only, once per 5 minutes (429 rate_limit.resend_window with the exact wait); telegram resends aren't gated and return a fresh verification_code202 channel
test{ "action": "test" }Webhook only — POSTs a sample payload (10 s timeout). Any 2xx marks the channel verified and attempts activation200 — { success, status_code, verified }

Response — test

{
"data": { "success": true, "status_code": 200, "verified": true },
"request_id": "5f0c…"
}

Update

PATCH/manage/channels/{id}api.daily-tube.com/v1

One field per call — status (active / disabled) for any type, or url for webhooks (same validation as add):

curl -X PATCH https://api.daily-tube.com/v1/manage/channels/c44f… \
-H "Authorization: Bearer dtk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"active"}'

200 with the updated channel. Status toggling requires a verified channel (400 channel.not_verified); web-push channels aren't patchable through the API.

Delete (reset)

DELETE/manage/channels/{id}api.daily-tube.com/v1

Resets the channel — the row is removed regardless of status (the web app's own reset behavior). 204, no body.

curl -X DELETE https://api.daily-tube.com/v1/manage/channels/c44f… \
-H "Authorization: Bearer dtk_YOUR_KEY"

Errors

Every error returns the same body — code is the stable machine string, message is human: The full registry of every code lives on Errors.

{
"error": { "code": "channel.invalid_url", "message": "Invalid webhook URL" },
"request_id": "5f0c…"
}
CodeStatusWhen
channel.invalid_email / email_in_use400Email add/resend — bad address, or active on another account
channel.invalid_url400Webhook URL rules (https, host, no credentials, ≤2048, SSRF)
channel.invalid_code400Wrong/expired verification code, or nothing pending
channel.verification_pending400Telegram handshake incomplete — finish it in the bot
channel.action_not_supported400e.g. test on a non-webhook channel, verify on a webhook
channel.invalid_status / invalid_transition / not_verified / not_patchable / not_pending400PATCH/action preconditions
channel.type_not_in_plan / limit_reached403Plan gating
channel.webhook_test_failed400Test delivery failed (unreachable / non-2xx / timeout)
channel.not_found404Foreign or unknown channel

Every keyed endpoint on this page shares the per-key budget — Rate limits.