# pod.place

> An open standard

A shared lexicon for podcast publishing on the atmosphere. pod.place provides a
common language for shows, episodes, and subscriptions — so podcast content is
easier to discover, index, and move across any player.

- **Read the specification:** https://pod.place/schemas
- **Get involved on Bluesky:** https://bsky.app/profile/pod.place

---

## Why pod.place

pod.place is an attempt to create a portable, open standard for podcast metadata —
so show metadata, episodes, and other information don't need to be duplicated and
can travel with the creator.

- **01 — One schema, many surfaces.** Indexers, apps, and directories all read from
  the same record format. No custom parsers per platform.
- **02 — Creator-owned data.** Switch hosts without re-uploading your catalog. Your
  show history and subscriber graph stay in your repository.
- **03 — Open and extensible.** Core fields are required. Everything else is
  optional. Anyone can propose additions. Add metadata as your product grows;
  well-implemented changes get adopted by the ecosystem.

---

## The core lexicons

Three core lexicons define how podcast shows, episodes, and subscriptions are
represented on AT Protocol. Each schema is designed to be minimal, extensible, and
implementation-agnostic.

| Lexicon                  | Name         | Description                                           |
| ------------------------ | ------------ | ----------------------------------------------------- |
| `place.pod.show`         | Channel      | A podcast show or channel.                            |
| `place.pod.episode`      | Episode      | A single podcast episode.                             |
| `place.pod.subscription` | Subscription | A listener subscribing to a show.                     |
| `.well-known`            | Verification | Link domains back to records with a well-known route. |

### Getting started

To build on pod.place, you need three things: a way to write AT Protocol records
into user repositories, a way to read and index them, and an understanding of the
three core lexicons below.

Start by implementing the **Channel** schema for creating shows, then add
**Episode** records that reference them. Use **Subscription** to let users follow
shows they care about.

Most fields are optional. You can adopt the standard incrementally: start with
required fields, then add optional metadata as your product needs it.

### Reference implementation

For a working example of how to read and write these records, see the reference
implementation at <https://pds.ls>. It demonstrates creating show and episode
records, subscribing to channels, and resolving verification endpoints in a
real-world application context.

---

## Verification

pod.place records point to domain names and webpages. We need a way for those to
point back to the record. This is done through a `.well-known` route for shows.

### Show — `place.pod.show`

Add a `/.well-known/place.pod.show` endpoint to your show's domain. The response
should be the AT-URI of your show record.

This confirms the link between the web presence and the atproto record, improving
discovery and preventing impersonation.

**Request:**

```
https://example.show/.well-known/place.pod.show
```

**Response:**

```
at://did:plc:abc123/place.pod.show/rkey
```

### Episode — `place.pod.episode`

Add a `<link>` tag in the episode page's `<head>` that references its AT-URI.

```html
<link
  rel="place.pod.episode"
  href="at://did:plc:xyz789/place.pod.episode/rkey"
/>
```

---

## Adoption

Being implemented by:

- **Maincasts** — <https://maincasts.com>
- More soon…

Building a podcast app or platform? The standard is open for collaboration. Reach
out on Bluesky to discuss implementation and help shape the spec.

---

## Questions

Common questions about pod.place, its governance, and implementation. If something
is missing, ask us on Bluesky.

**How do I implement this?**

Start by creating records using the place.pod.show and place.pod.episode lexicons
in your users' PDS repositories. You can use the @atproto/api SDK to read and write
records. Index the records for fast queries, or use an existing AppView if one is
available. Reach out on Bluesky if you need guidance.

**Can I extend the lexicons?**

Yes — within your own namespace. Keep the core pod.place fields as-is for
compatibility, and use a platform-specific namespace (e.g., com.yourapp.\*) for
features unique to your product. This mirrors how platforms extend standard.site
without forking it.

**Why is content format not specified?**

The lexicons focus on metadata, not audio encoding. Your platform decides whether
to serve MP3, AAC, Opus, or something else. The audioUrl field is just a pointer.
This keeps the standard minimal and universally adoptable.

**Why not just use RSS?**

RSS is great for distribution, but it is pull-only, static, and controlled by the
host. AT Protocol gives us user-owned repositories, real-time subscriptions,
portable social graphs, and a path toward interactive features like comments and
follows that RSS cannot support natively.

**Who maintains pod.place?**

Initiated by @usaa.ma with the goal of becoming a community-maintained standard.
No single person or company controls it. If you are building on AT Protocol and
care about podcast interoperability, you are invited to participate in shaping the
spec.

**Who owns the domain?**

The pod.place domain is held in trust for the community. Its purpose is to serve as
a neutral reference point for the standard — not as a product or company.

**How can I get involved?**

Reach out on Bluesky. Share what you are building. Ask questions. Propose additions
or changes. The standard grows through adoption and real-world use, so the best way
to get involved is to implement it and report back on what works and what does not.

---

# Schemas — Technical Specification

The `place.pod.*` lexicons build on top of existing podcasting standards already in
use across the industry. That means fields and properties required by Apple iTunes
RSS channel define how podcast content is stored and discovered on AT Protocol.

---

## Channel — `place.pod.show`

A podcast show or channel.

### Required properties

| Name          | Type     | Description                                                                                  |
| ------------- | -------- | -------------------------------------------------------------------------------------------- |
| `title`       | string   | The display name of the podcast show. Keep under 100 characters for directory compatibility. |
| `description` | string   | A short summary describing the show's content, format, and purpose.                          |
| `createdAt`   | datetime | ISO 8601 timestamp of when the show record was created.                                      |

### Optional properties

| Name            | Type    | Description                                                                           |
| --------------- | ------- | ------------------------------------------------------------------------------------- |
| `coverImageUrl` | uri     | URL of the show's primary cover artwork. Should be square and at least 1400x1400px.   |
| `language`      | string  | Primary language of the show content, formatted as an IETF language tag (e.g. en-US). |
| `categories`    | array   | List of content categories or genres. Use standard values where possible.             |
| `explicit`      | boolean | Whether the show typically contains explicit content. Defaults to false if omitted.   |
| `website`       | uri     | Official website URL for the show. Should use HTTPS.                                  |
| `author`        | string  | Name of the show's author or primary creator.                                         |
| `ownerName`     | string  | Legal or business owner name. Useful for copyright and licensing.                     |
| `ownerEmail`    | string  | Contact email for the show owner.                                                     |
| `copyright`     | string  | Copyright notice or license identifier.                                               |
| `people`        | array   | List of people involved in the show (hosts, producers, editors, etc.).                |
| `locked`        | boolean | Whether the show record is locked from edits. Defaults to false.                      |
| `episodeType`   | string  | Default episode type for the show. Common values: full, trailer, bonus.               |

### Example

```json
{
  "$type": "place.pod.show",
  "title": "The Future of Podcasting",
  "description": "A weekly show about open standards and decentralized media.",
  "createdAt": "2024-01-15T10:00:00.000Z",
  "language": "en-US",
  "explicit": false,
  "author": "Jane Doe",
  "website": "https://example.com/podcast"
}
```

### Best practices

- Keep title under 100 characters for compatibility with directory listings and mobile displays.
- Use HTTPS for all external URLs (coverImageUrl, website).
- Set explicit accurately to help directories and clients filter content appropriately.
- Cover images should be square and at least 1400x1400px for maximum compatibility.

---

## Episode — `place.pod.episode`

A single podcast episode.

### Required properties

| Name          | Type     | Description                                                              |
| ------------- | -------- | ------------------------------------------------------------------------ |
| `showUri`     | uri      | AT Protocol URI of the parent place.pod.show record.                     |
| `title`       | string   | Title of the episode.                                                    |
| `description` | string   | Summary or show notes for the episode. May contain basic formatting.     |
| `audioUrl`    | uri      | Direct URL to the audio file. Must be publicly accessible and use HTTPS. |
| `createdAt`   | datetime | ISO 8601 timestamp of when the episode record was created.               |

### Optional properties

| Name              | Type     | Description                                                                            |
| ----------------- | -------- | -------------------------------------------------------------------------------------- |
| `audioMimeType`   | string   | MIME type of the audio file. Common values: audio/mpeg, audio/wav, audio/aac.          |
| `audioSizeBytes`  | integer  | File size of the audio asset in bytes. Useful for download progress indicators.        |
| `durationSeconds` | integer  | Length of the episode in whole seconds. Strongly recommended for player UX.            |
| `episodeNumber`   | integer  | Episode number within the season or series.                                            |
| `seasonNumber`    | integer  | Season number the episode belongs to.                                                  |
| `publishedAt`     | datetime | ISO 8601 timestamp when the episode was published. May differ from createdAt.          |
| `explicit`        | boolean  | Whether this specific episode contains explicit content. Defaults to false if omitted. |
| `imageUrl`        | uri      | Episode-specific artwork URL. Falls back to show cover if omitted.                     |
| `transcriptUrl`   | uri      | URL to a transcript file. Improves accessibility and searchability.                    |
| `chaptersUrl`     | uri      | URL to a chapters file. Accepts JSON or WebVTT formats.                                |

### Example

```json
{
  "$type": "place.pod.episode",
  "showUri": "at://did:plc:abc123/place.pod.show/self",
  "title": "Episode 42: Open Standards",
  "description": "We discuss the importance of open protocols in podcasting.",
  "audioUrl": "https://cdn.example.com/ep42.mp3",
  "createdAt": "2024-01-20T08:00:00.000Z",
  "durationSeconds": 3600,
  "audioMimeType": "audio/mpeg",
  "explicit": false
}
```

### Best practices

- Always reference a valid, resolvable showUri. Broken references will cause episodes to be orphaned in directories.
- Include durationSeconds whenever possible. Players rely on this for timeline rendering and resume tracking.
- Provide transcriptUrl when available. Transcripts significantly improve accessibility and search indexing.
- Use consistent audio formats and MIME types across episodes to simplify client implementations.

---

## Subscription — `place.pod.subscription`

A listener subscribing to a show.

### Required properties

| Name           | Type     | Description                                                       |
| -------------- | -------- | ----------------------------------------------------------------- |
| `showUri`      | uri      | AT Protocol URI of the place.pod.show record being subscribed to. |
| `subscribedAt` | datetime | ISO 8601 timestamp of when the subscription was created.          |

### Optional properties

This schema defines no optional properties.

### Example

```json
{
  "$type": "place.pod.subscription",
  "showUri": "at://did:plc:abc123/place.pod.show/self",
  "subscribedAt": "2024-01-21T14:30:00.000Z"
}
```

### Best practices

- Subscription records are user-specific and should respect the user's privacy and block lists.
- Use subscribedAt to determine subscription recency and ordering.
- Clients should handle missing or deleted show records gracefully instead of crashing.

---

_Open standard. No rights reserved._
