콘텐츠로 건너뛰기
FreshApp Demo

개발자 문서

생성 API 문서

생성 API로 내 코드에서 사이트의 모델을 사용해 생성 작업을 만듭니다. 요청에는 모델과 입력을 적고, 응답으로 받은 생성 작업을 끝날 때까지 따라간 뒤 파일을 이 사이트에서 내려받습니다. 이 페이지의 모델, 가격, 한도, 오류 코드는 지금 실제로 적용되는 값입니다.

API로 생성 작업을 만들려면 유료 크레딧 팩이나 활성 유료 구독이 필요하며, 유료 크레딧만 사용합니다. 조회, 목록, 다운로드는 계정의 어떤 키로도 할 수 있습니다.

빠른 시작

API 키 페이지에서 키를 만들고, 서버에만 두고, API_KEY로 설정하세요. 아래 예시는 seed-audio-1.0(으)로 생성 작업을 만들고, 끝날 때까지 조회한 뒤, 첫 파일을 내려받습니다.

새 요청마다 새 Idempotency-Key를 보내세요. 응답을 받지 못한 요청은 같은 키와 같은 본문으로 다시 보내면 됩니다. 첫 요청이 만든 작업을 받으며 청구는 한 번뿐입니다.

cURL

export API_ORIGIN='https://demo.freshapp.ai'
export API_KEY='sk_YOUR_API_KEY'

curl --fail-with-body "$API_ORIGIN/api/v1/generations" \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-1001' \
  -d '{"model":"seed-audio-1.0","input":{"prompt":"새벽녘 절벽 위의 등대, 잔잔한 바다, 부드러운 빛."}}'

# Read it every 5 to 10 seconds until its status ends.
curl --fail-with-body "$API_ORIGIN/api/v1/generations/GENERATION_ID" \
  -H "Authorization: Bearer $API_KEY"

# A delivered output's url is a signed link: no key needed.
curl --fail-with-body -o result "OUTPUT_URL"

TypeScript 클라이언트

import { createClient } from './open-api-client';

const client = createClient({
  baseUrl: "https://demo.freshapp.ai",
  apiKey: process.env.API_KEY, // on your server only
});
const generation = await client.create(
  {
    "model": "seed-audio-1.0",
    "input": {
      "prompt": "새벽녘 절벽 위의 등대, 잔잔한 바다, 부드러운 빛."
    }
  },
  { idempotencyKey: "order-1001" }
);
const done = await client.wait(generation.id);
for (const output of done.outputs)
  if (output.status === 'delivered') {
    const file = await client.download(output);
    // file.body is the output, as output.content_type says
  }

React 훅

import { createClient } from './open-api-client';
import { useGeneration } from './open-api-react';

// In a browser on this site: no key, the visitor's own session.
const client = createClient();

export function Progress({ id }: { id: string }) {
  const { generation, error, done } = useGeneration(client, id);
  if (error) return <p>{String(error)}</p>;
  return <p>{generation?.status ?? '…'}{done ? ' ✓' : ''}</p>;
}

키와 권한

모든 요청은 API 키 페이지에서 만든 키를 Authorization: Bearer에 담아 보냅니다. 키는 sk_ 뒤에 영문자, 숫자, 하이픈, 밑줄 43자가 붙은 형태이며, 만들거나 교체할 때 한 번만 보입니다. Authorization이 있는 요청은 키로만 판단하며, 함께 있는 로그인 세션은 쓰지 않습니다.

키는 읽기만 하거나(목록, 조회, 다운로드) 생성까지 할 수 있습니다(생성과 취소). 읽기 전용 키로 생성이나 취소를 시도하면 403 insufficient_scope가 되고 아무것도 기록되지 않습니다.

키에는 주소와 네트워크로 된 IP 허용 목록을 붙일 수 있으며, 다른 주소에서 오면 403 ip_not_allowed가 됩니다. 키 권한을 넓히거나 한도를 올리거나 허용 목록을 넓히려면 최근 로그인이 필요하지만, 좁힐 때는 필요 없습니다.

키를 교체하면 즉시 새 값이 생기고 이전 값은 멈춥니다. 키를 폐기하면 영구히 멈춥니다. 아직 모델에 보내지 않은 작업은 취소되어 크레딧이 돌아오고, 이미 진행 중인 작업은 그대로 끝납니다.

유료 이용 자격이 있는 계정만 API로 생성 작업을 만들 수 있으며(아니면 403 not_eligible), API는 유료 크레딧만 씁니다(부족하면 402 insufficient_credits). 선물·출석 크레딧은 웹사이트용으로 남습니다.

생성 API 엔드포인트

모든 경로는 이 사이트에 있습니다. 요청과 응답 본문은 결과 파일을 빼고 모두 JSON입니다.

https://demo.freshapp.ai

메서드경로필요한 권한하는 일
POST/api/v1/generationsgenerations:write생성 작업을 만듭니다. Idempotency-Key가 필요하며 202와 작업을 돌려줍니다.
GET/api/v1/generationsgenerations:read계정의 생성 작업을 최신순으로 한 페이지씩 돌려줍니다(limit, cursor, module). 텍스트 작업은 ID로만 조회합니다.
GET/api/v1/generations/{id}generations:read계정의 생성 작업 하나를 출력, 크레딧, 종료 이유와 함께 돌려줍니다.
POST/api/v1/generations/{id}/cancelgenerations:write아직 모델에 보내지 않은 작업을 취소하고 크레딧을 돌려줍니다.
GET, HEAD/api/media/{id}generations:read (또는 서명된 링크)출력의 파일이며 바이트 범위는 하나까지입니다. 서명된 링크는 키가 필요 없고 어느 주소에서든 열립니다.

모델과 가격

이 사이트에서 활성화된 모델을 API에서 쓰는 형태로 보여 줍니다. ID는 model에, 필드는 input에 넣으세요. 요청은 만들 때 가장 비싼 결과의 금액을 잡아 두고, 끝나면 전달된 만큼만 냅니다.

모델 ID이름종류가격요청당 최대입력 필드
seed-audio-1.0Seed Audio 1.0오디오분당 75 크레딧; 결과 전달 시 최소 10 크레딧150 크레딧prompt (필수), voice, audio_references, image_url, output_format, sample_rate, speed, volume, pitch, multilingual

멱등성

생성 작업을 만들려면 영문자, 숫자, 점, 콜론, 밑줄, 하이픈 1~128자로 된 Idempotency-Key 헤더가 필요합니다. 주문 번호처럼 내 시스템의 ID를 쓰면 같은 일에는 늘 같은 키가 붙습니다.

같은 키와 같은 요청은 몇 번을 보내도 같은 작업을 돌려주며 청구는 한 번뿐입니다. 같은 키로 다른 요청을 보내면 409 idempotency_conflict가 되고 아무것도 만들어지지 않습니다.

시간 초과나 연결 끊김은 요청이 실패했다는 뜻이 아닙니다. 같은 키와 같은 본문으로 다시 보내고, 응답을 받을 때까지 둘 다 보관하세요. 5xx, 429, 408도 마찬가지로 Retry-After만큼 기다린 뒤 요청을 그대로 다시 보냅니다.

상태와 폴링

GET /api/v1/generations/{id}로 작업을 조회합니다. 처음에는 5초마다, 이후에는 최대 10초마다, 상태가 끝날 때까지 조회하세요. 429가 오면 Retry-After에 다시 조회할 때가 적혀 있습니다.

상태의미
queued접수되어 모델로 보내지기를 기다립니다. 아직 취소할 수 있습니다.
processing모델로 보내졌거나, 파일을 저장하고 정산하는 중입니다.
succeeded모든 출력이 전달되었고 크레딧 정산이 끝났습니다.
partially_succeeded일부 출력이 전달되어 청구되었고, 나머지 몫의 크레딧은 돌아왔습니다.
failed아무것도 전달되지 않았습니다. 이유는 error에 있고, 잡아 둔 크레딧은 돌아왔습니다.
canceled보내지기 전에 사용자가 또는 키 폐기로 취소되었습니다. 크레딧은 돌아왔습니다.

billing.reserved_credits는 작업을 만들 때 잡아 둔 금액입니다. 정산 후 charged_credits는 낸 금액, refunded_credits는 돌아온 금액이며, 그전에는 둘 다 null이고 held_credits에 잡아 둔 금액이 나옵니다.

수동 확인을 기다리는 작업은 review에 확인이 시작된 시각이 나오고, 확인이 끝날 때까지 크레딧을 잡아 둡니다. 그 뒤 작업이 이어지거나 크레딧이 돌아옵니다.

결과 파일

전달된 출력마다 이 사이트의 url이 있습니다. 키로 조회하면 서명된 링크가 되어 1시간 동안 키 없이 어느 주소에서든 열리므로 다운로드 도구에 그대로 넘길 수 있습니다. 1시간이 지나면 작업을 다시 조회해 새 링크를 받으세요.

키를 직접 써서 GET /api/media/{id}로도 파일을 받을 수 있으며, 이때는 키의 허용 목록이 적용됩니다. 두 방법 모두 HEAD와 바이트 범위 하나(Range: bytes=0-1023)를 지원하고 다른 사이트로 리디렉션하지 않습니다.

입력에서 참조하는 파일(오디오 샘플이나 이미지 등)은 이 계정이 웹사이트에 올린 파일, 사이트가 제공하는 샘플, 또는 사이트가 허용하는 출처의 링크여야 합니다. 그 밖의 참조는 크레딧을 잡기 전에 거절됩니다.

한도

아래 한도는 모두 이 사이트가 지금 적용하는 값이며, 거절될 때는 어느 한도에 걸렸는지 알려 줍니다.

  • 요청 한 번에 잡아 두는 크레딧은 최대 150이며, 활성 모델 중 가장 비싼 요청의 가격입니다. 키에 더 낮은 값을 정할 수 있고 요청의 max_credits로 그 요청만 더 낮출 수 있습니다. 넘으면 400 request_limit_exceeded가 됩니다.
  • 키 하나는 UTC 기준 하루에 최대 5,000 크레딧을 쓰며, 키별 한도를 최대 1,000,000까지 정할 수 있습니다. 넘은 키는 다음 UTC 날까지 429 key_daily_limit_exceeded가 됩니다.
  • 계정의 모든 키와 AI 클라이언트를 합쳐 UTC 기준 하루 최대 10,000 크레딧을 쓰며, 계정 한도를 따로 정할 수 있습니다. 넘으면 429 account_daily_limit_exceeded가 됩니다.
  • 키마다, 계정마다 1분에 생성·취소 20번, 조회·다운로드 240번까지이며, 넘으면 Retry-After와 함께 429 rate_limited가 됩니다.
  • 계정에서 동시에 실행되는 생성 작업은 최대 2개이며, 더 만들면 429 too_many_active로 기다려야 합니다.
  • 요청 본문은 최대 32 KiB의 JSON이며, 더 크면 413 request_too_large가 됩니다.

오류 코드

오류는 {"error": {"code": …, "message": …}} 형태로 옵니다. code는 언제나 아래 표 중 하나이고, message는 개발자를 위한 영어 설명입니다. 429와 503은 기다릴 초를 Retry-After에 담습니다. 실패하거나 취소된 작업은 작업용으로 표시된 코드 중 하나를 error 필드에 담습니다.

HTTP코드의미할 일
401invalid_credentialAPI 키가 없거나, 형식이 잘못되었거나, 존재하지 않거나, 폐기 또는 교체되었습니다.API 키와 그 권한, 허용 목록을 확인하세요.
401credential_revoked요청 처리 중에 키가 폐기되거나 교체되었습니다. 폐기된 키의 대기 중인 작업은 취소되고 크레딧이 돌아옵니다.API 키와 그 권한, 허용 목록을 확인하세요.
403insufficient_scope이 키로는 할 수 없는 일입니다. 필요한 권한은 오류의 required_scope에 있습니다.API 키와 그 권한, 허용 목록을 확인하세요.
403ip_not_allowed이 주소에서는 이 키를 쓸 수 없습니다. 키의 IP 허용 목록 밖입니다.API 키와 그 권한, 허용 목록을 확인하세요.
401unauthorized웹사이트 로그인이 끝났습니다. 다시 로그인하세요.요청을 고친 뒤 다시 보내세요.
403invalid_origin웹사이트 요청은 이 사이트 자체에서 와야 합니다.요청을 고친 뒤 다시 보내세요.
403forbidden신뢰할 수 있는 클라이언트 주소가 없는 요청입니다.사이트 지원팀에 문의하세요.
400invalid_request요청 형식이 잘못되었습니다(JSON, 헤더(Idempotency-Key, Content-Type), 또는 쿼리).요청을 고친 뒤 다시 보내세요.
400invalid_input입력이 모델의 필드에 맞지 않거나, 모델이 쓸 수 없는 입력입니다.요청을 고친 뒤 다시 보내세요.
413request_too_large요청 본문이 너무 큽니다.요청을 고친 뒤 다시 보내세요.
409idempotency_conflict이 Idempotency-Key는 이미 다른 요청에 쓰였습니다.요청을 고친 뒤 다시 보내세요.
404model_unavailable모델이 없거나 지금은 쓸 수 없습니다.요청을 고친 뒤 다시 보내세요.
404not_found이 계정에는 그런 경로, 작업, 파일이 없습니다.요청을 고친 뒤 다시 보내세요.
405method_not_allowed이 경로는 이 메서드를 받지 않습니다. 받는 메서드는 Allow에 있습니다.요청을 고친 뒤 다시 보내세요.
409not_cancelable작업이 이미 모델로 보내졌거나 끝났습니다.요청을 고친 뒤 다시 보내세요.
409not_ready파일이 아직 준비되지 않았습니다.Retry-After만큼 기다린 뒤 다시 보내세요.
410expired보관 기간이 지나 파일이 삭제되었습니다.요청을 고친 뒤 다시 보내세요.
400request_limit_exceeded이 요청의 비용이 max_credits나 키 또는 사이트의 요청당 한도를 넘습니다.요청을 고친 뒤 다시 보내세요.
403not_eligibleAPI로 생성하려면 유료 계정이 필요합니다.크레딧 팩이나 요금제를 구매하세요. API는 유료 크레딧만 씁니다.
403email_unverified생성하려면 계정 이메일을 인증하세요.요청을 고친 뒤 다시 보내세요.
402insufficient_credits크레딧이 부족합니다. API는 유료 크레딧만 씁니다.크레딧 팩이나 요금제를 구매하세요. API는 유료 크레딧만 씁니다.
403generation_restricted콘텐츠 거절이 반복되어 이 계정의 생성이 일시 중지되었습니다. 언제까지인지는 ends_at에 있습니다.사이트 지원팀에 문의하세요.
403trial_paused체험 출력이 여러 번 체험 한도를 넘어 이 계정의 웹사이트 체험이 일시 중지되었습니다. 언제까지인지는 ends_at에 있습니다. 체험이 아닌 요청은 평소처럼 처리됩니다.요청을 고친 뒤 다시 보내세요.
429key_daily_limit_exceeded이 키의 하루 사용 한도에 도달했습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 다음 UTC 날까지.
429account_daily_limit_exceeded계정의 API 하루 사용 한도에 도달했습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 다음 UTC 날까지.
429rate_limited짧은 시간에 요청이 너무 많습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 한도 구간의 남은 시간.
429too_many_active계정에서 실행 중인 작업이 너무 많습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 30초.
429too_many_under_review계정의 일부 작업이 수동 확인을 기다리고 있습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 3,600초.
503busy지금 사이트 전체에서 실행 중인 작업이 너무 많습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 30초.
503paused생성이 잠시 중지되었습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 60초.
503temporarily_unavailable지금은 요청을 마칠 수 없습니다.같은 Idempotency-Key로 같은 요청을 다시 보내세요. Retry-After: 60초.
503api_unavailable이 사이트에서는 아직 생성을 쓸 수 없습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 60초.
503retry요청 처리 중에 키 설정 같은 것이 바뀌었습니다.같은 Idempotency-Key로 같은 요청을 다시 보내세요. Retry-After: 60초.
503unavailable파일에 잠시 접근할 수 없습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 60초.
500internal_error사이트에 문제가 생겼습니다.같은 Idempotency-Key로 같은 요청을 다시 보내세요.
400request_failed전용 코드가 없는 이유로 요청이 거절되었습니다.사이트 지원팀에 문의하세요.
400captcha_required웹사이트의 보안 확인을 마치세요.요청을 고친 뒤 다시 보내세요.
403captcha_failed웹사이트의 보안 확인을 통과하지 못했습니다.요청을 고친 뒤 다시 보내세요.
503captcha_unavailable웹사이트의 보안 확인을 쓸 수 없습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 60초.
400reference_unavailable참조한 업로드가 없거나 이 계정의 것이 아닙니다.요청을 고친 뒤 다시 보내세요.
413reference_too_large참조하는 업로드는 합쳐서 최대 10MB입니다.요청을 고친 뒤 다시 보내세요.
503reference_storage_unavailable참조 파일 저장소를 쓸 수 없습니다.Retry-After만큼 기다린 뒤 다시 보내세요. Retry-After: 60초.
409storage_quota_exceeded계정의 저장 공간이 가득 찼습니다.사이트 지원팀에 문의하세요.
작업 안canceled작업이 보내지기 전에 취소되었고 크레딧은 돌아왔습니다.요청을 고친 뒤 다시 보내세요.
작업 안submission_expired작업을 제시간에 보내지 못해 크레딧이 돌아왔습니다.같은 Idempotency-Key로 같은 요청을 다시 보내세요.
작업 안model_busy모델이 바빠서 크레딧이 돌아왔습니다.Retry-After만큼 기다린 뒤 다시 보내세요.
작업 안content_rejected콘텐츠 안전 검사에서 입력이나 출력이 거절되었습니다.요청을 고친 뒤 다시 보내세요.
작업 안result_expired결과를 제시간에 저장하지 못했습니다.사이트 지원팀에 문의하세요.
작업 안generation_failed생성에 실패했습니다.사이트 지원팀에 문의하세요.
작업 안delivery_failed결과를 전달하지 못해 크레딧이 돌아왔습니다.사이트 지원팀에 문의하세요.
작업 안trial_limit_exceeded웹사이트 체험의 출력이 체험 한도를 넘어 전달되지 않았고 크레딧이 돌아왔습니다.요청을 고친 뒤 다시 보내세요.

TypeScript 클라이언트와 React 훅

TypeScript 클라이언트 open-api-client.ts는 다른 패키지가 필요 없고 서버, 워커, 브라우저에서 실행됩니다. 서버에서는 baseUrl과 apiKey를 주고, 이 사이트의 브라우저 페이지에서는 둘 다 주지 않으면 방문자 자신의 로그인 세션으로 요청합니다.

create는 Idempotency-Key(지정한 값 또는 새 무작위 값)를 보내고, 연결 끊김, 5xx, 429, 408이 오면 Retry-After만큼 기다린 뒤 같은 요청을 다시 보냅니다. 포기할 때는 오류에 키가 담겨 있어 나중에 그 키로 다시 보낼 수 있습니다. localStorage 같은 store를 주면 페이지를 새로 고쳐도 처음 키를 유지합니다.

wait는 작업이 끝날 때까지 조회합니다. 처음에는 5초, 이후 최대 10초 간격이며 중단하면 바로 멈춥니다. download는 출력의 파일을 받아 오며, 키는 이 사이트의 서명되지 않은 링크에만 붙입니다.

React 훅 open-api-react.ts는 클라이언트의 wait로 작업 하나를 따라가고, 컴포넌트가 언마운트되면 멈춥니다. 두 파일을 내려받아 같은 곳에 두고 확장자를 .ts로 바꾸세요.

다운로드