API Reference
The sayer API uses NIP-98 HTTP authentication. Every request must include a signed Nostr event in the Authorization header. Paid jobs require a Lightning invoice to be settled before processing begins.
Authentication
All API endpoints require NIP-98 authentication. Create a kind 27235 Nostr event with u and method tags, sign it, base64-encode the JSON, and send it as a Bearer-style header.
Authorization: Nostr <base64-encoded-signed-event>The event timestamp must be within 60 seconds of server time. Your pubkey must be in the server's allowlist.
/v1/pricingReturns the current pricing configuration. In paid mode, the price is calculated per chunk of words.
Response
{
"free_mode": false,
"unit": "words",
"price_per_chunk": 79,
"chunk_size": 50
}/v1/voicesLists all available TTS voices. Voices with embeddings are cloned from uploaded samples.
Response
{
"voices": [
{ "name": "alice", "has_embedding": true },
{ "name": "default", "has_embedding": false }
]
}/v1/jobsSubmit text for synthesis. In paid mode, a Lightning invoice is returned and must be paid before the job begins processing. Admin pubkeys bypass payment entirely.
Request body
{
"text": "The text to synthesize.",
"voice": "alice",
"speed": 1.0,
"language": "en",
"format": "mp3"
}Only text and voice are required. Other fields are optional.
Response (paid mode)
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "awaiting_payment",
"voice": "alice",
"invoice": "lnbc...",
"amount_sats": 79,
"created_at": "2025-01-15T10:30:00Z"
}Response (free mode / admin)
{
"job_id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"voice": "alice",
"created_at": "2025-01-15T10:30:00Z"
}/v1/jobsLists all jobs belonging to the authenticated pubkey.
Response
{
"jobs": [
{
"id": "550e8400-...",
"status": "completed",
"created_at": "2025-01-15T10:30:00Z",
"completed_at": "2025-01-15T10:31:00Z",
"result_url": "https://sayer.nostr.xyz/v1/jobs/550e8400-.../result"
}
]
}/v1/jobs/:job_idReturns the current state of a job. Poll this endpoint to track progress. If the job is awaiting payment and the invoice has been settled, the server automatically advances the job to processing.
Job statuses
/v1/jobs/:job_id/resultDownloads the synthesized audio file. Only available for completed jobs. Returns the audio stream with the appropriate Content-Type header (typically audio/mpeg).
Returns 409 Conflict when the job is not yet completed.
/healthHealth check endpoint. Requires authentication.
Response
{ "status": "ok" }