문서
발행
글을 올리고, 상태를 확인하고, 실패한 곳만 다시 보내고, 지우는 방법이에요.
GET /v1/posts
최근에 올린 글 목록이에요. 최신순으로 오고, 답글은 이 목록에 섞이지 않아요.
페이지 넘기기
| 이름 | 타입 | 설명 |
|---|---|---|
limit | query | 1~100, 기본 20 |
before | query | 앞 페이지의 nextBefore로 받은 발행 id. 그보다 오래된 글을 줘요. |
includeDeleted | query | true면 채널에서 지운 글도 같이 줘요. 기본은 숨겨요. 포샌디 기록과 지표는 어느 쪽이든 남아요. |
status | query | 상태로 거르기. 쉼표로 여러 개: scheduled, draft, publishing, published, partial, failed, cancelled. 빼면 예약 글과 초안까지 전부 줘요. |
since | query | YYYY-MM-DD 또는 ISO 8601. 이 날짜 이후 글. 예약 글은 scheduledAt, 보낸 글은 만든 시각 기준이에요. |
until | query | YYYY-MM-DD 또는 ISO 8601. 이 날짜까지의 글. 날짜만 넣으면 그날 하루 전체가 들어가요. |
sort | query | scheduled면 글 날짜 오름차순으로 정렬하고 페이지를 나누지 않아요. 빼면 최신순이에요. |
hasMore | response | 목록이 중간에 잘렸다는 뜻이에요. |
nextBefore | response | 다음 요청의 before에 넣어요. 더 없으면 오지 않아요. |
POST /v1/posts
연결된 계정 하나 이상에 글을 올려요.
| 이름 | 타입 | 설명 |
|---|---|---|
content (필수) | string | 글 내용. 이모지는 UTF-8 바이트로 세요. |
accountIds (필수) | string[] | GET /v1/accounts에서 받은 id |
mediaIds | string[] | complete까지 끝난 미디어. 네이버 블로그는 본문에 media: 참조로 넣은 id를 빼도 돼요. 포샌디가 본문에서 읽어 붙여요. |
options | object | 채널별 설정. 채널 id를 키로 써요. 모양은 GET /v1/platforms의 options와 각 채널 페이지에 있어요. 이 값이 없으면 못 올리는 채널도 있어요. YouTube는 options.youtube.title, 네이버 블로그는 options.naver_blog.title과 카테고리가 필요해요. 모든 채널이 그 채널에만 다른 본문을 넣는 options.<채널>.content를 받아요. |
scheduledAt | string | 시간대 오프셋이 있는 ISO 8601. 10분 뒤부터 1년 안까지. 포샌디가 scheduled 상태로 보관했다가 그 시각에 모든 채널로 보내요. |
draft | boolean | true면 보내지 않고 저장만 해요. accountIds가 아직 없어도 돼요. 나중에 POST /v1/posts/{id}/publish로 보내요. |
batchId | string | 함께 만든 글을 묶는 선택 태그, 40자까지(예: 같은 글을 두 워크스페이스에 보낼 때). 모든 글에 그대로 돌아와요. |
replyTo | string | 이 글을 그 발행 id의 답글로 올려요. |
threadItems | object[] | 긴 글을 연결 글(체인)로 나눠요: [{ content, mediaIds? }]. 첫 항목이 원글이고 나머지는 차례대로 그 아래 답글이 돼요. 항목마다 글자 수 제한을 따로 지켜요. content와 같이 쓸 수 없어요. 체인은 Threads와 Bluesky(준비 중)만 받아요. 뒤 항목이 실패해도 이미 올라간 항목은 남고, 응답에 thread.resumeFrom이 와요. 한 항목이 실패하면 그 계정의 뒤 항목은 errorCode thread_broken으로 실패 처리되고, retry_post가 실패한 항목부터 이어서 보내요. 뒤 항목이 있는 글은 threadItems로 돌려주고, 예약 글이나 초안일 때는 PATCH도 같은 값을 받아요. |
topicTag | string | 글에 붙일 주제 태그 하나. Threads는 정확히 하나만 받고 마침표와 앰퍼샌드(&)는 거절해요. 체인에서는 첫 항목에만 붙어요. |
Idempotency-Key | header | 재시도할 때 같은 키를 보내면 두 번 올리지 않고 첫 응답을 그대로 돌려줘요. 같은 키에 다른 본문을 보내면 422예요. 24시간 보관해요. |
wait | boolean | 글이 실제로 올라갈 때까지 응답을 기다려요. 글만 있으면 최대 10초, 미디어가 있으면 최대 75초. 넘으면 평소처럼 202와 next 안내가 오고, 발행은 계속 진행돼요. 기본 false |
curl -X POST https://api.posendy.com/v1/posts \
-H "authorization: Bearer $POSENDY_KEY" \
-H "content-type: application/json" \
-d '{
"content": "Now with images",
"accountIds": ["acc_01H..."],
"mediaIds": ["med_01H..."]
}'
202는 발행 완료가 아니에요. 응답이 채널보다 먼저 와요. 모든 대상이 publishing 상태를 벗어날 때까지 GET /v1/posts/{id}로 다시 확인해요.
GET /v1/posts/{id}
발행 하나와 대상별 상태를 줘요.
대상 상태
| 이름 | 종류 | 설명 |
|---|---|---|
publishing | status | 채널에 올리는 중 |
published | status | externalId와 url이 붙어요. 나중에 계정 연결이 끊겨도 published로 남고, 같은 계정을 다시 연결할 때까지 connectionId는 null, accountHandle은 그 계정 아이디예요. |
partial | status | 일부 채널만 올라갔어요. 재시도하면 실패한 곳만 보내요. 207 응답은 없어요. 발행은 202를 받고 상태를 다시 확인하는 방식이라 연결을 붙잡아 두지 않아요. |
cancelled | status | 채널에서 지워졌어요. 포샌디 기록과 지표는 남아요. includeDeleted=true를 넣지 않으면 GET /v1/posts에서 숨겨져요. |
failed | status | error가 붙어요. |
scheduled | status | scheduledAt까지 보관 중. 아직 어느 채널에도 없어요. 고칠 수 있어요. |
draft | status | 시각 없이 저장된 글. 대상이 없을 수도 있어요. 고칠 수 있어요. |
발행 하나에 채널마다 줄이 하나씩 있어요. publishing은 올리는 중, published는 채널의 글 id와 주소를, failed는 실패 이유를 담고 있어요.
{id}에 넣을 수 있는 값
글을 가리키는 값이면 돼요. 발행 id(post_…), 채널이 준 글 id, shortcode, 글 링크 중 하나를 넣어요. 링크는 encodeURIComponent로 감싸서 경로 한 칸으로 보내요. POST /v1/engagement/like와 /v1/replies/{replyId} 호출의 postId도 같은 값을 받아요.
- 채널 앱에서 직접 쓴 글은 처음 한 번 채널에서 찾아 기록으로 가져와요. 그래서 댓글, 지표, 수정, 삭제를 할 수 있어요. 같은 링크로 다시 부르면 채널을 부르지 않고 포샌디 기록을 읽어요.
- shortcode로 찾을 때는 그 계정의 최근 글(최대 500편)을 읽어요. 더 오래된 글은
scanned와 함께post_not_in_recent로 답해요. 그때는 채널이 준 글 id를 넣어요. - 이 워크스페이스가 연결하지 않은 채널의 글은
post_not_owned예요. - 다른 사람 블로그의 네이버 글은
naver_wrong_blog예요. 댓글과 공감은ownerHandle과externalId로POST /v1/engagement/reply,POST /v1/engagement/like에 보내요. - 포샌디의 YouTube 하루 한도가 다 찬 날에는 YouTube 링크가 429
youtube_quota_exhausted로 와요.
예약과 초안
scheduledAt을 넣으면 글을 scheduled로 보관했다가 그 시각에 포샌디가 모든 채널로 보내요. draft: true를 넣으면 누군가 publish를 부르거나 대시보드에서 보내기 전까지 아무것도 나가지 않아요.
- 두 경우 모두 status가
scheduled나draft로 와요. - PATCH로 고치고,
/publish로 앞당겨 보내고, DELETE로 지워요. scheduledAt은 시간대 오프셋이 꼭 있어야 하고, 10분 뒤부터 1년 안까지예요.- 채널 자체 예약 기능도 있어요(
options.youtube.publishAt,options.facebook.scheduledPublishTime,options.naver_blog.scheduledAt). API로는 그대로 쓸 수 있지만 대시보드에는 보이지 않아요. 한 글에 예약 시각이 두 개면 서로 어긋날 수 있으니 하나만 써요.
채널마다 다른 본문
모든 채널이 options.<채널>.content를 받아요. 이 값이 있으면 그 채널에는 공통 본문 대신 이 본문이 나가고, 글자 수와 미디어 검사도 이 본문으로 해요. 이 값을 쓰면 Threads용 500자 글과 네이버 블로그용 마크다운 본문을 호출 한 번에 같이 보낼 수 있어요. 채널이 그 밖에 받는 값은 GET /v1/platforms의 options에 있어요.
PATCH /v1/posts/{id}
예약 글이나 초안을 보내기 전에 고쳐요.
- 보내지 않은 값은 그대로 남아요. 네이버에만 가는 글에서
mediaIds를 빼면 새 본문의media:참조가 사진 목록이 돼요. options는 통째로 바뀌어요.threadItems는 체인 전체를 바꾸고,content만 보내면 첫 항목만 바뀌어요.- 이미 올라간 글의 수정은 비동기예요.
wait: true면 결과가 나올 때까지(최대 75초) 응답을 기다리고, 넘으면 202와 함께 글을 다시 읽으라는next를 줘요. - 네이버 임시저장이 중간에 끊기면 네이버 임시저장함에서 찾아보고, 있으면 가져와요.
publish_naver_draft로 올린 글은 네이버 에디터에서 쓴 글과 같은 방식으로 고쳐요. 첫 수정 요청이 지금 원문을 409naver_source_required로 돌려주고,sourceVersion과 함께 다시 보내면 같은 주소에 다시 써요. 네이버에 있던 사진과 서식은 그대로 남아요.- 포샌디로 올린 네이버 글도 올린 사진 파일이 정리된 뒤(올리고 하루쯤 지나면)에는 같은 방식이에요. 옵션만 고치면 바로 반영되고, 본문을 고치면 지금 원문이 먼저 와요.
| 이름 | 타입 | 설명 |
|---|---|---|
content | string | 새 글 내용 |
accountIds | string[] | 새 대상 계정. 지금 목록을 통째로 바꿔요. |
mediaIds | string[] | 새 미디어, 순서대로. 지금 목록을 통째로 바꿔요. 네이버 블로그에만 가는 글에서 본문이 media: 참조로 미디어 자리를 정하면 이 값을 빼요. 그 참조가 목록이 되고, 새 본문에 없는 미디어는 빠져요(몇 개 빠졌는지 응답의 note에 적혀요). |
options | object | 채널별 설정. 객체 전체를 바꿔요. |
scheduledAt | string | 새 보낼 시각. 만들 때와 같은 규칙이에요. null이면 초안이 돼요. |
draft | boolean | true면 예약 글을 다시 초안으로 돌려요. |
POST /v1/posts/{id}/publish
예약 글이나 초안을 지금 보내요. 예약 발송과 같은 함수를 써서 두 번 나가지 않아요.
| 이름 | 타입 | 설명 |
|---|---|---|
wait | boolean | 글이 실제로 올라갈 때까지 응답을 기다려요. 만들 때와 같아요. |
POST /v1/posts/{id}/retry
실패한 대상만 다시 보내요. 이미 올라간 대상은 건너뛰어요.
- 네이버 임시저장 직후 끊긴 대상(
naver_draft_unknown)이나 제때 확인되지 않은 네이버 답글(naver_reply_unknown)은 본문에{"force": true}를 넣어야 다시 보내요. - 같은 계정에 같은 내용과 파일의 다른 글이 이미 있으면 그 글 id와 함께 409
duplicate_post로 답하고 아무것도 보내지 않아요.{"force": true}면 그래도 보내요.
DELETE /v1/posts/{id}
채널에서 글을 지우고 포샌디 기록에 삭제로 표시해요.
예약 글이나 초안은 채널에 아직 아무것도 없어서 포샌디 기록만 지워요. 이미 올라간 글은 채널에서 먼저 지우고, 포샌디 기록은 지운 것으로 표시해서 남겨 둬요.
채널에 이미 있는 글 읽기
포샌디 기록에는 포샌디로 올린 글만 있어요. 아래 엔드포인트는 채널 자체를 읽거나 올릴 채널을 골라요. list_channel_posts, get_quota, open_post, select_channels 도구가 쓰는 라우트라서 REST로 불러도 같은 답이 와요.
GET /v1/posts/{id}/thread
글 하나와 댓글, 지표를 한 번에 가져와요.
GET /v1/channels/posts
지금 채널에 있는 글이에요. 채널 앱에서 직접 쓴 글도 나와요.
쿼리
| 이름 | 타입 | 설명 |
|---|---|---|
accountId | query | 연결 계정 하나로 좁혀요. 빼면 모든 채널을 봐요. |
limit | query | 1~100, 기본 25 |
GET /v1/channels/quota
24시간 한도를 얼마나 썼는지 채널이 알려 주는 값이에요.
GET /v1/channels/bridge
네이버 블로그 브리지(브라우저 확장)가 켜져 있는지, 꺼져 있으면 어떻게 켜는지 알려 줘요.
GET /v1/channels/publish-options
발행 전에 채널에 물어봐야 하는 값이에요. TikTok(준비 중) 전용이에요. 글이 나갈 닉네임, 이 계정이 지금 고를 수 있는 공개 범위, 올릴 수 있는 상태인지, 영상 길이 상한을 줘요. 다른 채널은 not_supported예요.
| 이름 | 타입 | 설명 |
|---|---|---|
accountId | query | 필수. 이 값들은 연결 계정마다 다르고, 사람이 채널 설정을 바꾸면 같이 바뀌어요. 저장해 두고 쓰지 마세요. |
GET /v1/channels/instagram/audio
Instagram 계정 하나가 릴스에 넣을 수 있는 음악과 원본 소리예요. options.instagram.audio에 넣어요. Instagram 전용이고 Facebook으로 연결한 계정만 돼요. query가 없으면 그 계정의 인기 목록이 오고, query가 있으면 Meta의 로열티 프리 음악(Sound Collection)에서만 찾아요. 그래서 가수나 곡 이름으로 찾아도 그 곡은 안 나와요.
| 이름 | 타입 | 설명 |
|---|---|---|
accountId | query | 필수. 연결된 Instagram 계정. 인기 소리는 계정마다 달라서 같은 계정 결과의 id를 써요. |
type | query | music(기본) 또는 original_sound |
query | query | 선택, 100자까지. 없으면 이 계정의 인기 소리가 와요. type이 music이면 Meta Sound Collection의 로열티 프리 음악에서만 찾아요. |
limit | query | 1~50, 기본 25 |
cursor | query | 앞 페이지의 nextCursor를 그대로 넣어요. |
POST /v1/accounts/select
연결된 채널 중 어디에 올릴지 골라요.
| 이름 | 타입 | 설명 |
|---|---|---|
scope | string 또는 string[] | 빼면 후보 목록을 줘요. "all"이면 켜진 채널 전부, 배열이면 플랫폼 이름, 아이디, 계정 id를 섞어 넣을 수 있어요. |
POST /v1/accounts/:id/refresh
채널 정보(네이버 블로그 카테고리, Pinterest 보드 등)를 다시 읽어요. 브라우저 확장을 최대 1분 기다려요.
PUT /v1/accounts/:id/pinterest/default-board
Pinterest(준비 중)에서 글에 options.pinterest.boardId가 비어 있을 때 핀을 올릴 기본 보드를 정해요. 연결의 보드 목록에 있는 보드만 받아요. 연결한 뒤에 만든 보드라면 refresh를 먼저 불러요.
| 이름 | 타입 | 설명 |
|---|---|---|
boardId | string | 필수. GET /v1/accounts의 그 계정 pinterest.boards에 있는 보드 id. 응답으로 pinterest.defaultBoardId가 바뀐 계정 정보가 와요. |
GET /v1/naver/blog/diagnose
네이버 블로그의 공개 RSS(최근 글, 최대 50편)를 읽고 제목이 검색을 노리고 쓰였는지 재요.
- 검색 의도어(가격, 방법, 후기)가 든 제목 비율, 날짜나 회차로 시작하는 제목 수, 한 달 글 수, 카테고리, 제목에 반복되는 말을 돌려줘요. 반복되는 말은 조사해 볼 후보이고, 실제로 검색되는 키워드라는 뜻은 아니에요.
- 읽은 날짜 범위를 같이 줘요. 글이 드문 블로그의 50편을 블로그 전체로 착각하지 않게 하려는 거예요.
- 사용자와 상관없이 24시간 캐시돼요. 캐시에 없을 때만 사람당 하루 20회 한도를 써요. 네이버 API 키는 필요 없어요.
| 이름 | 타입 | 설명 |
|---|---|---|
blog (필수) | string | 네이버 블로그 id(영문, 숫자, -, _로 2~40자) 또는 블로그 링크. blog.naver.com/{id}, m.blog.naver.com/{id}/{logNo}, PostView.naver?blogId={id} 모양을 받아요. |
POST /v1/naver/keywords/judge
네이버 검색 키워드를 측정하고, 글 하나에 쓸 키워드 세트를 골라요. 키워드를 펼치지는 않으니 가진 키워드를 보내요. 월간 검색수(검색광고), 블로그 문서수, 월 발행량(API HUB), 키워드별 판정, 같은 의도의 메인 1개 + 서브 2~5개 세트를 돌려줘요. 결과는 사용자와 상관없이 7일 캐시되고, 사용자당 하루 60회, 600개 키워드까지 돼요.
| 이름 | 타입 | 설명 |
|---|---|---|
keywords | string[] | 필수. 1~300개. 띄어쓰기가 있어도 돼요. 숫자는 보낸 키워드 그대로 돌아와요. |
save | boolean | 기본 false. true면 이 조사를 보고서로 저장하고(키워드, 첫 세트의 메인과 서브, 세트별 프롬프트) reportId를 줘요. 같은 사람이 10분 안에 같은 키워드 묶음을 보내면 새로 만들지 않고 기존 reportId를 주고, judge 횟수도 쓰지 않아요. |
seedText | string | 사람이 입력한 말. 저장된 보고서의 이름으로 남아요. 기본은 앞의 키워드 5개예요. |
cacheOnly | boolean | 기본 false. true면 네이버를 부르지 않아요. 최근 캐시가 없는 키워드는 숫자 없이 unmeasured로 와요. 나눠서 측정한 뒤에 쓰면 judge 호출이 바로 끝나고 외부 호출도 쓰지 않아요. |
budgetMs | number | 새 측정에 쓸 시간 예산. 기본이자 최대 60000. 시간이 다 되면 새 외부 호출을 시작하지 않고 partial: true와 unmeasured를 줘요. 다시 부르면 캐시된 부분은 건너뛰어요. |
POST /v1/naver/keywords/measure
판정과 세트 없이 측정만 해요. withDocs: false면 문서수는 건너뛰어요.
| 이름 | 타입 | 설명 |
|---|---|---|
keywords | string[] | 필수. 1~300개. 한 번에 새로 측정하는 건 최대 40개이고, 나머지는 unmeasured로 와서 다음 호출이 이어서 측정해요. |
withDocs | boolean | 기본 true. false면 검색량만 측정해요. |
budgetMs | number | 새 측정에 쓸 시간 예산. 기본이자 최대 60000. 넘으면 외부 요청을 더 시작하지 않고 partial: true와 unmeasured를 줘요. |
POST /v1/naver/keywords/expand
AI나 API 키 사용자를 위해 네이버 자동완성으로 씨앗 키워드를 한 단계 펼쳐요(대시보드에서는 브라우저가 해요). 그 사람의 포샌디 크롬 확장이 켜져 있으면 확장이 그 사람 인터넷 연결로 창 없이 가져오고, 아니면 서버가 가져와요. 찾은 단어, 어느 씨앗에서 나왔는지, 어느 경로로 받았는지(via)를 줘요. 둘 다 안 되면 503 naver_autocomplete_unavailable이에요. 그때는 키워드 목록을 judge에 바로 넘겨요.
| 이름 | 타입 | 설명 |
|---|---|---|
seeds | string[] | 필수. 씨앗 키워드 1~10개. 씨앗마다 네이버 자동완성을 한 번(한 단계) 불러요. 돌아온 단계는 judge로 측정해 볼 후보이고, 검증된 키워드는 아니에요. 사용자와 상관없이 7일 캐시돼요. 하루 한도는 없어요. 크롬 확장이 답하면 기다림이 없고, 서버가 답하면 사람당 60초에 한 번이에요(naver_autocomplete_busy와 retryAfterSeconds). |
돌려주는 값은 이래요.
| 이름 | 타입 | 설명 |
|---|---|---|
found | { keyword, from }[] | 찾은 단어 전부, 씨앗이 먼저 와요. from은 씨앗이면 seed, 씨앗에서 나온 단어면 L1: 뒤에 그 씨앗이 붙어요. |
errors | { query, error }[] | 찾지 못한 씨앗과 이유 |
cached | number | 7일 캐시에서 나온 씨앗 수 |
via | { cache, extension, server } | 경로별로 답한 씨앗 수. 공용 캐시, 그 사람의 크롬 확장(뒤에서, 그 사람 연결로), 포샌디 서버 |
GET /v1/naver/keywords/reports
저장한 키워드 조사 기록(judge에 save: true)을 최신순으로 줘요. 언제 무엇을 넣었는지, 첫 세트의 메인과 서브, 세트마다 붙여넣을 프롬프트까지 와요. 기록은 사람 단위라서, 워크스페이스로 범위를 좁힌 API 키로 부르면 403이에요.
| 이름 | 타입 | 설명 |
|---|---|---|
limit | number | 기본 50, 최신순 |
GET /v1/naver/keywords/history
키워드 하나의 측정 기록이에요. 실제로 측정한 날마다 한 점씩(캐시에서 나온 건 쌓이지 않아요), 최신순으로 검색량, 문서수, 월 발행량을 줘요. 기록이 없으면 200과 data: []가 와요.
| 이름 | 타입 | 설명 |
|---|---|---|
keyword (필수) | string | measure에 보내는 그대로의 키워드. 키워드가 보통 한글이라 쿼리 파라미터로 받아요. |
limit | number | 기본 100일, 최신순 |
GET /v1/research/youtube/search
검색어로 YouTube를 찾아 상위 영상의 정보를 줘요.
- 조회수, 구독자 수, 길이, 게시일은 YouTube가 준 그대로예요.
- 조회/구독 비율과 쇼츠/롱폼 구분은 포샌디가 계산한 값이고 YouTube 지표가 아니에요.
dataNotes에 그렇게 적혀 있어요. - 제목과 훅을 뽑는 붙여넣을 프롬프트를 그 사람의 포샌디 언어(한국어, 영어)로 줘요.
- 같은 검색은 24시간 캐시라 횟수에 안 세요. 새 검색은 사람당 하루 횟수(응답의
quota)와 공용 YouTube Data API 단위를 써요. - 기록에
reportId로 저장돼요.
| 이름 | 타입 | 설명 |
|---|---|---|
q (필수) | string | 시청자가 입력할 법한 검색어 |
order | string | viewCount(기본), date, relevance |
period | string | 7d, 1m, 3m, 6m, 1y. 빼면 기간 제한 없음 |
format | string | all(기본), shorts, long. 60초 이하는 쇼츠로 쳐요. |
max | number | 1~50, 기본 25 |
topic | string | 사람이 만들려는 영상 한 줄. 프롬프트에 들어가고 기록에 같이 저장돼요. |
GET /v1/research/youtube/reports
저장된 YouTube 검색 기록을 최신순으로 줘요. 언제, 검색어와 필터, 주제, 영상 수, 캐시였는지가 와요. 최대 30일 보관하고 지워요.
| 이름 | 타입 | 설명 |
|---|---|---|
limit | number | 기본 50, 최신순 |
GET /v1/research/youtube/reports/{id}
저장된 검색 하나를 그때의 영상 목록, 그 목록으로 만든 프롬프트와 함께 줘요.
POST /v1/naver/visibility/checks
키워드 10개까지를 그 사람의 포샌디 크롬 확장으로 네이버 통합검색에서 확인해요. 확장은 그 사람 브라우저에서 공개 검색 결과 페이지를 약 3초 간격으로, 쿠키와 창 없이 읽어요.
- 키워드마다 AI 브리핑이 답했는지와 형태, 본문과 이미지 출처의 순위, 출처별로 인용된 답변 문단 수, 검색 결과 안 블로그 글 위치, 관련 질문을 줘요.
- 202와
runId,waitMs를 주면 200과 결과가 와요. - 사람당 하루 200페이지예요. 확장이 꺼져 있으면 503
bridge_offline이에요. - 200 응답에는
citationRules도 와요. AI 브리핑이 인용한 글에서 포샌디가 측정한 문장 규칙(rules)과, 등급, 근거, 주의가 붙은 더 약한 제안(suggestions)이에요. 네이버의 기준이 아니라 포샌디가 측정한 값이에요.
| 이름 | 타입 | 설명 |
|---|---|---|
keywords (필수) | string[] | 독자가 검색할 법한 키워드 1~10개 |
blog | string | 네이버 블로그 id 또는 블로그 링크. 그 블로그 글에 mine: true가 붙고, 결과마다 verdict(bodyRank, imageRank, citedParagraphs, organicRank, organicArea, cited, exposed)가 와요. |
fresh | boolean | 기본 false. 이 사람이 30분 안에 읽은 키워드는 저장된 결과로 와요. true면 다시 읽고 하루 한도를 써요. |
waitMs | number | 최대 이 밀리초(최대 60000)까지 응답을 기다렸다가 지금까지 결과를 200으로 줘요. 남은 키워드는 partial: true와 pending으로 알려 주고 뒤에서 계속 읽어요. 이 값이 없으면 202와 runId로 답해요. |
GET /v1/naver/visibility/runs/{runId}
확인 하나의 상태(running, done, partial, failed), 돌아온 키워드 수, 요청한 순서대로의 결과, 아직 읽는 키워드(pending)를 줘요. 확인이 끝나면(done, partial, failed) 확인 응답과 같은 citationRules도 와요.
GET /v1/naver/visibility/runs
이 사람의 최근 확인 목록이에요. 최신순으로 종류, 키워드 수, 돌아온 수를 주고, 블로그를 넣었던 확인은 인용된 수와 노출된 수도 줘요.
| 이름 | 타입 | 설명 |
|---|---|---|
limit | number | 기본 20, 최대 50, 최신순 |
POST /v1/naver/visibility/scan
블로그 성적표를 시작해요. 공개 RSS로 최근 글을 읽고, 글마다 대표 키워드를 골라 뒤에서 확인해요. 202와 runId, etaSeconds를 줘요. 같은 블로그의 6시간 안 성적표가 있으면 200과 reused: true로 답해요.
| 이름 | 타입 | 설명 |
|---|---|---|
blog (필수) | string | 네이버 블로그 id 또는 블로그 링크 |
limit | number | 읽을 최근 글 수, 1~30, 기본 20 |
GET /v1/naver/visibility/blog
기록으로 만든 블로그 성적표예요.
- 숫자 카드: AI 인용률, 통합검색 노출률, AI 브리핑이 뜬 키워드 수, 인용된 글 수
- 오각형 축: 포샌디 기준 10점 만점 점수 다섯 개, 원값과 기준값이 같이 와요. 네이버 점수가 아니에요.
- 가장 먼저 할 일, 글별 대표 키워드와 마지막 판정, 카테고리, 추세, 사건
| 이름 | 타입 | 설명 |
|---|---|---|
blog (필수) | string | 네이버 블로그 id 또는 블로그 링크 |
tz | number | 보는 사람의 시간대 오프셋(분). JavaScript getTimezoneOffset과 같은 부호예요(한국은 -540). 추세를 그 시간대의 날짜로 묶어요. 기본 0(UTC) |
GET /v1/naver/visibility/posts/{blogId}/{logNo}
글 하나의 기록이에요. 지켜보는 글(대표 키워드와 그 출처), 그 키워드를 확인할 때마다 나온 그 글의 판정, 사건(인용, 노출이 시작되거나 빠진 때)을 줘요.
PATCH /v1/naver/visibility/posts/{blogId}/{logNo}
글의 대표 키워드(확인할 때 검색하는 말)를 바꿔요. 그 글의 기록으로 답해요.
| 이름 | 타입 | 설명 |
|---|---|---|
mainKeyword (필수) | string | 1~100자. 다음 확인부터 쓰이고, 그 글의 이전 판정은 지워져요. |
title | string | 글 제목. 아직 지켜보지 않는 글일 때만 써요(300자까지). |
GET /v1/naver/visibility/keywords
이 사람이 키워드 하나를 확인한 기록 전체예요. 최신순으로, 확인마다 AI 브리핑 출처와 검색 결과의 블로그 글을 줘요.
| 이름 | 타입 | 설명 |
|---|---|---|
keyword (필수) | string | 키워드, 100자까지. 키워드가 보통 한글이라 쿼리 파라미터로 받아요. |
blog | string | 그 블로그 글을 표시하고 확인마다 판정을 붙여요. |
limit | number | 기본 30, 최대 100, 최신순 |
POST /v1/naver/seo/check
발행 전에 네이버 블로그 마크다운 본문의 배치 규칙을 검사해요. 발행을 막지는 않고, 무엇이 어긋났는지와 이유를 알려 줘요.
검사 항목은 이래요.
- 소제목과 서브 키워드가 1:1로 맞는지
- 메인 키워드가 3~5회 나오는지
- 태그 12~15개가 전부 본문에 있는지
- 첫 3단락에 상품 이름이 없는지
- 첨부 이미지가 전부 자리를 잡았고 캡션이 10자 이상인지
- 분량이 하한을 넘는지
응답에는 pentagon(같은 검사 다섯 개를 0~10점으로: 키워드, 구조, 분량, 사진, 태그)과 citation(AI 브리핑이 가져다 쓰는 문장 모양의 개수: 정의 문장, 조작 순서, 괄호 속 구체 값, 앞쪽의 정의, 링크 카드)이 같이 와요. 둘 다 참고용이고 발행을 막지 않아요.
| 이름 | 타입 | 설명 |
|---|---|---|
content | string | 필수. 마크다운 본문, 60,000자까지 |
title | string | 글 제목 |
main | string | 메인 키워드. 없으면 키워드 검사를 통과할 수 없어요. |
subs | string[] | 서브 키워드. 소제목 하나에 하나씩 |
tags | string[] | options.naver_blog.tags로 보낼 태그 |
fixedTags | string[] | 본문에 없어도 되는 태그(브랜드 태그) |
products | string[] | 첫 3단락에 나오면 안 되는 상품, 브랜드 이름 |
mediaIds | string[] | 글에 붙인 미디어 id. 각각 자리를 잡았는지 확인해요. |
POST /v1/naver/layout
발행 전에 본문이 어떻게 놓일지 미리 봐요. 발행할 때 기본으로 도는 재배치(layout: template)와 같은 계산을 아무것도 보내지 않고 돌려줘요. forms: "all"이면 모든 프리셋 결과를 한 번에 줘서 사람이 비교하고 고를 수 있어요.
| 이름 | 타입 | 설명 |
|---|---|---|
content (필수) | string | 배치할 마크다운 본문 |
mediaIds | string[] | 붙인 미디어, 순서대로. 본문이 가리키지 않은 이미지는 폼이 자리를 정해요. |
form | string | 프리셋 id 하나(기본 photo-story). forms가 있으면 무시해요. |
forms | "all" 또는 string[] | 같은 본문을 여러 프리셋으로 한 번에 배치해요. 응답의 layouts[]로 사람이 비교하고 고를 수 있어요. |
GET /v1/naver/forms
기본으로 제공하는 글 폼 7개예요. 폼은 글의 짜임새를 정해요.
- 섹션을 무엇으로 시작하는지
- 인용을 소제목으로 쓰는지, 인용문으로 쓰는지
- 핵심 문장을 얼마나 자주 강조하는지
- 섹션마다 사진이 몇 장인지
- 사진에 캡션을 다는지
모두 실제로 올라간 글을 측정해서 만들었어요. 글을 만들 때 폼 id를 넣으면 돼요. 폼은 AI에게 무엇을 시킬지만 정하고, 발행 자체에는 영향이 없어요.
GET /v1/naver/drafts
네이버 블로그 임시저장함의 초안 목록이에요. draftOnly로 저장한 글과 네이버 에디터에서 손으로 저장한 글이 같이 나와요. 확장 0.7.2 이상이 필요해요.
POST /v1/naver/drafts/{logNo}/publish
임시저장함의 초안을 네이버에 있는 그대로 발행해요. 확장이 그 초안을 에디터에 불러와 발행 버튼을 누르기 때문에, 손으로 고친 내용이 그대로 나가요. 응답 모양은 POST /v1/posts와 같아요. 포샌디가 만든 초안이면 그 글 기록이 발행됨으로 바뀌어요. 올라간 뒤에 글을 고치려면 그 글에 update_post를 불러요. 지금 원문이 먼저 돌아와요.
| 이름 | 타입 | 설명 |
|---|---|---|
logNo (필수) | string | GET /v1/naver/drafts에서 받은 초안 id |
category | string | 카테고리. 빼면 초안에 있는 값을 써요. |
tags | string[] | 태그. 빼면 초안에 있는 값을 써요. |
openType | string | 공개 범위. 빼면 초안에 있는 값을 써요. |
