API웹훅
reward.issue
리퍼럴 보상이 확정되어 고객사 회원에게 지급해야 할 때 발송되는 이벤트입니다.
이벤트 개요
| 항목 | 값 |
|---|---|
| 이벤트 타입 | reward.issue |
| 트리거 | 리퍼럴 보상 평가 통과 후 |
| 수신 방식 | POST — 고객사가 등록한 웹훅 URL |
고객사 서버는 이 이벤트를 수신하면 member_id에 해당하는 회원에게 reward_type과 reward_value에 따른 보상을 지급합니다.
페이로드
{
"reward_request_id": "550e8400-e29b-41d4-a716-446655440000",
"member_id": "user_abc123",
"reward_type": "point",
"reward_value": "500",
"source_type": "order",
"campaign_id": "7f3e1200-a1b2-4c3d-8e5f-112233445566"
}필드 설명
| 필드 | 타입 | 설명 |
|---|---|---|
reward_request_id | string (UUID) | 보상 요청 고유 ID — 멱등성 처리에 사용하세요 |
member_id | string | 보상을 받을 회원 ID. 주문 동기화 시 전달한 member_id와 일치합니다 |
reward_type | string | 보상 종류 (예: point, coupon) |
reward_value | string | 보상 값. reward_type이 point이면 포인트 금액(예: "500"), coupon이면 쿠폰 코드(예: "PROMO2024") |
source_type | string | 보상 트리거 유형 (signup, order, message_share) |
campaign_id | string (UUID) | 보상이 속한 캠페인 ID |
리워드 종류별 처리
포인트 (reward_type: "point")
reward_value는 지급할 포인트 금액 문자열입니다 (예: "500"). 수신 즉시 member_id 회원에게 해당 금액만큼 포인트를 적립하세요.
쿠폰 (reward_type: "coupon")
reward_value에는 대시보드의 캠페인 리워드 설정에서 입력한 쿠폰 코드가 그대로 전달됩니다.
쿠폰 코드는 고객사 쿠폰 시스템에서 해당 쿠폰을 고유하게 식별할 수 있는 값으로 입력해주세요. 웹훅 수신 시 이 코드를 기준으로 회원에게 지급할 쿠폰을 특정합니다.
처리 예시
app.post('/webhooks/incento', (req, res) => {
// 1. 서명 검증 (권장)
const isValid = verifySignature(
process.env.INCENTO_WEBHOOK_SECRET,
req.rawBody,
req.headers['x-incento-signature'],
);
if (!isValid) return res.status(401).end();
const { reward_request_id, member_id, reward_type, reward_value } = req.body;
// 2. 멱등성 처리 — 동일한 reward_request_id는 한 번만 처리
if (await isAlreadyProcessed(reward_request_id)) {
return res.status(200).end();
}
// 3. 보상 지급
if (reward_type === 'point') {
await addPoints(member_id, Number(reward_value));
} else if (reward_type === 'coupon') {
await issueCoupon(member_id, reward_value);
}
// 4. 2xx 응답 반환 (필수)
res.status(200).end();
});import os
from flask import Flask, request
app = Flask(__name__)
@app.post('/webhooks/incento')
async def handle_webhook():
# 1. 서명 검증 (권장)
is_valid = verify_signature(
os.environ['INCENTO_WEBHOOK_SECRET'],
request.get_data(),
request.headers.get('x-incento-signature', ''),
)
if not is_valid:
return '', 401
payload = request.get_json()
reward_request_id = payload['reward_request_id']
member_id = payload['member_id']
reward_type = payload['reward_type']
reward_value = payload['reward_value']
# 2. 멱등성 처리 — 동일한 reward_request_id는 한 번만 처리
if await is_already_processed(reward_request_id):
return '', 200
# 3. 보상 지급
if reward_type == 'point':
await add_points(member_id, int(reward_value))
elif reward_type == 'coupon':
await issue_coupon(member_id, reward_value)
# 4. 2xx 응답 반환 (필수)
return '', 200