웹훅 (JSON)
웹훅 규칙은 일치하는 각 응답을 JSON으로 지정한 URL에 POST합니다. CRM, 스프레드시트 도구, 자체 서버, 또는 Zapier, Make, n8n 같은 자동화 플랫폼에 데이터를 보낼 때 쓰세요.
웹훅 규칙 만들기
- + 새 규칙을 클릭하고 웹훅을 고릅니다
- 시점: 모든 응답을 그대로 두거나 승인 후에만 / 거부될 때를 고르고 승인자를 지정합니다. 일치하는 응답만 보내려면 추가 조건을 넣으세요
- 대상: 엔드포인트 URL을 붙여넣습니다 (HTTPS만 가능). 메시지 단계는 없습니다. 규칙은 고정 JSON 페이로드를 보냅니다. URL 아래의 페이로드 보기에서 양식 질문이 담긴 페이로드를 확인하고 복사할 수 있습니다
- 규칙 만들기를 클릭한 뒤, 한 번만 표시되는 서명 비밀키를 복사합니다 (아래 참고)

테스트 보내기는 서명된 샘플 페이로드를 엔드포인트로 보내고 돌아온 HTTP 상태를 보여 줍니다. 저장된 URL은 암호화되어 보관되고 가려진 형태로 표시됩니다. 새 URL을 붙여넣으려면 교체를 클릭하세요.
페이로드
각 요청은 POST, Content-Type: application/json이며 본문은 다음과 같습니다:
{
"version": 1,
"event": "submitted",
"form": { "id": "1AbC...", "name": "Workshop sign-up" },
"response": {
"id": "a3f1...",
"submittedAt": "2026-01-31T09:30:00.000Z",
"respondentEmail": "respondent@example.com",
"answers": [
{ "questionId": "q1", "title": "Your name", "value": "Ada Lovelace" },
{ "questionId": "q3", "title": "Department", "value": "Ops" }
]
},
"rule": { "id": "rule id", "name": "Zapier: new lead" }
}
event는submitted,approved,rejected중 하나이며X-Skyfield-Event헤더에도 담깁니다response.respondentEmail은 설문지가 이메일 주소를 수집하지 않는 한null입니다answers[].value는 항상 문자열이며, 체크박스 답변은,로 이어집니다rule.id와rule.name은 실행된 규칙을 가리킵니다. 규칙에 이름이 없으면name은null입니다approved와rejected일 때는approval: { "decision": "approved", "decidedBy": "Dana" }가 추가됩니다.decidedBy는 승인자가 승인 페이지에 입력한 이름이며, 없으면 승인자의 이메일, 그것도 없으면null입니다
위 형태가 유지되는 한 version은 1로 남습니다. 새 필드가 추가될 수는 있지만, 버전을 올리지 않고 필드를 제거하거나 이름을 바꾸지는 않습니다.
서명 검증하기
모든 요청에는 X-Skyfield-Signature 헤더가 있습니다: sha256=<hex>, 즉 규칙의 서명 비밀키를 키로 한 원본 요청 본문의 HMAC-SHA256입니다. 요청을 신뢰하기 전에 검증하세요.

비밀키(whsec_...)는 규칙에 처음 웹훅 URL을 넣고 저장한 직후 한 번만 표시됩니다. 그때 복사하세요. 다시 표시할 수 없습니다. 나중에 URL을 교체해도 비밀키는 그대로입니다. 잃어버렸다면 규칙을 열고 새 서명 비밀키를 클릭한 뒤 저장하세요. 새 비밀키가 한 번 표시되고 이전 비밀키는 즉시 동작을 멈춥니다.
HMAC은 수신한 본문 바이트 그대로에 대해 계산하세요. JSON을 먼저 파싱한 뒤 다시 직렬화하면 공백이 바뀌어 비교가 실패합니다.
Node.js
import { createHmac, timingSafeEqual } from 'node:crypto'
// rawBody: string or Buffer of the request body, before any JSON parsing
function verify(rawBody, header, secret) {
const expected = 'sha256=' + createHmac('sha256', secret).update(rawBody).digest('hex')
const a = Buffer.from(expected)
const b = Buffer.from(header ?? '')
return a.length === b.length && timingSafeEqual(a, b)
}
// Express example: use express.raw() so req.body is the untouched bytes
app.post('/hook', express.raw({ type: 'application/json' }), (req, res) => {
if (!verify(req.body, req.get('X-Skyfield-Signature'), process.env.SKYFIELD_SECRET))
return res.status(401).end()
const payload = JSON.parse(req.body)
res.status(200).end()
})
Python
import hmac, hashlib
def verify(raw_body: bytes, header: str, secret: str) -> bool:
digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest("sha256=" + digest, header or "")
# Flask example
@app.post("/hook")
def hook():
if not verify(request.get_data(), request.headers.get("X-Skyfield-Signature"), SECRET):
return "", 401
payload = request.get_json()
return "", 200
아무 2xx 상태로 응답하세요. 본문은 무시됩니다.
Zapier, Make, n8n
셋 모두 일반 JSON 웹훅을 받습니다:
- Zapier: 트리거 Webhooks by Zapier, 이벤트 Catch Hook (서명을 직접 검증하려면 Catch Raw Hook). Zapier가 보여 주는 URL을 규칙에 붙여 넣으세요
- Make: Webhooks 모듈의 Custom webhook을 추가하고 URL을 복사합니다
- n8n: Webhook 노드를 추가하고 메서드를 POST로 설정한 뒤 프로덕션 URL을 사용합니다
규칙에서 테스트를 보낸 다음 플랫폼에서 response.answers 필드를 매핑하세요. 샘플 페이로드는 예시 답변을 사용하므로 모든 필드가 들어 있습니다.
전송과 한도
- 엔드포인트는 공개 인터넷에서 HTTPS로 접근할 수 있어야 합니다. 사설 주소와 로컬 주소는 저장할 때 거부됩니다
- 리디렉션은 따라가지 않습니다. 최종 URL을 사용하세요
- 엔드포인트는 5초 안에 응답해야 합니다. 시간 초과나 5xx 응답은 한 번 재시도합니다
- 404 또는 410 응답은 엔드포인트가 없어졌다는 뜻입니다. 규칙이 일시중지되고 이메일이 한 통 갑니다. 규칙에 새 URL을 붙여넣으면 다시 작동합니다
- 기록 페이지에 각 전송과 엔드포인트가 돌려준 HTTP 상태가 나열됩니다
- 일시중지되었거나 꺼진 웹훅 규칙은 양식의 다른 규칙을 막지 않습니다
알아 두기
- 웹훅 규칙은 보내는 시점을 따르므로, 엔드포인트가 모든 제출 대신 승인 결정만 받을 수도 있습니다. 보내는 시점을 참고하세요
- 검증된 응답만 보내려면 규칙의 보내는 시점을 승인 후에만으로 설정하고 승인자를 고르세요. 승인을 참고하세요. 그러면 페이로드에
approval.decision이 들어갑니다 - 채널 변경… 으로 웹훅 규칙을 이메일이나 채팅 채널로 옮길 수 있습니다. 새 대상은 거기서 지정하세요. 다시 웹훅으로 바꾸면 URL을 새로 붙여넣어야 합니다
- 웹훅 규칙에는 유효한 라이선스가 필요합니다. 무료 체험도 포함됩니다. 라이선스가 필요한 기능을 참고하세요
