신규어떤 에이전트든 UberLLM에 연결하세요. 키 하나로 모든 모델을 공식 가격 이하로 사용할 수 있습니다.
UberLLM

이미지, 비디오, 음악 및 음성

텍스트에 사용하는 키로 이미지, 비디오, 음악, 음성을 만들고 녹음을 텍스트로 변환할 수 있으며, 이 모든 것이 동일한 잔액에서 차감됩니다. 모델 표 (또는 ?type=image, ?type=music, ?type=audio)에서 모델을 선택하세요. 각 모델 페이지에는 가격, 유형 및 작동하는 요청 예시가 나와 있습니다.

원하는 것 경로 원본 사진 입력 위치
프롬프트에서 새 이미지 POST /v1/images/generations (없음)
편집된 사진 POST /v1/images/edits image (또는 image_url, input_images, images)
프롬프트에서 비디오 POST /v1/video/generations (없음)
사진에서 시작하는 비디오 POST /v1/video/generations image_url (첫 프레임); end_image_url (마지막 프레임)
참조 사진에서 비디오 POST /v1/video/generations input_images ("role": "reference"와 함께)
사진에 대한 텍스트 답변 POST /v1/chat/completions messages[].content의 image_url 부분
음악 POST /v1/music/generations (없음)
텍스트에서 음성 POST /v1/audio/speech (없음)
녹음에서 텍스트 POST /v1/audio/transcriptions (없음; 녹음은 file에 입력)

원본 사진은 https:// 링크, data: URI (data:image/png;base64,iVBORw0…) 또는 PNG, JPEG, WebP의 일반 base64이며, 요청당 최대 8까지 가능합니다. 이미지 경로는 멀티파트 업로드(아래 참조)도 지원합니다. 링크는 공개 https:// 링크여야 합니다. http:// 링크는 거부됩니다. 리디렉션되는 링크(예: https://picsum.photos/640/360)는 최대 5회까지, 그리고 다른 공개 https:// 링크로만 추적되며, 모델은 최종 도착한 링크를 받습니다. 사진으로 연결되지 않거나 사용할 수 없는 곳으로 리디렉션되는 링크는 어떠한 보류나 요금 청구 없이 400 invalid_image_url으로 거부됩니다. 인라인으로 전송된 사진은 요청 크기를 늘립니다. 10 MB 미만으로 유지하거나 링크를 보내세요.

채팅 메시지(messages[].content의 image_url)에서 링크(https:// 또는 http://)는 UberLLM에 의해 열리고 data: URL로 모델에 전송됩니다. 대부분의 비전 모델은 그것만 받기 때문입니다. 각 사진은 최대 20 MB(요청당 40 MB)까지 가능하며, 리디렉션은 최대 5회까지, 공개 주소로만 추적됩니다. Gemini 모델은 링크를 있는 그대로 받습니다. 사진으로 연결되지 않는 링크는 400 invalid_image_url으로 거부되며, 요금은 청구되지 않습니다.

이미지 만들기

이미지는 답변으로 돌아옵니다.

curl https://api.uberllm.dev/v1/images/generations \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "venice/z-image-turbo", "prompt": "a red apple on a white table", "n": 1, "size": "1024x1024"}'
{ "created": 1792429247, "data": [{ "url": "https://api.uberllm.dev/v1/media/artifacts/<id>/0" }],
  "usage": { "cost_usd": 0.0099, "max_cost_usd": 0.0109 } }

usage.cost_usd는 이미지 비용입니다 (X-UberLLM-Cost-USD 헤더에도 있습니다). 가격이 아직 알려지지 않은 드문 답변의 경우 null입니다. 제공업체가 청구한 금액을 지불하며, 이를 위해 보류된 max_cost_usd를 초과하지 않습니다.

response_format는 /v1/images/generations와 /v1/images/edits 모두에 대해 기본적으로 url입니다. 대신 답변 안에 이미지를 받으려면 "response_format": "b64_json"를 보내세요. 모델이 이미지 자체를 반환하면, UberLLM은 이를 24시간 동안 귀하의 계정 파일로 보관하고 해당 링크(https://api.uberllm.dev/v1/files/file_…/content)로 답변합니다. 이 링크는 나중에 편집할 원본 이미지로도 작동합니다. 동일한 키로 URL을 다운로드하세요:

curl -L -o image.png -H "Authorization: Bearer $UBERLLM_API_KEY" \
  "https://api.uberllm.dev/v1/media/artifacts/<id>/0"

n는 1에서 10까지입니다.

사진 편집하기

편집 모델(ID는 보통 -edit로 끝납니다)을 사용하고, 원본 사진을 image에 보내세요:

curl https://api.uberllm.dev/v1/images/edits \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "google/nano-banana-pro-edit", "prompt": "make the sky a sunset",
       "image": "https://example.com/skyline.png"}'

동일한 사진은 다음 형식으로 입력할 수 있습니다:

  • "image": "data:image/png;base64,iVBORw0…"
  • "image_url": "https://…"
  • "input_images": ["https://…", "https://…"]: 첫 번째는 편집할 사진이고, 나머지는 참조용입니다. 항목은 {"url": "…", "role": "reference"}일 수도 있습니다.
  • "images": [{"image_url": "https://…"}], OpenAI SDK가 보내는 형식

일반 base64도 작동하며, "input_image"는 "image"으로 읽힙니다.

또는 OpenAI의 이미지 편집처럼 파일을 업로드할 수도 있습니다:

curl https://api.uberllm.dev/v1/images/edits \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -F model=google/nano-banana-pro-edit -F prompt="make the sky a sunset" \
  -F [email protected]

원본 사진이 없는 편집 요청은 400 image_required 오류와 함께 거부됩니다. 마스크(인페인팅)는 지원되지 않습니다.

사진 한 번만 업로드하세요

/v1/files에 사진을 업로드하고, 매번 요청에 보낼 필요 없이 24시간 동안 원하는 만큼 많은 요청에 사용하세요:

curl https://api.uberllm.dev/v1/files \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -F [email protected]
{ "id": "file_3f9c…", "object": "file", "bytes": 482113, "content_type": "image/png",
  "filename": "skyline.png", "created_at": 1792540800, "expires_at": 1792627200,
  "url": "https://api.uberllm.dev/v1/files/file_3f9c…/content" }

그런 다음 ID 또는 url을(를) 원본 사진이 들어가는 모든 곳에 넣으세요: "image": "file_3f9c…", "image": {"file_id": "file_3f9c…"}, "image_url": "file_3f9c…", input_images의 항목, 또는 비디오의 시작 프레임. 귀하의 계정만 해당 파일을 사용할 수 있습니다.

  • PNG, JPEG, WebP, GIF, HEIC 또는 AVIF, 각 파일당 최대 10MB, 계정당 한 번에 최대 500개까지 보관됩니다.
  • 24시간 동안 보관된 후 삭제됩니다. GET /v1/files/{id}은(는) 하나를 설명하고, GET /v1/files/{id}/content은(는) 다운로드하며, DELETE /v1/files/{id}은(는) 지금 삭제합니다.

비디오 만들기

비디오는 1분 이상 걸리므로, 시작하고, 확인하고, 다운로드하는 작업입니다.

1. 시작하기

curl https://api.uberllm.dev/v1/video/generations \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"model": "fal-ai/vidu/q3/text-to-video/turbo", "prompt": "a red ball bouncing on green grass",
       "duration_seconds": 5, "models": ["fal-ai/kling-video/v3/standard/text-to-video"]}'

models은 선택 사항입니다. 첫 번째 모델에 현재 무료 제공자가 없을 때만 백업 모델이 순서대로 시도되므로, 바쁜 순간에도 요청이 실패하지 않습니다 (대체 모델] 참조). 위 비디오는 약 1분 정도 걸리며 약 $0.33의 비용이 듭니다.

사진으로 시작하려면, 이미지-투-비디오 모델을 사용하고 image_url을 추가하세요:

  -d '{"model": "bytedance/seedance-2-0-image-to-video", "prompt": "slow push-in as the waves roll",
       "image_url": "https://example.com/first-frame.png", "duration_seconds": 5}'

두 장의 사진을 혼합하는 모델은 end_image_url (마지막 프레임)도 받습니다. 텍스트만으로는 비디오를 만들 수 없는 이미지-투-비디오 또는 레퍼런스-투-비디오 모델은 요청에 사진이 없을 경우, 요금이 부과되기 전에 400 image_required으로 거부됩니다. 레퍼런스-투-비디오 모델은 input_images에 있는 사진을 사용합니다:

  -d '{"model": "pixverse/pixverse-c1-reference-to-video", "prompt": "the cat walks across the room",
       "input_images": [{"url": "https://example.com/cat.png", "role": "reference"}],
       "aspect_ratio": "16:9", "duration_seconds": 5}'

모델이 제공하는 다른 필드: resolution (480p, 720p, 1080p…), aspect_ratio (16:9, 9:16, 1:1…) 및 audio (true / false; 사운드 설정이 없는 모델에는 이 설정이 전송되지 않으며, 항상 하던 대로 클립을 만듭니다). 레퍼런스-투-비디오 모델은 모양이 필요하므로, aspect_ratio을 비워두면 16:9로 전송됩니다 (또는 16:9를 만들지 않는 경우 모델의 첫 번째 모양으로). 모델의 schema에 해당 기본값이 표시됩니다. 각 모델의 선택 사항은 GET /v1/models/<model id>에 나열되어 있습니다 (각 모델의 옵션] 참조).

각 모델은 특정 클립 길이, 해상도 및 모양만 만듭니다. 모델이 만들 수 없는 것에 대한 요청은, 요금이 부과되기 전에 모델이 만들 수 있는 것들을 나열하는 메시지와 함께 거부됩니다.

HTTP 202:

{
  "id": "6f1c…",
  "object": "media.job",
  "kind": "video",
  "status": "queued",
  "model": "fal-ai/vidu/q3/text-to-video/turbo",
  "estimated_cost_usd": 0.32725,
  "estimated_cost_usdc": "327250",
  "max_cost_usd": 0.359975,
  "max_cost_usdc": "359975",
  "poll_url": "/v1/video/generations/6f1c…",
  "cancel_url": "/v1/video/generations/6f1c…"
}

model은 작업을 수행한 모델입니다 (첫 번째 모델이 실패했을 때 models의 백업 모델). _usdc로 끝나는 비용은 100만분의 1달러 단위입니다 (327250 = $0.33). estimated_cost_usd은 요청한 항목의 정가입니다. validate와 POST /v1/quote은 cost_usd와 동일한 숫자로 응답합니다. 이는 현재 모델 가격에 초 (요청된 해상도 기준), 이미지 또는 기타 단위를 곱한 값입니다. 작업은 제공자가 청구한 금액으로 청구되며, 이는 더 많거나 적을 수 있습니다. max_cost_usd는 작업에 대해 잔액에서 보류되는 금액입니다. 작업이 실행 중일 때와 완료된 후에도 동일한 금액이며, 작업에 청구될 수 있는 최대 금액입니다. second당 가격이 책정된 비디오 모델은 클립의 초당 요금이 청구됩니다. job당 가격이 책정된 모델은 비디오당 해당 비용이 듭니다.

2. 확인하기 5–10초마다:

curl -H "Authorization: Bearer $UBERLLM_API_KEY" \
  https://api.uberllm.dev/v1/video/generations/<job id>

작업 실행 중에는 HTTP 202, 작업 완료 시에는 HTTP 200:

{
  "id": "6f1c…",
  "status": "succeeded",
  "results": [{ "artifact_index": 0, "url": "https://api.uberllm.dev/v1/media/artifacts/6f1c…/0",
                "content_type": "video/mp4", "duration_seconds": 5 }],
  "usage": { "cost_usdc": "40000", "cost_usd": 0.04 }
}

모델은 파일이 준비된 직후, 일반적으로 30초 이내에 작업의 정확한 요금을 보고합니다. 그때까지 succeeded 작업은 "usage": { "cost_usd": null, "cost_pending": true }를 표시합니다. 몇 초 후에 다시 요청하세요. 만약 30분 이내에 요금이 나오지 않으면, 작업은 정가 (estimated_cost_usd)로 청구되며 usage.cost_note에 그렇게 표시됩니다.

3. 다운로드하기

curl -L -o video.mp4 -H "Authorization: Bearer $UBERLLM_API_KEY" \
  https://api.uberllm.dev/v1/media/artifacts/<job id>/0

더 이상 필요 없는 작업을 중지하려면 DELETE /v1/video/generations/<job id>를 요청하세요. 저희는 제공자에게 중지를 요청합니다. 이미 만들어진 작업은 평소와 같이 청구되며, 중지된 작업은 canceled으로 끝나며 비용이 들지 않습니다.

Fal 비디오 모델

ID가 fal-ai/로 시작하는 모델은 Fal에서 Fal 자체 가격보다 저렴하게 실행됩니다. 현재 마켓플레이스에서 가장 저렴한 Fal 판매자의 할인 가격을 제외한 Fal 가격을 지불합니다 (2026년 10월 30일에서는 15% 할인; 해당 판매자가 판매할 때마다 25% 할인). 가격은 요청하는 내용(초당 해상도 요율, 클립에 사운드 유무)에 따라 결정되므로, 작업 시작 시 비용을 알 수 있으며 estimated_cost_usd가 정확히 청구됩니다. 실패한 작업에는 비용이 청구되지 않습니다. 작업 중단은 최선을 다하지만, Fal이 이미 클립을 생성했다면 비용이 청구됩니다.

curl https://api.uberllm.dev/v1/video/generations \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "fal-ai/wan/v2.7/text-to-video", "prompt": "a woman twirls at a garden party at night",
       "duration_seconds": 15, "resolution": "720p", "aspect_ratio": "9:16"}'

Fal 자체의 초당 가격 (귀하의 가격은 실시간 할인을 제외한 가격입니다; 각 모델 페이지 GET /v1/models 및 POST /v1/quote에서 현재 정확한 가격을 확인할 수 있습니다):

모델 길이 (초) Fal의 초당 가격, 시작
fal-ai/wan/v2.7/text-to-video, …/image-to-video 2–15 720p $0.10 · 1080p $0.15
fal-ai/kling-video/v3/standard/text-to-video, …/image-to-video 3–15 $0.084 · 사운드 포함 $0.126
fal-ai/kling-video/v3/pro/text-to-video, …/image-to-video 3–15 $0.112 · 사운드 포함 $0.168
fal-ai/kling-video/o3/standard/text-to-video, …/image-to-video 3–15 $0.084 · 사운드 포함 $0.112
fal-ai/kling-video/v2.6/pro/text-to-video, …/image-to-video 5, 10 $0.07 · 사운드 포함 $0.14
fal-ai/veo3.1/fast, fal-ai/veo3.1/fast/image-to-video 4, 6, 8 720p/1080p $0.10 · 사운드 포함 $0.15 · 4k $0.30
fal-ai/veo3.1, fal-ai/veo3.1/image-to-video 4, 6, 8 720p/1080p $0.20 · 사운드 포함 $0.40 · 4k $0.40
fal-ai/veo3.1/lite 4, 6, 8 720p $0.03 · 사운드 포함 $0.05 · 1080p $0.05
fal-ai/ltx-2.3/text-to-video/fast, …/image-to-video/fast 6, 8, 10 1080p $0.06 · 1440p $0.12 · 2160p $0.24
fal-ai/ltx-2.3/text-to-video 6, 8, 10 1080p $0.08
fal-ai/minimax/hailuo-02/standard/text-to-video, …/image-to-video 6, 10 768P $0.045 · 512P (이미지) $0.017
fal-ai/vidu/q3/text-to-video/turbo, …/image-to-video/turbo 1–16 360p/540p $0.035 · 720p/1080p $0.077
fal-ai/vidu/q3/text-to-video, …/image-to-video 1–16 360p/540p $0.07 · 720p/1080p $0.154

각 가격은 Fal 자체 가격입니다; 작업 시작 시 할인이 적용됩니다. 가장 저렴한 판매자가 작업을 거부하면, 더 비싼 판매자가 작업을 수행하며 해당 판매자의 가격으로 작업이 청구됩니다. 이 경우 응답 시 estimated_cost_usd를 초과하지 않습니다.

일부 모델은 판매자 할인에 명시된 것보다 적은 비용이 듭니다. 매 6시간마다 지난 7일 동안 마켓플레이스가 각 모델에 대해 청구한 금액을 동일한 작업에 대한 Fal의 가격과 비교합니다. 해당 기간 동안 최소 20개의 작업을 수행한 모델은, 더 낮은 경우 실제 점유율에 5%를 더한 가격으로 책정됩니다. 모델 페이지 /v1/models와 청구서 모두 동일한 가격을 사용합니다. 해당 수치가 3일보다 오래된 경우, 판매자 할인이 다시 적용됩니다.

다음 필드는 당사에서 제공합니다: duration_seconds, resolution, aspect_ratio, audio 및 image_url (또는 input_images). Fal 자체 표기법 (duration, generate_audio, start_image_url)도 작동합니다. Kling, Veo 및 Kling 2.6은 "audio": false을 보내지 않는 한 사운드를 추가합니다.

작업 상태

status HTTP 의미
queued 202 승인됨, 모델이 시작하기를 기다리는 중
running 202 제작 중; 모델이 보고하면 progress이 0에서 1으로 변경됩니다
succeeded 200 완료됨; results[].url 다운로드
failed 200 제작되지 않음. error.message은 이유를 알려주고; error.retryable은 다시 시도할 수 있는지 알려줍니다
canceled 200 제작되기 전에 중단됨
expired 200 시간 내에 완료되지 않음

이 여섯 가지가 유일한 값입니다. failed, canceled, expired은 비용이 들지 않습니다. DELETE는 중단 요청이지 약속이 아닙니다: 공급자가 어쨌든 완료하는 작업은 succeeded로 끝나고 요금이 청구됩니다.

바쁜 순간에는 자동으로 재시도됩니다. 비디오를 제작할 수 있는 공급자가 없거나, 현재 너무 바쁠 때, UberLLM은 10분 이내에 최대 두 번까지 작업을 자동으로 다시 시작합니다. 동일한 job id와 최대 예상 비용을 유지합니다. 작업은 단지 조금 더 오래 걸릴 뿐입니다. 모든 시도가 실패했을 때만 failed을 보게 되며, 실패한 작업에는 비용이 들지 않습니다.

대기 중. callback_url을 보내주시면 작업이 언제 끝나는지 알려드리거나 ( Callbacks 참조), 5–10초마다 poll URL을 확인하세요. 대부분의 비디오는 1–5분 정도 걸리며; 일부 길거나 4K 작업은 더 오래 걸립니다. 요금 정산을 위해 계속 확인할 필요는 없습니다: 아무도 확인하지 않는 작업도 UberLLM에 의해 완료되고 청구(또는 환불)되며, Dashboard → Activity에 표시됩니다.

콜백

비디오 또는 음악 작업에 callback_url를 추가하세요: 공개 호스트의 https:// 링크입니다. 작업이 완전히 종료되면 UberLLM은 작업에서 GET가 반환하는 것과 동일한 JSON과 함께 해당 링크로 POST를 보냅니다.

{ "model": "kling/kling-o3", "prompt": "a red ball bouncing", "duration_seconds": 5,
  "callback_url": "https://your-app.example/uberllm/jobs" }
  • 시기. 작업이 종료되고 요금이 확정되면 한 번: usage.cost_usd가 설정된 succeeded (절대 cost_pending 아님), 또는 failed, canceled 또는 expired (비용 0). 비용이 도착할 때 다시 전송되지 않습니다. 비용 도착 후에만 전송되기 때문입니다. output_upload_url의 경우에도 업로드가 완료된 후에 콜백이 오므로 output_upload.status는 이미 delivered 또는 failed입니다.
  • 헤더. Content-Type: application/json, UberLLM-Event: job.succeeded (또는 job.failed, job.canceled, job.expired), UberLLM-Event-Id: <job id>:<status> 및 UberLLM-Signature: t=<unix seconds>,v1=<hex>.
  • 재시도. 15초 이내에 2xx로 응답하세요. 다른 응답이거나 응답이 없는 경우, 30초, 2분, 10분, 30분, 2시간 후에 다시 시도한 다음 포기합니다. 언제든지 작업을 폴링할 수 있습니다.
  • 반복. 메시지가 두 번 이상 도착할 수 있습니다 (예: 응답이 손실된 경우). 이벤트 ID는 동일하게 유지되므로 이미 처리한 메시지는 삭제하세요.
  • 상태. 작업 진행 상황은 다음과 같습니다: "callback": { "status": "delivered", "attempts": 1, "http_status": 200, "delivered_at": 1792540990 }. status은 pending, delivered 또는 failed입니다 (error은 일반 텍스트로 표시됨).
  • 링크는 공개 호스트에 https://여야 하며, 사용자 이름이나 비밀번호를 포함해서는 안 됩니다. 이 링크는 다시 표시되지 않으며 콜백이 끝나면 삭제됩니다. webhook_url는 동일한 필드로 읽힙니다. 이미지와 음성은 이를 사용하지 않습니다. 응답 자체로 돌아옵니다.

서명 확인

모든 메시지는 계정의 웹훅 비밀로 서명됩니다. 대시보드 → API keys → Webhook signing secret]에서 찾을 수 있습니다. 처음 열 때 생성되며, Replace secret를 통해 즉시 변경할 수 있습니다.

v1은 전체 비밀 (whsec_…)로 키가 지정된 <t>.<raw body>의 헥스 HMAC-SHA256입니다. 수신한 원시 바이트 (JSON 파싱 전)에 대해 계산하고, 상수 시간으로 비교하며, 5분 이상 된 t는 거부하세요.

Node.js (Express):

import crypto from "node:crypto";
import express from "express";

const app = express();
const SECRET = process.env.UBERLLM_WEBHOOK_SECRET; // whsec_…

app.post("/uberllm/jobs", express.raw({ type: "application/json" }), (req, res) => {
  const header = req.get("UberLLM-Signature") || "";
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=", 2)));
  const expected = crypto.createHmac("sha256", SECRET)
    .update(`${parts.t}.`).update(req.body).digest("hex");
  const ok = parts.v1 && parts.v1.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected)) &&
    Math.abs(Date.now() / 1000 - Number(parts.t)) < 300;
  if (!ok) return res.status(400).send("bad signature");
  const job = JSON.parse(req.body);
  // Drop a repeat: req.get("UberLLM-Event-Id") is the same each time.
  console.log(job.id, job.status, job.usage?.cost_usd);
  res.sendStatus(204);
});

Python (Flask):

import hashlib, hmac, os, time
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = os.environ["UBERLLM_WEBHOOK_SECRET"].encode()  # whsec_…

@app.post("/uberllm/jobs")
def uberllm_job():
    raw = request.get_data()  # the raw bytes, before any JSON parsing
    parts = dict(p.split("=", 1) for p in request.headers.get("UberLLM-Signature", "").split(",") if "=" in p)
    expected = hmac.new(SECRET, parts.get("t", "").encode() + b"." + raw, hashlib.sha256).hexdigest()
    if not hmac.compare_digest(parts.get("v1", ""), expected) or abs(time.time() - int(parts.get("t", "0"))) > 300:
        abort(400)
    job = request.get_json()
    # Drop a repeat: request.headers["UberLLM-Event-Id"] is the same each time.
    print(job["id"], job["status"], job.get("usage", {}).get("cost_usd"))
    return "", 204

웹훅으로 알림

알림 이메일은 웹훅으로도 전송될 수 있습니다. 대시보드 → Credits → For developers: also send alerts to a webhook]에서 링크를 설정하거나, PUT /api/v1/billing/alerts {"alerts_webhook_url": "https://…"} (null은 끄기)를 설정하세요. 메시지는 콜백과 동일한 방식으로 서명되고, 재시도되며, 식별됩니다. 본문은 다음과 같습니다.

{ "id": "evt_…", "object": "event", "type": "balance.low", "created": 1792540990,
  "data": { "balance_usd": 4.2, "threshold_usd": 5, "message": "Your balance is $4.20, below the $5.00 you set. Requests stop once it runs out.",
            "add_credits_url": "https://uberllm.dev/dashboard/credits" } }
  • balance.low: 잔액이 저잔액 이메일에 설정한 금액 미만으로 떨어졌습니다. 금액 미만으로 떨어질 때마다 한 번 전송됩니다. 금액을 설정하기 전까지는 아무것도 전송되지 않습니다.
  • hold.not_released: 작업이 종료된 후 15분 이상 작업에 할당된 금액이 계속 보류되었습니다. data.jobs에 해당 목록이 있으며 (id, kind, model, ended_at, held_usd), data.held_usd은 총액입니다. 이 금액은 여전히 귀하의 것이며, 저희 팀에 통보되었습니다.

파일 보관 기간

결과가 생성된 직후 다운로드하세요:

  • 동영상 및 음악 파일은 작업이 끝난 후 약 3시간 동안 보관됩니다.
  • /v1/media/artifacts/…로 연결되는 이미지 링크는 약 15분 동안 보관됩니다. /v1/files/…로 연결되는 이미지 링크는 24시간 동안 보관됩니다. 답변 내부에 그림을 포함하여 직접 보관하려면 "response_format": "b64_json"를 요청하세요.
  • /v1/files에 업로드한 사진은 24시간 동안 보관됩니다.

그 이후에는 다운로드 시 404 artifact_expired으로 응답합니다.

결과를 자체 스토리지로 전송

동영상 또는 음악 작업에 output_upload_url을 추가하세요: presigned S3, R2 또는 Google Cloud Storage 업로드 링크와 같이 HTTP PUT을 허용하는 https:// 링크입니다. 작업이 성공하면 UberLLM은 해당 파일의 콘텐츠 유형과 함께 파일을 그곳에 업로드합니다. 여러 파일을 생성하는 작업의 경우, 파일당 하나의 링크를 순서대로 output_upload_urls로 보내세요 (최대 4개).

{ "model": "kling/kling-o3", "prompt": "a red ball bouncing", "duration_seconds": 5,
  "output_upload_url": "https://my-bucket.s3.amazonaws.com/ball.mp4?X-Amz-Signature=…" }

그러면 작업 상태에 output_upload이(가) 포함됩니다:

"output_upload": { "status": "delivered", "attempts": 1, "delivered_at": 1792540990,
  "files": [{ "artifact_index": 0, "http_status": 200, "bytes": 5242880 }] }
  • status은(는) 업로드가 완료될 때까지 pending입니다. 그 후 delivered 또는 failed (error는 일반적인 단어로 표시됨)가 됩니다.
  • 업로드 실패 시 30초, 2, 10, 30분 후에 다시 시도됩니다. 그 후 failed으로 표시됩니다. 파일이 보관되는 동안에는 results[].url에서 계속 다운로드할 수 있습니다. 링크는 최소 한 시간 동안 유효해야 합니다.
  • 링크는 공용 호스트에서 https://이어야 하며, 사용자 이름이나 비밀번호가 포함되어서는 안 됩니다. 이 링크는 다시 표시되지 않으며, 업로드가 완료되면 삭제됩니다.
  • 이미지는 이를 사용하지 않습니다. 이미지는 답변 자체에 포함되어 돌아옵니다.

음악

/v1/music/generations에서 같은 세 단계입니다. curl -OJ는 저희가 보내는 파일 이름으로 트랙을 저장합니다.

음성

텍스트를 입력하면 오디오 파일이 답변으로 돌아옵니다.

curl https://api.uberllm.dev/v1/audio/speech \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "x-ai/tts-xai-v1", "input": "Hello from UberLLM."}' \
  -o speech.mp3

voice, response_format (예를 들어 mp3 또는 wav) 및 speed를 보낼 수도 있습니다. 각 모델에는 고유한 음성이 있습니다 (GET /v1/models/{id}에 목록이 있습니다). best-price:speech 또는 fastest:speech을 사용하면 어떤 모델이 사용될지 미리 알 수 없으므로, 음성이 모델에 맞춰집니다. 모델이 가지고 있는 음성은 유지되며, OpenAI의 이름은 모델이 해당 음성을 가지고 있는 경우 모델의 일치하는 음성에 매핑됩니다 (alloy → af_alloy). 다른 음성이거나 음성이 없는 경우, 모델의 첫 번째 음성이 사용됩니다. 모델 이름을 지정하면, 사용자의 음성은 그대로 전송됩니다. input의 1K자 단위로 요금이 청구됩니다. 답변은 오디오 파일이며, 해당 X-UberLLM-Cost-USD 헤더에는 비용이 명시되어 있고, X-Request-Id은 활동(Activity)에 나열된 요청 ID입니다. "validate": true, max_cost, metadata, models 및 provider.max_price은 이미지와 동일하게 작동합니다 (요금 안내] 참조).

녹음을 텍스트로 변환하기

녹음을 file 및 model을 포함한 양식으로 보내세요:

curl https://api.uberllm.dev/v1/audio/transcriptions \
  -H "Authorization: Bearer $UBERLLM_API_KEY" \
  -F model=venice/whisper-large-v3 \
  -F [email protected]
{ "text": "Hello from UberLLM.", "duration": 4.2,
  "usage": { "type": "duration", "seconds": 5, "cost_usd": 0.00055, "max_cost_usd": 0.00726 } }

비용은 usage.cost_usd입니다 (또한 X-UberLLM-Cost-USD 헤더에 있으며, text, srt, vtt 답변을 위한 유일한 장소입니다). 저희 자체 필드도 양식에 포함되며, 모델로 전송되지 않습니다: -F max_cost=0.10, -F "metadata[project]=podcast", -F validate=true.

또한 language, prompt, temperature, response_format를 보낼 수 있습니다: json (기본값), 또는 text, srt, vtt를 통해 일반 텍스트를 받을 수 있습니다. 오디오 1분당 요금이 청구됩니다. 파일은 최대 40 MB까지 가능합니다. 형식(mp3, wav, ogg, flac, m4a/mp4, webm, aac)은 파일 이름이 아닌 녹음 자체에서 읽히므로, tmp123.out이라는 이름의 업로드도 작동합니다.

OpenAI SDK로

from openai import OpenAI

client = OpenAI(base_url="https://api.uberllm.dev/v1", api_key="<your UberLLM key>")

speech = client.audio.speech.create(model="x-ai/tts-xai-v1", voice="eve", input="Hello from UberLLM.")
speech.write_to_file("speech.mp3")

with open("speech.mp3", "rb") as f:
    text = client.audio.transcriptions.create(model="venice/whisper-large-v3", file=f)
print(text.text)

지불하는 금액

  • 생성된 결과물 가격: 공급자가 청구한 금액이며, UberLLM 수수료는 없습니다. 이미지 또는 전사(transcription) 답변과 완료된 작업은 usage.cost_usd (미국 달러)로 청구됩니다. 무언가를 생성한 모든 답변은 X-UberLLM-Cost-USD response header에도 포함됩니다 (음성(speech)의 경우, 답변이 오디오 파일이므로 header가 유일한 위치입니다). 이 내역은 대시보드 → 활동에서 확인할 수 있습니다. 나머지 보류 금액은 반환됩니다.
  • failed, canceled 또는 expired된 작업, 또는 실패한 이미지, 음성(speech), 전사(transcription) 요청에 대해서는 아무것도 청구되지 않습니다.
  • 요청하신 내용을 정확히 생성하는 가장 저렴한 판매자. 많은 이미지 및 비디오 모델은 여러 판매자를 가집니다. 각 요청은 설정에 따라 생성할 수 있는 가장 저렴한 판매자에게 전달되며, 해당 판매자가 처리할 수 없는 경우 다른 판매자에게 전달됩니다. 모델 목록과 각 모델 페이지에는 현재 가장 저렴한 판매자의 가격이 표시됩니다.
  • GET /v1/balance (아래 참조)에서 잔액과 보류 중인 금액을 확인하세요.

사용 전 가격 확인

모든 이미지, 비디오, 음악 또는 음성(speech) 요청에 "validate": true를 추가하세요 (전사(transcription)의 경우, 녹음 파일과 함께 validate=true를 form field로 보내세요). 요청은 실제처럼 확인되지만 (모델, 옵션, 원본 이미지), 아무것도 생성되지 않고 아무것도 청구되지 않습니다. HTTP 200는 명시된 가격 (cost_usd, 모델 페이지에 표시된 가격; 실제로는 공급자가 청구한 금액을 지불하며, 이는 다를 수 있습니다)과 실행 중 보류되는 금액 (max_cost_usd, 최대 청구 금액)을 알려줍니다.

{ "object": "quote", "model": "bytedance/seedance-2-0-image-to-video", "kind": "video",
  "valid": true, "cost_usd": 0.2117, "max_cost_usd": 0.4235, "unit": "second", "units": 5, "duration_seconds": 5,
  "note": "Nothing was charged. …" }

모델 판매자가 누락된 설정 (예: 비디오 참조 모델이 aspect_ratio를 필요로 하는 경우)을 필요로 한다면, 기본값은 모델의 schema와 견적에 defaults_applied로 표시됩니다 (예: "defaults_applied": {"aspect_ratio": "16:9"}).

거부될 요청은 동일한 방식으로 이유와 함께 거부됩니다.

15분 동안 가격 유지

POST /v1/quote는 이미지, 비디오, 음악 또는 음성(speech) 요청과 동일한 body를 사용하며, 명시된 비용 (cost_usd), 실행 중 보류되는 금액 (max_cost_usd, 최대 청구 금액) 및 quote_id를 반환합니다 (전사(transcription)의 경우 model와 duration_seconds를 보내세요; 전사(transcription) 자체는 quote_id를 사용하지 않으므로 max_cost를 사용하여 제한하세요).

curl https://api.uberllm.dev/v1/quote \
  -H "Authorization: Bearer $UBERLLM_API_KEY" -H "Content-Type: application/json" \
  -d '{"model": "kling/kling-o3", "prompt": "a red ball bouncing", "duration_seconds": 5}'
{ "object": "quote", "id": "6f1c…", "quote_id": "6f1c…", "model": "kling/kling-o3",
  "kind": "video", "cost_usd": 0.225, "max_cost_usd": 0.495, "unit": "job", "units": 1,
  "expires_at": 1792541700, "note": "Nothing was charged. …" }

15분 이내에 "quote_id": "6f1c…"와 함께 동일한 요청을 보내면, 공급자가 청구한 금액 (최대 max_cost_usd)이 청구됩니다. 시작 시 보류되어야 할 금액이 max_cost_usd를 초과하면, 무료로 취소됩니다. 견적 자체에 대해서는 아무것도 청구되거나 보류되지 않습니다.

  • 하나의 견적은 하나의 요청을 시작합니다. 다시 사용하면 409 quote_used가 반환됩니다. 모델에 도달하지 못한 작업은 견적을 반환합니다.
  • 요청은 동일한 내용을 요구해야 합니다: 동일한 모델 및 동일한 설정 (prompt, size, clip length, source pictures …). 그 외의 모든 것은 400 quote_mismatch로 거부됩니다. max_cost, metadata 및 output_upload_url는 다를 수 있습니다.
  • 15분 후에는 400 quote_expired가 반환됩니다. 채팅 모델은 token당 청구되며 견적이 없습니다: provider.max_price로 제한하세요.

대체 모델 및 가격 상한선

"models": ["model-b", "model-c"]는 첫 번째 모델을 지금 바로 제공할 수 없거나 (no_available_provider) provider.max_price를 초과할 때 순서대로 시도할 모델의 이름을 지정합니다. 다른 모든 거부는 즉시 응답됩니다. 답변의 model는 결과물을 생성한 모델의 이름을 지정합니다 (음성(speech) 답변은 오디오 파일 자체입니다: 활동에서 해당 모델을 보여줍니다). quote_id가 포함된 요청은 models를 사용하지 않으며, 전사(transcription)는 둘 다 사용하지 않습니다.

"provider": {"max_price": 0.05}는 한 단위 (모델의 가격 책정 unit: 이미지, 초, 메가픽셀, 분, 1K 문자 또는 요청)가 미국 달러로 청구될 수 있는 최대 금액입니다. 이를 초과하는 모델은 400 max_price_exceeded로 거부되며, 요청은 해당 단위의 max_price배를 초과하여 청구되지 않습니다. 다른 provider 옵션은 400 unsupported_routing_option로 거부됩니다. 미디어 요청의 판매자 선택은 요청별로 조종할 수 없기 때문입니다.

"model": "best-price:image" (또는 image-edit, text-to-video, image-to-video, music, speech, transcription)는 작업에 가장 저렴한 활성 모델을 선택합니다. fastest:는 측정된 것 중 가장 빠른 모델을 선택합니다. 모델 별칭를 참조하세요.

태그

"metadata": {"project": "spring-ads"} (최대 16개의 텍스트 값)는 작업과 함께 저장되고, 상태에 따라 반환되며, 활동 및 CSV 내보내기에서 표시되고, 모델로 전송되지 않습니다. 전사(transcription)의 경우, form field로 보내세요: -F "metadata[project]=spring-ads". 태그를 참조하세요.

상한선 설정하기

모든 이미지, 비디오, 음악 또는 음성(speech) 요청에 "max_cost" (미국 달러, 예: 0.50)를 보내세요 (전사(transcription)의 경우 form field). 비용이 이를 초과할 수 있다면, 400 max_cost_too_low로 거부되며 아무것도 청구되지 않습니다. 비디오 또는 음악 작업의 경우 정확한 상한선은 작업 시작 시 설정됩니다. 만약 작업이 max_cost를 초과하면, 무료로 취소됩니다. "validate": true를 사용하면 견적에 within_max_cost가 추가됩니다.

두 번 결제 없이 재시도

비디오 또는 음악 작업을 시작할 때 Idempotency-Key header (UUID와 같이 최대 255자까지의 고유한 문자열)를 보내세요. 연결이 끊어지고 24시간 이내에 동일한 키로 동일한 요청을 다시 보내면, 두 번째 작업 대신 동일한 작업을 다시 받게 됩니다. 다른 요청과 함께 동일한 키를 사용하면 409 idempotency_key_reused로 거부됩니다. 이미지, 음성(speech) 및 전사(transcription) 요청은 키를 사용하지 않습니다: 실패한 요청은 청구되지 않았으므로 다시 보내세요.

잔액

curl -H "Authorization: Bearer $UBERLLM_API_KEY" https://api.uberllm.dev/v1/balance
{ "balance_usd": 12.40, "held_usd": 0.35, "available_usd": 12.05 }

held_usd는 아직 실행 중인 요청을 위해 할당되었습니다. 해당 요청이 완료되면 (실제 비용을 제외하고) 다시 돌아옵니다. available_usd는 새로운 요청에 사용할 수 있습니다.

각 모델의 옵션

GET /v1/models?type=image (또는 video, music, speech, transcription, 이 둘 모두에 대한 audio, chat, all; 쉼표로 여러 개 연결됨; type가 없으면 목록은 채팅 모델만 표시됩니다)는 현재 호출할 수 있는 모델을 나열하며, 각 모델은 해당 type, 그것을 보낼 endpoints, 그리고 해당 pricing를 포함합니다. GET /v1/models/<model id>은 하나의 모델을 제공하며, 미디어 모델의 경우 클립 길이, 해상도, 화면 비율 및 허용하는 크기, 그리고 필요한 원본 이미지를 포함하는 요청 본문의 JSON Schema인 parameters 객체를 제공합니다.

curl -H "Authorization: Bearer $UBERLLM_API_KEY" \
  https://api.uberllm.dev/v1/models/pixverse/pixverse-c1-reference-to-video

pricing는 usd (현재 unit 하나가 가장 비싼 가격)과 list_usd (모델 제작사 자체 가격)을 가집니다. 채팅 모델은 input_usd, output_usd 그리고 1M tokens당 list_ 가격을 가집니다.

오류

HTTP 코드 의미
400 wrong_endpoint 예를 들어, 이미지 모델을 /v1/video/generations로 보냈거나, 채팅 모델을 이미지 경로로 보냈거나, 음성 모델을 /v1/audio/transcriptions로 보낸 경우; 메시지에 올바른 경로가 표시됩니다. 요금은 청구되지 않으며, 활동 내역에 거부됨으로 표시됩니다.
400 invalid_request 요청이 잘못되었습니다 (메시지에 이유가 나와 있습니다. 예를 들어, 모델이 제공하지 않는 기간이거나 원본 사진이 없는 경우).
400 image_required 원본 사진이 없는 편집, 또는 이미지-비디오 또는 참조-비디오 모델 요청입니다.
400 max_cost_too_low max_cost보다 비용이 더 많이 들 수 있습니다. 요금은 청구되지 않았습니다.
409 idempotency_key_reused 해당 Idempotency-Key가 다른 요청에 사용되었습니다.
400 quote_mismatch / quote_expired 요청이 견적과 일치하지 않거나, 견적이 15분 이상 경과했습니다.
404 quote_not_found 계정에 해당 견적이 없습니다.
409 quote_used 해당 견적으로 이미 요청이 시작되었습니다.
400 max_price_exceeded 모델의 단위당 비용이 provider.max_price보다 높습니다.
400 unsupported_routing_option max_price 이외의 provider 옵션입니다.
404 file_not_found 계정에 해당 업로드 파일이 없거나, 만료되었습니다.
413 file_too_large 10 MB를 초과하는 업로드입니다.
429 too_many_files 이미 500개의 업로드 파일이 보관되어 있습니다. 일부를 삭제하거나 만료될 때까지 기다려 주세요.
503 files_unavailable 현재 업로드를 이용할 수 없습니다.
413 request_too_large 요청이 크기 제한(40 MB)을 초과했습니다. 사진은 https:// 링크로 보내고, 긴 녹음 파일은 분할하여 보내주세요.
402 insufficient_credits 잔액이 작업의 최대 비용을 충당할 수 없습니다. 메시지에 필요한 금액이 표시됩니다.
404 model_not_found / not_found 해당 모델이 없거나, 계정에 해당 작업이 없습니다.
404 artifact_expired 파일이 더 이상 보관되지 않습니다 (위 참조).
429 rate_limited Retry-After에 표시된 시간(표시되지 않은 경우 몇 초)만큼 기다린 후 다시 시도해 주세요. X-RateLimit-Remaining는 이번 분에 남은 요청 수를 보여줍니다.
503 no_available_provider 현재 이 작업을 수행할 수 있는 판매자가 없습니다. UberLLM이 이미 다른 판매자들을 시도했습니다. 메시지에 현재 작동하는 동일한 종류의 모델 이름이 표시됩니다.