Vitra_Translate_Suite
Vitra.ai media-localization suite. Single Animoca Minds app bundling three translation skills (image, audio, video) across two Vitra base URLs (api.translate.photo for image-text translation; api.translate.video for audio + video dubbing). Single-header auth: every authenticated request carries va-token: <VITRA_AGENT_TOKEN>, the one agent token vitra.ai issues for the partner integration — valid across both base URLs and all 8 tools. The bazaar injects the header; the Mind never reads, stores, or injects credentials. All three skills follow the async submit → poll pattern; the Steward only ever sees the final translated/dubbed cloud URL.
Submit an image for text translation via POST https://api.translate.photo/v1/image-translator/direct-translate. The runtime fetches source_url, enforces the http(s)-only + 10MB cap (https strongly preferred), then posts multipart/form-data with fields: file (binary), sourceLanguage (language identifier or 'auto'), targetLanguage (language identifier). Async — returns {jobId, translationVersionId} immediately; you MUST call Vitra_GetTranslationStatus to retrieve the translatedImageUrl. NEVER pass ISO codes ('es', 'fr', 'hi') — pass the identifier the API returned in the 'value' field of Vitra_ListImageLanguages (e.g. 'spanish', 'french', 'hindi'). Auto-detect aliases ('auto-detect', 'Auto Detect', 'autodetect', 'detect') are normalized to the literal 'auto' before send. This endpoint's errors arrive as standard HTTP status (401/403 = auth rejected; any other non-2xx = request/server error — read the JSON body for the message). Runtime mapping: source_url ? runtime fetches the URL body and uploads it as the 'file' multipart field; source_language ? 'sourceLanguage' form field; target_language ? 'targetLanguage' form field. Hard reject (before download) any source_url whose scheme is not http(s) or that resolves to a file >10MB.
Poll the async dubbing result via GET https://api.translate.video/v1/service/status/{processId}. Shared between Vitra_SubmitAudioDub and Vitra_SubmitVideoDub (same processId namespace, same status endpoint). Returns {status, data: [...], ...}. DONE statuses (uppercase): 'DONE', 'COMPLETED', 'SUCCESS'. FAILED statuses (uppercase): 'FAILED', 'ERROR', 'CANCELLED'. On a completed status, the output URL is at data[0].url — extract that and present it to the Steward. Recommended polling cadence: every 10 seconds within a 600-second total budget (dubbing is slower than image translation). NEVER expose processId to the Steward as a result — it is an intermediate identifier. Error handling: callers branch on raw HTTP status — a non-200 response is an error, and 401/403 means the va-token was rejected. On a completed status with empty data or no data[0].url, treat it as an error (surface it and stop; do not loop). Runtime mapping: the JSON Schema parameter 'process_id' (snake_case for Mind ergonomics) is substituted into the URL path segment '{processId}' (camelCase per Vitra's API). No request body.
Poll the async image-translation result via GET https://api.translate.photo/v1/image-translator/{jobId}/translations/{translationVersionId}. Returns {status, translatedImageUrl}. Status values include 'pending', 'translating', 'completed' (also 'complete', 'done', 'success', 'succeeded', 'finished' — case-insensitive), and failure states ('failed', 'error', 'errored', 'cancelled', 'canceled'). translatedImageUrl is the final cloud URL the Mind returns to the Steward — only present when status is in the completed family AND the URL starts with http(s). Recommended polling cadence: every 5 seconds within a 300-second total budget. NEVER expose jobId or translationVersionId to the Steward as a result — they are intermediate identifiers. This endpoint's errors arrive as standard HTTP status (401/403 = auth rejected). Runtime mapping: the JSON Schema parameter 'job_id' (snake_case for Mind ergonomics) is substituted into the URL path segment '{jobId}' (camelCase per Vitra's API); 'translation_version_id' is substituted into '{translationVersionId}'. No request body.
List languages supported by the vitra.ai audio dubbing service via GET https://api.translate.video/v1/service/audio/languages/list. Returns {data: [{value, label, ...}]} where 'value' is the locale-form identifier the dubbing endpoint accepts (e.g. 'hindi_india', 'spanish_spain', 'french_france') and 'label' is the human-readable name. Use this BEFORE Vitra_SubmitAudioDub whenever you are unsure of the exact target language locale or when the Steward gives a plain language name ('Spanish') that needs disambiguation to a locale ('spanish_spain' vs 'spanish_mexico'). Response is cacheable for ~1 hour. NOTE: this endpoint is called WITHOUT X-Client-Source: agent — errors arrive as standard non-2xx HTTP.
List languages supported by the vitra.ai image translator via GET https://api.translate.photo/v1/language/list. Returns an array of language objects, each with a 'value' field (the identifier the submit endpoint accepts, e.g. 'spanish') and a 'name' (or 'label') field (human-readable). The script normalizer also accepts 'code'/'key'/'language'/'id' as fallback identifier fields. Use this BEFORE Vitra_DirectTranslate whenever you are unsure of the exact target/source language identifier or when the Steward gives an ISO code ('es', 'fr') that needs to be mapped. Response is cacheable for ~1 hour. NOTE: this endpoint is called WITHOUT X-Client-Source: agent — errors arrive as standard non-2xx HTTP (401/403/4xx with payload), not as HTTP 200 + success:false.
List languages supported by the vitra.ai video dubbing service via GET https://api.translate.video/v1/service/video/languages/list. Returns {data: [{value, label, ...}]} where 'value' is the locale-form identifier the dubbing endpoint accepts (e.g. 'hindi_india', 'spanish_spain') and 'label' is the human-readable name. Use this BEFORE Vitra_SubmitVideoDub whenever you are unsure of the exact target language locale. Audio and video share the same locale convention but are listed under different endpoints — call this for video, Vitra_ListAudioLanguages for audio. Response is cacheable for ~1 hour. NOTE: this endpoint is called WITHOUT X-Client-Source: agent — errors arrive as standard non-2xx HTTP.
Submit an audio file for dubbing via POST https://api.translate.video/v1/service/dubbing (Content-Type: application/json). JSON body: {processName: 'Audio Dubbing: <filename>', sourceLanguage: 'auto' | identifier, targetLanguages: [{language: '<value-from-Vitra_ListAudioLanguages>'}], url: '<source-url>'}. Async — returns {processId, ...}; you MUST call Vitra_GetDubbingStatus to retrieve the dubbed audio URL. The vitra.ai source-language default is 'auto'; do NOT ask the Steward for source language unless they volunteer it. target_language MUST be the 'value' field of a Vitra_ListAudioLanguages entry (locale-form: 'hindi_india', not 'hindi'). http(s) cloud URLs only (https strongly preferred). This endpoint's errors arrive as standard non-2xx HTTP: 401/403 = auth rejected, any other non-2xx = request/server error (read the JSON body for the message). Runtime mapping (Mind passes snake_case params; runtime constructs the API JSON body): url ? source_url; sourceLanguage ? source_language; targetLanguages ? [{language: target_language}] (wrap the single target into a one-element array of objects); processName ? 'Audio Dubbing: ' + the source URL's filename (the basename of the source URL, matching the reference script's Path(url).name). Hard reject any source_url whose scheme is not http(s).
Submit a video file for dubbing via POST https://api.translate.video/v1/service/dubbing (Content-Type: application/json). JSON body: {processName: 'Dubbing: <filename>', sourceLanguage: 'auto' | identifier, targetLanguages: [{language: '<value-from-Vitra_ListVideoLanguages>'}], url: '<source-url>'}. Async — returns {processId, ...}; you MUST call Vitra_GetDubbingStatus to retrieve the dubbed video URL. The vitra.ai source-language default is 'auto'; do NOT ask the Steward for source language unless they volunteer it. target_language MUST be the 'value' field of a Vitra_ListVideoLanguages entry (locale-form). http(s) cloud URLs only (https strongly preferred). This endpoint's errors arrive as standard non-2xx HTTP: 401/403 = auth rejected, any other non-2xx = request/server error (read the JSON body for the message). Runtime mapping (Mind passes snake_case params; runtime constructs the API JSON body): url ? source_url; sourceLanguage ? source_language; targetLanguages ? [{language: target_language}] (wrap the single target into a one-element array of objects); processName ? 'Dubbing: ' + the source URL's filename (the basename of the source URL, matching the reference script's Path(url).name). Hard reject any source_url whose scheme is not http(s).