{
"id": "org.atpodcasting.episode",
"defs": {
"main": {
"key": "any",
"type": "record",
"record": {
"type": "object",
"required": [
"podcast",
"title",
"media",
"publishedAt",
"duration",
"feedItemGuid",
"updatedAt"
],
"properties": {
"media": {
"ref": "#externalMedia",
"type": "ref",
"description": "The primary media file for the episode."
},
"title": {
"type": "string",
"maxLength": 500,
"description": "The title of the episode."
},
"artwork": {
"type": "blob",
"accept": [
"image/png",
"image/jpeg"
],
"maxSize": 5000000,
"description": "Episode-specific artwork. Overrides the podcast artwork when set. Recommended: 1400x1400 to 3000x3000 pixels, square, no alpha channel."
},
"podcast": {
"ref": "#podcastRef",
"type": "ref",
"description": "Reference to the parent podcast."
},
"duration": {
"type": "integer",
"minimum": 0,
"description": "Duration of the episode in seconds."
},
"updatedAt": {
"type": "string",
"format": "datetime",
"description": "When the episode record was last updated."
},
"transcript": {
"type": "array",
"items": {
"ref": "#transcriptRef",
"type": "ref"
},
"maxLength": 10,
"description": "References to externally hosted transcript files (e.g. VTT, SRT, JSON). Multiple entries allow providing transcripts in different formats."
},
"description": {
"type": "string",
"maxLength": 10000,
"description": "A description or show notes for the episode."
},
"episodeType": {
"type": "string",
"description": "The type of episode. Defaults to full.",
"knownValues": [
"full",
"trailer",
"bonus"
]
},
"publishedAt": {
"type": "string",
"format": "datetime",
"description": "When the episode was published."
},
"feedItemGuid": {
"type": "string",
"maxLength": 2000,
"description": "The original feed item identifier. For syndicated podcasts, this must match the <guid> element of the corresponding RSS feed item. For AT-native implementations, this should be a generated TID. The record key (rkey) is derived from this value as uuid5(<podcast:guid>, feedItemGuid)."
},
"seasonNumber": {
"type": "integer",
"minimum": 1,
"description": "Season number of the episode."
},
"episodeNumber": {
"type": "integer",
"minimum": 1,
"description": "Episode number within its season or the overall series."
},
"alternateMedia": {
"type": "array",
"items": {
"ref": "#externalMedia",
"type": "ref"
},
"maxLength": 10,
"description": "Alternate versions of the episode media (e.g. different formats or audio-only versions of video episodes)."
}
}
},
"description": "A podcast episode. Record key is a UUIDv5 derived from the podcast GUID (as namespace) and the episode's feedItemGuid (as name), enabling deterministic lookup from RSS feed metadata."
},
"podcastRef": {
"type": "object",
"required": [
"uri"
],
"properties": {
"uri": {
"type": "string",
"format": "at-uri",
"description": "AT URI of the podcast record."
}
},
"description": "Weak reference to a podcast (no CID, allows mutation)."
},
"externalMedia": {
"type": "object",
"required": [
"url",
"mimeType"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "URL of the media file."
},
"mimeType": {
"type": "string",
"description": "MIME type of the media file (e.g. audio/mpeg, video/mp4)."
}
},
"description": "Reference to an externally hosted media file."
},
"transcriptRef": {
"type": "object",
"required": [
"url",
"mimeType"
],
"properties": {
"url": {
"type": "string",
"format": "uri",
"description": "URL of the transcript file."
},
"language": {
"type": "string",
"format": "language",
"description": "Language of the transcript (ISO 639-1 two-letter code, e.g. 'en', 'es', 'pt')."
},
"mimeType": {
"type": "string",
"description": "MIME type of the transcript file (e.g. text/vtt, application/srt, application/json)."
}
},
"description": "Reference to an externally hosted transcript file."
}
},
"$type": "com.atproto.lexicon.schema",
"lexicon": 1
}