블로그 팩토리 · CS 연동 · v1
VOC 수집 API 문서
blogfactory.kr 에 접수되는 고객 문의(VOC)와 앱 자동 진단(버그 리포트)을 외부 CS 시스템이 읽고 답변을 다는 API 입니다. 관리자가 발급한 키로만 호출할 수 있습니다. 읽기 권한이 기본이고, 관리자가 답변 권한을 허용한 키는 문의에 답변을 달고 상태를 바꿀 수 있습니다.
1. 인증
모든 요청에 발급받은 키를 헤더로 보냅니다. x-voc-api-key 가 기본이고 Authorization: Bearer <키> 도 같은 뜻으로 받습니다. 키는 bfvoc_ 로 시작하는 54자 문자열이며 서버에는 해시만 저장되므로, 분실하면 관리자에게 폐기·재발급을 요청해야 합니다.
연동을 시작할 때 키 확인부터 합니다.
curl -H "x-voc-api-key: $VOC_KEY" https://blogfactory.kr/api/v1/voc/me
# {"key":{"id":"…","name":"CS팀 개발 관리자","scopes":["voc:read"]},
# "server_time":"2026-09-17T10:20:00.000Z","endpoints":[…]}401 을 받습니다.2. 엔드포인트
/api/v1/voc/threads문의 목록공개·비공개 문의와 자동 버그 리포트를 모두 돌려주며, 관리자 화면과 같은 범위입니다.
| 파라미터 | 설명 | 기본 |
|---|---|---|
| status | open(답변 대기) · answered(답변 완료) · closed(종료) | 전체 |
| category | 제품 · 결제 · 기술 · 체험판 · 기타 · 자동 버그 리포트 (URL 인코딩 필수) | 전체 |
| since | last_message_at >= since. ISO 8601, 예 2026-09-01T00:00:00Z | 없음 |
| until | last_message_at < until | 없음 |
| order | asc · desc. last_message_at 기준, 같은 시각은 id 오름차순 | desc |
| page / page_size | 1부터 시작, 페이지 크기 1~100 | 1 / 50 |
| include | diagnostics 를 넣으면 자동 버그 리포트 행에 진단 요약(diagnostic)을 함께 붙입니다 | 없음 |
curl -G -H "x-voc-api-key: $VOC_KEY" "https://blogfactory.kr/api/v1/voc/threads" \
--data-urlencode "since=2026-09-01T00:00:00Z" \
--data-urlencode "order=asc" \
--data-urlencode "page_size=100" \
--data-urlencode "include=diagnostics"{
"threads": [
{
"id": "8f4c2a1e-5b7d-4c3e-9a1f-2d6b8e0c4a71",
"kind": "inquiry",
"category": "기술",
"title": "네이버 발행 시 주제 선택",
"status": "answered",
"author_name": "홍길동",
"has_account": true,
"is_public": true,
"is_faq": false,
"message_count": 2,
"last_message_at": "2026-09-17T06:34:10.123Z",
"created_at": "2026-09-16T23:01:00.000Z"
},
{
"id": "c5b36e87-1a2b-4c3d-8e9f-0a1b2c3d4e5f",
"kind": "bug_report",
"category": "자동 버그 리포트",
"title": "네이버 사진 업로드 실패",
"status": "open",
"author_name": "앱 자동 접수",
"has_account": false,
"is_public": false,
"is_faq": false,
"message_count": 1,
"last_message_at": "2026-09-17T02:10:44.000Z",
"created_at": "2026-09-17T02:10:44.000Z",
"diagnostic": {
"diagnostic_kind": "publishing",
"error_code": "NAVER_IMAGE_SESSION_HTTP_400",
"feature": "writing.publish",
"surface": "step3",
"failure_stage": "upload",
"action": "publish",
"error_message": "확정 이미지 전부를 업로드하지 못했습니다 …",
"app_version": "1.0.99",
"release_channel": "prod",
"os_name": "Windows",
"ai_provider": "",
"ai_model": "",
"license_mask": "••••-7235",
"user_comment": "",
"occurrence_count": 3,
"first_seen_at": "2026-09-16T22:00:00.000Z",
"last_seen_at": "2026-09-17T02:10:44.000Z",
"expires_at": "2026-10-17T02:10:44.000Z",
"image_count": 2
}
}
],
"page": 1,
"page_size": 100,
"total": 137,
"total_pages": 2,
"next_page": 2
}/api/v1/voc/threads/{id}문의 상세스레드, 메시지 전체, 작성자 이메일, 그리고 자동 버그 리포트라면 진단 상세와 캡처 이미지 URL 을 돌려줍니다.
{
"thread": { "… 목록과 같은 필드 …" },
"author_email": "user@example.com",
"messages": [
{ "id": "…", "author_role": "user", "author_name": "홍길동",
"body": "마크다운 본문", "attachments": [{ "type": "image", "url": "https://…" }],
"created_at": "2026-09-16T23:01:00.000Z" },
{ "id": "…", "author_role": "admin", "author_name": "블로그팩토리",
"body": "답변 본문", "attachments": [], "created_at": "2026-09-17T06:34:10.123Z" }
],
"diagnostic": {
"… 목록 요약 필드 …",
"context_snapshot": { "channel": "naver", "failure_code": "…" },
"log_excerpt": ["[발행로그] …", "[이미지진단] …"]
},
"diagnostic_images": [{ "url": "https://…signed…", "expires_in": 3600 }]
}author_email은 로그인 회원이 남긴 문의에만 값이 있습니다. 자동 버그 리포트는 항상 빈 문자열이고, 대신diagnostic.license_mask(라이선스 끝 4자)로 고객을 식별합니다.diagnostic과diagnostic_images는kind = "bug_report"일 때만 채워집니다. 이미지 URL 은 1시간 뒤 만료되므로 필요하면 그때 내려받습니다.body는 마크다운 원문입니다(HTML 아님). 문의id는 UUID 이며 다른 형식은 400 입니다.
/api/v1/voc/me키 확인키 이름·권한·서버 시각·엔드포인트 목록을 돌려줍니다. 배포 뒤 헬스체크로 써도 됩니다.
/api/v1/voc/threads/{id}/replies답변 등록 · 권한 voc:write관리자 화면에서 답변을 다는 것과 같은 효과입니다. 관리자 메시지로 저장되고 문의 상태가 answered 로 바뀌며, 로그인 회원의 문의면 고객에게 답변 알림 메일이 갑니다(응답의 mailed).
| 본문 필드 | 설명 | 기본 |
|---|---|---|
| body | 답변 본문(마크다운, 5,000자 이내). 필수 — 비어 있으면 첨부가 있어도 400 | — |
| author_name | 고객에게 보이는 답변자 이름(40자 이내) | 블로그팩토리 |
| attachments | [{ type: "image" | "youtube", url }] 최대 10개, https 만 | [] |
| close | true 면 답변과 함께 문의를 종료(closed) | false |
curl -X POST -H "x-voc-api-key: $VOC_KEY" -H "Content-Type: application/json" \
"https://blogfactory.kr/api/v1/voc/threads/8f4c2a1e-5b7d-4c3e-9a1f-2d6b8e0c4a71/replies" \
-d '{
"body": "안녕하세요, 확인해 보니 설정 → 계정설정 → 네이버 블로그에서 연결 테스트를 다시 해 주시면 됩니다.",
"author_name": "블로그팩토리 고객센터",
"attachments": [{ "type": "image", "url": "https://example.com/guide.png" }],
"close": false
}'{
"message": { "id": "…", "author_role": "admin", "author_name": "블로그팩토리 고객센터",
"body": "안녕하세요, …", "attachments": [{ "type": "image", "url": "https://example.com/guide.png" }],
"created_at": "2026-09-17T11:02:10.000Z" },
"thread": { "id": "8f4c2a1e-…", "kind": "inquiry", "status": "answered", "message_count": 3, "…": "…" },
"mailed": true
}/api/v1/voc/threads/{id}상태 변경 · 권한 voc:write본문 { "status": "open" | "answered" | "closed" }. 답변 없이 상태만 바꿀 때 씁니다(예: 처리 완료 후 종료). 공개 여부·FAQ 는 바꿀 수 없습니다.
curl -X PATCH -H "x-voc-api-key: $VOC_KEY" -H "Content-Type: application/json" \
"https://blogfactory.kr/api/v1/voc/threads/8f4c2a1e-5b7d-4c3e-9a1f-2d6b8e0c4a71" -d '{ "status": "closed" }'
# { "thread": { "id": "8f4c2a1e-…", "status": "closed", "…": "…" } }3. 응답 필드
thread
- kind
inquiry(사람이 남긴 문의) 또는bug_report(앱 자동 진단)- status
- open 답변 대기 · answered 답변 완료 · closed 종료
- has_account
- 로그인 회원의 문의인지. true 면 상세에서 author_email 을 받을 수 있습니다
- is_public / is_faq
- 공개 게시판 노출 여부 / 대표 질문(FAQ) 지정 여부
- message_count / last_message_at
- 메시지 수와 마지막 메시지 시각. 증분 동기화의 기준입니다
diagnostic (자동 버그 리포트)
오류 코드·기능·단계·메시지·앱 버전·채널·OS·AI 공급자/모델·라이선스 마스킹·사용자 코멘트·발생 횟수·최초/최근 발생·만료 시각·이미지 수. 상세 응답에는 context_snapshot(진단 문맥, 비밀값 제거됨)과 log_excerpt(로그 발췌, 최대 200줄)가 추가됩니다.
4. 증분 동기화 권장 방식
- 마지막으로 성공한 동기화 시각
T를 저장해 둡니다(처음엔 충분히 과거). since = T − 5분,order=asc,page_size=100,include=diagnostics로next_page가 null 이 될 때까지 넘깁니다. 같은 id 는 최신 값으로 덮어씁니다(멱등).- 메시지·진단 문맥이 필요한 스레드는 message_count 나 last_message_at 이 바뀐 것만 상세로 다시 읽습니다.
- 응답에서 가장 큰 last_message_at 을 새 T 로 저장합니다.
자동 진단은 접수 뒤 30일이 지나면 서버에서 지워집니다(diagnostic.expires_at). 오래 보관하려면 그 전에 가져가세요.
5. 오류
| 코드 | 뜻 | 조치 |
|---|---|---|
| 400 | 파라미터 오류. 본문 error 에 이유가 있습니다 | 요청을 수정합니다 |
| 401 | 키 없음 · 형식 오류 · 폐기 · 만료 | 관리자에게 키 확인 또는 재발급을 요청합니다 |
| 403 | 권한 범위 밖(읽기 키로 답변 등록·상태 변경 호출) | 관리자에게 답변 권한(voc:write) 부여를 요청합니다 |
| 404 | 없는 문의 id | — |
| 429 | 분당 120회 초과 | 잠시 뒤 재시도(지수 백오프) |
| 500 | 서버 오류 | 잠시 뒤 재시도. 반복되면 시각과 요청 URL 을 관리자에게 전달합니다 |
오류 응답은 항상 {"error": "사람이 읽을 수 있는 이유"} 형태입니다.
6. 운영 정보
- 키 발급·폐기·만료·권한(읽기 / 읽기+답변) 설정은 블로그 팩토리 관리자가 합니다. 키마다 발급자와 마지막 사용 시각이 기록됩니다.
- 답변 등록은 고객에게 바로 보이고 알림 메일이 나가므로, 연동 테스트는 반드시 관리자와 합의한 테스트 문의에서만 하세요.
- 호출 제한은 키 단위 분당 120회입니다. 대량 초기 적재는 page_size=100 으로 페이지를 넘기면 분당 최대 12,000건까지 읽을 수 있습니다.
- 응답은 모두 JSON(UTF-8)이며 시각은 ISO 8601 UTC 입니다. 한글 파라미터는 반드시 URL 인코딩해 보냅니다.
- 키 발급이나 범위 확장이 필요하면 고객센터로 문의하세요.
문서 버전 2026-09-17 (답변 등록·상태 변경 추가) · API 버전 v1