Glowb Dev Docs
SaaS API인플루언서 SaaS

연락처 인증

크리에이터 이메일 및 전화번호 인증 API

연락처 인증

크리에이터의 이메일과 전화번호 인증 상태를 조회하고, 6자리 인증번호를 발송/검증합니다.

신규 크리에이터는 온보딩 완료 전에 연락처 인증을 완료해야 합니다. 전화 국가번호(telDialCode)가 +82인 경우 이메일과 전화번호를 모두 인증하고, +82가 아니면 이메일만 인증합니다. 기존 크리에이터는 대시보드 최초 진입 시 status 응답의 verificationRequired 값을 보고 프론트에서 인증 플로우를 노출합니다.

이메일 인증번호는 Node 메일 API를 통해 발송됩니다. 이메일 bounce는 비동기로 반영되므로 발송 직후에는 deliveryStatusPENDING일 수 있습니다.

공통

항목
Base URL/ai/influence
인증필요
인증 방식JWT Bearer Token
인증번호6자리 숫자
만료 시간3분
요청 제한10분 3회

상태 조회

GET /ai/influence/contact-verification/status
Authorization: Bearer {access_token}

응답

{
  "status": 200,
  "code": null,
  "message": "연락처 인증 상태 조회 성공",
  "data": {
    "verificationRequired": true,
    "onboardingCompleted": true,
    "emailVerified": false,
    "telVerified": false,
    "email": "creator@example.com",
    "tel": "01012345678",
    "telDialCode": "+82",
    "maskedEmail": "c****@example.com",
    "maskedTel": "010****5678",
    "lastEmailDeliveryStatus": "BOUNCED",
    "lastEmailFailureReason": "mailbox unavailable"
  }
}

Prop

Type

이메일 인증번호 발송

POST /ai/influence/contact-verification/email/send
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "contact": "creator@example.com",
  "purpose": "ONBOARDING"
}

contact를 비우면 현재 계정에 저장된 이메일로 발송합니다.

응답

{
  "status": 200,
  "code": null,
  "message": "이메일 인증번호를 발송했습니다.",
  "data": {
    "channel": "EMAIL",
    "maskedContact": "c****@example.com",
    "expiresInSeconds": 180,
    "attemptId": "8a83d5cc-b8e2-4ed4-9c45-a5f4ab1fb2a0",
    "deliveryStatus": "PENDING"
  }
}

Prop

Type

Node 메일 연동 참고

연락처 인증 이메일도 기존 Node 메일 API를 공용으로 사용합니다. Java에서 Node로 보낼 때 기존 경로는 유지하고, purposeattemptId로 용도를 구분합니다.

POST {node.api.base-url}/contract/send-otp-email
Content-Type: application/json
{
  "toEmail": "creator@example.com",
  "otpCode": "123456",
  "purpose": "CREATOR_CONTACT_VERIFICATION",
  "attemptId": "8a83d5cc-b8e2-4ed4-9c45-a5f4ab1fb2a0"
}

Node에서 메일 벤더 webhook 등을 통해 bounce 또는 발송 실패를 확인하면 아래 Java API로 다시 알려줍니다.

POST /ai/internal/contact-verification/email-delivery
Content-Type: application/json
{
  "attemptId": "8a83d5cc-b8e2-4ed4-9c45-a5f4ab1fb2a0",
  "messageId": "provider-message-id",
  "status": "BOUNCED",
  "reason": "mailbox unavailable"
}

현재 연동 기준으로 별도 secret header는 사용하지 않습니다. Java 설정에 internal.contact-verification.secret 값이 있으면 X-Internal-Secret 헤더가 필요합니다. Java는 BOUNCE, BOUNCED, FAIL, FAILED, DELIVERY_FAILED를 실패 상태로 처리하고, 실패가 들어오면 해당 이메일 인증번호를 무효화합니다.

이메일 인증번호 검증

POST /ai/influence/contact-verification/email/verify
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "contact": "creator@example.com",
  "code": "123456",
  "purpose": "ONBOARDING"
}

검증 성공 시 해당 이메일이 계정 이메일로 저장되고 이메일 인증 상태가 완료 처리됩니다.

문자 인증번호 발송

POST /ai/influence/contact-verification/sms/send
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "contact": "01012345678",
  "telDialCode": "+82",
  "purpose": "ONBOARDING"
}

contact를 비우면 현재 계정에 저장된 전화번호로 발송합니다. SMS 인증은 telDialCode+82인 경우에만 지원합니다. +82가 아닌 전화번호는 SMS 인증번호를 발송하지 않고, 요청한 전화번호와 telDialCode를 계정에 저장한 뒤 CONTACT_VERIFICATION_SMS_UNSUPPORTED를 반환합니다. 프론트는 이 응답의 data.saved=true를 전화번호 저장 완료로 보고 이메일 인증만 진행합니다.

문자 인증번호 검증

POST /ai/influence/contact-verification/sms/verify
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "contact": "01012345678",
  "telDialCode": "+82",
  "code": "123456",
  "purpose": "ONBOARDING"
}

검증 성공 시 해당 전화번호와 telDialCode가 계정에 저장되고 전화번호 인증 상태가 완료 처리됩니다.

에러 응답

모든 에러는 HTTP 200으로 내려오고, 실제 상태는 body의 status/code를 확인합니다.

인증 필요

{
  "status": 403,
  "code": "CONTACT_VERIFICATION_REQUIRED",
  "message": "이메일 인증이 필요합니다.",
  "data": {
    "channel": "EMAIL",
    "maskedContact": "c****@example.com"
  }
}

인증번호 불일치

{
  "status": 400,
  "code": "CONTACT_VERIFICATION_INVALID",
  "message": "인증번호가 올바르지 않습니다.",
  "data": null
}

인증번호 만료

{
  "status": 400,
  "code": "CONTACT_VERIFICATION_EXPIRED",
  "message": "인증번호가 만료되었습니다. 다시 요청해주세요.",
  "data": null
}

이메일 형식 오류

{
  "status": 400,
  "code": "CONTACT_VERIFICATION_INVALID_EMAIL_FORMAT",
  "message": "유효한 이메일 주소를 입력해주세요.",
  "data": null
}

이메일 bounce

{
  "status": 400,
  "code": "CONTACT_VERIFICATION_EMAIL_BOUNCED",
  "message": "이메일 수신이 실패했습니다. 다른 이메일로 다시 인증해주세요.",
  "data": {
    "channel": "EMAIL",
    "maskedContact": "c****@example.com"
  }
}

SMS 미지원 국가번호

{
  "status": 400,
  "code": "CONTACT_VERIFICATION_SMS_UNSUPPORTED",
  "message": "해외 전화번호는 SMS 인증 대상이 아닙니다. 이메일 인증을 진행해주세요.",
  "data": {
    "channel": "SMS",
    "maskedContact": "901****5678",
    "telDialCode": "+81",
    "saved": true
  }
}

요청 제한

{
  "status": 429,
  "code": "CONTACT_VERIFICATION_RATE_LIMIT",
  "message": "인증번호 요청이 너무 많습니다. 잠시 후 다시 시도해주세요.",
  "data": null
}

프론트 적용 순서

  1. 대시보드 진입 시 GET /contact-verification/status 호출
  2. verificationRequired=true이면 인증 모달 노출
  3. 이메일 인증번호 발송 및 검증
  4. telDialCode=+82이고 telVerified=false인 경우만 문자 인증번호 발송 및 검증
  5. 상태 재조회 후 verificationRequired=false이면 대시보드 진입 허용

이메일 bounce 처리

  • attemptId는 프론트가 저장하거나 재전송할 필요가 없습니다.
  • 이메일 bounce는 비동기로 반영됩니다.
  • 최소 구현은 email/verify 응답에서 CONTACT_VERIFICATION_EMAIL_BOUNCED를 처리하면 됩니다.
  • 더 나은 UX가 필요하면 이메일 발송 후 1015초 동안만 status를 23초 간격으로 짧게 polling합니다.
  • lastEmailDeliveryStatusBOUNCED 또는 FAILED이면 인증번호 입력 UI 대신 다른 이메일 입력을 유도합니다.

권장 문구:

인증 메일을 받을 수 없는 이메일입니다. 다른 이메일 주소로 다시 인증해주세요.

마이페이지 변경

마이페이지에서 이메일을 변경할 때는 새 이메일로 인증번호를 발송하고, 검증 성공 후 저장 API를 호출해야 합니다. 전화번호를 변경할 때는 원칙적으로 teltelDialCode를 함께 보냅니다. 다만 sms/verify 또는 해외번호 sms/send에서 이미 저장된 전화번호를 그대로 다시 저장하는 경우에는 telDialCode를 생략해도 서버가 기존 저장값을 재사용합니다. 전화번호가 바뀌었는데 telDialCode가 없으면 기존 저장된 국가번호를 사용하고, 기존 국가번호도 없으면 CONTACT_VERIFICATION_TARGET_REQUIRED가 반환됩니다. telDialCode=+82이면 SMS 인증이 필요하고, +82가 아니면 SMS 인증을 요구하지 않습니다. 온보딩 완료 요청도 배송지 연락처와 함께 telDialCode를 보내야 합니다. 인증되지 않은 필수 연락처로 저장을 시도하면 CONTACT_VERIFICATION_REQUIRED가 반환됩니다.

On this page