자버 발송 API (OpenAPI v1)
자버 발송 API는 자버 웹에서 미리 만들어 둔 빠른 발송 세트(서식, 입력값, 발송 채널, 메시지 템플릿)와 수신자 목록만 보내면 전자문서와 메시지를 일괄 발송하는 HTTP API입니다. 사내 시스템, CRM, 예약 시스템에서 이벤트가 생길 때 서버에서 호출하는 용도로 씁니다.
발송은 비동기로 처리됩니다. 요청이 유효하면 바로 접수 결과를 돌려주고 실제 발송은 백그라운드에서 진행되며, 결과는 문서 조회 API로 확인합니다.
연동 흐름
- 세트 목록 조회: 발송에 쓸 세트의
id를 얻습니다. - 발송 정보 조회: 세트의 발송 채널, 수신자 연락처 종류, 채워야 할 입력 항목과 선택지, 링크 필요 여부를 확인합니다.
- 발송: 세트
id와 수신자 목록(최대 100명)을 보냅니다. - 결과 확인: 문서 목록·상세 조회로 진행 상태를 확인합니다.
| 단계 | 메서드와 경로 | 용도 |
|---|---|---|
| 1 | GET /document/preset/list | 빠른 발송 세트 목록 |
| 2 | GET /document/preset/{presetId}/send-context | 발송 전 확인 정보 |
| 3 | POST /document/preset/{presetId}/send | 발송 |
| 4 | GET /document/list, GET /document/detail/{documentId} | 문서 상태와 입력값 조회 |
시작하기
처음이면
자버 계정이 없으면 먼저 자버에 가입합니다. 가입비는 없고 가입 보너스 500원이 들어옵니다. AI 도구(Claude, ChatGPT 등)에서 대화로 보내려면 AI 도구용 가입 안내로 가입하고 MCP 서버를 보세요. 가입한 뒤 아래 순서로 키를 발급하고 세트를 만듭니다.
1. API 키 발급
발송 API 에는 회사 API 키(jbr_co_ 로 시작)를 씁니다. 두 곳에서 발급할 수 있고, 콘솔에서 만든 문서 발송 키도 설정의 회사 API 키 목록에 함께 보입니다.
| 발급 위치 | 누가 | 특징 |
|---|---|---|
| 설정 > AI 도구 연동 > 회사 API 키 | 스페이스 관리자 | 이름과 권한(scope)을 골라 발급·재발급·폐기. 스페이스당 활성 5개. 새 키의 기본 권한은 문서 발송(openapi:document) |
왼쪽 메뉴 전자문서 환경설정 > API 연동(빠른 발송 API 콘솔 /developers/quick-send-console, 새 탭) > API 키 관리 | 전자문서 전체 관리 권한이 있는 관리자 | 문서 발송 권한 키 1개만 발급·재발급·삭제 |
- 위 화면 중 한 곳에서 키를 발급합니다. 이 문서의 API 를 쓰려면 문서 발송(
openapi:document) 권한이 있어야 합니다. - 키는 발급 직후 한 번만 보입니다. 복사해 서버에만 보관하세요.
- 다시 발급하면 같은 이름·권한의 새 키가 나오고 이전 키는 바로 쓸 수 없습니다.
API 키는 스페이스의 발송 권한을 위임받은 값입니다. 서버에서만 보관하고 브라우저나 앱 코드에 넣지 마세요. 노출이 의심되면 바로 재발급하세요.
- 문서 발송 권한으로 이 문서의 문서(
/document)·서식(/frame) API 를 호출할 수 있습니다. - 같은 회사 API 키에 AI 에이전트 권한을 더 주면 자유 발송 API에도 쓸 수 있습니다(그때는
Authorization: Bearer헤더). 권한 종류와 줄 수 있는 사람은 키 발급에 있습니다. - 개인 API 키(
jbr_live_)와 OAuth 토큰은 발송 API 에 쓸 수 없습니다(400J_40_01_1_2). - 예전에 발급받은 키도 그대로 쓸 수 있습니다.
- 연락처·스페이스 생성·로그인 연동 OpenAPI 의 레퍼런스는 공개하지 않습니다. 필요하면 도입 문의로 요청하세요.
2. 빠른 발송 세트 만들기
자버 웹의 전자문서 빠른 발송에서 서식, 미리 채울 입력값, 발송 채널, 메시지 템플릿을 정해 세트로 저장합니다. API로 보낼 때는 이 세트의 설정을 그대로 쓰고, 요청마다 바꿀 값만 보냅니다.
3. 첫 호출
curl "https://api.jober.io/openapi/v1/document/preset/list?limit=20&offset=0" \
-H "x-jober-openapi: YOUR_API_KEY"인증과 기본 주소
모든 요청에 발급받은 키를 헤더로 보냅니다. 키가 스페이스를 정하므로 스페이스 ID 헤더는 따로 없습니다.
x-jober-openapi: YOUR_API_KEY| 항목 | 값 |
|---|---|
| 기본 주소 | https://api.jober.io/openapi/v1 |
| 형식 | 요청·응답 모두 JSON (Content-Type: application/json), 문자 인코딩 UTF-8 |
| 호출 위치 | 서버 간 호출. 브라우저에서 다른 도메인으로 직접 호출하면 CORS 로 막힙니다 |
| 요청 본문 크기 | 최대 10MB |
예전에 안내된
https://open-api.jober.io/v1주소도 같은 API로 연결되지만, 이 주소로는 오류 응답의data필드(예: 정책 제한 표현 목록)가 전달되지 않습니다. 새 연동은 위 기본 주소를 쓰세요.
인증 오류
| HTTP | errorCode | message | 원인 |
|---|---|---|---|
| 400 | J_40_000_1_1 | openApiKey is required | x-jober-openapi 헤더가 없음 |
| 400 | J_40_01_1_2 | apiSyncInfoList is no registered | 등록되지 않았거나 재발급·삭제된 키 |
| 400 | J_40_01_1_3 | document openAPI request is not authorized | 이 키로 호출할 수 없는 API(키에 문서 발송 권한이 없음) |
응답 형식
성공하면 HTTP 200과 함께 다음 형태로 응답합니다.
{ "message": "사람이 읽는 안내 문구", "data": { } }실패하면 4xx·5xx 와 함께 다음 형태로 응답합니다.
{ "message": "error message", "errorCode": "J_44_42_1_2", "httpStatusCode": 400, "data": null }- 성공·실패 판단과 재시도 여부는 실제 HTTP 상태 코드로 하세요. 본문의
httpStatusCode는 실제 상태와 다를 수 있습니다(예: HTTP 403 응답의 본문에 400). - 분기 처리는
errorCode로 하세요.message문구는 바뀔 수 있습니다. - 없는 경로를 호출하면 JSON이 아닌 HTML 404 페이지가 옵니다.
API 목록
| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | /document/preset/list | 빠른 발송 세트 목록 |
| GET | /document/preset/{presetId}/send-context | 세트의 발송 정보(채널, 입력 항목, 링크) |
| POST | /document/preset/{presetId}/send | 세트로 일괄 발송(비동기) |
| GET | /document/list | 문서 목록 |
| GET | /document/detail/{documentId} | 문서 상세(입력값 포함) |
| POST | /document/resend | 알림 재발송 |
| POST | /document/cancel | 문서 요청 취소 |
| GET | /document/preview/{documentId} | 문서 PDF 미리보기(data URL) |
| GET | /document/download/{documentId} | 문서 파일 다운로드 링크 |
| GET | /frame/list | 서식 목록 |
| GET | /frame/one | 서식 상세(입력 항목) |
세트 목록 조회
GET /document/preset/list?limit=20&offset=0| 쿼리 | 타입 | 기본값 | 설명 |
|---|---|---|---|
limit | 정수 | 20 | 1~100. 범위를 벗어나거나 숫자가 아니면 20 또는 경계값으로 맞춥니다 |
offset | 정수 | 0 | 0 이상 |
API 발송용으로 저장한 세트만 최근 수정 순으로 돌려줍니다.
{
"message": "API 발송 목록 조회에 성공하였습니다.",
"data": {
"presets": [
{
"id": 123,
"title": "예약 확인 안내",
"personId": "세트를 만든 매니저의 사용자 ID",
"documentFrameId": 4567,
"frameTitle": "예약 확인서",
"isEmptyDocument": false,
"notificationTemplateInfo": { "kakaoTemplateInfo": { "variables": [ { "key": "예약일", "value": "" } ] } },
"updatedAt": "2026-10-30T09:00:00.000Z"
}
],
"total": 1,
"limit": 20,
"offset": 0
}
}- 위 예시는 주요 필드만 줄여 보인 것입니다. 실제로는
spaceId,type,description,inputValues,saveFolderId,documentFrame등 세트 정보가 함께 옵니다. - 발송 때
templateValues로 바꿀 수 있는 메시지 변수의 키는notificationTemplateInfo안 템플릿의variables[].key입니다.
발송 정보 조회
GET /document/preset/{presetId}/send-context{
"message": "API 발송 정보 조회에 성공하였습니다.",
"data": {
"preset": { "id": 123, "title": "예약 확인 안내" },
"documentFrame": {
"inputs": [
{
"id": 1, "key": "visitType", "label": "방문 유형", "type": "radio",
"options": [
{ "value": "first", "label": "첫 방문", "order": 1, "isDirectInput": false },
{ "value": null, "label": "기타(직접 입력)", "order": 2, "isDirectInput": true }
]
}
]
},
"channel": { "type": "KAKAO" },
"receiverContactField": "phone",
"sendable": true,
"messageType": "document",
"link": { "supported": true, "required": false, "presetTargetUrl": null }
}
}| 필드 | 설명 |
|---|---|
documentFrame.inputs[] | 서식 입력 항목. key 가 발송 때 inputValues 의 키입니다. 서식이 없거나 접근할 수 없으면 documentFrame 이 null |
inputs[].options[] | 선택형 항목의 선택지. inputValues 에는 label 이 아닌 value 를 넣습니다. isDirectInput 이 true 면 value 가 null 이고 임의 글자를 넣을 수 있습니다. 선택지가 없으면 빈 배열 |
channel.type | KAKAO, EMAIL, SLACK, TEAMS, DISCORD, GCHAT, JANDI, DOORAY, TELEGRAM, LINE, SMS_DIRECT, WHATSAPP, VIBER 중 하나 |
receiverContactField | 수신자에게 꼭 넣을 연락처: phone, email, phoneOrEmail |
messengerAddressField, messengerAddressLabel | 웹훅·Telegram·LINE 채널일 때만. 수신처(messengerAddress)로 웹훅 URL, chat ID, userId 를 받습니다 |
sendable | 세트의 서식을 쓸 수 있어 발송할 수 있는지 |
messageType | document(메시지+전자문서), link(메시지+링크), message(메시지만) |
link | supported: 수신자별 링크(receivers[].targetUrl)를 적용할 수 있는지, required: 링크를 꼭 보내야 하는지, presetTargetUrl: 세트에 저장된 링크 |
| HTTP | errorCode | 원인 |
|---|---|---|
| 400 | J_44_41_1_1 | presetId 가 숫자가 아님 |
| 403 | J_44_41_3_1 | 다른 스페이스의 세트 |
| 404 | J_44_41_4_1 | 세트가 없음 |
입력 항목의 필수 여부와 세트에 미리 채운 값은 이 응답에 없습니다.
발송
POST /document/preset/{presetId}/send요청 본문
| 필드 | 타입 | 필수 | 설명 |
|---|---|---|---|
receivers | 배열 | 예 | 수신자 목록. 1~100명 |
inputValues | 객체 | 아니요 | 모든 수신자 공통 문서 입력값 { "입력키": 값 }. 세트에 저장된 값에 덮어씁니다(보낸 키만) |
templateValues | 객체 | 아니요 | 카카오·이메일 메시지 변수 값 { "변수키": 값 }. 세트 템플릿에 이미 있는 키만 바뀌고 없는 키는 무시합니다. 문자열·숫자만 받으며 HTML 태그는 지웁니다. 메신저 채널 세트에는 적용되지 않습니다 |
targetUrl | 문자열 | 아니요 | 모든 수신자 공통 링크. 메시지+링크 세트에만 적용합니다 |
actionPersonId | 문자열 | 아니요 | 발신자로 기록할 스페이스 멤버의 사용자 ID. 없으면 스페이스 소유자 |
notifyOnMassiveSent | 불리언 | 아니요 | 기본 true. false 면 발송 전체가 끝났을 때 발신자에게 가는 완료 알림(이메일·사이트 알림)을 보내지 않습니다 |
notifyOnIssued | 불리언 | 아니요 | 기본 true. false 면 문서가 완료될 때마다 발신자·폴더 관리자에게 가는 완료 알림을 보내지 않습니다 |
수신자에게 가는 발송 알림은 위 알림 옵션과 상관없이 항상 나갑니다. 예약 발송, 수신자마다 다른 inputValues 는 지원하지 않습니다.
수신자
| 필드 | 타입 | 설명 |
|---|---|---|
name | 문자열 | 수신자 이름. 새 연락처를 만들 때 이름으로 쓰고, 기존 연락처와 맞으면 이름을 갱신합니다 |
phone | 문자열 | 휴대전화 번호. 숫자가 아닌 글자(하이픈, 공백)는 지우고 검사합니다. 01012345678, 010-1234-5678 처럼 국내 표기로 넣으세요. +82 국제 표기는 유효하지 않은 연락처로 처리됩니다 |
email | 문자열 | 이메일. 앞뒤 공백을 지우고 소문자로 바꿔 검사합니다 |
targetUrl | 문자열 | 이 수신자만의 링크. 공통 targetUrl 과 세트 링크보다 우선합니다 |
messengerAddress | 문자열 | 웹훅·Telegram·LINE 채널의 수신처(웹훅 URL, chat ID, userId). 없으면 연락처에 저장된 값을 씁니다 |
채널에 따라 쓰는 연락처가 다릅니다. 다른 채널용 연락처는 무시합니다.
| 채널 | 쓰는 연락처 |
|---|---|
KAKAO, SMS_DIRECT, WHATSAPP, VIBER | phone |
EMAIL | email |
웹훅 채널(SLACK, TEAMS, DISCORD, GCHAT, JANDI, DOORAY), TELEGRAM, LINE | phone, 없으면 email 로 연락처를 찾고 수신처는 messengerAddress |
수신자는 스페이스 연락처에 자동으로 등록되거나(없으면 생성) 기존 연락처와 연결됩니다.
링크 규칙
- 링크 우선순위는
receivers[].targetUrl>targetUrl> 세트에 저장된 링크입니다. - 공통
targetUrl은 메시지+링크 세트에만 적용합니다. 수신자별targetUrl은 카카오는 모든 세트, 이메일·메신저는 메시지+링크 세트에만 적용합니다. - 메시지+전자문서 세트에 수신자별
targetUrl을 넣으면 문서 보기 버튼이 그 링크로 바뀌어 수신자가 문서에 들어갈 수 없습니다. - 링크는
http·https주소만, 500자까지 받습니다. 아이디·비밀번호가 든 주소,localhost, 사설·내부 IP와 도메인(.local,.internal)은 받지 않습니다. 문자(SMS)·Viber 는 300바이트, Discord 는 900바이트까지입니다. - 링크를 넣었는데 규칙에 맞지 않으면 다른 링크로 바꿔 보내지 않고 요청 전체를 거부합니다(
J_44_42_1_14).
요청 예시
curl -X POST "https://api.jober.io/openapi/v1/document/preset/123/send" \
-H "x-jober-openapi: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputValues": { "visitType": "first" },
"templateValues": { "예약일": "11월 7일 14:00" },
"notifyOnMassiveSent": false,
"receivers": [
{ "name": "홍길동", "phone": "01012345678" },
{ "name": "김자버", "phone": "010-9876-5432" }
]
}'응답
{
"message": "API 발송 요청이 접수되었습니다.",
"data": {
"requestId": "0f8c2a4e-5b1d-4c7a-9e2f-3a6b8d1c4e5f",
"documentTaskDefinitionId": 4567,
"totalTargets": 2,
"skipped": [],
"receiverInputRequired": false
}
}| 필드 | 설명 |
|---|---|
requestId | 요청 ID(UUID). 문의할 때 알려 주세요 |
documentTaskDefinitionId | 이번 일괄 발송 작업 ID |
totalTargets | 실제 발송 대상 수(중복·잘못된 연락처 제외) |
skipped[] | 발송에서 뺀 수신자. { index, reason, errorCode, message }. index 는 receivers 배열 위치 |
receiverInputRequired | true 면 수신자가 채울 항목이 있어 문서가 진행 중(IN_PROGRESS)으로 발송되고 수신자가 제출하면 완료(ISSUED)됩니다 |
발송할 수 있는 수신자가 한 명도 없으면 HTTP 200에 "message": "API 발송할 유효한 수신자가 없습니다.", totalTargets: 0, documentTaskDefinitionId: null 을 돌려줍니다.
| reason | errorCode | 의미 |
|---|---|---|
INVALID_CONTACT | J_44_07_1_3 | 채널에 맞는 유효한 연락처가 없음 |
DUPLICATE_CONTACT | J_44_42_1_8 | 같은 요청 안에서 연락처가 중복(첫 수신자만 발송) |
DUPLICATE_PROFILE_CARD | J_44_42_1_8 | 같은 요청 안에서 같은 연락처 카드로 이어짐(첫 수신자만 발송) |
PROFILE_UPSERT_FAILED | J_44_07_2_1 | 연락처 등록 실패 |
MESSENGER_ADDRESS_MISSING | J_07_130_1_14 | 메신저 채널인데 수신처가 없음 |
발송 전 검사
요청 전체를 검사해 하나라도 걸리면 아무것도 보내지 않습니다.
| HTTP | errorCode | 원인 |
|---|---|---|
| 400 | J_44_42_1_1 | presetId 가 없음 |
| 400 | J_44_42_1_2 | receivers 가 비어 있음 |
| 400 | J_44_42_1_3 | 수신자가 100명을 넘음 |
| 403 | J_44_42_3_1 | 다른 스페이스의 세트 |
| 404 | J_44_42_4_1 | 세트가 없음 |
| 403 | J_44_42_3_2 | 세트의 서식에 접근할 수 없음 |
| 403 | J_44_42_3_3 | 스페이스 이용이 제한됨 |
| 400 | J_44_42_1_18 | 이 스페이스에서 쓸 수 없는 메신저 채널 |
| 400 | J_44_42_1_7 | 무료 문서 사용 한도 초과 |
| 400 | J_44_42_1_6 | 선불 잔액 부족(메신저 채널 세트는 제외) |
| 400 | J_44_42_1_9 | 카카오 발송 한도 또는 잔액으로 이번 발송 수를 감당할 수 없음 |
| 400 | J_44_42_1_4, J_44_42_1_5, J_44_42_4_2 | actionPersonId 가 잘못됐거나 스페이스 멤버가 아님 |
| 400 | J_44_42_1_13 | 카카오 채널 세트에 알림톡 템플릿이 없음 |
| 400 | J_44_42_1_14 | targetUrl 또는 receivers[].targetUrl 이 규칙에 맞지 않음 |
| 400 | J_44_42_1_15 | 메시지+링크 세트인데 링크가 없는 수신자가 있음 |
| 402 | J_07_53_02_1 | 직접 연동한 카카오 채널로 보내려면 연동비 결제가 필요 |
| 400 | J_44_42_1_16 | 수신자 링크의 도메인이 너무 많거나 길어 스팸 검사를 할 수 없음. 요청을 나누거나 링크를 줄이세요 |
| 400 | J_44_42_1_17 | 카카오 알림톡 정책상 제한된 표현(주류·담배 등)이 있음. data.restrictedKeywords 에 해당 표현 |
| 400 | J_44_42_1_11 | 세트에 발송 채널 정보가 없음 |
| 400 | J_07_130_1_13, J_07_130_1_28, J_07_130_1_29, J_07_130_1_30 | 메신저 메시지 내용이 없거나 길거나, 채널이 지원하지 않는 세트 유형 |
| 400 | J_07_130_1_15 | messengerAddress 형식이 잘못됨 |
| 400 | J_44_42_1_12 | 한 명씩 보내는 서식이 아니라 일괄 발송할 수 없음 |
| 400 | J_07_130_1_18 | 문자(SMS) 채널 하루 발송 한도 초과 |
처리 순서
- 수신자마다 연락처를 등록하거나 기존 연락처와 연결합니다.
- 중복 수신자를 정리하고 발송 대상을 확정합니다.
- 세트에 지정한 폴더(없으면 공유 폴더, 그것도 없으면
API 발송폴더)에 문서를 만들고 발송 작업을 시작합니다. - 접수 결과를 바로 응답합니다. 이후 발송은 백그라운드에서 진행됩니다.
발송 API에는 결과 웹훅이 없습니다. 진행 상태는 문서 목록·문서 상세로 확인하세요.
문서 목록 조회
GET /document/list?status[]=IN_PROGRESS&status[]=ISSUED¤t=1&pageSize=20| 쿼리 | 필수 | 설명 |
|---|---|---|
status | 예 | 배열. status[]=값 처럼 보냅니다. READY, IN_PROGRESS(진행 중), ISSUED(완료), CANCELED(취소), FAILED(실패), ALL |
current | 아니요 | 페이지 번호, 기본 1 |
pageSize | 아니요 | 페이지 크기, 기본 20. 0 이면 전체 |
searchKey | 아니요 | frameTitle(서식 이름), hashtags, issueTargetNames(수신자 이름) |
searchValue | 아니요 | 검색어 |
actionPersonId | 아니요 | 폴더 권한 기준 사용자 ID. 없으면 스페이스 소유자 |
{
"message": "전자문서 목록 조회에 성공하였습니다.",
"data": {
"list": [
{
"id": 98765, "frameId": 4567, "frameHistoryId": 8910, "frameTitle": "예약 확인서", "folderId": 12,
"status": "ISSUED",
"issueTargets": [ { "profileCardId": 555, "name": "홍길동", "email": null, "phone": "01012345678", "receiptDate": "2026-10-30T09:05:00.000Z", "useCertification": false } ],
"files": [], "sentDate": "2026-10-30T09:00:00.000Z", "issuedDate": "2026-10-30T09:10:00.000Z",
"createdAt": "2026-10-30T09:00:00.000Z", "updatedAt": "2026-10-30T09:10:00.000Z"
}
],
"total": 1, "current": 1, "pageSize": 20
}
}status 가 없거나 배열이 아니면 400 O_document_5_1_1, 허용하지 않는 값이면 400 O_document_5_2_1 입니다.
문서 상세 조회
GET /document/detail/{documentId}data.documentDetail 에 목록 항목과 같은 필드와 함께 입력값 value({ "입력키": 값 })가 옵니다. 자동표 셀은 부모키_자식키_행 키로 옵니다. 문서가 없거나 삭제됐으면 400 O_document_4_3_2 입니다.
알림 재발송
POST /document/resend{
"actionPersonId": "재발송하는 매니저의 사용자 ID",
"targetDocuments": [ { "id": 98765, "frameId": 4567, "contact": "01012345678" } ],
"sendOptions": { "defaultLanguage": "ko", "useCertification": false, "memo": "확인 부탁드립니다." }
}actionPersonId와targetDocuments[].id·frameId·contact(이메일 또는 전화번호)는 필수입니다. 한 번에 같은 서식의 문서만 보낼 수 있습니다(O_document_3_2_2).- 비동기로 처리되며
{ "started": true }를 바로 돌려줍니다. - 사용자 ID 는 세트 목록 응답의
personId(세트를 만든 매니저)를 쓸 수 있습니다. - 참여자 정보(
targetDocuments[].participants[])를 함께 보내면id는 그 대상 문서의 참여자여야 합니다. 다른 문서의 참여자가 섞이면 요청 전체를 거부합니다(O_document_3_4_5). 참여자의documentId는 보내도 쓰지 않고 대상 문서 ID 로 고정합니다.
요청 전체를 검사해 하나라도 걸리면 아무것도 보내지 않습니다.
| HTTP | errorCode | 원인 |
|---|---|---|
| 400 | O_document_3_1_1 | targetDocuments 가 없음 |
| 400 | O_document_3_1_2 | actionPersonId 가 없음 |
| 400 | O_document_3_2_1 | targetDocuments 항목 형식이 잘못됨 |
| 400 | O_document_3_2_2 | 서로 다른 서식의 문서를 한 번에 보냄 |
| 400 | O_document_3_3_2 | actionPersonId 사용자가 없음 |
| 403 | O_document_3_4_4 | actionPersonId 가 이 스페이스 멤버(초대 수락)가 아님 |
| 400 | O_document_3_3_3 | 서식이 없음 |
| 403 | O_document_3_4_1 | 이 스페이스의 서식도 공용 서식도 아님 |
| 403 | O_document_3_4_2 | 대상 문서가 없거나 삭제됐거나 이 스페이스 문서가 아님. data.documentIds 에 해당 문서 |
| 400 | O_document_3_4_3 | 대상 문서가 요청한 frameId 서식의 문서가 아님. data.documentIds 에 해당 문서 |
| 403 | O_document_3_4_5 | targetDocuments[].participants[].id 가 그 대상 문서의 참여자가 아님. data.documentIds 에 해당 문서 |
문서 요청 취소
POST /document/cancel{ "documentIds": [98765], "actionPersonId": "취소하는 매니저의 사용자 ID", "memo": "일정이 변경되어 취소합니다." }documentIds(최대 25개)와actionPersonId는 필수입니다.memo는 취소 알림에 함께 나갑니다.- 다른 참여자에게 이메일이나 카카오로 취소 알림이 갑니다.
- 응답
data.canceledDocumentIds에 실제로 취소된 문서만 담깁니다. 취소하지 못한 문서는 오류 없이 빠지므로 이 목록으로 확인하세요.
| HTTP | errorCode | 원인 |
|---|---|---|
| 400 | O_document_2_1_1 | documentIds 가 없음 |
| 400 | O_document_2_2_1 | documentIds 가 25개를 넘음 |
| 400 | O_document_2_1_2 | actionPersonId 가 없음 |
| 400 | O_document_2_3_2 | actionPersonId 사용자가 없음 |
| 403 | O_document_2_4_1 | actionPersonId 가 이 스페이스 멤버(초대 수락)가 아님 |
문서 파일
| 메서드와 경로 | 응답 data |
|---|---|
GET /document/preview/{documentId} | { "dataUrl": "data:application/pdf;base64,..." } |
GET /document/download/{documentId} | { "downloadLinks": [ { "fileName": "...", "link": "https://..." } ] } |
수신자 입력이 있는 문서는 수신자가 제출해 완료(ISSUED)된 뒤에 받으세요.
서식 조회
| 메서드와 경로 | 설명 |
|---|---|
GET /frame/list | 스페이스 서식 목록(숨김 제외, 페이지 없음). data.list[]: id, title, description, companyId, hashtags, createdAt, updatedAt |
GET /frame/one?id={frameId} | 서식 상세. frameHistoryId, frameInputs[](id, key, keyName, type, selectOptions, sortOrder, childInputs) 등 |
/frame/one 에 id 가 없으면 400 O_frame_1_1_1, 이 스페이스에서 쓸 수 없는 서식이면 400 O_frame_1_2_2 입니다.
한도와 정책
| 항목 | 값 |
|---|---|
| 발송 요청당 수신자 | 최대 100명. 더 많으면 요청을 나누세요 |
세트 목록 limit | 최대 100 |
| 취소 요청당 문서 | 최대 25개 |
| 링크 길이 | 500자(문자·Viber 300바이트, Discord 900바이트) |
| 요금 | 웹에서 보낼 때와 같은 기준으로 스페이스에서 차감. 요금제 참고 |
- 스팸·금지 표현 검사, 수신거부, 카카오 발송 한도, 선불 잔액 검사는 자버 웹 발송과 같게 적용됩니다.
- 메신저 채널 발송은 현재 무과금 시범 운영이라 선불 잔액 검사를 하지 않습니다.
자주 묻는 질문
API 키는 어디서 발급하나요?
설정 > AI 도구 연동의 회사 API 키에서 스페이스 관리자가 권한을 골라 발급합니다(스페이스당 활성 5개). 문서 발송 키 하나만 필요하면 왼쪽 메뉴의 전자문서 환경설정 > API 연동에서 열리는 빠른 발송 API 콘솔에서도 발급할 수 있습니다. 다시 발급하면 이전 키는 바로 쓸 수 없게 됩니다.
수신자가 100명보다 많으면 어떻게 하나요?
요청 하나에 최대 100명까지 보낼 수 있습니다. 100명씩 나눠 여러 번 호출하세요. 같은 요청 안의 중복 연락처는 한 번만 발송되지만, 요청을 나눌 때 같은 수신자를 두 요청에 넣으면 두 번 발송됩니다.
발송 결과는 어떻게 받나요?
발송 API는 결과 웹훅을 보내지 않습니다. 발송 응답의 totalTargets·skipped 로 접수 결과를 확인하고, 이후 상태는 문서 목록 조회(status[]=ISSUED 등)와 문서 상세 조회로 확인하세요.
문서가 바로 완료되지 않고 진행 중으로 남아요.
서식에 수신자가 채울 항목이 남아 있으면 문서가 진행 중(IN_PROGRESS)으로 발송되고, 수신자가 제출해야 완료(ISSUED)됩니다. 발송 응답의 receiverInputRequired 가 true 면 이 경우입니다. 발신자가 모든 값을 채워 보내려면 inputValues 로 값을 넣으세요.
AI 도구에서 대화로 보내고 싶어요.
Claude, ChatGPT 같은 AI 도구에서는 자버 MCP 서버를 연결하면 대화로 알림톡·이메일 캠페인을 만들고 보낼 수 있습니다.
세트 없이 문자 원문으로 보내고 싶어요.
자유 발송 API를 쓰세요. 문자 원문을 보내면 자버가 알림톡·이메일 캠페인으로 바꾸고, 버튼에 내 링크를 붙이고, 받는 사람을 확인해 발송·예약까지 합니다. AI 에이전트 권한을 준 회사 API 키(jbr_co_), 개인 API 키(jbr_live_) 또는 OAuth 토큰으로 호출하고, 카카오 채널을 연동하지 않았으면 자버 공용 채널로 한도 안에서 보냅니다.