Feeds are the sources your briefings are built from. The API exposes the full lifecycle across four platforms: YouTube, X (Twitter), Reddit, and TikTok.
## List feeds
```endpoint
GET /manage/feeds
```
Returns every feed on the account, newest added first (complete list — no pagination):
```responses
~~~200 OK
{
"data": {
"items": [
{
"id": "b21e…",
"platform": "youtube",
"name": "Veritasium",
"url": "https://www.youtube.com/@veritasium",
"status": "active",
"added_at": "2026-10-01T10:00:00Z",
"updated_at": "2026-10-20T10:00:00Z"
}
]
},
"request_id": "5f0c…"
}
~~~
```
`status` runs `active` / `disabled`, plus `resolving` while a feed is being resolved. `feed_identifier` and `thumbnail` appear when the platform provides them.
`GET /manage/feeds/{id}` returns one feed (`404 feed.not_found` for foreign or unknown ids).
## Add a feed
```endpoint
POST /manage/feeds
```
### Request body
| Field | Type | Rules |
|---|---|---|
| `url_or_handle` | string | **Required.** 1–500 characters — a full URL or a bare handle |
| `platform` | string | Optional. One of `youtube` / `twitter` / `reddit` / `tiktok`; inferred from the URL when omitted. A bare handle that doesn't reveal its platform needs it explicitly (`400 feed.type_required`) |
### Request
```tabs
~~~curl
curl -X POST https://api.daily-tube.com/v1/manage/feeds \
-H "Authorization: Bearer dtk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url_or_handle":"https://www.youtube.com/@veritasium"}'
~~~
~~~javascript
const res = await fetch("https://api.daily-tube.com/v1/manage/feeds", {
method: "POST",
headers: { Authorization: "Bearer dtk_YOUR_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ url_or_handle: "https://www.youtube.com/@veritasium" }),
});
~~~
~~~python
import urllib.request, json
body = json.dumps({"url_or_handle": "https://www.youtube.com/@veritasium"}).encode()
req = urllib.request.Request(
"https://api.daily-tube.com/v1/manage/feeds",
data=body,
headers={"Authorization": "Bearer dtk_YOUR_KEY", "Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as r:
print(r.status)
~~~
```
### Response
`201` with the created feed. The add **waits for platform resolution** — the response is the resolved feed, and duplicates, plan caps, and platform gates surface inline as errors rather than later.
```responses
~~~201 Created
{
"data": {
"id": "b21e…",
"platform": "youtube",
"name": "Veritasium",
"url": "https://www.youtube.com/@veritasium",
"status": "active",
"added_at": "2026-10-26T10:00:00Z",
"updated_at": "2026-10-26T10:00:00Z"
},
"request_id": "5f0c…"
}
~~~
```
## Update status
```endpoint
PATCH /manage/feeds/{id}
```
### Request body
| Field | Type | Rules |
|---|---|---|
| `status` | enum | **Required.** `active` or `disabled` |
```tabs
~~~curl
curl -X PATCH https://api.daily-tube.com/v1/manage/feeds/b21e… \
-H "Authorization: Bearer dtk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"disabled"}'
~~~
```
`200` with the updated feed. Transitioning out of `resolving` is locked until resolution finishes (`400 feed.invalid_transition`); re-enabling counts against the plan cap (`400 feed.limit_reached`).
## Delete a feed
```endpoint
DELETE /manage/feeds/{id}
```
Removes the feed permanently — `204`, no body. Foreign or unknown ids are a uniform `404 feed.not_found`.
```tabs
~~~curl
curl -X DELETE https://api.daily-tube.com/v1/manage/feeds/b21e… \
-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](/docs/errors).
```responses
~~~400 Bad Request
{
"error": { "code": "feed.limit_reached", "message": "Plan feed limit reached" },
"request_id": "5f0c…"
}
~~~
```
| Code | Status | When |
|---|---|---|
| `feed.missing_params` | 400 | `url_or_handle` absent |
| `feed.invalid_type` / `type_required` | 400 | Unknown platform / not derivable from a bare handle |
| `feed.already_added` | 400 | Duplicate feed |
| `feed.limit_reached` | 400 | Plan feed cap (add or re-enable) |
| `feed.platform_not_in_plan` / `platform_unavailable` | 400 | Platform gating |
| `feed.invalid_status` / `invalid_transition` | 400 | PATCH rules |
| `feed.not_found` | 404 | Foreign or unknown feed |
| `validation.invalid_input` | 400 | `url_or_handle` over 500 characters |
> Every keyed endpoint on this page shares the per-key budget — [Rate limits](/docs/rate-limits).
Feeds
Feeds are the sources your briefings are built from. The API exposes the full lifecycle across four platforms: YouTube, X (Twitter), Reddit, and TikTok.
List feeds
GET /manage/feeds
Returns every feed on the account, newest added first (complete list — no pagination):
~~~200 OK
{
"data": {
"items": [
{
"id": "b21e…",
"platform": "youtube",
"name": "Veritasium",
"url": "https://www.youtube.com/@veritasium",
"status": "active",
"added_at": "2026-10-01T10:00:00Z",
"updated_at": "2026-10-20T10:00:00Z"
}
]
},
"request_id": "5f0c…"
}
~~~
status runs active / disabled, plus resolving while a feed is being resolved. feed_identifier and thumbnail appear when the platform provides them.
GET /manage/feeds/{id} returns one feed (404 feed.not_found for foreign or unknown ids).
Add a feed
POST /manage/feeds
Request body
| Field | Type | Rules |
|---|---|---|
| url_or_handle | string | Required. 1–500 characters — a full URL or a bare handle |
| platform | string | Optional. One of youtube / twitter / reddit / tiktok; inferred from the URL when omitted. A bare handle that doesn't reveal its platform needs it explicitly (400 feed.type_required) |
Request
~~~curl
curl -X POST https://api.daily-tube.com/v1/manage/feeds \
-H "Authorization: Bearer dtk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"url_or_handle":"https://www.youtube.com/@veritasium"}'
~~~
~~~javascript
const res = await fetch("https://api.daily-tube.com/v1/manage/feeds", {
method: "POST",
headers: { Authorization: "Bearer dtk_YOUR_KEY", "Content-Type": "application/json" },
body: JSON.stringify({ url_or_handle: "https://www.youtube.com/@veritasium" }),
});
~~~
~~~python
import urllib.request, json
body = json.dumps({"url_or_handle": "https://www.youtube.com/@veritasium"}).encode()
req = urllib.request.Request(
"https://api.daily-tube.com/v1/manage/feeds",
data=body,
headers={"Authorization": "Bearer dtk_YOUR_KEY", "Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as r:
print(r.status)
~~~
Response
201 with the created feed. The add waits for platform resolution — the response is the resolved feed, and duplicates, plan caps, and platform gates surface inline as errors rather than later.
~~~201 Created
{
"data": {
"id": "b21e…",
"platform": "youtube",
"name": "Veritasium",
"url": "https://www.youtube.com/@veritasium",
"status": "active",
"added_at": "2026-10-26T10:00:00Z",
"updated_at": "2026-10-26T10:00:00Z"
},
"request_id": "5f0c…"
}
~~~
Update status
PATCH /manage/feeds/{id}
Request body
| Field | Type | Rules |
|---|---|---|
| status | enum | Required. active or disabled |
~~~curl
curl -X PATCH https://api.daily-tube.com/v1/manage/feeds/b21e… \
-H "Authorization: Bearer dtk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"disabled"}'
~~~
200 with the updated feed. Transitioning out of resolving is locked until resolution finishes (400 feed.invalid_transition); re-enabling counts against the plan cap (400 feed.limit_reached).
Delete a feed
DELETE /manage/feeds/{id}
Removes the feed permanently — 204, no body. Foreign or unknown ids are a uniform 404 feed.not_found.
~~~curl
curl -X DELETE https://api.daily-tube.com/v1/manage/feeds/b21e… \
-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 (/docs/errors).
~~~400 Bad Request
{
"error": { "code": "feed.limit_reached", "message": "Plan feed limit reached" },
"request_id": "5f0c…"
}
~~~
| Code | Status | When |
|---|---|---|
| feed.missing_params | 400 | url_or_handle absent |
| feed.invalid_type / type_required | 400 | Unknown platform / not derivable from a bare handle |
| feed.already_added | 400 | Duplicate feed |
| feed.limit_reached | 400 | Plan feed cap (add or re-enable) |
| feed.platform_not_in_plan / platform_unavailable | 400 | Platform gating |
| feed.invalid_status / invalid_transition | 400 | PATCH rules |
| feed.not_found | 404 | Foreign or unknown feed |
| validation.invalid_input | 400 | url_or_handle over 500 characters |
Every keyed endpoint on this page shares the per-key budget — Rate limits (/docs/rate-limits).
Feeds are the sources your briefings are built from. The API exposes the full lifecycle across four platforms: YouTube, X (Twitter), Reddit, and TikTok.
List feeds
GET/manage/feedsapi.daily-tube.com/v1
Returns every feed on the account, newest added first (complete list — no pagination):
status runs active / disabled, plus resolving while a feed is being resolved. feed_identifier and thumbnail appear when the platform provides them.
GET /manage/feeds/{id} returns one feed (404 feed.not_found for foreign or unknown ids).
Add a feed
POST/manage/feedsapi.daily-tube.com/v1
Request body
Field
Type
Rules
url_or_handle
string
Required. 1–500 characters — a full URL or a bare handle
platform
string
Optional. One of youtube / twitter / reddit / tiktok; inferred from the URL when omitted. A bare handle that doesn't reveal its platform needs it explicitly (400 feed.type_required)
import urllib.request, json
body = json.dumps({"url_or_handle": "https://www.youtube.com/@veritasium"}).encode()
req = urllib.request.Request(
"https://api.daily-tube.com/v1/manage/feeds",
data=body,
headers={"Authorization": "Bearer dtk_YOUR_KEY", "Content-Type": "application/json"},
)
with urllib.request.urlopen(req) as r:
print(r.status)
import urllib.request, json body = json.dumps({"url_or_handle": "https://www.youtube.com/@veritasium"}).encode() req = urllib.request.Request( "https://api.daily-tube.com/v1/manage/feeds", data=body, headers={"Authorization": "Bearer dtk_YOUR_KEY", "Content-Type": "application/json"}, ) with urllib.request.urlopen(req) as r: print(r.status)
Response
201 with the created feed. The add waits for platform resolution — the response is the resolved feed, and duplicates, plan caps, and platform gates surface inline as errors rather than later.
200 with the updated feed. Transitioning out of resolving is locked until resolution finishes (400 feed.invalid_transition); re-enabling counts against the plan cap (400 feed.limit_reached).
Delete a feed
DELETE/manage/feeds/{id}api.daily-tube.com/v1
Removes the feed permanently — 204, no body. Foreign or unknown ids are a uniform 404 feed.not_found.