메뉴 경로: 대시보드 > APIs > 엔드포인트 상세 > 테스트하기

테스트 및 연동 가이드

개요

엔드포인트 상세 페이지에서 테스트하기 버튼을 누르면 열리는 페이지입니다. 별도의 도구 없이 브라우저에서 바로 API 호출을 테스트할 수 있고, 협업자에게 공유하면 연동에 필요한 정보를 한눈에 확인할 수 있어요.

이 페이지에서의 테스트는 샌드박스 환경에서만 진행됩니다. 프로덕션 데이터에는 영향을 주지 않으니 자유롭게 테스트하세요.

페이지는 두 개의 탭으로 구성되어 있습니다.

  • 빠른 시작 — API 키 인증 후 바로 호출 테스트
  • 가이드 — 소유자·협업자 역할별 연동 안내 (단계 가이드, API 엔드포인트, 헤더, 필드 정의, 코드 예시 등)

진입 경로

  • 엔드포인트 상세 우측 사이드바 > 테스트하기 버튼 (Sandbox 탭)
  • 협업자는 초대 수락 후 자신의 대시보드에서도 접근 가능

엔드포인트 정보

엔드포인트 정보

  • 엔드포인트 이름과 설명이 표시됩니다
  • 환경 배지(샌드박스)와 버전 정보가 함께 나타납니다
  • 빠른 시작 / 가이드 탭을 전환할 수 있어요

빠른 시작 탭

인증

테스트를 시작하려면 먼저 API 키로 인증해야 합니다.

인증 전

  • API 키 입력란에 샌드박스 키(tm_test_로 시작)를 붙여넣고 인증 버튼을 누르세요
  • 사용할 수 있는 키는 두 가지입니다:

인증 후

인증이 완료되면 입력란이 사라지고 로그아웃 버튼이 나타납니다. 다른 키로 테스트하고 싶다면 로그아웃 후 다시 인증하세요.

Try it out

Try it out

인증이 완료되면 CRUD 호출을 바로 실행할 수 있는 영역이 활성화됩니다. 메서드를 선택하고 요청 본문(JSON)을 입력한 뒤 실행 버튼을 누르면 결과가 바로 표시돼요.

전체 흐름을 한 번에 테스트하고 싶다면 아래 순서대로 진행해 보세요.

CRUD 전체 테스트 가이드

  1. CREATE (POST) — 요청 본문에 테스트 JSON을 입력하고 실행합니다. 응답에 포함된 id 값을 복사해 두세요. 이후 단계에서 이 ID가 필요합니다.

  2. READ — 단건 조회 (GET) — 위에서 받은 id를 Record ID 입력란에 붙여넣고 실행합니다. 해당 레코드의 payload 전체가 조회됩니다.

  3. READ — 목록 조회 (GET list) — Record ID 없이 GET을 호출하면 최근 레코드가 시간 역순으로 반환됩니다. limit(1~30, 기본 10)과 cursor로 페이지네이션하며, 응답의 pagination.next_cursor를 다음 호출의 cursor로 전달하면 다음 페이지를 받습니다.

  4. READ — 검색 (GET search) — payload 안의 키워드로 레코드를 찾습니다. q(필수, 3~200자)와 선택적인 start/end(미지정 시 최근 30일), limit, cursor를 사용합니다. 대소문자 무시 부분 매칭이며 cursor 페이지네이션을 사용합니다.

  5. READ — 폴링 (GET poll) — 마지막 폴링 이후 생성된 레코드를 오래된 순으로 가져옵니다. 첫 호출은 아무것도 넘기지 않거나(지금부터 구독) since를 쓰고, 이후 호출은 직전 응답의 커서를 그대로 돌려보냅니다. next_cursor는 아직 밀린 데이터가 남았다는 뜻이니 즉시 다시 호출하고, poll_cursor는 따라잡았다는 뜻이니 저장한 뒤 다음 주기까지 기다립니다.

  6. UPDATE (PUT) — 같은 id를 입력하고, 요청 본문에 수정할 JSON을 넣어 실행합니다. 전체 교체(full replacement) 방식이므로 변경할 필드뿐 아니라 유지할 필드도 함께 포함해야 합니다.

  7. DELETE — 같은 id를 입력하고 실행합니다. 이후 READ를 다시 시도하면 해당 레코드가 삭제된 것을 확인할 수 있어요.

권한 확인: 협업 키로 테스트하는 경우, 해당 키에 허용된 메서드만 실행할 수 있습니다. 권한이 없는 메서드를 호출하면 403 오류가 반환돼요. 권한 설정은 협업키 관리 > 권한에서 확인할 수 있습니다.

협업자 웹훅

협업자 웹훅 설정

Try it out 섹션 하단에 접힘 영역으로 웹훅 설정이 있습니다. 이것은 소유자가 대시보드에서 설정하는 웹훅과는 별개로, API를 호출하는 쪽에서 요청 헤더에 웹훅 정보를 포함하여 처리 결과를 받아보는 기능입니다. 여기서는 해당 헤더를 미리 테스트해 볼 수 있어요.

  • 소유자 웹훅과 독립적으로 동작합니다
  • 실제 연동 시에는 API 호출 코드에 웹훅 헤더를 직접 포함하여 구현합니다
  • 자세한 헤더 이름과 구현 방식은 가이드 탭의 웹훅 설정 섹션을 참고하세요

가이드 탭

가이드 탭은 소유자와 협업자 모두가 연동 전체 흐름과 기술 세부 사항을 한 곳에서 확인할 수 있도록 구성되어 있습니다. 상단에는 역할별 단계 가이드, 하단에는 API 연동에 필요한 기술 레퍼런스가 이어집니다.

시작 가이드 — 소유자

소유자 가이드

엔드포인트를 만들었나요? 탭을 선택하면, 소유자 관점에서 진행해야 할 단계가 순서대로 안내됩니다.

  1. 엔드포인트 생성 — API 이름만 정하면 CRUD가 자동 생성됩니다. 설명과 필수 필드는 나중에 추가해도 됩니다
  2. 샌드박스 테스트 및 로그 확인 — 빠른 시작 탭에서 기본 API 키로 호출해 보고, 대시보드 로그에서 데이터 수신을 확인합니다
  3. 협업 키 생성 및 협업자 초대 — 협업 키를 만들고 상세 페이지에서 이메일 초대를 보냅니다
  4. 연동 테스트 — 협업자가 샌드박스에서 정상 호출하는지 로그로 함께 확인합니다
  5. 프로덕션 배포 — 협업자의 배포 요청을 승인하거나, 소유자가 직접 배포합니다. 배포 후 협업자에게 알림이 전달됩니다

시작 가이드 — 협업자

협업자 가이드

초대를 받았나요? 탭을 선택하면, 초대받은 협업자 관점에서 진행할 단계가 안내됩니다.

  1. 초대 수락 — 초대 이메일을 확인하고, 로그인 후 대시보드에서 수락합니다
  2. API 키 확인 — 엔드포인트 상세에서 샌드박스 API 키(tm_test_)를 확인합니다
  3. 연동 및 테스트 — 빠른 시작 탭에서 호출을 테스트하고, 가이드 탭의 기술 정보를 참고해 연동을 개발합니다. 202 응답을 받았다면 이후 처리는 시스템이 보장합니다
  4. 배포 요청 — 테스트가 완료되면 엔드포인트 상세에서 배포 요청을 보냅니다
  5. 프로덕션 전환 — 소유자가 배포를 완료하면 알림을 받고, 프로덕션 API 키(tm_live_)로 전환합니다

API 엔드포인트

API 엔드포인트

이 엔드포인트에서 사용할 수 있는 API 경로와 메서드가 표시됩니다. 엔드포인트를 생성하면 다음 메서드들이 자동으로 준비됩니다.

메서드 경로 설명
POST /api/v1/data/{slug} 새 레코드 생성
GET /api/v1/data/{slug}/{record_id} ID로 레코드 조회
GET /api/v1/data/{slug} 최근 레코드 목록 조회 (cursor 페이지네이션)
GET /api/v1/data/{slug}/search payload 텍스트 검색 (q, 선택 start/end; 최소 3자, 커서 페이지네이션)
GET /api/v1/data/{slug}/poll 마지막 폴링 이후 생성된 레코드를 오래된 순으로 조회 (since 또는 cursor, 커서 페이지네이션)
PUT /api/v1/data/{slug}/{record_id} 레코드 교체
DELETE /api/v1/data/{slug}/{record_id} 레코드 삭제

{slug}는 엔드포인트 생성 시 자동으로 부여되는 고유 식별자이며, 이 페이지에서 실제 값을 확인할 수 있습니다.

검색(search) 호출은 q(3~200자)가 필수입니다. start/end(YYYY-MM-DD 또는 RFC 3339)는 선택사항이며, 생략 시 최근 30일이 자동 적용됩니다. 범위 상한은 없습니다. 결과는 커서 페이지네이션이며, 다음 페이지가 있으면 응답에 pagination.next_cursor가 포함됩니다. payload 전체에 대해 대소문자 무시 부분 매칭이라 숫자나 JSON 키가 우연히 매칭될 수 있습니다(예: 32로 검색 시 132도 매칭). 검색은 단건 GET / 목록 GET과 동일한 read 권한으로 동작합니다.

폴링(poll) 호출은 created_at 오름차순으로 레코드를 훑습니다 — 목록·검색과 반대입니다. 파라미터를 아무것도 넘기지 않으면 지금부터 구독하고, since(YYYY-MM-DD 또는 RFC 3339, 전부 UTC — 2026-08-28은 KST 자정이 아니라 UTC 자정입니다)로 시작 시점을 지정하거나 cursor로 이어받습니다. sincecursor를 동시에 보내면 400입니다. limit은 1~100(기본 100)이며 커서에 담기지 않으므로 페이지마다 다시 보내야 합니다. 응답에는 두 커서 중 정확히 하나만 담깁니다. next_cursor는 아직 밀린 데이터가 남았다는 뜻이니 즉시 다시 호출하고, poll_cursor는 따라잡았다는 뜻이니 저장한 뒤 다음 주기까지 기다립니다. 최신 약 60초는 제외됩니다. created_at은 게이트웨이가 발급하지만 실제 삽입은 큐를 거쳐 비동기라, 이 마진이 없으면 아직 도착하지 않은 레코드를 건너뛴 채 워터마크가 전진합니다. 그 레코드는 다음 폴링에 들어옵니다 — 유실이 아니라 연기입니다. 재시도·재시작 시 같은 레코드가 다시 올 수 있으므로 record id 기준으로 멱등 처리하세요. 폴링은 단건 GET / 목록 GET / 검색 GET과 동일한 read 권한으로 동작합니다.

API 키

API 키

API 호출 시 인증에 사용할 키 정보입니다.

환경 키 접두사 용도
샌드박스 tm_test_ 개발 및 테스트
프로덕션 tm_live_ 상용 서비스

프로덕션 API 키는 배포가 완료된 후에 엔드포인트 상세 페이지에서 확인할 수 있습니다. 배포 전에는 프로덕션 키로 호출해도 거부됩니다.

요청 헤더

요청 헤더

API 호출 시 포함해야 하는 HTTP 헤더입니다. Content-TypeAuthorization은 필수이며, 웹훅 관련 헤더는 필요한 경우에만 추가합니다.

헤더 필수 여부 설명
Content-Type 필수 application/json (POST/PUT 요청 시)
Authorization 필수 Bearer {API_KEY} 형식
X-Webhook-Callback 선택 호출자 웹훅을 받을 URL
X-Webhook-Auth 선택 웹훅 인증 값 (예: Bearer 토큰)
X-Webhook-Auth-Header 선택 웹훅 인증 헤더 키 (기본값: Authorization)

요청 본문

요청 본문

POST/PUT 요청 시 전송할 JSON 본문에 대한 안내입니다.

  • 형식: JSON (application/json) · 최대 100KB · UTF-8
  • 소유자가 필수 필드를 정의한 경우, 해당 필드가 반드시 포함되어야 합니다. 필수 필드 외에 추가 필드도 자유롭게 함께 전송할 수 있어요
  • 필수 필드가 정의되지 않았다면 어떤 JSON이든 받아들입니다
  • 요청은 비동기로 처리됩니다. 즉시 202 응답을 받고, 실제 저장과 웹훅 전달은 백그라운드에서 진행돼요

응답 형식

응답 형식

각 메서드별 성공 응답과 주요 에러 코드가 표시됩니다.

성공 응답:

  • POST/PUT/DELETE → 202 Accepted (요청이 수락되어 처리 대기열에 추가됨)
  • GET (단건) → 200 OK (레코드 즉시 반환)
  • GET (목록) → 200 OK (페이지네이션된 데이터 + 다음 페이지가 있으면 next_cursor)
  • GET (검색) → 200 OK (페이지네이션된 데이터 + 다음 페이지가 있으면 next_cursor)
  • GET (폴링) → 200 OK (오래된 순 데이터 + next_cursor / poll_cursor 중 정확히 하나)

주요 에러 코드:

코드 상태 의미
400 잘못된 요청 JSON 형식 오류, 필수 필드 누락, 잘못된 레코드 ID
401 인증 실패 API 키가 없거나 유효하지 않음
403 접근 거부 엔드포인트 비활성, 구독 없음, 또는 권한 부족
413 페이로드 크기 초과 요청 본문이 100KB 한도를 초과
415 지원하지 않는 미디어 타입 Content-Type이 application/json이 아닌 경우
429 요청 한도 초과 월간 사용량 한도 초과
5xx 서버 오류 서버 측 일시 오류 — 재시도 로직 구현 권장

5xx 에러를 받았다면 요청이 서버에 도달하지 못한 것이므로, 코드에 재시도 로직(예: 1s → 2s → 4s 백오프)을 구현하세요. 202 응답을 받았다면 이후 처리는 시스템이 보장합니다.

웹훅 설정

웹훅 설정

API를 호출하는 쪽에서 처리 결과를 자동으로 받아보고 싶을 때 사용하는 호출자 웹훅 설정 안내입니다. 소유자가 대시보드에서 설정하는 웹훅과는 별개로, 각각 독립적으로 동작합니다.

설정 방법: API 호출 시 요청 헤더에 다음을 포함합니다.

헤더 필수 여부 설명
X-Webhook-Callback 필수 웹훅을 받을 URL
X-Webhook-Auth 선택 인증 값 (예: Bearer 토큰)
X-Webhook-Auth-Header 선택 인증 헤더 키 (기본값: Authorization)

모든 웹훅에 함께 보내는 헤더:

헤더 설명
X-3minapi-Record-Id 레코드 ID. 모든 배달 시도에서 값이 같습니다 — 중복 판단에 쓰세요
X-3minapi-Delivery-Attempt 시도 번호 (1부터 시작)
webhook-id 레코드 ID. X-3minapi-Record-Id같은 값입니다
webhook-timestamp 서명한 시각(unix 초). 시도할 때마다 새로 만듭니다
webhook-signature HMAC-SHA256 서명. 시크릿 교체 중에는 두 개가 옵니다

수신 서버가 지켜야 할 것:

  • 15초 안에 2xx를 반환하세요. 무거운 처리는 여러분 쪽 큐로 넘기고 응답부터 하세요
  • 2xx는 "성공했다"가 아니라 "받았다"는 뜻입니다. 여러분 쪽 처리가 실패해도 2xx를 반환하세요 — 상위 API 거부, 자체 검증 오류, 처리할 수 없는 주문 모두 해당합니다 — 그리고 그 실패는 여러분 시스템에 기록하세요. 5xx는 그것이 실제로 뜻하는 상황에만 쓰세요: 수신기 자신이나 그 의존 대상이 일시적으로 죽어서, 같은 레코드를 나중에 다시 받으면 성공할 수 있는 경우입니다. 5xx를 반환하면 우리가 그 레코드를 아래 재시도 일정대로 다시 보내므로, 여러분 수신기는 그때마다 같은 작업을 다시 실행하게 됩니다
  • 같은 X-3minapi-Record-Id여러 번 도착할 수 있습니다. 이 값으로 이미 처리한 레코드인지 판단하세요

재시도 정책:

  • 성공 기준: 2xx 상태 코드 — 배달을 받았다는 확인일 뿐, 여러분 쪽 처리가 성공했다는 뜻이 아닙니다
  • 프로덕션은 총 6회 시도 — 최초 배달 1회 + 재시도 5회(30초·2분·10분·1시간·4시간, 약 5시간). 샌드박스는 총 4회 시도 — 최초 배달 1회 + 재시도 3회(30초·2분·10분, 약 12분)
  • 재시도하는 경우: 5xx(501·505 제외), 429, 타임아웃, 연결 오류. 429에 Retry-After가 있으면 그보다 더 기다리라는 요청으로만 반영합니다 — 기본 간격보다 짧게 당기지는 않고, 4시간을 넘는 값은 무시합니다
  • 재시도하지 않는 경우: 429를 제외한 모든 4xx — 409도 포함됩니다(수신기가 이미 받았다는 뜻으로 읽습니다). 설정을 고치면 다음 호출부터 정상 전달됩니다
  • 모두 실패해도 데이터는 안전하게 저장됩니다 — 보관 기간(프로덕션 최소 60일, 샌드박스 30일) 안에서는 폴링 엔드포인트로 나중에 가져올 수 있어요. 실패했거나 재시도 중인 배달은 로그 화면의 웹훅 배달에서 응답 본문과 시도 이력까지 확인할 수 있어요
  • 배달을 포기하면 엔드포인트 소유자에게 메일을 보냅니다 (재시도 소진, 또는 재시도하지 않는 영구 응답) — 플랜과 무관하게(무료 포함) 받으실 수 있고, 프로덕션의 소유자 웹훅일 때만이며 엔드포인트당 하루 한 통까지입니다. 후속 메일도 복구 알림도 없어요. 협업자 웹훅 실패는 메일로 알리지 않습니다. 그 URL은 엔드포인트 소유자가 바꿀 수 없기 때문이에요

웹훅 서명 검증

보내는 모든 웹훅에 HMAC-SHA256 서명을 붙입니다. 이 요청이 정말 3Min API에서 왔는지, 중간에 내용이 바뀌지 않았는지 확인할 수 있어요.

검증은 선택입니다. 지금 웹훅을 받고 있다면 아무것도 하지 않아도 그대로 동작합니다. 다만 켜 두면, 수신 URL을 알아낸 누군가가 가짜 요청을 보내 진짜 배달을 "이미 처리함"으로 버리게 만드는 것을 막을 수 있습니다.

암호화가 아닙니다. 본문은 지금까지와 똑같이 평문으로 갑니다. 달라지는 건 "이 본문이 3Min API에서 나온 뒤 한 글자도 바뀌지 않았다"를 증명하는 지문이 헤더에 붙는다는 것뿐이에요.

지문은 세 조각을 이어 붙여 만듭니다.

서명 대상 = "{webhook-id}.{webhook-timestamp}.{요청 본문 원본}"
키        = 시크릿에서 whsec_ 를 떼고 base64 디코드한 바이트
서명      = base64( HMAC-SHA256(키, 서명 대상) )

세 조각은 각각 다른 것을 막습니다.

조각 막는 것
요청 본문 중간에서 내용을 바꿔치기하는 것
webhook-timestamp 예전에 오갔던 진짜 요청을 그대로 다시 보내는 것(리플레이)
webhook-id 남의 레코드 ID를 붙여 보내, 진짜 배달을 "이미 처리함"으로 버리게 만드는 것

시크릿 위치: 대시보드 > 엔드포인트 상세 > 웹훅 서명 시크릿. 샌드박스와 프로덕션이 각각 다릅니다.

라이브러리로 검증하기 (권장)

Standard Webhooks 규격을 그대로 따르므로, 공식 라이브러리를 설치하면 몇 줄로 끝납니다.

언어 패키지
Node.js / TypeScript standardwebhooks (npm)
Python standardwebhooks (pip)
PHP standard-webhooks/standard-webhooks (composer)
Go github.com/standard-webhooks/standard-webhooks/libraries/go
Ruby standardwebhooks (gem)
Java / Kotlin com.standardwebhooks:standardwebhooks
C# StandardWebhooks (NuGet)
Rust standardwebhooks (crates.io)
Elixir standard_webhooks (hex)
// npm i standardwebhooks
import { Webhook } from 'standardwebhooks';
import express from 'express';

const app = express();
// 서명은 우리가 보낸 바이트 그대로에 대해 계산됩니다.
// JSON으로 파싱한 뒤 다시 문자열로 만들면 반드시 실패합니다.
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
	const wh = new Webhook(process.env.WEBHOOK_SIGNING_SECRET.replace('whsec_', ''));
	try {
		const payload = wh.verify(req.body, {
			'webhook-id': req.header('webhook-id'),
			'webhook-timestamp': req.header('webhook-timestamp'),
			'webhook-signature': req.header('webhook-signature')
		});
		// 검증 통과 — payload를 처리하세요
		res.sendStatus(200);
	} catch {
		res.sendStatus(401);
	}
});

직접 구현할 때

  1. 시크릿에서 whsec_ 접두사를 떼고 base64 디코드해 키 바이트를 얻습니다
  2. webhook-timestamp가 현재 시각 ±5분 안인지 확인합니다 (오래된 요청 재사용 차단)
  3. base64(HMAC_SHA256(키, "{webhook-id}.{webhook-timestamp}.{원문 본문}")) 를 계산합니다
  4. webhook-signature공백으로 나눠, v1,로 시작하는 항목 중 하나라도 일치하면 통과입니다

주의할 점

  • 원문 바이트로 계산하세요. JSON으로 파싱한 뒤 다시 문자열로 만들면 키 순서·공백이 달라져 100% 실패합니다. Express는 express.raw, Flask는 request.get_data(), PHP는 file_get_contents('php://input')를 쓰세요
  • 서명이 여러 개일 수 있습니다. 시크릿 교체 중에는 두 개가 오므로, 첫 번째만 보고 실패 처리하면 교체 기간 내내 전부 거부됩니다
  • v1,이 아닌 항목은 무시하세요. 나중에 다른 버전이 추가돼도 안전하게 동작합니다
  • == 비교는 쓰지 마세요. crypto.timingSafeEqual(Node), hmac.compare_digest(Python), hash_equals(PHP)처럼 시간이 일정한 비교를 쓰세요

시크릿 교체

시크릿 재발급은 엔드포인트 소유자만 할 수 있고, 유출됐을 때의 대응 수단입니다 — 정기적으로 돌릴 값이 아니에요. 재발급 후 24시간 동안은 새 서명과 이전 서명이 함께 전송되므로, 그 사이 아무 때나 수신 서버를 교체하면 배달이 끊기지 않습니다. 24시간이 지나면 새 서명만 갑니다.

협업자로서 웹훅을 받고 있다면 시크릿을 조회할 수 있습니다 — 자기 웹훅도 같은 시크릿으로 서명되기 때문입니다. 재발급만 소유자 권한이에요.

코드 예시

코드 예시

curl, JavaScript, Python 등 주요 언어별 API 호출 코드 샘플이 제공됩니다. 탭을 전환하면 각 언어에 맞는 예시를 확인할 수 있으며, 실제 엔드포인트 URL과 필수 헤더가 미리 채워져 있어 복사하여 바로 사용할 수 있어요.


API 레퍼런스 탭

API 레퍼런스 탭

이 엔드포인트의 사양을 OpenAPI 형식으로 한눈에 정리해 보여주는 탭입니다. 메서드별 카드에 요청 URL · 헤더 · 경로·쿼리 파라미터 · 요청 본문 스키마 · 응답 예시가 모두 포함되어 있어, 외부 도구 없이 이 페이지만으로 연동 사양을 파악할 수 있어요.

  • 빠른 시작 탭이 "직접 호출해서 확인"이라면, API 레퍼런스 탭은 "사양을 보고 연동 코드를 작성" 하는 용도예요
  • POST / GET (단건) / GET (목록) / GET (검색) / GET (폴링) / PUT / DELETE 가 카드 단위로 분리되어 있어 메서드별 차이를 한눈에 비교할 수 있습니다
  • 응답 예시는 실제 응답과 동일한 JSON 구조로 표시됩니다 — 클라이언트의 타입 정의에 그대로 활용 가능해요

자주 막히는 부분

  • 인증 버튼을 눌렀는데 반응이 없어요: API 키가 tm_test_로 시작하는 샌드박스 키인지 확인하세요. 프로덕션 키(tm_live_)는 이 페이지에서 사용할 수 없습니다
  • CREATE 후 ID를 잃어버렸어요: CREATE를 다시 호출하면 새 레코드가 생성되므로 이어서 테스트할 수 있어요. 이전에 생성한 레코드의 ID가 필요하다면 대시보드의 로그 페이지에서 해당 엔드포인트의 호출 기록을 확인하세요
  • 403 오류가 나와요: 사용 중인 협업 키에 해당 메서드 권한이 없을 수 있습니다. 협업키 관리 > 권한에서 확인하세요
  • 웹훅이 안 도착해요: 웹훅 서버가 15초 안에 응답하지 않으면 실패로 처리됩니다. 서버가 공개 인터넷에서 접근 가능한지, HTTPS를 사용하고 있는지 확인하세요. Discord나 Slack 같은 플랫폼은 자체 호출 횟수 제한(Rate Limit)이 있어서, 짧은 시간에 너무 많은 웹훅이 발생하면 일부가 차단될 수 있습니다