# Spoken Agent Instructions

Spoken turns a published podcast episode into a clean Markdown transcript with real speaker names and timestamps. Use it when you need the text of a podcast that has already been published.

Spoken is a transcript retrieval API, not a speech-to-text service. It works on published podcasts only — not on your own audio files. Real speaker names are already in the response, so there are no diarization labels to map afterwards.

## Key Facts

- **Base URL:** `https://spoken.md`
- **Authentication:** `x-api-key` header. Use the free demo key `pt_demo` to fetch the demo episode with no signup.
- **Output:** `text/markdown` with speaker names and timestamps.
- **Private:** transcripts are returned to your request only — Spoken does not publish them to a public library.
- **Credits:** 1 per episode on first fetch. Repeat fetches of the same episode are free, and errors are never charged. `/search` and `/balance` require a key but never deduct credits.

## Recommended Flow

1. Find an episode with `GET /search?q={query or URL}` — returns episode IDs.
2. Fetch the transcript with `GET /transcripts/{id}` — returns Markdown.
3. Check remaining credits any time with `GET /balance`.
4. On a `402`, `POST` to the `top_up_url` in the response to buy more credits.

## Search For An Episode

Search by text, or paste an episode URL from any platform (Spotify, YouTube, etc.).

~~~sh
curl -s 'https://spoken.md/search?q=huberman+sleep' \
  -H 'x-api-key: pt_demo'
~~~

Returns a JSON object `{ "results": [...] }`; each result in the array has `id`, `title`, `podcast`, and `date`. Use the `id` with `/transcripts/{id}`.

## Get A Transcript

~~~sh
curl -s 'https://spoken.md/transcripts/1000651996090' \
  -H 'x-api-key: pt_demo'
~~~

Returns Markdown:

~~~md
**John Smith** (0:00)
Welcome to the show. Today we're talking about...

**Jane Doe** (0:15)
Thanks for having me.
~~~

Response headers:

| Header | Meaning |
| --- | --- |
| `X-Credits-Remaining` | Credits left on this key. |
| `X-Credits-Charged` | `1` on first fetch, `0` for a repeat fetch or the demo episode. |
| `X-Top-Up-Url` | Present when the balance is low (10 or fewer); `POST` to it to top up. |

## Check Balance

~~~sh
curl -s 'https://spoken.md/balance' -H 'x-api-key: pt_your_key'
~~~

Returns current credit balance, account email, top-up links, and recent usage history. Requires a real key — the `pt_demo` key returns `401`.

## Buy Or Top Up Credits

Both endpoints redirect (`302`) to Stripe Checkout.

~~~sh
# New key (new-customer pricing): 100/$15, 500/$50 (?pack=500), 2,000/$160 (?pack=2000)
curl -s -X POST 'https://spoken.md/buy'

# Existing key (returning pricing): 100/$10, 500/$40 (&pack=500), 2,000/$120 (&pack=2000)
curl -s -X POST 'https://spoken.md/top-up?key=pt_your_key'
~~~

The `top_up_url` returned in `402` responses points at `/top-up` — use `POST`, not `GET`.

## Errors

| Status | Meaning | Charged? | Retry? |
| --- | --- | --- | --- |
| `401` | Missing or invalid API key. Response includes `demo_key` and `purchase_url`. | No | No — fix the key. |
| `402` | No credits remaining. Response includes `top_up_url` (`POST` to it). | No | After topping up. |
| `404` | Episode not found or has no transcript. | No | No. |
| `429` | Temporarily throttled under load. | No | Yes — back off and retry. |
| `502` | Upstream error. | No | Yes — safe to retry. |

`401`, `402`, `404`, and `502` return a JSON `{ "error": { "code", "message", ... } }` shape. `429` is a raw service throttle without that shape — treat any `429` as "back off and retry."

## Integration Resources

- OpenAPI spec: `https://spoken.md/.well-known/openapi.json`
- Agent skill: `https://spoken.md/.well-known/skills/spoken-md/SKILL.md`
- MCP server: `npx spoken-mcp` (npm `spoken-mcp`, MCP registry `io.github.spokenmd/spoken`, source `https://github.com/spokenmd/spoken`) — set `SPOKEN_API_KEY`. Tools: `search_podcasts`, `get_transcript`, `get_balance`.
- LLM-friendly overview: `https://spoken.md/llms.txt`
- Machine-readable pricing: `https://spoken.md/pricing.md`
