핵심 가이드
웹훅(Webhook) 관리 API
대시보드, API 또는 MCP를 통해 작업 알림을 구성하고, 서명을 검증하며, 전송 문제를 해결합니다.
웹훅은 비동기 작업이 완료, 실패 또는 시간 초과될 때 앱에 알림을 보냅니다. 대시보드 → API → 웹훅, 관리 API 또는 TokenLab MCP의 full 프로필을 통해 구성할 수 있습니다. 웹훅은 동일한 워크스페이스 엔드포인트와 전송 기록을 공유합니다.
사용할 자격 증명
| 자격 증명 | 목적 | 사용 위치 |
|---|---|---|
관리 토큰 mt-… | 웹훅 생성, 목록 조회, 업데이트, 삭제, 테스트 및 교체 | /v1/management/webhooks*의 Authorization: Bearer mt-… |
API 키 sk-… | 모델 요청 제출 및 작업 상태 조회 | 모델 API 및 /v1/tasks/{id} |
서명 비밀 키 whsec_… | 수신된 알림의 진위 여부 확인 | 수신 측; API Bearer 토큰으로 절대 사용 금지 |
대시보드 → API → 관리 토큰에서 관리 토큰을 생성하세요. 토큰은 워크스페이스 범위로 지정되므로, 작업을 제출하는 API 키와 동일한 워크스페이스를 선택해야 합니다. 토큰은 다른 워크스페이스의 엔드포인트를 읽거나 수정할 수 없습니다. API 키와 서명 비밀 키는 관리 API에서 거부됩니다. 대시보드 구성은 로그인한 워크스페이스 관리자 세션을 사용합니다.
mt-… 및 whsec_…는 백엔드에 저장하세요. 브라우저 코드, 프롬프트, 저장소 파일 또는 URL에 포함하지 마십시오. 관리 토큰은 다른 워크스페이스 관리 작업도 승인하므로 웹훅 전용 자격 증명이 아닙니다.
엔드포인트 구성
export TOKENLAB_MANAGEMENT_TOKEN="mt-your-management-token"
curl https://api.tokenlab.sh/v1/management/webhooks \
-H "Authorization: Bearer $TOKENLAB_MANAGEMENT_TOKEN" \
-H 'Content-Type: application/json' \
-d '{"url":"https://your-app.example/webhooks/tokenlab","events":["task.completed","task.failed","task.timeout"],"description":"Production task results"}'201 응답에는 id와 whsec_로 시작하는 일회성 secret이 포함됩니다. 이 단계를 떠나기 전에 비밀 키를 저장하십시오. 목록/조회/업데이트 응답에서는 비밀 키가 노출되지 않습니다. 워크스페이스당 최대 10개의 엔드포인트를 구성할 수 있습니다. URL은 공개 HTTPS를 사용해야 하며 자격 증명, 쿼리 문자열 또는 프래그먼트를 포함할 수 없습니다. 리다이렉트는 따르지 않습니다.
| 작업 | 엔드포인트 |
|---|---|
| 목록 조회 / 생성 | GET / POST /v1/management/webhooks |
| 조회 / 업데이트 / 삭제 | GET / PATCH / DELETE /v1/management/webhooks/{webhookId} |
| 서명 비밀 키 교체 | POST /v1/management/webhooks/{webhookId}/rotate-secret |
| 테스트 전송 | POST /v1/management/webhooks/{webhookId}/test |
| 전송 기록 | GET /v1/management/webhooks/{webhookId}/deliveries?page=1&limit=50 |
PATCH {"is_active":false}로 일시 중지하고, PATCH {"is_active":true}로 재개합니다. 재개하면 연속 실패 횟수가 초기화됩니다. 교체 작업은 새로운 비밀 키를 한 번 반환하므로, 즉시 수신 측에 구성하십시오. 진행 중인 요청은 이전 서명을 포함할 수 있으므로 교체 중에는 잠시 동안 두 비밀 키를 모두 허용하십시오. 교체는 되돌릴 수 없습니다.
이벤트 및 페이로드
구독은 향후 발생하는 비동기 작업 이벤트에 적용됩니다. 동기식 결과나 과거 작업은 다시 전송되지 않습니다. 선택한 이벤트 유형에 대해 모든 워크스페이스 작업을 수신하며, data.taskId를 작업 생성 시 반환된 ID와 대조하십시오. 콜백 필드는 camelCase를 사용하고, 관리 응답 필드는 snake_case를 사용합니다.
{
"id": "event-unique-id",
"type": "task.completed",
"created": 1790000000,
"data": {
"taskType": "video",
"taskId": "ldtask_0123456789abcdef0123456789abcdef",
"model": "your-selected-model",
"durationMs": 42000,
"resultUrls": ["https://api.tokenlab.sh/v1/media-results/7c9e6679-7425-40de-944b-e07fc1f90ae7.mp4?token=…"],
"settledCost": 0.12
}
}| 이벤트 | 데이터 |
|---|---|
task.completed | taskType, taskId, 선택적 model, durationMs, resultUrls, settledCost |
task.failed | taskType, taskId, error, errorCode, retryable, refundOutcome |
task.timeout | taskType, taskId, expectedTimeoutMs, actualWaitMs, refundIssued, resolutionSource, refundOutcome |
webhook.test | 테스트 메시지 및 구성된 구독; 테스트 작업에 의해서만 전송됨 |
resultUrls의 각 항목은 30일 동안 유효한 TokenLab 미디어 결과 URL입니다. 데이터 보관을 참조하세요.
task.timeout의 경우, expectedTimeoutMs는 구성된 시간 초과 임계값이며 actualWaitMs는 경과된 대기 시간으로, 둘 다 밀리초 단위입니다. refundIssued: true는 환불이 성공했거나 이미 발행되었음을 의미하며, false라고 해서 나중에 환불되지 않는다는 의미는 아닙니다. refundOutcome은 환불 처리 결과를 설명합니다. 시간 초과 이벤트에는 durationMs가 포함되지 않습니다.
필드는 작업에 따라 달라질 수 있으며 없을 수도 있습니다. 권한 있는 결과 및 청구 상태를 확인하려면 원본 워크스페이스의 sk-… 키와 함께 GET /v1/tasks/{id}를 사용하십시오. 이벤트의 retryable은 생성 실패를 설명하며, 종료된 작업을 무기한 폴링하거나 자동으로 새로운 유료 작업을 제출하라는 지침이 아닙니다. task.failed에서 error, errorCode, retryable은 해당 작업의 공개 error_details.message, code, retryable이며, 이는 상태 조회 시 반환되는 값과 동일합니다.
처리 전 검증
각 POST 요청에는 X-Webhook-ID, X-Webhook-Timestamp (Unix 초 단위) 및 X-Webhook-Signature (sha256=<hex>)가 포함됩니다. 정확한 타임스탬프 문자열, 마침표(.), 그리고 **원시 요청 본문 바이트(raw request body bytes)**에 대해 전체 whsec_… 비밀 키를 사용하여 HMAC-SHA256을 계산하십시오. 검증 전에 JSON을 파싱하고 다시 직렬화하지 마십시오.
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyWebhook(rawBody, headers, secrets) {
const timestamp = headers['x-webhook-timestamp'];
const signature = headers['x-webhook-signature'];
if (typeof timestamp !== 'string' || !/^\d+$/.test(timestamp)) return false;
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false;
if (typeof signature !== 'string' || !/^sha256=[a-f0-9]{64}$/.test(signature)) return false;
const received = Buffer.from(signature.slice(7), 'hex');
return secrets.some(secret => {
const expected = createHmac('sha256', secret).update(timestamp + '.').update(rawBody).digest();
return timingSafeEqual(expected, received);
});
}검증 후 본문의 id가 X-Webhook-ID와 일치하는지 확인하고, 이벤트 ID를 작업 항목과 원자적으로(atomically) 유지하며, 2xx 응답을 빠르게 반환하십시오. 무거운 작업은 자체 큐에서 처리하십시오. 수신 엔드포인트 내에서 이벤트 ID를 기준으로 중복 제거를 수행하십시오. 전송은 반복될 수 있으며 순서가 보장되지 않습니다. 5분의 타임스탬프 허용 오차는 재전송(replay) 기간을 제한하며, ID 중복 제거는 해당 기간 내의 반복 처리를 방지합니다.
재시도 및 복구
각 전송 주기는 최대 3회 시도하며, 1초 후 4초를 대기합니다. 각 HTTP 시도는 10초의 타임아웃과 새로운 타임스탬프/서명을 가집니다. 네트워크 오류, 429, 5xx는 재시도 가능합니다. 다른 4xx, 리다이렉트 및 잘못된 네트워크 대상은 재시도 없이 해당 주기를 중단합니다. 일시적인 오류는 동일한 전송 ID로 나중에 이벤트 재시도를 트리거할 수 있습니다. 10회 연속 실패 시 엔드포인트가 자동으로 일시 중지됩니다.
테스트 작업과 전송 기록을 사용하여 outcome, http_status, attempts, delivered_at을 확인하십시오. 성공적인 테스트 API 응답(200)은 시도가 기록되었음을 의미할 뿐이므로 outcome == "delivered"인지 확인하십시오. 수신 측을 수정하고 엔드포인트를 재개한 후 다시 테스트를 보내십시오. 기록에는 전송 메타데이터만 포함되며 페이로드는 포함되지 않습니다. 이전 이벤트의 수동 재전송은 불가능합니다. 작업 ID를 유지하고 수신 측이 일시 중지되었거나 사용할 수 없었던 경우 작업 상태와 대조하십시오.
MCP 구성
웹훅 관리 도구는 full 프로필에서 사용할 수 있습니다. 관리 자격 증명은 추론 키와 별개입니다. 카탈로그 및 웹훅 관리는 추론 키 없이도 작동할 수 있습니다.
{
"mcpServers": {
"tokenlab": {
"command": "npx",
"args": ["-y", "@tokenlabai/mcp-server@latest"],
"env": {
"TOKENLAB_MCP_TOOL_PROFILE": "full",
"TOKENLAB_MANAGEMENT_TOKEN": "mt-your-management-token",
"TOKENLAB_API_KEY": "sk-your-inference-key"
}
}
}
}도구: list_webhooks, create_webhook, get_webhook, update_webhook, delete_webhook, rotate_webhook_secret, test_webhook, list_webhook_deliveries. 도구 인수에 자격 증명을 절대 붙여넣지 마십시오. 신뢰할 수 있는 MCP 클라이언트에만 관리 액세스 권한을 부여하십시오.
폴링(Polling) 대체 방식
웹훅은 상태 조회 액세스를 제거하거나 새로운 폴링 제한을 부과하지 않습니다. 폴링을 사용하는 경우 생성 응답의 poll_url을 사용하고, 대기 중일 때는 백오프(back off)하며, 종료 상태에서 중단하십시오. 401, 403, 404 또는 error.retryable == false일 때 중단하고, 일시적인 503 async_task_owner_unavailable 오류는 백오프를 사용하여 재시도하십시오. 존재하지 않거나 만료된 작업은 404 async_task_not_found를 반환합니다. 존재하지 않는 작업을 반복적으로 조회해도 다시 생성할 수는 없습니다.
Seedance 호환성 API의 callback_url은 요청별로 별도의 콜백 계약입니다. 해당 작업 생성 시 설정할 수 있으며, 이 워크스페이스 이벤트 페이로드나 HMAC 헤더를 사용하지 않습니다.