{"openapi":"3.1.0","info":{"title":"GimmeText API","version":"1.0.0","description":"Private speech-to-text. Media is deleted after the job; transcripts are deleted after 30 days."},"servers":[{"url":"/"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"API key: gt_live_<prefix>_<secret>"}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}},"JobStatus":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["queued","running","done","failed"]},"progress":{"type":"number"},"error":{"type":["string","null"]},"duration_seconds":{"type":["number","null"]}}}}},"paths":{"/api/v1/uploads":{"post":{"summary":"Create a signed upload URL","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["content_type","size_bytes"],"properties":{"content_type":{"type":"string","enum":["audio/ogg","audio/mp4","audio/mpeg","audio/wav","audio/x-wav","audio/webm","audio/flac"]},"size_bytes":{"type":"integer","minimum":1,"description":"At most min(plan limit, 50 MB)."}}}}}},"responses":{"201":{"description":"Upload URL created. PUT the file to upload_url with the same Content-Type.","content":{"application/json":{"schema":{"type":"object","properties":{"upload_id":{"type":"string"},"upload_url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan isn't active, or not enough minutes left (free plan: upgrade at gimmetext.com/pricing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"File too large for your plan.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit (free: 10, paid: 60 requests per minute per key) or too many running jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait (rate limit)."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/jobs":{"get":{"summary":"List your jobs, newest first","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}}],"responses":{"200":{"description":"Jobs (no transcript text).","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"duration_seconds":{"type":["number","null"]},"created_at":{"type":"string","format":"date-time"},"completed_at":{"type":["string","null"],"format":"date-time"}}}}}}}}},"400":{"description":"Invalid limit.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan isn't active, or not enough minutes left (free plan: upgrade at gimmetext.com/pricing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit (free: 10, paid: 60 requests per minute per key) or too many running jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait (rate limit)."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"summary":"Start a transcription","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["upload_id","duration_seconds"],"properties":{"upload_id":{"type":"string"},"duration_seconds":{"type":"number","exclusiveMinimum":0,"maximum":86400},"language":{"type":"string","pattern":"^[a-z]{2,3}$"}}}}}},"responses":{"202":{"description":"Job accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"const":"queued"}}}}}},"400":{"description":"Invalid request or upload not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan isn't active, or not enough minutes left (free plan: upgrade at gimmetext.com/pricing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit (free: 10, paid: 60 requests per minute per key) or too many running jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait (rate limit)."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Could not start transcription.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/jobs/{id}":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Job status","responses":{"200":{"description":"Status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobStatus"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan isn't active, or not enough minutes left (free plan: upgrade at gimmetext.com/pricing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Job not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit (free: 10, paid: 60 requests per minute per key) or too many running jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait (rate limit)."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"summary":"Delete a job, its media and transcript","responses":{"204":{"description":"Deleted."},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan isn't active, or not enough minutes left (free plan: upgrade at gimmetext.com/pricing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Job not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit (free: 10, paid: 60 requests per minute per key) or too many running jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait (rate limit)."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"502":{"description":"Delete failed; retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/jobs/{id}/transcript":{"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"get":{"summary":"Get the transcript","parameters":[{"name":"format","in":"query","schema":{"type":"string","enum":["txt","srt","json"],"default":"json"}}],"responses":{"200":{"description":"Transcript.","content":{"text/plain":{"schema":{"type":"string"}},"application/x-subrip":{"schema":{"type":"string"}},"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string"},"srt":{"type":"string"},"language":{"type":["string","null"]},"duration_seconds":{"type":["number","null"]}}}}}},"400":{"description":"Invalid format.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan isn't active, or not enough minutes left (free plan: upgrade at gimmetext.com/pricing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Job not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Transcript not ready.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit (free: 10, paid: 60 requests per minute per key) or too many running jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait (rate limit)."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/usage":{"get":{"summary":"Plan and remaining minutes","responses":{"200":{"description":"Usage.","content":{"application/json":{"schema":{"type":"object","properties":{"plan":{"type":"string"},"remaining_seconds":{"type":"number"},"monthly_seconds":{"type":"integer"},"bonus_seconds":{"type":"integer"},"period_end":{"type":"string","format":"date-time"}}}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Plan isn't active, or not enough minutes left (free plan: upgrade at gimmetext.com/pricing).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Rate limit (free: 10, paid: 60 requests per minute per key) or too many running jobs.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"schema":{"type":"integer"},"description":"Seconds to wait (rate limit)."}}},"500":{"description":"Internal error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}}}