What is Antiphony?
Antiphony is MIT-licensed, open infrastructure — and an AT Protocol lexicon — for audio-based call-and-response applications. These are apps where someone publishes an audio prompt (the call) and an audience records audio replies (the response). Antiphony handles identity, the post → reply data model, audio upload and playback, machine transcription, and a public HTTP API, so you can build the app on top instead of rebuilding the plumbing.
It’s the kind of backend that sits behind a podcaster’s audience-questions feature, a “leave a voice note” embed, an audio AMA, a call-in show’s voicemail wall, or any surface built on the same call-and-response shape. Vox Pop is one such app, built on Antiphony; this repo also ships a minimal one you can read and run (apps/reference).
The one record at the center
Section titled “The one record at the center”Antiphony has a single canonical content record: dev.antiphony.audio.post. A post without a reply is a prompt (the root of a thread); a post with a reply is a reply. The audio rides in a dev.antiphony.embed.audio attachment; the machine transcript is platform enrichment lifted into the view at read time, never stored on the post itself. That one record, mirrored on app.bsky.feed.post’s field structure, is what makes the data portable and legible to AT Protocol tooling.
What’s in the open core
Section titled “What’s in the open core”- Hono HTTP service at
apps/core-api/— the/api/v1/*JSON API surface. - Service bindings at
packages/core/— pure TypeScript services (PostService,AudioService,ActorService,FeedService, …) with pluggable dependency interfaces. Swap in your own backend without touching the route layer. - Shared types and Zod schemas at
packages/shared/— records, views, and request codecs. The same schemas validate the wire format, generate the API reference, and mirror the lexicons. - Lexicons at
lexicons/dev/antiphony/— the portable AT Protocol record definitions.
What’s intentionally not in the open core
Section titled “What’s intentionally not in the open core”The core stops at the infrastructure boundary. Anything that’s a product or UX decision rather than shared plumbing — how an app distributes an embed, whether it offers telephony, how it handles teams or billing, which sign-in methods it accepts before someone can reply — belongs to the app, not the core. The core stays unopinionated so different apps can make those calls differently.
The protocol has no “organization” primitive, either: grouping people into teams is product machinery an app layers on top. The core treats any orgId it sees as an opaque scoping key, nothing more. The tenancy boundary the core does enforce is the origin app (originAppId) — see multi-tenancy.
Who is this for?
Section titled “Who is this for?”- Self-hosters who want a ready-made audio call-and-response backend instead of building one.
- App builders putting their own surface — mobile app, embed, bot, static site — on top of the public API or the lexicons.
- Contributors who want to extend the API surface, evolve the lexicons, or help generalize the backend beyond Firebase.
Where next?
Section titled “Where next?”- New to the project? Read the architecture overview.
- Want the contract? The Antiphony lexicons.
- Want to run it locally? Quick start.
- Building your own surface on the core? Build your own app.
- Building against the API? API reference.