PageSourceSearch

https://smartblog.ai/assets/DocsPublicApi-CsIq8G0q.js

js smartblog.ai collected 2026-10-05 15:05:40 UTC 34,234 bytes, 143 lines download raw bytes

1import{j as e}from"./elevenlabs-CpW4MH00.js";import{u as x}from"./index-CdHZ8Cp1.js";import"./livekit-C6cR2JI6.js";import"./framer-motion-efzc2Ucs.js";const g="Public API — Talking Avatar Videos",f="Public self-serve API for generating talking-avatar videos from a photo and an audio file. Closed beta — no billing yet.<br/><br/>Base URL: <code>https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api</code>",k="Table of Contents",T="Authentication",w="Every request must include your API key in the <code>Authorization</code> header as a Bearer token. Keys are created in your account settings under <strong>Settings → Public API</strong>.",v="Authorization: Bearer plk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",j="Keep your key secret. If a key is compromised, revoke it immediately in Settings and generate a new one.",y="Create a video",P="Submit a photo and an audio file. The server queues a render job and returns a <code>job_id</code>. The actual processing is asynchronous.",_="Endpoint",R="POST /v1/avatar-videos",A="Request body (multipart/form-data)",S=["Field","Type","Required","Description"],$=[["photo","file","yes","PNG or JPEG. Must be exactly 720×1280 (portrait 9:16) or 1280×720 (landscape 16:9)."],["audio","file","yes","Audio file to drive lip-sync (MP3, WAV, OGG, M4A). Max 10 MB."],["webhook_url","string","no","URL to call when the job completes or fails. HMAC-SHA256 signed."],["prompt","string","no","Positive video prompt (scene, lighting, framing). Overrides the persona/built-in default for this render. Max 4000 chars. Omit to use the default."],["negative_prompt","string","no","Negative video prompt (artifacts to avoid). Overrides the persona/built-in default for this render. Max 4000 chars. Omit to use the default."],["watermark_text","string","no",'Optional promo/watermark text the worker burns into the final MP4 (e.g. "Created by VlogMe.AI"). Max 120 chars. Omit or empty → no watermark.']],E="cURL example",C="Replace <code>$API_KEY</code> with your actual key. The photo dimensions are validated server-side.",D=`curl -X POST "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos" \\
2  -H "Authorization: Bearer $API_KEY" \\
3  -F "[email protected]" \\
4  -F "[email protected]" \\
5  -F "webhook_url=https://your-site.com/webhook"`,H="Response (202 Accepted)",N="The job is queued. Use the returned <code>job_id</code> to poll status or receive a webhook.",M=`{
6  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
7  "status": "queued",
8  "poll_url": "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
9}`,q='<strong>
9Photo dimensions are strictly enforced.</strong> If the uploaded photo is not exactly 720×1280 or 1280×720, the request returns <code>400 Bad Request</code> with <code>{"error": "Photo must be 720x1280 (portrait) or 1280x720 (landscape)"}</code>. No cropping or resizing is performed — your client must supply the correct size.',I="Multi-frame video (several photos + audios)",L="Build a single video from <strong>several photos</strong>, each with its own ordered list of audio chunks. The renderer plays all audios of frame <em>k</em> in order while showing photo <em>k</em>, then switches to photo <em>k+1</em> and plays its audios, and so on. Use this when you want the avatar to change between paragraphs/scenes without splitting into multiple jobs.",U="Endpoint",O="POST /v1/avatar-videos/multi",B="Request body (application/json)",G=["Field","Type","Required","Description"],V=[["frames","array","yes","One or more frames. Each frame: <code>{ image_url | image_base64, audios: [ {audio_url | audio_base64, subtitles?}, ... ] }</code>. All images must share the same orientation (all 720×1280 or all 1280×720)."],["frames[].image_url","string","one of","Public HTTPS URL of a PNG/JPEG, exactly 720×1280 or 1280×720, ≤ 8 MB."],["frames[].image_base64","string","one of","Base64-encoded image (with or without <code>data:</code> prefix). Same size/format rules as image_url."],["frames[].audios","array","yes","1..20 audio chunks for this frame, in playback order. Each: <code>{audio_url | audio_base64, subtitles?}</code>. MP3/WAV/M4A, ≤ 10 MB each."],["frames[].audios[].subtitles","object","no","Optional per-chunk word timings: <code>{ words: [{text, start, end}, ...] }</code> — <code>start</code>/<code>end</code> are seconds <em>relative to this audio chunk</em>. When provided, the worker burns captions in sync; when omitted, no captions are burned for that chunk."],["webhook_url","string","no","Same as the single-photo endpoint."],["prompt","string","no","Same as the single-photo endpoint. Max 4000 chars."],["negative_prompt","string","no","Same as the single-photo endpoint. Max 4000 chars."],["watermark_text","string","no","Same as the single-photo endpoint. Max 120 chars."],["face_restore","number","no","0..1 (default 0.5)."],["background_restore","number","no","0..1 (default 0.5)."]],W="cURL example",F=`curl -X POST "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos/multi" \\
10  -H "Authorization: Bearer $API_KEY" \\
11  -H "Content-Type: application/json" \\
12  -d '{
13    "frames": [
14      {
15        "image_url": "https://cdn.example.com/portrait_1.png",
16        "audios": [
17          { "audio_url": "https://cdn.example.com/intro.mp3" },
18          { "audio_url": "https://cdn.example.com/part1.mp3" }
19        ]
20      },
21      {
22        "image_url": "https://cdn.example.com/portrait_2.png",
23        "audios": [
24          { "audio_url": "https://cdn.example.com/part2.mp3" }
25        ]
26      }
27    ],
28    "webhook_url": "https://your-site.com/webhook"
29  }'`,z="Response (202 Accepted)",K="Returns the same poll URL contract as the single-photo endpoint. Use <code>GET /v1/avatar-videos/:id</code> to fetch the result.",X=`{
30  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
31  "status": "queued",
32  "orientation": "portrait",
33  "frames": 2,
34  "chunks": 3,
35  "poll_url": "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
36  "webhook_url": "https://your-site.com/webhook"
37}`,Z="Notes & limits",J=["No upper limit on frames per job; <strong>20 audios</strong> per frame.","Total upload (all images + audios combined) is capped at <strong>150 MB</strong>.","All frame images must have the same orientation — mixing portrait and landscape inside one job returns 400.","Each <code>image_url</code> / <code>audio_url</code> is fetched server-side with a 20-second timeout. Use either URLs <strong>or</strong> base64 per asset.","Frames are played strictly in the order you send them. Within a frame, audios are concatenated in the order you send them.","Subt
37itles are optional per chunk — providing <code>words</code> for some chunks and omitting it for others is fine."],Y="Check status",Q="Poll the status of a job. When the job is <code>completed</code>, the response includes a signed URL to download the resulting MP4 video.",ee="Endpoint",te="GET /v1/avatar-videos/:id",oe="cURL example",se=`curl -H "Authorization: Bearer $API_KEY" \\
38  "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos/a1b2c3d4-e5f6-7890-abcd-ef1234567890"`,ae="Response",re="The <code>video_url</code> field is present only when <code>status</code> is <code>completed</code>. It is a signed URL valid for 1 hour.",ne=`{
39  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
40  "status": "completed",
41  "video_url": "https://...signed-url-to-mp4...",
42  "created_at": "2026-05-25T10:00:00.000Z",
43  "completed_at": "2026-05-25T10:02:15.000Z"
44}
45
46# While processing:
47{
48  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
49  "status": "running",
50  "progress": 45,
51  "stage": "inference",
52  "created_at": "2026-05-25T10:00:00.000Z"
53}`,ie="Status values",ce=["Status","Meaning"],le=[["queued","Waiting for a worker to pick up the job."],["running","A worker is actively processing. Check <code>progress</code> and <code>stage</code>."],["completed","Done. <code>video_url</code> contains a signed download link."],["failed","Processing failed. <code>error</code> field contains a description."]],de="Webhooks",ue="If you provided a <code>webhook_url</code> when creating the job, the server sends a POST request there when the job reaches a terminal state (<code>completed</code> or <code>failed</code>). The payload is identical to the GET status response.",me="Webhook payload",pe="The body is a JSON object with the same fields as the GET status response.",he=`{
54  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
55  "status": "completed",
56  "video_url": "https://...signed-url-to-mp4...",
57  "created_at": "2026-05-25T10:00:00.000Z",
58  "completed_at": "2026-05-25T10:02:15.000Z"
59}`,be="Signature verification",xe="Every webhook request includes an <code>X-Public-Api-Signature</code> header containing an HMAC-SHA256 hex digest of the raw JSON body, using your key's <strong>webhook_secret</strong>. Verify it to ensure the payload came from us.",ge=`import hmac
60import hashlib
61
62secret = b"your_webhook_secret"
63
64# Raw request body as bytes
65payload = request.body
66
67# Header value (hex string)
68signature = request.headers.get("X-Public-Api-Signature")
69
70expected = hmac.new(secret, payload, hashlib.sha256).hexdigest()
71if not hmac.compare_digest(expected, signature):
72    raise ValueError("Invalid webhook signature")`,fe="Webhook headers",ke=[{key:"Content-Type",desc:"application/json"},{key:"X-Public-Api-Signature",desc:"HMAC-SHA256 hex digest of the raw body, keyed with your webhook_secret."},{key:"User-Agent",desc:"PublicApiWebhook/1.0"}],Te="<strong>Fallback:</strong> If the webhook delivery fails (non-2xx response, timeout, or network error), the server retries up to 3 times with exponential backoff. If all retries fail, the job still completes and you can always poll the status endpoint.",we="Error codes",ve={400:"Bad Request — invalid photo dimensions, missing required field, or malformed multipart body.",401:"Unauthorized — missing, malformed, or revoked API key.",403:"Forbidden — key revoked or rate limit exceeded (60 req/min).",404:"Not Found — job ID does not exist or belongs to another key.",413:"Payload Too Large — photo or audio exceeds size limits.",429:"Too Many Requests — rate limit exceeded.",500:"Internal Server Error — unexpected failure. Retry with backoff."},je="Limits",ye="During the closed beta, the following limits apply:",Pe=["<strong>Rate limit:</strong> 60 requests per minute per API key.","<strong>Photo:</strong> exact 720×1280 (portrait) or 1280×720 (landscape). No cropping server-side.","<strong>Audio:</strong> max 10 MB. Supported formats: MP3, WAV, OGG, M4A.","<strong>Video output:</strong> MP4, H.264 + AAC. Portrait 720×1280 or landscape 1280×720, 30 FPS.","<strong>Webhook URL:</strong> must be publicly accessible HTTPS. Localhost and private IPs are rejected."],_e="Public API v1.0 — Closed Beta",Re={pageTitle:g,intro:f,tocTitle:k,authTitle:T,authDesc:w,authExample:v,authNote:j,createTitle:y,createDesc:P,createEndpoint:_,createEndpointCode:R,createParams:A,createParamsHeaders:S,createParamsRows:$,createCurlTitle:E,createCurlDesc:C,createCurl:D,createResponseTitle:H,createResponseDesc:N,createResponse:M,createPhotoWarning:q,multiTitle:I,multiDesc:L,multiEndpoint:U,multiEndpointCode:O,multiParams:B,multiParamsHeaders:G,multiParamsRows:V,multiCurlTitle:W,multiCurl:F,multiResponseTitle:z,multiResponseDesc:K,multiResponse:X,multiNotesTitle:Z,multiNotes:J,statusTitle:Y,statusDesc:Q,statusEndpoint:ee,statusEndpointCode:te,statusCurlTitle:oe,statusCurl:se,statusResponseTitle:ae,statusResponseDesc:re,statusResponse:ne,statusStatesTitle:ie,statusStatesHeaders:ce,statusStatesRows:le,webhooksTitle:de,webhooksDesc:ue,
72webhookPayloadTitle:me,webhookPayloadDesc:pe,webhookPayload:he,webhookSignatureTitle:be,webhookSignatureDesc:xe,webhookSignatureVerify:ge,webhookHeadersTitle:fe,webhookHeaders:ke,webhookFallback:Te,errorsTitle:we,errors:ve,limitsTitle:je,limitsDesc:ye,limitsList:Pe,footerVersion:_e},Ae="Public API — Говорящие аватары",Se="Публичный self-serve API для генерации видео с говорящими аватарами из фото и аудио. Закрытая бета — биллинг пока не включён.<br/><br/>Base URL: <code>https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api</code>",$e="Содержание",Ee="Аутентификация",Ce="Каждый запрос должен содержать ваш API-ключ в заголовке <code>Authorization</code> в формате Bearer. Ключи создаются в настройках аккаунта в разделе <strong>Settings → Public API</strong>.",De="Authorization: Bearer plk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",He="Храните ключ в секрете. Если ключ скомпрометирован — отзовите его в настройках и создайте новый.",Ne="Создание видео",Me="Отправьте фото и аудиофайл. Сервер ставит задачу в очередь и возвращает <code>job_id</code>. Обработка происходит асинхронно.",qe="Endpoint",Ie="POST /v1/avatar-videos",Le="Тело запроса (multipart/form-data)",Ue=["Поле","Тип","Обязательное","Описание"],Oe=[["photo","file","да","PNG или JPEG. Ровно 720×1280 (портрет 9:16) или 1280×720 (ландшафт 16:9)."],["audio","file","да","Аудиофайл для синхронизации губ (MP3, WAV, OGG, M4A). Макс 10 МБ."],["webhook_url","string","нет","URL для уведомления о завершении или ошибке. Подписан HMAC-SHA256."],["prompt","string","нет","Положительный промпт для видео (сцена, свет, ракурс). Переопределяет промпт персоны и встроенное значение по умолчанию для этого рендера. Макс 4000 символов. Опустите — будет использовано значение по умолчанию."],["negative_prompt","string","нет","Негативный промпт для видео (что избегать). Переопределяет промпт персоны и встроенное значение по умолчанию для этого рендера. Макс 4000 символов. Опустите — будет использовано значение по умолчанию."],["watermark_text","string","нет","Необязательный текст-вотермарка/реклама, который воркер вшивает в финальный MP4 (например, «Created by VlogMe.AI»). Макс 120 символов. Опустите или передайте пустую строку — вотермарка не добавляется."]],Be="cURL пример",Ge="Замените <code>$API_KEY</code> на ваш реальный ключ. Размеры фото проверяются на сервере.",Ve=`curl -X POST "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos" \\
73  -H "Authorization: Bearer $API_KEY" \\
74  -F "[email protected]" \\
75  -F "[email protected]" \\
76  -F "webhook_url=https://your-site.com/webhook"`,We="Ответ (202 Accepted)",Fe="Задача поставлена в очередь. Используйте возвращённый <code>job_id</code> для опроса статуса или получения webhook.",ze=`{
77  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
78  "status": "queued",
79  "poll_url": "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos/a1b2c3d4-e5f6-7890-abcd-ef1234567890"
80}`,Ke='<strong>Размеры фото строго контролируются.</strong> Если загруженное фото не ровно 720×1280 или 1280×720, запрос вернёт <code>400 Bad Request</code> с <code>{"error": "Photo must be 720x1280 (portrait) or 1280x720 (landscape)"}</code>. На сервере не выполняется никакая обрезка или ресайз — клиент должен прислать фото правильного размера.',Xe="Видео из нескольких кадров (несколько фото + аудио)",Ze="Соберите одно видео из <strong>нескольких фотографий</strong>, где у каждой свой упорядоченный список аудио-чанков. Рендерер проиграет все аудио кадра <em>k</em> по порядку, показывая фото <em>k</em>, затем переключится на фото <em>k+1</em> и проиграет его аудио, и так далее. Удобно, когда нужно менять аватар между абзацами/сценами без дробления на несколько задач.",Je="Endpoint",Ye="POST /v1/avatar-videos/multi",Qe="Тело запроса (application/json)",et=["Поле","Тип","Обязательное","Описание"],tt=[["frames","array","да","Один или больше кадров. Каждый: <code>{ image_url | image_base64, audios: [ {audio_url | audio_base64, subtitles?}, ... ] }</code>. Все картинки должны быть одной ориентации (все 720×1280 либо все 1280×720)."],["frames[].image_url","string","одно из","Публичный HTTPS 
80URL картинки PNG/JPEG, ровно 720×1280 или 1280×720, ≤ 8 МБ."],["frames[].image_base64","string","одно из","Картинка в base64 (с префиксом <code>data:</code> или без). Правила размера/формата те же, что у image_url."],["frames[].audios","array","да","1..20 аудио-чанков для этого кадра, в порядке воспроизведения. Каждый: <code>{audio_url | audio_base64, subtitles?}</code>. MP3/WAV/M4A, ≤ 10 МБ каждый."],["frames[].audios[].subtitles","object","нет","Опциональные тайминги слов для конкретного чанка: <code>{ words: [{text, start, end}, ...] }</code> — <code>start</code>/<code>end</code> в секундах <em>относительно этого аудио</em>. Если переданы — воркер вшивает субтитры синхронно; если нет — субтитры для этого чанка не вшиваются."],["webhook_url","string","нет","Как у обычного endpoint."],["prompt","string","нет","Как у обычного endpoint. Макс 4000 символов."],["negative_prompt","string","нет","Как у обычного endpoint. Макс 4000 символов."],["watermark_text","string","нет","Как у обычного endpoint. Макс 120 символов."],["face_restore","number","нет","0..1 (по умолчанию 0.5)."],["background_restore","number","нет","0..1 (по умолчанию 0.5)."]],ot="cURL пример",st=`curl -X POST "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos/multi" \\
81  -H "Authorization: Bearer $API_KEY" \\
82  -H "Content-Type: application/json" \\
83  -d '{
84    "frames": [
85      {
86        "image_url": "https://cdn.example.com/portrait_1.png",
87        "audios": [
88          { "audio_url": "https://cdn.example.com/intro.mp3" },
89          { "audio_url": "https://cdn.example.com/part1.mp3" }
90        ]
91      },
92      {
93        "image_url": "https://cdn.example.com/portrait_2.png",
94        "audios": [
95          { "audio_url": "https://cdn.example.com/part2.mp3" }
96        ]
97      }
98    ],
99    "webhook_url": "https://your-site.com/webhook"
100  }'`,at="Ответ (202 Accepted)",rt="Возвращает тот же контракт с poll URL, что и обычный endpoint. Для получения результата используйте <code>GET /v1/avatar-videos/:id</code>.",nt=`{
101  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
102  "status": "queued",
103  "orientation": "portrait",
104  "frames": 2,
105  "chunks": 3,
106  "poll_url": "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos/a1b2c3d4-e5f6-7890-abcd-ef1234567890",
107  "webhook_url": "https://your-site.com/webhook"
108}`,it="Заметки и лимиты",ct=["Лимита на число кадров в задаче нет; <strong>20 аудио</strong> на кадр.","Суммарный размер загрузки (все картинки + аудио) ограничен <strong>150 МБ</strong>.","Все картинки в одной задаче должны быть одной ориентации — смешение портретных и ландшафтных вернёт 400.","Каждый <code>image_url</code> / <code>audio_url</code> скачивается сервером с таймаутом 20 секунд. Используйте либо URL, либо base64 для каждого ассета.","Кадры проигрываются строго в том порядке, в котором вы их прислали. Внутри кадра аудио склеиваются в том порядке, в котором они переданы.","Субтитры опциональны для каждого чанка — можно для одних чанков передать <code>words</code>, а для других опустить."],lt="Проверка статуса",dt="Опросите статус задачи. Когда статус <code>completed</code>, в ответе будет подписанная ссылка для скачивания итогового MP4-видео.",ut="Endpoint",mt="GET /v1/avatar-videos/:id",pt="cURL пример",ht=`curl -H "Authorization: Bearer $API_KEY" \\
109  "https://nfqxajdgklseicehjolk.supabase.co/functions/v1/public-api/v1/avatar-videos/a1b2c3d4-e5f6-7890-abcd-ef1234567890"`,bt="Ответ",xt="Поле <code>video_url</code> присутствует только при <code>status: completed</code>. Это подписанная ссылка, действительная 1 час.",gt=`{
110  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
111  "status": "completed",
112  "video_url": "https://...signed-url-to-mp4...",
113  "created_at": "2026-05-25T10:00:00.000Z",
114  "completed_at": "2026-05-25T10:02:15.000Z"
115}
116
117# В процессе обработки:
118{
119  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
120  "status": "running",
121  "progress": 45,
122  "stage": "inference",
123  "created_at": "2026-05-25T10:00:00.000Z"
124}`,ft="Значения статуса",kt=["Статус","Значение"],Tt=[["queued","Ожидает в очереди. Ð
124’оркер ещё не взял задачу."],["running","Воркер обрабатывает. Смотрите <code>progress</code> и <code>stage</code>."],["completed","Готово. Поле <code>video_url</code> содержит подписанную ссылку на скачивание."],["failed","Ошибка обработки. Поле <code>error</code> содержит описание."]],wt="Вебхуки",vt="Если при создании задачи вы указали <code>webhook_url</code>, сервер отправит POST-запрос туда, когда задача достигнет конечного статуса (<code>completed</code> или <code>failed</code>). Тело запроса идентично ответу GET status.",jt="Payload вебхука",yt="Тело запроса — JSON-объект с теми же полями, что и в ответе GET status.",Pt=`{
125  "job_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
126  "status": "completed",
127  "video_url": "https://...signed-url-to-mp4...",
128  "created_at": "2026-05-25T10:00:00.000Z",
129  "completed_at": "2026-05-25T10:02:15.000Z"
130}`,_t="Проверка подписи",Rt="Каждый запрос вебхука содержит заголовок <code>X-Public-Api-Signature</code> с HMAC-SHA256 hex-дайджестом сырого JSON-тела, вычисленным с помощью <strong>webhook_secret</strong> вашего ключа. Проверяйте его, чтобы убедиться, что данные пришли от нас.",At=`import hmac
131import hashlib
132
133secret = b"your_webhook_secret"
134
135# Сырое тело запроса в байтах
136payload = request.body
137
138# Значение заголовка (hex-строка)
139signature = request.headers.get("X-Public-Api-Signature")
140
141expected = hmac.new(secret, payload, hashlib.sha256).hexdigest()
142if not hmac.compare_digest(expected, signature):
143    raise ValueError("Invalid webhook signature")`,St="Заголовки вебхука",$t=[{key:"Content-Type",desc:"application/json"},{key:"X-Public-Api-Signature",desc:"HMAC-SHA256 hex-дайджест сырого тела, ключ — ваш webhook_secret."},{key:"User-Agent",desc:"PublicApiWebhook/1.0"}],Et="<strong>Fallback:</strong> Если доставка вебхука не удалась (не-2xx ответ, таймаут или сетевая ошибка), сервер повторяет до 3 раз с экспоненциальным откладыванием. Если все попытки провалились — задача всё равно завершится, и вы всегда можете опросить status endpoint.",Ct="Коды ошибок",Dt={400:"Bad Request — неверные размеры фото, отсутствует обязательное поле или некорректное multipart-тело.",401:"Unauthorized — отсутствует, повреждён или отозван API-ключ.",403:"Forbidden — ключ отозван или превышен лимит запросов (60 в минуту).",404:"Not Found — задача с таким ID не существует или принадлежит другому ключу.",413:"Payload Too Large — фото или аудио превышают лимит размера.",429:"Too Many Requests — превышен rate limit.",500:"Internal Server Error — неожиданная ошибка. Повторите с backoff."},Ht="Ограничения",Nt="В закрытой бете действуют следующие лимиты:",Mt=["<strong>Rate limit:</strong> 60 запросов в минуту на один API-ключ.","<strong>Фото:</strong> ровно 720×1280 (портрет) или 1280×720 (ландшафт). Обрезка на сервере не производится.","<strong>Аудио:</strong> макс 10 МБ. Поддерживаемые форматы: MP3, WAV, OGG, M4A.","<strong>Видео на выходе:</strong> MP4, H.264 + AAC. Портрет 720×1280 или ландшафт 1280×720, 30 FPS.","<strong>Webhook URL:</strong> должен быть публично доступен по HTTPS. Localhost и приватные IP отклоняются."],qt="Public API v1.0 — Closed Beta",It={pageTitle:Ae,intro:Se,tocTitle:$e,authTitle:Ee,authDesc:Ce,authExample:De,authNote:He,createTitle:Ne,createDesc:Me,createEndpoint:qe,createEndpointCode:Ie,createParams:Le,createParamsHeaders:Ue,createParamsRows:Oe,createCurlTitle:Be,createCurlDesc:Ge,createCurl:Ve,createResponseTitle:We,createResponseDesc:Fe,createResponse:ze,createPhotoWarning:Ke,multiTitle:Xe,multiDesc:Ze,multiEndpoint:Je,multiEndpointCode:Ye,multiParams:Qe,multiParamsHeaders:et,multiParamsRows:tt,multiCurlTitle:ot,multiCurl:st,multiResponseTitle:at,multiResponseDesc:rt,multiResponse:nt,multiNotesTitle:it,multiNotes:ct,statusTitle:lt,statusDesc:dt,statusEndpoint:ut,statusEndpointCode:mt,statusCurlTitle:pt,statusCurl:ht,statusResponseTitle:bt,statusResponseDesc:xt,statusResponse:gt,statusStatesTitle:ft,statusStatesHeaders:kt,statusStatesRows:Tt,webhooksTitle:wt,webhooksDesc:vt,webhookPayloadTitle:jt,webhookPayloadDesc:yt,webhookPayload:Pt,webhookSignatureTitle:_t,webhookSignatureDesc:Rt,webhookSignatureVerify:At,webhookHeadersTitle:St,webhookHeaders:$t,webhookFallback:Et,errorsTitle:Ct,errors:Dt,limitsTitle:Ht,limitsDesc:Nt,limitsList:Mt,footerVersion:qt},n=({children:r})=>e.jsx("pre",{className:"rounded-lg border border-border bg-muted/50 p-3 text-[13px] leading-relaxed font-mono text-foreground whitespace-pre overflow-x-auto mb-4",children:r}),u=({headers:r,rows:i})=>e.jsx("div",{className:"overflow-x-auto rounded-lg border border-border mb-4",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsx("tr",{className:"bg-muted/50 border-b border-border",children:r.map(t=>e.jsx("th",{className:"px-3 py-2 text-left font-semibold text-foreground",children:t},t))})}),e.jsx("tbody",{children:i.map((t,m)=>e.jsx("tr",{className:"border-b border-border last:border-0",children:t.map((d,o)=>e.jsx("td",{className:"px-3 py-2 text-muted-foreground font-mono text-xs",children:d},o))},m))})]})}),c=({id:r,children:i})=>e.jsx("h2",{id:r,className:"text-lg font-bold text-foreground mt-10 mb-3 border-b border-border pb-2 scroll-mt-6",children:i}),s=({id:r,children:i})=>e.jsx("h3",{id:r,className:"text-base font-semibold text-foreground mt-6 mb-2 scroll-mt-6",children:i}),a=({html:r})=>e.jsx("p",{className:"text-sm text-muted-foreground leading-relaxed mb-3",dangerouslySetInnerHTML:{__html:r}}
143),b=({items:r})=>e.jsx("ul",{className:"list-disc list-inside text-sm text-muted-foreground space-y-1.5 mb-4 ml-1",children:r.map((i,t)=>e.jsx("li",{dangerouslySetInnerHTML:{__html:i}},t))}),p=({children:r,variant:i="default"})=>{const t={default:"bg-amber-500/10 border-amber-500/30",warning:"bg-destructive/5 border-destructive/30",info:"bg-primary/5 border-primary/30"};return e.jsx("div",{className:`${t[i]} border rounded-lg p-4 mb-4 space-y-2`,children:r})};function Gt(){const{i18n:r}=x(),i=r.language==="ru"?It:Re,t=(o,l)=>{const h=i[o];return h!==void 0?h:o},m=t("errors"),d=t("webhookHeaders");return e.jsx("div",{className:"min-h-screen bg-background",children:e.jsxs("div",{className:"max-w-3xl mx-auto px-6 py-10 space-y-1",children:[e.jsx("h1",{className:"text-2xl font-bold text-foreground mb-1",children:t("pageTitle")}),e.jsx(a,{html:t("intro")}),e.jsxs("nav",{className:"rounded-lg border border-border bg-muted/30 p-4 mb-6",children:[e.jsx("p",{className:"text-sm font-semibold text-foreground mb-2",children:t("tocTitle")}),e.jsx("ul",{className:"columns-2 gap-x-6 text-sm space-y-1",children:[["auth","authTitle"],["create","createTitle"],["multi","multiTitle"],["status","statusTitle"],["webhooks","webhooksTitle"],["errors","errorsTitle"],["limits","limitsTitle"]].map(([o,l])=>e.jsx("li",{children:e.jsx("a",{href:`#${o}`,className:"text-primary hover:underline",children:t(l)})},o))})]}),e.jsx(c,{id:"auth",children:t("authTitle")}),e.jsx(a,{html:t("authDesc")}),e.jsx(n,{children:t("authExample")}),e.jsx(p,{variant:"info",children:e.jsx(a,{html:t("authNote")})}),e.jsx(c,{id:"create",children:t("createTitle")}),e.jsx(a,{html:t("createDesc")}),e.jsx(s,{children:t("createEndpoint")}),e.jsx(n,{children:t("createEndpointCode")}),e.jsx(s,{children:t("createParams")}),e.jsx(u,{headers:t("createParamsHeaders"),rows:t("createParamsRows")}),e.jsx(s,{children:t("createCurlTitle")}),e.jsx(a,{html:t("createCurlDesc")}),e.jsx(n,{children:t("createCurl")}),e.jsx(s,{children:t("createResponseTitle")}),e.jsx(a,{html:t("createResponseDesc")}),e.jsx(n,{children:t("createResponse")}),e.jsx(p,{variant:"warning",children:e.jsx(a,{html:t("createPhotoWarning")})}),e.jsx(c,{id:"multi",children:t("multiTitle")}),e.jsx(a,{html:t("multiDesc")}),e.jsx(s,{children:t("multiEndpoint")}),e.jsx(n,{children:t("multiEndpointCode")}),e.jsx(s,{children:t("multiParams")}),e.jsx(u,{headers:t("multiParamsHeaders"),rows:t("multiParamsRows")}),e.jsx(s,{children:t("multiCurlTitle")}),e.jsx(n,{children:t("multiCurl")}),e.jsx(s,{children:t("multiResponseTitle")}),e.jsx(a,{html:t("multiResponseDesc")}),e.jsx(n,{children:t("multiResponse")}),e.jsx(s,{children:t("multiNotesTitle")}),(()=>{const o=t("multiNotes");return Array.isArray(o)?e.jsx(b,{items:o}):null})(),e.jsx(c,{id:"status",children:t("statusTitle")}),e.jsx(a,{html:t("statusDesc")}),e.jsx(s,{children:t("statusEndpoint")}),e.jsx(n,{children:t("statusEndpointCode")}),e.jsx(s,{children:t("statusCurlTitle")}),e.jsx(n,{children:t("statusCurl")}),e.jsx(s,{children:t("statusResponseTitle")}),e.jsx(a,{html:t("statusResponseDesc")}),e.jsx(n,{children:t("statusResponse")}),e.jsx(s,{children:t("statusStatesTitle")}),e.jsx(u,{headers:t("statusStatesHeaders"),rows:t("statusStatesRows")}),e.jsx(c,{id:"webhooks",children:t("webhooksTitle")}),e.jsx(a,{html:t("webhooksDesc")}),e.jsx(s,{children:t("webhookPayloadTitle")}),e.jsx(a,{html:t("webhookPayloadDesc")}),e.jsx(n,{children:t("webhookPayload")}),e.jsx(s,{children:t("webhookSignatureTitle")}),e.jsx(a,{html:t("webhookSignatureDesc")}),e.jsx(n,{children:t("webhookSignatureVerify")}),e.jsx(s,{children:t("webhookHeadersTitle")}),Array.isArray(d)&&d.map((o,l)=>e.jsxs("div",{className:"flex gap-3 items-baseline mb-2",children:[e.jsx("code",{className:"text-xs font-mono font-bold text-foreground shrink-0",children:o.key}),e.jsx("span",{className:"text-xs text-muted-foreground",children:o.desc})]},l)),e.jsx(p,{variant:"info",children:e.jsx(a,{html:t("webhookFallback")})}),e.jsx(c,{id:"errors",children:t("errorsTitle")}),e.jsx(u,{headers:["HTTP",""],rows:Object.entries(m).map(([o,l])=>[o,l])}),e.jsx(c,{id:"limits",children:t("limitsTitle")}),e.jsx(a,{html:t("limitsDesc")}),(()=>{const o=t("limitsList");return Array.isArray(o)?e.jsx(b,{items:o}):null})(),e.jsx("div",{className:"pt-6 border-t border-border mt-8",children:e.jsx("p",{className:"text-xs text-muted-foreground",children:t("footerVersion")})})]})})}export{Gt as default};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.