APIFuseAPIFuseDocs

Getting started

  • 개요
  • 빠른 시작

Authentication

  • Managed key
  • Scope

Errors

  • 에러 모델
  • 재시도

Webhooks

  • 개요
  • 서명 검증

API reference

  • 아마존 재팬
  • 배달의민족 프로바이더
  • 빗썸
  • Buyee
  • 캐치테이블 음식점 검색 및 예약
  • 차란 커머스
  • 당근 공개 매물
  • 다이소 상품 및 매장 데이터
  • 다나와 가격 비교
  • Demaecan
  • 에키탄
  • 여기어때 국내 숙소
  • Google Flights
  • 한강 수위
  • 핫페퍼 구루메(Hot Pepper Gourmet) 프로바이더
  • 현대카드
  • 인천공항 여객편 운항현황
  • Jalan
  • 일본 국회 회의록
  • 일본 재난 알림
  • 일본 EDINET 공시 서류
  • 일본 e-Gov 법령
  • 일본 e-Stat
  • 일본 gBizINFO (경제산업성 법인정보)
  • 일본 GSI 지오코딩
  • 일본 e-Gov 오픈데이터
  • Japan Post ZIP
  • 일본 공휴일
  • JMA Weather
  • 카카오맵 장소 검색과 길찾기
  • 카카오 T 택시 호출
  • 카카오톡 네이티브 메시징
  • 한국 주소 검색
  • AirKorea 실시간 대기오염 정보
  • 전국 동물병원
  • 한국 아파트 전월세 실거래가
  • 한국 아파트 매매 실거래가
  • 나라장터 입찰공고
  • 한국 박스오피스
  • 건축물대장 (Korea Building Register)
  • 전국 버스 도착정보
  • Korea Business Verify
  • 대한민국 캠핑장
  • 한국 DART 기업 재무정보
  • DART 기업 정보
  • 한국 문화행사(한눈에 보는 문화정보)
  • 한국 재난 알림
  • 한국 응급의료기관
  • 한국 ETF
  • 한국 전기차 충전소
  • 한국 환율 (한국수출입은행)
  • 한국 고속도로 교통
  • 금융상품 비교공시 (금융감독원 금융상품한눈에)
  • 한국 주유소 유가
  • 국가유산 정보 (국가유산청)
  • Korea Holiday
  • Korea Hospital Info
  • 전국 고속·시외버스 시간표
  • 한국 토지 매매 실거래가
  • 식약처 의약품 안전정보
  • 식약처 식품 안전 정보
  • 생활쓰레기 배출정보
  • 국가법령정보 검색·조회
  • NEIS 학교 급식 식단
  • 배송사 목록 및 택배 배송 조회
  • 전국 주차장
  • 공연예술 정보 (KOPIS)
  • Korea Pharmacy
  • 한국 인구 통계
  • 한국 주식시장지수
  • 한국 주식 시세
  • 전국 상가업소 정보
  • 한국 유기동물 (국가동물보호정보시스템)
  • 한국 관광정보 (한국관광공사)
  • 한국 열차 시간표
  • 한국 기상청 예보 데이터
  • Korea Weather Forecast
  • 대한민국 복지서비스
  • K-Startup
  • LH 청약 공고
  • 마켓컬리 상품 데이터
  • Mercari
  • 모두의주차장
  • 네이버 블로그 검색
  • 네이버 항공권 API
  • 네이버 지역 검색
  • 네이버 지도
  • 네이버 뉴스 검색
  • NHK 편성표
  • NOL 숙소
  • 오늘의집 스토어 및 콘텐츠
  • 라쿠텐 북스
  • 라쿠텐 이치바
  • 라쿠텐 레시피
  • 라쿠텐 트래블
  • SEC EDGAR Filings
  • 서울 따릉이
  • 서울 실시간 혼잡도
  • 서울 지하철 실시간 도착
  • 신한은행
  • 신한카드
  • Skiplagged
  • Steam 스토어
  • SUUMO
  • 스윙 택시
  • Tabelog
  • TableCheck
  • 업비트
  • Visit Japan Web (일본 입국 수속 서비스)
  • Weverse 프로바이더
  • 야후! 쇼핑 (일본)
  • Yogiyo
  • ZOZOTOWN

Guides

  • APIFuse 문서
  • 시작하기
  • 인증과 connection
  • 플레이그라운드
  • OpenAPI와 스키마 아티팩트
  • MCP 엔드포인트
  • 개발자 MCP 가이드
  • 스키마 번들과 변환 경고
  • Next.js App Router 연동
  • FastAPI 연동
  • 에러 처리
  • 자주 묻는 질문
  • 추가 리소스

Changelog

  • 체인지로그
APIFuseAPIFuse
문서서비스플레이그라운드상태
로그인회원가입

Errors

재시도

멱등한 호출의 재시도 규칙과 backoff 동작을 설명합니다.

실패한 호출을 무작정 다시 보내면 예약이 두 번 생기거나 rate limit이 더 깊어질 수 있습니다. 재시도는 세 가지 질문으로 정리됩니다. 이 호출이 멱등한가, 얼마나 기다렸다 다시 보낼 것인가, 이 에러가 재시도로 해결되는 종류인가. 마지막 질문에는 에러 모델의 envelope가 직접 답을 줍니다.

무엇을 재시도해도 되는가

GET과 DELETE는 멱등합니다. 같은 요청을 몇 번 보내도 결과가 달라지지 않으므로 네트워크 오류나 502 이후 안심하고 재시도할 수 있습니다. POST는 기본적으로 멱등하지 않습니다. 응답을 받지 못한 Create reservation 호출을 그대로 다시 보내면 예약이 두 건 생길 수 있습니다.

메서드멱등성재시도
GET멱등안전합니다. backoff와 jitter로 재시도합니다.
DELETE멱등안전합니다. 같은 취소를 반복해도 결과가 달라지지 않습니다.
POST비멱등상태를 만드는 POST는 Idempotency-Key 헤더가 있을 때만 안전합니다. Estimate ride처럼 상태를 바꾸지 않는 POST는 레퍼런스 설명에 명시되어 있고 그대로 재시도해도 안전합니다.

POST를 재시도 가능하게 만들려면 첫 시도부터 Idempotency-Key 헤더를 보냅니다. 게이트웨이가 키를 24시간 동안 기억하고, 같은 키로 다시 도착한 요청에는 첫 처리의 결과를 그대로 반환합니다. Create reservation과 Join waitlist처럼 상태를 만드는 모든 POST가 이 헤더를 받습니다.

Idempotency-Key와 함께 보내는 POST
curl -X POST "https://api.frism.dev/v1/catch-table/reservations" \
  -H "Authorization: Bearer frism_test_k3xample" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: idem_b1f7c2d0" \
  -d '{
    "restaurant_id": "res_01J8Q9W3TE",
    "slot_id": "slt_1900_2",
    "party_size": 2,
    "contact_name": "Han Jiwoo"
  }'
Idempotency-Key는 24시간 뒤 만료됩니다. 그 이후 같은 키로 도착한 요청은 새 요청으로 처리됩니다.

Backoff와 jitter

재시도 간격은 지수적으로 늘리고, 매 간격에 무작위 jitter를 더합니다. 모든 클라이언트가 고정 간격으로 재시도하면 장애에서 복구 중인 서비스에 요청이 동시에 몰려 복구가 늦어집니다. 예외가 하나 있습니다. 429 응답에는 Retry-After 헤더가 포함되며, 이 값이 있으면 계산한 backoff 대신 헤더를 따릅니다.

시도 횟수에는 상한을 둡니다. 서너 번의 재시도로 성공하지 못한 요청은 대기열에 더 잡아두지 말고 에러를 그대로 반환해, 호출한 쪽이 사용자에게 알리거나 나중에 다시 시도하도록 넘깁니다. 상한 없이 재시도를 반복하는 클라이언트는 장애를 연장시킬 뿐입니다.

retryable 플래그

envelope의 retryable 필드는 게이트웨이가 판단한 재시도 가능 여부입니다. 429 rate_limited와 502 provider_unavailable에서 true입니다. status 목록을 클라이언트에 하드코딩하는 대신 이 플래그로 분기하면, 매핑이 확장되어도 코드를 고칠 필요가 없습니다.

재시도 helper

아래 helper가 위 규칙 전부를 구현합니다. 재시도 대상은 네트워크 오류와 429, 502뿐이고, Retry-After가 있으면 그 값을 우선하며, 없으면 full jitter backoff를 사용합니다.

fetch 재시도 wrapper
const BASE_URL = "https://api.frism.dev/v1";
const RETRYABLE_STATUSES = new Set([429, 502]);

interface FrismRequest {
  method?: "GET" | "POST" | "DELETE";
  headers?: Record<string, string>;
  body?: string;
}

function sleep(ms: number): Promise<void> {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

// full jitter: 0과 지수 상한 사이의 무작위 대기.
function backoffMs(attempt: number, baseMs = 500, capMs = 8_000): number {
  const ceiling = Math.min(capMs, baseMs * 2 ** (attempt - 1));
  return Math.random() * ceiling;
}

export async function frismFetch(
  path: string,
  init: FrismRequest = {},
  maxAttempts = ,
): Promise<Response> {
  for ( attempt = ; ; attempt += ) {
     response: Response | undefined;
     {
      response =  fetch(`${BASE_URL}${path}`, {
        ...init,
        headers: {
          Authorization: ,
          ...init.headers,
        },
      });
    }  (cause) {
      
       (attempt >= maxAttempts)  cause;
    }

     (response) {
      
       (!RETRYABLE_STATUSES.has(response.status))  response;
       (attempt >= maxAttempts)  response;
    }

    
     retryAfter = Number(response?.headers.get());
     delayMs = retryAfter >  ? retryAfter *  : backoffMs(attempt);
     sleep(delayMs);
  }
}

POST를 통과시킬 때는 Idempotency-Key를 함께 전달합니다.

helper로 예약 생성
const response = await frismFetch("/catch-table/reservations", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    "Idempotency-Key": "idem_b1f7c2d0",
  },
  body: JSON.stringify({
    restaurant_id: "res_01J8Q9W3TE",
    slot_id: "slt_1900_2",
    party_size: 2,
    contact_name: "Han Jiwoo",
  }),
});

if (!response.ok) {
  // 여기 도달했다면 재시도로 해결되지 않는 에러입니다. code로 분기합니다.
  const { error } = (await response.json()) as { error: { code: string } };
  console.error(error.code);
}

재시도하면 안 되는 것

  • 409 conflict: 리소스 상태가 바뀌었다는 뜻입니다. 같은 요청을 반복하지 말고, 를 다시 읽은 뒤 다른 슬롯으로 새 요청을 만듭니다.
  • 422 provider_rejected: 서비스 정책이 요청을 거부했습니다. 같은 요청은 몇 번을 보내도 같은 답이 돌아옵니다.
  • 400, 401, 403, 404: 요청 자체의 문제입니다. 요청을 고치기 전에는 재시도할 이유가 없습니다.

각 status와 code의 의미는 에 정리되어 있습니다. 상태 변화를 폴링 대신 푸시로 받으면 재시도할 일 자체가 줄어듭니다. 를 참고합니다.

4
let
1
1
let
try
await
"Bearer frism_test_k3xample"
catch
// 네트워크 오류는 502처럼 재시도합니다.
if
throw
if
// 성공, 그리고 재시도로 해결되지 않는 에러는 그대로 반환합니다.
if
return
if
return
// 429가 알려준 Retry-After가 있으면 backoff보다 우선합니다.
const
"Retry-After"
const
0
1000
await
availability
에러 모델
webhook 가이드