Getting started
sandbox key를 발급받고 첫 예약 생성까지 진행합니다.
전체 흐름은 key 발급, 매장 검색, availability 조회, 예약 생성의 네 단계이며, 모두 Catch Table sandbox에서 진행합니다. 필요한 것은 터미널과 fetch를 지원하는 런타임뿐입니다. 아래의 모든 호출은 sandbox fixture로 응답되므로 실제 매장에는 어떤 요청도 전달되지 않습니다.
APIFuse의 key는 두 종류입니다. live key는 frism_live_, sandbox key는 frism_test_로 시작합니다. 둘 다 managed key이므로 서비스별 credential은 APIFuse이 보관하고, Catch Table 계정을 직접 만들 일은 없습니다.
frism_test_로 시작하며 발급 시 한 번만 표시되므로 secret manager에 보관합니다.catch-table:read와 catch-table:write로 좁힐 수 있습니다. 자세한 내용은 scope를 참고합니다.먼저 예약 가능한 매장을 찾습니다. Search restaurants는 area, cuisine, party_size로 필터링하고 cursor 기반으로 페이지네이션합니다.
curl "https://api.frism.dev/v1/catch-table/restaurants?area=seongsu&cuisine=japanese&party_size=2" \
-H "Authorization: Bearer frism_test_k3xample"응답을 일부 줄이면 다음과 같습니다. 각 항목의 id가 이후 호출에 사용할 매장 식별자입니다. bookable_online이 false인 매장은 waitlist 등록만 받습니다.
{
"items": [
{
"id": "res_01J8Q9W3TE",
"name": "Sushi Aoyagi",
"area": "seongsu",
"cuisine": "japanese",
"price_band": "high",
"bookable_online": true
}
],
"next_cursor": "cur_9f2kq"
}next_cursor를 cursor 파라미터로 넘기면 다음 페이지를 받습니다. 마지막 페이지에서는 null입니다.
예약은 두 호출로 완성됩니다. 가 날짜와 일행 수 기준의 열린 슬롯을 반환하고, 이 그중 하나를 예약합니다. POST에는 Idempotency-Key 헤더를 붙입니다. 타임아웃이나 프로세스 중단 후에도 같은 키로 24시간 동안 안전하게 재시도할 수 있습니다.
const base = "https://api.frism.dev/v1";
const headers = { Authorization: "Bearer frism_test_k3xample" };
// 1. 날짜와 일행 수 기준으로 열려 있는 슬롯을 조회합니다.
const availabilityRes = await fetch(
base +
"/catch-table/restaurants/res_01J8Q9W3TE/availability" +
"?date=2026-09-02&party_size=2",
{ headers },
);
const availability = await availabilityRes.json();
const slot = availability.slots[0];
// slot: { slot_id: "slt_1900_2", starts_at: "2026-09-02T19:00:00+09:00" }
// 2. 슬롯을 예약합니다. Idempotency-Key가 이 POST의 재시도를 안전하게 만듭니다.
const created = await fetch(base + "/catch-table/reservations", {
method: "POST",
headers: {
...headers,
"Content-Type": "application/json",
"Idempotency-Key": "idem_b1f7c2d0",
},
body: JSON.stringify({
restaurant_id: "res_01J8Q9W3TE",
slot_id: slot.slot_id,
party_size: 2,
contact_name: "Han Jiwoo",
note: "Window seat if possible.",
}),
});
console.log(created.status);
console.log( created.json());성공하면 게이트웨이가 201과 함께 예약 본문을 반환합니다.
{
"id": "rsv_01J8QDGT2K",
"status": "confirmed",
"restaurant_id": "res_01J8Q9W3TE",
"starts_at": "2026-09-02T19:00:00+09:00",
"party_size": 2
}status가 confirmed인 것은 이 매장이 즉시 확정하기 때문입니다. 매장 승인이 필요한 곳은 pending으로 시작하고, 확정되는 시점에 reservation.confirmed 이벤트가 으로 도착합니다. 폴링보다 webhook 구독을 권장합니다.
두 호출 사이에 슬롯이 소진되면 409와 code conflict가 표준 로 반환됩니다. availability를 다시 조회한 뒤 다른 슬롯으로 시도합니다.
이 과정에서 key는 Catch Table에 전달되지 않았습니다. 게이트웨이가 경로의 catch-table 세그먼트를 해석하고, key의 scope를 확인한 뒤, APIFuse이 보관 중인 매장 credential로 예약을 수행하고 응답을 위의 스키마로 정규화했습니다. 서비스 장애도 같은 방식으로 돌아옵니다. 502와 provider_unavailable이 같은 envelope에 담기고 retryable: true가 표시되므로, 클라이언트는 backoff 로 이어갈 수 있습니다. 이 구조 덕분에 다른 서비스를 붙일 때에도 인증과 에러 처리 코드는 그대로 재사용됩니다.