연락처 SDK 연동 가이드
웹/앱 SDK의 identify()로 회원 정보·수신동의·커스텀 속성·행동 데이터를 주소록(연락처)에 수집합니다.
연락처 데이터 구성
하나의 연락처는 세 층으로 이루어지며, 각각 다른 API 호출로 채워집니다.
| 층 | 담기는 정보 | 채우는 방법 | 세그먼트 조건 |
|---|---|---|---|
| 기본 정보 | 이름·전화·이메일·앱푸시 식별자·수신동의 | POST /identify, /opt-in |
이름/이메일/전화/수신동의 |
| 커스텀 속성 | 등급·생일·포인트 등 내 서비스 고유 항목 | /identify의 customFields |
custom.* |
| 행동 데이터 | 로그인·구매·커스텀 이벤트의 최초/마지막 시각·횟수·누적액 | /session/event, /session/funnel/track |
activity.* |
externalUserId로 식별됩니다.
같은 externalUserId로 다시 호출하면 새 레코드가 아니라 기존 연락처가 갱신됩니다.
인증 & 베이스 URL
연락처 API는 /api/v1/cross-platform/** 경로를 사용하며,
모든 요청에 두 개의 헤더가 반드시 필요합니다.
| 헤더 | 필수 | 설명 |
|---|---|---|
| X-App-ID | 필수 | 연동할 앱의 ID (숫자) |
| X-Mobile-App-API-Key | 필수 | 해당 앱의 API Key |
| Content-Type | 필수 | application/json |
X-App-ID와 X-Mobile-App-API-Key는
둘 다 있어야 하며 서로 매칭되는 쌍이어야 합니다. 하나라도 없거나 쌍이 일치하지 않으면
401을 반환합니다. API Key는 서버 측에만 보관하고 브라우저·앱 클라이언트에 노출하지 마세요.
베이스 URL은 https://api.fingerpush.link/api/v1/cross-platform 입니다.
사용자 수집 엔드포인트
SDK는 아래 세 엔드포인트로 회원 정보와 수신동의를 주소록에 upsert합니다.
POST /api/v1/cross-platform/identify
로그인·회원가입·프로필 변경 시 호출합니다. externalUserId 기준으로
없으면 새로 만들고(INSERT), 있으면 전달한 필드만 갱신합니다(보내지 않은 필드는 기존 값 유지).
요청 본문
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| externalUserId | String | 필수 | 내 서비스의 회원 ID (최대 200자) |
| name | String | 이름 (최대 100자) | |
| phone | String | 전화번호 — 서버에서 AES-256 암호화 저장 (최대 50자) | |
| String | 이메일 — 서버에서 AES-256 암호화 저장 (최대 200자) | ||
| pushIdentify | String | 앱푸시 식별자 (핑거푸시 토큰, 최대 200자) | |
| smsOptIn | Boolean | SMS 수신동의 | |
| emailOptIn | Boolean | 이메일 수신동의 | |
| pushOptIn | Boolean | 앱푸시 수신동의 | |
| smsAdOptIn | Boolean | SMS 광고 수신동의 | |
| emailAdOptIn | Boolean | 이메일 광고 수신동의 | |
| pushAdOptIn | Boolean | 앱푸시 광고 수신동의 | |
| nightAdOptIn | Boolean | 야간 광고 수신동의 | |
| alimtalkAdOptIn | Boolean | 알림톡 광고 수신동의 | |
| whatsappOptIn | Boolean | WhatsApp 수신동의 | |
| customFields | Object | 등급·생일 등 임의 속성 — 키 단위 병합, 세그먼트 custom.* 소스 |
요청 예시
curl -X POST https://api.fingerpush.link/api/v1/cross-platform/identify \
-H "X-App-ID: 12345" \
-H "X-Mobile-App-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{
"externalUserId": "u1001",
"name": "홍길동",
"phone": "01012345678",
"email": "gildong@example.com",
"smsOptIn": true,
"emailAdOptIn": true,
"customFields": { "grade": "gold", "birthday": "1990-07-26", "point": 15000 }
}'
응답
{
"success": true,
"action": "created", // "created" | "updated" | "reactivated"
"externalUserId": "u1001"
}
- created — 신규 연락처 생성
- updated — 기존 연락처 갱신
- reactivated — 탈퇴했던 연락처가 재가입으로 되살아남
YYYY-MM-DD
(또는 YYYY-MM-DDTHH:mm:ss) 형식으로 보내야 날짜 조건에서 인식됩니다.
자세한 내용은 세그먼트 가이드를 참고하세요.
- 커스텀 필드 키는 연락처당 기본 50개까지(조직별 조정 가능), 키 이름은 최대 50자입니다.
- 값은 텍스트로 저장됩니다. 숫자·불리언을 보내도 문자열로 저장·반환됩니다(예:
15000→"15000"). 값 길이는 기본 2000자까지(조직별 조정 가능)입니다. - 상한을 넘는 키는 무시되고, 길이를 초과한 값은 잘려서 저장됩니다. 오류로 반환되지 않습니다.
- 가입일 주의:
createdAt은 연락처가 이 플랫폼에 처음 생성된 시각(유입일)입니다. 실시간 SDK 가입이면 실제 가입일과 같지만, 기존 회원 가져오기·지연 식별이면 다릅니다. 고객사 서비스 기준 실제 가입일로 세그먼트하려면signup_date(YYYY-MM-DD)를 커스텀 필드로 명시해 보내세요 — createdAt이 표현하지 못하는 과거 사실이라 중복이 아닙니다. - 반복·금액 행동(구매 등)은
activity.purchase.first/last/count/sum으로 서버가 자동 집계합니다. 마지막 구매 "일"만 커스텀 필드로 추가로 저장하는 중복은 피하세요. 커스텀 필드는 등급·관심사·유입 전 과거 사실처럼 서비스가 정하는 속성에 쓰는 것을 권장합니다.
POST /api/v1/cross-platform/opt-in
마이페이지 등에서 수신동의만 단독으로 변경할 때 호출합니다.
identify()를 먼저 호출하지 않은 사용자는 404를 반환합니다.
요청 본문
externalUserId(필수) + identify와 동일한 수신동의 필드들
(smsOptIn, emailOptIn,
pushOptIn, smsAdOptIn,
emailAdOptIn, pushAdOptIn,
nightAdOptIn, alimtalkAdOptIn,
whatsappOptIn). 전달한 항목만 갱신됩니다.
curl -X POST https://api.fingerpush.link/api/v1/cross-platform/opt-in \
-H "X-App-ID: 12345" \
-H "X-Mobile-App-API-Key: your_api_key" \
-H "Content-Type: application/json" \
-d '{ "externalUserId": "u1001", "smsOptIn": false, "emailAdOptIn": true }'
POST /api/v1/cross-platform/withdraw
탈퇴 시 호출합니다. 연락처를 비활성화하고 이름·전화번호·이메일·앱푸시 식별자·커스텀 속성을 즉시 공백 처리하며 수신동의를 모두 해제합니다. 행동 기록도 함께 삭제됩니다.
요청 본문
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| externalUserId | String | 필수 | 탈퇴할 회원 ID |
{
"success": true,
"externalUserId": "u1001",
"withdrawnCount": 1 // 공백 처리된 연락처 수
}
externalUserId로
다시 identify()를 호출하면 재가입(reactivated)으로
처리되며 정보를 다시 보내야 합니다. 발송 이력은 통신이력 보관 의무에 따라 발송일로부터 12개월 동안, 누적 통계는 그대로 보존됩니다.
관리자가 콘솔에서 차단한 연락처는 재가입해도 되살아나지 않습니다.
대상이 없으면 404를 반환합니다(이미 탈퇴했거나 등록된 적 없는 사용자).
행동 데이터(activity) 수집
로그인·구매·커스텀 이벤트 같은 행동은 세션 API로 기록됩니다. 서버는 세션에 연결된
externalUserId로 연락처를 찾아, 이벤트를 해당 연락처의
activity(최초 시각·마지막 시각·발생 횟수·누적 금액)로 집계합니다.
이 값들이 세그먼트의 activity.* 조건 소스가 됩니다.
| 메서드 | 경로 | 설명 |
|---|---|---|
| POST | /session/event | 커스텀 이벤트 기록 — eventType이 metric 이름이 됨 |
| POST | /session/funnel/track | 퍼널 이벤트 추적 — 로그인·구매·앱설치·앱실행 등 표준 전환 |
/session/event 요청 필드
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
| sessionId | String | 필수 | 세션 ID |
| eventType | String | 필수 | 이벤트명 — activity metric 이름으로 사용 (예: wishlist_add) |
| eventData | Object | 이벤트 추가 데이터 | |
| clientTimestamp | String | ISO 8601 UTC | |
| clientTimezone | String | 예: Asia/Seoul |
- 커스텀 이벤트 metric은 조직당 기본 50개까지 생성됩니다. 상한에 도달하면 기존 metric은 계속 누적되지만 새 metric은 만들어지지 않습니다. metric 이름은 최대 50자입니다.
login·purchase·app_open·app_install은 서버 표준 metric으로, 퍼널 추적(/session/funnel/track)에서 자동 기록되며 커스텀 상한과 무관합니다.- 구매 금액 누적(LTV)은 조직 기준통화와 일치할 때만 합산됩니다(다른 통화는 발생 횟수만 기록).
세그먼트 연계
이 API로 수집한 데이터는 콘솔의 세그먼트 조건으로 즉시 활용됩니다.
커스텀 속성은 custom.키로, 행동 데이터는
activity.metric.first|last|count|sum 형태로 참조됩니다.
조건에 맞는 대상자는 매일 자동으로 다시 계산되어 캠페인·자동화 발송 대상으로 쓰입니다.
조건 문법과 활용 예시는 세그먼트 사용자 속성 가이드를 참고하세요.
오류 응답
| 상태 코드 | 상황 | 비고 |
|---|---|---|
| 400 | X-App-ID가 숫자가 아님, 또는 요청 본문 검증 실패 | externalUserId 누락 등 |
| 401 | 인증 헤더 누락 또는 App ID / API Key 쌍 불일치 | 두 헤더 모두 필요 |
| 403 | 필요한 애드온 미구독 | 세션/퍼널 API의 애드온 요구사항 |
| 404 | 대상 연락처 없음 | /opt-in·/withdraw에서 identify 선행 안 됨 |
// 401 — 헤더 누락
{ "error": "X-App-ID 헤더는 필수입니다." }
// 404 — opt-in 선행 identify 없음
{ "success": false, "message": "등록되지 않은 사용자입니다. identify()를 먼저 호출하세요." }