Episode Management
Manage podcast episodes, transcripts, and generated content.
List Episodes
Retrieve all episodes with metadata and guest information.
curl https://production.youvebeenheard.com/api/sanity/episodes \
-H "Cookie: auth_token=<token>"
Response
[
{
"_id": "episode_abc123",
"_type": "episodeContent",
"_rev": "v1",
"transcript": "...",
"prf": "...",
"viralHooks": "...",
"metadata": {
"title": "Episode 385: Chris Pacifico on IT Leadership",
"guestName": "Chris Pacifico",
"guestLinkedinUrl": "https://www.linkedin.com/in/chris-pacifico/",
"episodeNumber": 385,
"topics": ["IT Leadership", "Vendor Management"],
"summary": "Chris discusses modern IT leadership challenges"
},
"releaseDate": "2024-03-15",
"socialPosts": {
"linkedin": ["Post 1", "Post 2"],
"instagram": [],
"twitter": []
},
"generatedAssets": [],
"assets": [],
"videoAssets": [],
"visualSuggestions": [],
"scheduledPosts": [],
"status": "complete",
"isApproved": false,
"prfApproved": true,
"prfApprovedAt": "2024-03-10T10:30:00Z",
"hooksApproved": true,
"hooksApprovedAt": "2024-03-10T11:00:00Z",
"linkedinApproved": false,
"shareToken": "abc123xyz",
"shareCreatedAt": "2024-03-10T09:00:00Z",
"galleryUuid": "gallery_xyz",
"createdAt": "2024-03-10T08:00:00Z",
"updatedAt": "2024-03-15T14:30:00Z",
"guestRef": {
"_type": "reference",
"_ref": "guest_123"
},
"guest": {
"_id": "guest_123",
"name": "Chris Pacifico",
"linkedinUrl": "https://www.linkedin.com/in/chris-pacifico/",
"position": "CIO",
"company": "TechCorp"
}
}
]
Array of episode objects, ordered by updatedAt descending
Get Episode
Retrieve a single episode by ID.
GET /api/sanity/episodes/:id
curl https://production.youvebeenheard.com/api/sanity/episodes/episode_abc123 \
-H "Cookie: auth_token=<token>"
Response
{
"_id": "episode_abc123",
"transcript": "Full transcript text...",
"prf": "PRF document...",
"viralHooks": "<h2>Hook 1</h2>...",
"metadata": {
"title": "Episode 385",
"guestName": "Chris Pacifico",
"episodeNumber": 385
},
"guest": {
"_id": "guest_123",
"name": "Chris Pacifico"
}
}
Error Responses
| Status | Error | Description |
|---|
400 | Episode ID is required | Missing ID parameter |
404 | Episode not found | Episode does not exist |
401 | Unauthorized | Not authenticated |
Create Episode
Create a new episode with optional transcript and guest reference.
POST /api/sanity/episodes
curl -X POST https://production.youvebeenheard.com/api/sanity/episodes \
-H "Content-Type: application/json" \
-H "Cookie: auth_token=<token>" \
-d '{
"transcript": "385-Chris Pacifico\nGuest: Chris Pacifico\n...",
"guestId": "guest_123",
"metadata": {
"title": "Episode 385",
"episodeNumber": 385
}
}'
Request
Episode transcript. If provided, metadata will be parsed from header.
Guest ID to link to episode. Guest data will pre-fill metadata.
Episode metadata (optional if guest provided)
Guest LinkedIn profile URL
Episode number (automatically coerced to integer)
Response
{
"_id": "episode_new123",
"_type": "episodeContent",
"transcript": "...",
"metadata": {
"title": "Episode 385",
"guestName": "Chris Pacifico",
"episodeNumber": 385,
"topics": [],
"summary": ""
},
"guestRef": {
"_type": "reference",
"_ref": "guest_123"
},
"status": "draft",
"isApproved": false,
"socialPosts": {
"linkedin": [],
"instagram": [],
"twitter": []
},
"createdAt": "2024-03-15T10:00:00Z",
"updatedAt": "2024-03-15T10:00:00Z"
}
Transcript Parsing: If a transcript is provided, the API automatically extracts metadata from the header (episode number, guest name, LinkedIn URL).
Error Responses
| Status | Error | Description |
|---|
400 | Invalid JSON | Request body is not valid JSON |
400 | Transcript too large | Transcript exceeds 5MB limit |
401 | Unauthorized | Not authenticated |
500 | Server configuration error | Missing SANITY_API_TOKEN |
Update Episode
Update episode fields. Only provided fields are updated.
PATCH /api/sanity/episodes/:id
curl -X PATCH https://production.youvebeenheard.com/api/sanity/episodes/episode_abc123 \
-H "Content-Type: application/json" \
-H "Cookie: auth_token=<token>" \
-d '{
"prf": "Updated PRF content...",
"prfApproved": true,
"prfApprovedAt": "2024-03-15T10:30:00Z"
}'
Request Fields
All fields are optional. Only include fields you want to update:
PRF (Podcast Repurposing Framework) document
Release date (YYYY-MM-DD format)
Episode metadata (see Create Episode for fields)
Metadata for Sanity podcast episode pageShow sanityPageMetadata fields
Short description (1-2 sentences)
Key takeaways (exactly 3)
Social media postsShow socialPosts structure
Episode status: draft, in_progress, or complete
Viral hooks approval status
LinkedIn posts approval status
Generated image assets (unified asset storage)
Response
Returns the updated episode object (same structure as Get Episode).
Delete Episode
Delete an episode and remove references from linked guests.
DELETE /api/sanity/episodes/:id
curl -X DELETE https://production.youvebeenheard.com/api/sanity/episodes/episode_abc123 \
-H "Cookie: auth_token=<token>"
Response
{
"success": true,
"id": "episode_abc123",
"removedFromGuests": 1
}
Number of guest records updated to remove episode reference
Permanent Deletion: This action cannot be undone. The episode and all associated data will be permanently removed.
Episode Status Workflow
Episodes progress through these statuses:
| Status | Description |
|---|
draft | Episode created, no content generated |
in_progress | PRF or hooks being generated |
complete | All content generated and approved |
Approval Flags
Each content type has independent approval:
prfApproved / prfApprovedAt - PRF document
hooksApproved / hooksApprovedAt - Viral hooks
linkedinApproved / linkedinApprovedAt - LinkedIn posts
isApproved - Overall episode approval
Approval timestamps are ISO 8601 strings:
{
"prfApproved": true,
"prfApprovedAt": "2024-03-15T10:30:00Z"
}