the doors
the voice reads any spotify song in one line. these are every way in and out of it — working, right here. no key needed for anything on this page.
the read
paste a spotify link. the voice answers with one line — the same answer a bot, a notification or a shortcut gets.
the line · what a bot gets
reading…
the call
curl "/api/hermit/read?song=75IQVo8hqI1iwVZyvkN2VT&format=text"the audition
the voice, judging: write one line as if it were on the wall and the distilled profile scores how convincingly it passes — with the tell, what gave you away. the same button sits beside every line being written, on the front door and in the filing sheet. free, six per address per ten minutes.
the call
curl -s -X POST /api/hermit/audition -H 'content-type: application/json' \
-d '{ "text": "this chorus files its taxes early", "songTitle": "Show Me How", "songArtist": "Men I Trust" }'
# → { "score": 0-100, "verdict": "…", "tell": "…" }the mood
a feeling in words in; the moods the wall maps it to and the human lines that match out, each with its record and its writer. the door behind /explore.
the call
curl -s -X POST /api/explore -H 'content-type: application/json' -d '{"query":"leaving a party early"}'free, no key. every line that comes back is a person’s, credited, with its address; the moods are the wall’s own vocabulary, not tags anyone typed.
the paperwork
the read door with the receipt attached. who wrote the line — a person, or the model — what it was made from, how sure the wall is, and whether it came from the cache. for anyone deciding whether to build on the voice.
the call
curl -s -X POST /api/hermit/interpret -H 'content-type: application/json' -d '{"spotifyId":"75IQVo8hqI1iwVZyvkN2VT"}' | jq '{interpretation, source, quality, cached, provenance}'this is the read door with the receipt attached: a human line names its writer and votes, a house line names the model and how many wall lines it leaned on. ?fresh=1 forces a new house read and is the only metered call; without it a cache miss generates once and is cached a day.
the playlist
a whole playlist, one line per song, as one picture. spotify keeps playlist contents from server apps, so this door takes the tracks themselves; a playlist link answers with a note.
the call
/api/hermit/playlist?ids=75IQVo8hqI1iwVZyvkN2VT,0bu0to8kgrXDzWklgZ3BuQ,5vkkhwtKWnGkFu3tagE71D&format=card # drop format for jsonthe embed
any page that speaks oembed — a blog, a forum, a newsletter cms — unfurls a take link into this on its own. every take page carries the discovery tag.
the call
/api/oembed?url=https%3A%2F%2Fphotoprompting.org%2Ft%2Ff9fdc3d9&format=jsonthe filing
the wall takes lines from anywhere — a bot, a script, a shortcut. one line about one element of a spotify song, filed with a key. nothing on this page holds a key; the call is the same from your terminal.
the call
curl -X POST /api/v1/takes \
-H "content-type: application/json" \
-H "x-api-key: <your key>" \
-d '{ "spotifyId": "75IQVo8hqI1iwVZyvkN2VT", "text": "this guy needs a job", "element": "canvas", "author": "you" }'201 { "take": { "id", "short", "url", "text", "element",
"song": { "spotify_id", "title", "artist" } } }
200 the same shape with "deduped": true when the line is already therethe two human doors: the discord bot — /take link: line: part: in any server that has the bot — and the composer on the wall: file a line on this record →
filed on this record
asking the wall…
the call
curl "/api/v1/takes?song=75IQVo8hqI1iwVZyvkN2VT"the voice
everything filed here distills, weekly, into a house voice. this is it, in three doors: the profile it distilled, the prose it writes — the longer register, free — and the licensed door that sells that register with a version pin and a provenance stamp. nothing generated ever goes on the wall.
the profile, as a call
curl -s /api/hermit/voice-profile | jq '{week_epoch, corpus_size, moves: .profile.moves}'the prose · the voice’s longer register · free, eight a day per address
the prose, as a call
curl -s -X POST /api/hermit/prose -H 'content-type: application/json' -d '{"form":"review","topic":"a folding chair","length":"short"}' | jq -r .prosethe licensed voice · POST /api/v1/voice · x-api-key
the same register, metered by the key’s daily quota and then by credits, every answer stamped with voice.version and corpus_takes, and best: true for three drafts and a judge. pin a version and the door answers 409 before anything is charged when the voice re-distills. outputs are yours commercially; the corpus and the voice are not.
the licensed door, as a call
curl -s -X POST /api/v1/voice -H "x-api-key: pp_…" -H 'content-type: application/json' -d '{"prompt":"a folding chair","form":"review","length":"short"}' | jq '{text, version: .voice.version, corpus: .voice.corpus_takes, usage}'the same voice, inside an assistant
one address for claude, chatgpt, cursor and claude code — seven tools, one sign-in screen, and the rule the server states on connect: quote a line exactly and name its writer. the three-step setup →
the mcp door, as a call
claude mcp add --transport http photoprompting /api/mcpthe till
every way to pay, through one door — and none of it needs a form here. a key for the api, credits past the daily quota, a read from the desk, a tip on any line. the buyer is sent to stripe and comes back to a receipt; keys are shown there once.
- $10
100 credits · credits-100
100 fresh reads past the daily quota
- $50
600 credits · credits-600
600 fresh reads · 20% bonus
- $100
1500 credits · credits-1500
1500 fresh reads · 50% bonus
- $29
starter key · key-starter
an api key · 100 fresh reads a day · no expiry
- $99
pro key · key-pro
an api key · 350 fresh reads a day · no expiry
- $25
the desk · a single · desk-single
one line about your release, written first, published on payment
- $75
the desk · an EP · desk-ep
three reads, one per track
- $199
the desk · album press kit · desk-kit
every track read + printed broadsides from the press
a tip for the writer · tip
from $2, on any take — the ♡ under every line on the wall goes here.
/api/till/go?sku=tip&amount=500&take=<id>
the call
curl -X POST /api/till/checkout \
-H "content-type: application/json" \
-d '{ "sku": "key-starter" }' # → { "url": "https://checkout.stripe.com/…" }plain links work too: /api/till/go?sku=credits-100 · the catalog with prices is /api/till
the recipes
six things people have built on these doors, each a single file you can run tonight. every one is plain fetch against the calls above — no library, no account beyond a key where it files.
the journal that asks first journal.mjs ↗
give it a song; the house reads it first; you answer with one line; it is filed under your name. once a day and a diary accumulates.
run it
curl -sO /examples/journal.mjs && PP_KEY=pp_… PP_NAME="you" node journal.mjs https://open.spotify.com/track/75IQVo8hqI1iwVZyvkN2VTthe private game game.mjs ↗
five rounds from your own group’s records — a line, four songs, which one is it. --print makes rounds you can paste into a chat.
run it
curl -sO /examples/game.mjs && node game.mjs 75IQVo8hqI1iwVZyvkN2VT 0bu0to8kgrXDzWklgZ3BuQ 5vkkhwtKWnGkFu3tagE71D 1byxxkw33SsLEYNRKdmaOQpassphrases you remember passphrase.mjs ↗
reads the lines on songs you name and mints long passphrases from their strangest words. it only reads public lines; nothing you type goes anywhere.
run it
curl -sO /examples/passphrase.mjs && node passphrase.mjs 75IQVo8hqI1iwVZyvkN2VT 0bu0to8kgrXDzWklgZ3BuQ 1byxxkw33SsLEYNRKdmaOQthe office speaker nowplaying.sh ↗
one deadpan line in slack for whatever is playing. eight lines of shell around the read call in text format.
run it
curl -sO /examples/nowplaying.sh && SLACK_WEBHOOK=https://hooks.slack.com/services/… bash nowplaying.sh 75IQVo8hqI1iwVZyvkN2VTthe record beside the photograph photos.mjs ↗
photography: a folder of pictures becomes print-ready wall labels — each photo paired with the record people wrote about that mood, one line, and a qr that plays the 30 seconds at the frame. the photographs never leave your machine.
run it
curl -sO /examples/photos.mjs && node photos.mjs ./shots # → shots/wall.html, open it, press printthe footer footer.html ↗
end a newsletter or a page with one take as a card. swap the eight characters for any take on the wall.
run it
curl -s /examples/footer.htmlninety-four more — alarms, classrooms, kiosks, agents, print, and four that walk the whole house — each with the exact call, on the recipes →
the pattern under all six: read (the house's line, with the 30 seconds), list (every line on a record), file (your line, with a key). anything that can hold those three is a new way to use the wall — a shortcut, a bot, a cron, a kiosk, a card in an email.
the wire
today’s crown — what the wire posts at 13:00 utc (9am et) to bluesky, mastodon and threads, by itself. this exact picture: the card, the record, the line, the door.
2026-09-28 · that's me · on Eggshell Tap Dancer — The All-American Rejects
@photoprompting.bsky.social · @[email protected] · @photoprompting (threads)
the call
/api/hermit/card?take=19c44844the day
the site has a clock. one record is crowned a day and two lines fight on one record; both are doors, and the qr draws the way to either.
today’s record
reading…
today’s battle
reading…
the day, as three calls
curl -s /api/daily-song | jq '{date, song: .song.title, top: .topTake.text}'
curl -s /api/battles/today | jq '.battle | {a: .take_a.text, b: .take_b.text, votes: [.votes_a, .votes_b]}'
curl -s "/api/qr?text=/s/<spotify id>" -o today.svgthe song pages
every record the voice has read has a page of its own: the lines filed on it, the voice’s read, the 30 seconds, the doors. they are the address a search engine finds first, and the sitemap lists all of them — 594 records and counting.
the call
/s/75IQVo8hqI1iwVZyvkN2VT