{
  "info": {
    "name": "VowelMarks Developer API v1",
    "description": "Server-side examples for the VowelMarks Persian reading API. Generation JSON bodies are limited to 32 KiB and 6,000 Unicode code points. Some origins sleep while idle, so a first request can take several extra seconds. Retry an uncertain timeout with the same Idempotency-Key and exact body. Basic asynchronous jobs, Basic MP3 events, and completed-audio HEAD/range requests are available in production. Premium asynchronous jobs remain a development/staging preview and return non-retryable 503 premium_speech_jobs_unavailable in production; synchronous Premium remains available at POST /v1/speech. The current staging Premium experiment buffers and checkpoints provider sections, emits status but no audio events before completion, and publishes one finished WAV. Poll the accepted job. Its approximately 150-second target and estimated 180-second section-planning ceiling are not guaranteed audio-duration limits.",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "variable": [
    { "key": "base_url", "value": "https://api.vowelmarks.com" },
    { "key": "api_key", "value": "vm_test_replace_me" },
    { "key": "job_id", "value": "replace-with-speech-job-id" },
    { "key": "audio_url", "value": "paste-the-complete-signed-audio-url" }
  ],
  "auth": { "type": "bearer", "bearer": [{ "key": "token", "value": "{{api_key}}", "type": "string" }] },
  "item": [
    { "name": "Diacritize", "request": { "method": "POST", "header": [{ "key": "Content-Type", "value": "application/json" }, { "key": "Idempotency-Key", "value": "postman-diacritize-001" }], "body": { "mode": "raw", "raw": "{\n  \"text\": \"من فارسی می‌خوانم\",\n  \"include_ezafe\": true\n}" }, "url": "{{base_url}}/v1/diacritize" } },
    { "name": "Pinglish", "request": { "method": "POST", "header": [{ "key": "Content-Type", "value": "application/json" }], "body": { "mode": "raw", "raw": "{\n  \"text\": \"من فارسی می‌خوانم\",\n  \"style\": \"readable\"\n}" }, "url": "{{base_url}}/v1/pinglish" } },
    { "name": "Translate", "request": { "method": "POST", "header": [{ "key": "Content-Type", "value": "application/json" }], "body": { "mode": "raw", "raw": "{\n  \"text\": \"من فارسی می‌خوانم\"\n}" }, "url": "{{base_url}}/v1/translate" } },
    { "name": "Basic speech", "request": { "method": "POST", "header": [{ "key": "Content-Type", "value": "application/json" }, { "key": "Idempotency-Key", "value": "postman-speech-001" }], "body": { "mode": "raw", "raw": "{\n  \"text\": \"من فارسی می‌خوانم\",\n  \"tier\": \"basic\",\n  \"voice\": \"kian\"\n}" }, "url": "{{base_url}}/v1/speech" } },
    { "name": "Queue Basic speech job", "request": { "description": "Production Basic job creation. Reuse the same Idempotency-Key and exact body after an uncertain timeout. Premium uses this same published request shape only in development/staging; production returns non-retryable 503 premium_speech_jobs_unavailable before reserving allowance or starting work. The current staging Premium experiment is buffered: submit one client job and poll it for one finished WAV rather than requiring live audio events.", "method": "POST", "header": [{ "key": "Content-Type", "value": "application/json" }, { "key": "Idempotency-Key", "value": "postman-speech-job-001" }], "body": { "mode": "raw", "raw": "{\n  \"text\": \"من فارسی می‌خوانم\",\n  \"tier\": \"basic\",\n  \"voice\": \"kian\"\n}" }, "url": "{{base_url}}/v1/speech/jobs" } },
    { "name": "Read Basic speech job", "request": { "description": "Poll until succeeded, failed, or cancelled. Reading a succeeded job during its 24-hour lifetime returns a fresh one-hour signed audio URL.", "method": "GET", "url": "{{base_url}}/v1/speech/jobs/{{job_id}}" } },
    { "name": "Stream Basic speech job events", "request": { "description": "Production Server-Sent Events with MP3 audio when available. Live chunks currently come only from fresh Kian or Leyla synthesis; legacy voices, cache hits, and fallback completion may produce zero audio events. The current staging Premium buffered experiment also emits no audio events before completion, so treat status-only SSE as normal and poll for the finished WAV. A client disconnect does not cancel the Workflow. EOF is not success; require a complete event or poll terminal status.", "method": "GET", "header": [{ "key": "Accept", "value": "text/event-stream" }], "url": "{{base_url}}/v1/speech/jobs/{{job_id}}/events" } },
    { "name": "Cancel Basic speech job", "request": { "description": "Best effort and idempotent. A completed race remains succeeded and is charged normally.", "method": "POST", "url": "{{base_url}}/v1/speech/jobs/{{job_id}}/cancel" } },
    { "name": "Inspect completed audio", "request": { "description": "Paste the complete signed audio_url returned by speech. No Bearer key is sent.", "auth": { "type": "noauth" }, "method": "HEAD", "url": "{{audio_url}}" } },
    { "name": "Download completed audio range", "request": { "description": "Requests one byte range from the signed completed file. No Bearer key is sent.", "auth": { "type": "noauth" }, "method": "GET", "header": [{ "key": "Range", "value": "bytes=0-1023" }], "url": "{{audio_url}}" } },
    { "name": "Usage", "request": { "method": "GET", "url": "{{base_url}}/v1/usage" } }
  ]
}
