Sume API에서 생성한 영상 다운로드하기: 401과 302

Sume의 unsigned_urls는 API 키가 필요하고 302 리다이렉트로 응답합니다. curl -L이나 코드로 MP4를 내려받고, 401, 404, 409를 각각 해결하세요.

읽는 시간 5분Sume
전체 글

Sume API에서 생성한 영상을 내려받으려면 Job의 status가 completed가 될 때까지 기다린 다음, API 키를 붙여 unsigned_urls 항목인 https://api.sume.com/v1/videos/{id}/content?index=0에 GET 요청을 보내고, 302 리다이렉트를 따라 파일로 가세요. 키가 없으면 이 경로는 401 unauthorized로 응답하고, 리다이렉트를 따라가지 않으면 MP4 대신 리다이렉트 응답을 저장하게 됩니다.

이 글의 사실은 Sume의 영상 생성 (영문)과 Job과 결과 (영문) 문서, Sume API 레퍼런스, curl 매뉴얼 페이지에서 가져왔으며, 모두 2026-09-27에 확인했습니다. 현재 코드로 표시한 동작은 API 소스에서 읽은 것입니다. Job 제출과 폴링은 OpenRouter 호환 영상 API에서 다룹니다.

다운로드 URL이 왜 401을 반환하나요?

unsigned_urls에 담긴 것은 파일 URL이 아니라 API URL입니다. 각 항목은 출력 하나에 대한 content 경로이며, 제출이나 폴링과 마찬가지로 키를 Authorization: Bearer나 x-api-key 중 하나로만 받고, 둘 다 받지는 않습니다. 키가 없거나, 형식이 잘못됐거나 폐기된 키를 쓰거나, 두 헤더를 모두 보낸 요청은 401 unauthorized를 받습니다. index의 기본값은 0이며, 모델이 출력을 여러 개 돌려줄 때 그중 하나를 고릅니다.

또한 키는 자기 워크스페이스만 볼 수 있습니다. 현재 코드에서는 알 수 없는 Job ID, 다른 워크스페이스의 Job, 영상 생성이 아닌 Job에 404로 응답합니다.

curl로 파일을 어떻게 내려받나요?

-L을 붙이세요. 이 옵션이 없으면 curl은 302를 따라가지 않으므로 --output에는 MP4가 아니라 리다이렉트 응답이 저장됩니다. --fail도 붙이세요. curl은 기본적으로 HTTP 오류 코드를 실패로 취급하지 않으므로, 이 옵션이 없으면 409 오류 본문이 영상 파일에 들어가게 됩니다. 바이트 대신 파일 URL을 보관하려면 -L을 빼고 %{redirect_url}을 출력하세요. curl은 리다이렉트가 향했을 URL로 이 값을 채웁니다.

# Download the first output, following the redirect
curl -L --fail -o video.mp4 \
  -H "Authorization: Bearer $SUME_API_KEY" \
  "https://api.sume.com/v1/videos/job_123/content?index=0"

# Or print the file's URL without downloading it
curl -s -o /dev/null -w '%{redirect_url}\n' \
  -H "Authorization: Bearer $SUME_API_KEY" \
  "https://api.sume.com/v1/videos/job_123/content?index=0"

API 키가 파일 호스트로도 전달되나요?

Authorization으로 보내면 전달되지 않습니다. 현재 코드에서 302는 api.sume.com과 다른 호스트인 media.sume.com의 공개 영상 파일을 가리키며, 이 두 번째 요청에는 Sume 키가 필요 없습니다. curl 매뉴얼 페이지에 따르면 Authorization:과 Cookie: 헤더는 --location-trusted를 쓰지 않는 한 다른 오리진으로 가는 리다이렉트에 전달되지 않지만, -H로 설정한 다른 헤더는 리다이렉트를 포함한 모든 요청에 실립니다. 그러니 -L을 쓸 때는 Authorization: Bearer를 보내세요. x-api-key 헤더라면 파일 호스트로도 가게 됩니다.

Python의 Requests 라이브러리도 빠른 시작 문서에 따르면 리다이렉트가 다른 호스트로 갈 때 Authorization 헤더를 제거합니다. Python 따라 하기는 이 방식으로 파일을 스트리밍합니다. 리다이렉트를 스스로 따라가지 않는 클라이언트라면 302의 Location 헤더를 읽고 그 URL을 Sume 키 없이 가져오면 됩니다.

content 경로는 무엇을 반환하나요?

레퍼런스는 409 job_not_completed를 재시도 가능한 오류로 설명하는데, 현재 코드에서는 취소된 Job도 details.status: "canceled"와 함께 같은 코드를 받습니다. 재시도하기 전에 details.status를 읽고, canceled이면 멈추세요.

영상 생성 (영문), Sume API 레퍼런스, 오류와 요청 한도 (영문), 현재 API 코드 기준, 2026-09-27 확인.
응답경우할 일
302 리다이렉트Job이 completed이고 index에 출력이 있음영상 파일로 따라가기
400 invalid_requestindex가 0 이상의 정수가 아님쿼리 문자열 수정
401 unauthorized키 없음, 형식이 잘못됐거나 폐기된 키, 또는 인증 헤더를 둘 다 보냄유효한 키 하나만 보내기
404 not_foundJob ID가 이 키의 워크스페이스에 있는 영상 생성 Job이 아님ID와 키의 워크스페이스 확인
404 video_content_not_found해당 index에 출력이 없음unsigned_urls 길이보다 작은 인덱스 사용
409 job_not_completedJob이 아직 끝나지 않았거나 취소됨실행 중이면 재시도 가능: GET /v1/videos/{id}를 폴링한 뒤 재시도
409 job_failed생성 실패재시도 불가: error.message에 공개 사유가 담김
429읽기 예산 소진retry-after만큼 대기

어떤 URL을 저장하거나 사용자에게 보여 줘야 하나요?

unsigned_urls 항목이 아니라 리다이렉트가 가리키는 Sume 미디어 URL을 저장하거나 보여 주세요. 브라우저나 앱이 API URL을 열려면 API 키가 필요한데, 키는 프론트엔드 JavaScript나 모바일 앱에 절대 넣으면 안 됩니다. 같은 Job은 GET /v1/jobs/{id}/result에서도 읽을 수 있으며, 그 산출물 목록에는 파일이 공개 media.sume.com URL로 나옵니다. 현재 코드에서 리다이렉트는 바로 그 산출물의 URL로 갑니다.

Sume 소유의 산출물 URL은 공개 계약이지만 원본 프로바이더 URL은 그렇지 않으므로, Sume URL을 보관하세요. 이 URL이 만료되는지, 만료된다면 언제인지는 Sume 영상 URL은 만료되나요?에서 다룹니다.

출처

관련 글

개발자 카테고리의 다른 글

개발자 글 전체 보기

작성자 Sume