{"openapi":"3.1.0","info":{"title":"EzTranslate API","version":"1.0.0","description":"Account-owned Hokkien and Manga translation jobs. APIs spend only Plus credits (subscription and purchased credits) from the shared account balance; daily free Basic credits are excluded. See /docs for availability, billing and safe retries."},"servers":[{"url":"https://eztranslate.com.tw"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Hokkien","description":"Chinese text to Taiwanese Hokkien, with optional speech."},{"name":"Manga","description":"Image translation, one durable job per page."}],"paths":{"/api/v1/hokkien/translations":{"post":{"operationId":"createHokkienTranslation","tags":["Hokkien"],"summary":"Translate Chinese text into Taiwanese Hokkien","description":"Save a job and charge its full input-based credit cost up front. Generated text and audio do not add charges. Same account, UUID and normalized text/audio replay the original job; changed content conflicts. A terminal replay returns 200. New work is accepted only when the API is enabled.","x-accepting-jobs":true,"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Generate once per intended translation and reuse unchanged when retrying."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HokkienRequest"}}}},"responses":{"200":{"description":"Saved translation. Pending jobs include Retry-After; no browser session is created.","headers":{"Retry-After":{"schema":{"type":"string","const":"2"},"description":"Present while queued or processing."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HokkienJob"}}}},"202":{"description":"Saved translation. Pending jobs include Retry-After; no browser session is created.","headers":{"Retry-After":{"schema":{"type":"string","const":"2"},"description":"Present while queued or processing."},"Location":{"schema":{"type":"string"},"description":"Authenticated status URL."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HokkienJob"}}}},"400":{"description":"Invalid request","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Insufficient credits","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflicting retry identity or result not ready","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Result expired","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Request too large","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Unsupported media type or encoding","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Request or queue limit reached","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal error","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Service temporarily unavailable","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/hokkien/translations/{id}":{"get":{"operationId":"getHokkienTranslation","tags":["Hokkien"],"summary":"Read an account-owned API job","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Saved translation. Pending jobs include Retry-After; no browser session is created.","headers":{"Retry-After":{"schema":{"type":"string","const":"2"},"description":"Present while queued or processing."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HokkienJob"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Request or queue limit reached","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal error","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/hokkien/translations/{id}/audio/{index}":{"get":{"operationId":"downloadHokkienAudio","tags":["Hokkien"],"summary":"Download one saved WAV audio segment","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"index","in":"path","required":true,"schema":{"type":"integer","minimum":0},"description":"Zero-based segment index in audioUrls."}],"responses":{"200":{"description":"Private WAV audio. No additional credits. Cache-Control: no-store.","content":{"audio/wav":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflicting retry identity or result not ready","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Result expired","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Request or queue limit reached","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal error","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Service temporarily unavailable","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/manga/translations":{"post":{"operationId":"createMangaTranslations","tags":["Manga"],"summary":"Upload one or more Manga pages for translation","description":"Each requestIds entry identifies one page in upload order. Reuse the same UUID, file bytes, target language and font on retry. New pages and charges are saved together; no parent batch job is created. Existing jobs add no charge.","x-accepting-jobs":true,"x-upload-limits":{"fileBytes":10485760,"totalBytes":52428800,"megapixels":40,"width":16383,"height":16383},"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/MangaRequest"},"encoding":{"pages":{"contentType":"image/jpeg, image/png, image/webp"}}}}},"responses":{"202":{"description":"Ordered per-page jobs. There is no batch Location header.","headers":{"Retry-After":{"schema":{"type":"string","const":"2"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MangaBatch"}}}},"400":{"description":"Invalid request","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"402":{"description":"Insufficient credits","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflicting retry identity or result not ready","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Result expired","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"413":{"description":"Request too large","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"415":{"description":"Unsupported media type or encoding","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Request or queue limit reached","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal error","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Service temporarily unavailable","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/manga/translations/{id}":{"get":{"operationId":"getMangaTranslation","tags":["Manga"],"summary":"Read one account-owned API page job","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Job state, result link and settlement. Failed jobs also return HTTP 200.","headers":{"Retry-After":{"schema":{"type":"string","const":"2"},"description":"Present while queued or processing."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MangaJob"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Request or queue limit reached","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal error","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/v1/manga/translations/{id}/result":{"get":{"operationId":"downloadMangaResult","tags":["Manga"],"summary":"Download a saved translated image","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Private translated image. No additional credits. Cache-Control: no-store.","content":{"image/webp":{"schema":{"type":"string","format":"binary"}},"image/png":{"schema":{"type":"string","format":"binary"}},"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Missing or invalid API key","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"404":{"description":"Not found","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"409":{"description":"Conflicting retry identity or result not ready","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"410":{"description":"Result expired","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Request or queue limit reached","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"500":{"description":"Internal error","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"503":{"description":"Service temporarily unavailable","headers":{"X-Request-ID":{"schema":{"type":"string"},"description":"Request identifier for support."},"Retry-After":{"schema":{"type":"string"},"description":"Seconds to wait before retrying."}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Account API key, managed through /account/developers. Keep it on your server."}},"schemas":{"ApiError":{"type":"object","required":["error","requestId"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}},"requestId":{"type":"string"}}},"HokkienRequest":{"type":"object","additionalProperties":false,"required":["text"],"properties":{"text":{"type":"string","minLength":1,"maxLength":2000,"description":"Trimmed input, counted in Unicode code points."},"audio":{"type":"boolean","default":false}}},"HokkienJob":{"type":"object","required":["id","statusUrl","status","creditCost","refundedCredits","refundPending","result","error","createdAt","completedAt","expiresAt","resultExpired"],"properties":{"id":{"type":"string","format":"uuid"},"statusUrl":{"type":"string","format":"uri-reference"},"status":{"type":"string","enum":["queued","processing","completed","failed"]},"creditCost":{"type":"integer","minimum":0,"description":"Current net debit. Charged in full at acceptance; decreases if refunded."},"refundedCredits":{"type":"integer","minimum":0},"refundPending":{"type":"boolean"},"result":{"oneOf":[{"type":"null"},{"type":"object","required":["hanji","tailo","poj","spokenCharacterCount","audioUrls"],"properties":{"hanji":{"type":"string","maxLength":3000},"tailo":{"type":"string"},"poj":{"type":"string"},"spokenCharacterCount":{"type":"integer","maximum":3000,"description":"Output character count; not used for billing."},"audioUrls":{"type":"array","items":{"type":"string","format":"uri-reference"},"description":"Ordered authenticated WAV download paths. Empty for text-only requests."}}}]},"error":{"type":["object","null"],"properties":{"code":{"type":"string"}},"required":["code"]},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time","description":"Expiry time for this job's saved content. Null while pending."},"resultExpired":{"type":"boolean"}}},"MangaRequest":{"type":"object","additionalProperties":false,"required":["pages","requestIds","targetLanguage"],"properties":{"pages":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"string","format":"binary"},"description":"Repeat the pages part for each file. JPEG, PNG or WebP. See x-upload-limits."},"requestIds":{"type":"string","contentMediaType":"application/json","contentSchema":{"type":"array","minItems":1,"maxItems":10,"uniqueItems":true,"items":{"type":"string","format":"uuid"}},"description":"JSON-encoded UUID array. One UUID per page in the same order; no duplicates."},"targetLanguage":{"type":"string","enum":["traditional-chinese-taiwan","english","japanese","vietnamese","indonesian","simplified-chinese","thai","taiwanese-hokkien","french","hakka","german","spanish","russian","cantonese","filipino","italian","korean","latin"]},"fontId":{"type":"string","enum":["noto-sans","comic-shanns","noto-sans-cjk"],"default":"noto-sans"}}},"MangaBatch":{"type":"object","required":["pageCount","createdCount","creditCost","jobs"],"properties":{"pageCount":{"type":"integer","minimum":1,"maximum":10},"createdCount":{"type":"integer","minimum":0},"creditCost":{"type":"integer","minimum":0,"description":"New credits charged by this submission only."},"jobs":{"type":"array","items":{"$ref":"#/components/schemas/MangaJob"}}}},"MangaJob":{"type":"object","required":["id","statusUrl","status","creditCost","refundedCredits","refundPending","result","error","createdAt","completedAt","expiresAt","resultExpired"],"properties":{"id":{"type":"string","format":"uuid"},"statusUrl":{"type":"string","format":"uri-reference"},"status":{"type":"string","enum":["queued","processing","completed","failed"]},"creditCost":{"type":"integer","minimum":0},"refundedCredits":{"type":"integer","minimum":0},"refundPending":{"type":"boolean"},"result":{"type":["object","null"],"required":["url","mimeType","width","height"],"properties":{"url":{"type":"string","format":"uri-reference"},"mimeType":{"type":"string","enum":["image/webp","image/jpeg","image/png"]},"width":{"type":"integer","minimum":1},"height":{"type":"integer","minimum":1}}},"error":{"type":["object","null"],"required":["code"],"properties":{"code":{"type":"string","enum":["translation_failed","translation_timeout","translation_cancelled"]}}},"createdAt":{"type":"string","format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time","description":"Expiry time for this job's saved content. Null while pending."},"resultExpired":{"type":"boolean"}}}}}}