소개
DIBO Extension API는 웹사이트에 다양한 확장 기능을 추가할 수 있는 REST API 서비스입니다. 본 문서는 개발자를 위한 기술 가이드입니다.
Base URL
https://api.di-bo.me제공 기능
인증
모든 API 요청에는 인증이 필요합니다.
인증 헤더
access-token: {your_access_token}
# 회원(end-user) 본인 요청 시 추가
member-token: {member_token}방법 1: DIBO 관리 페이지에서 토큰 발급
- 1DIBO 관리 페이지 로그인
- 2관리 → 사이트 선택 후 대시보드 메뉴 이동
- 3기본 정보 하단에 토큰 생성 버튼 클릭
- 4발급된 코드 복사
발급된 코드에는 다음 두 가지 변수가 포함됩니다:
<!-- Axios CDN -->
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<!-- dibo-token Info -->
<script>
const diboToken = 'eyJhbGciOiJIUzI1NiIsInR...'
let diboMemberToken;
</script>
<!-- member-token 유효성 확인 -->
<script>
window._diboMemberReady = (async function checkMemberToken() {
const memberToken = localStorage.getItem('member-token');
if (!memberToken) return;
try {
await axios.get('https://api.di-bo.me/member/token', {
headers: {
'access-token': diboToken,
'member-token': memberToken,
}
});
diboMemberToken = memberToken;
} catch (error) {
if (error.response && error.response.status === 401) {
localStorage.removeItem('member-token');
}
}
})();
</script>| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| diboToken | string | 필수 | 모든 API 호출에 access-token 헤더로 사용하는 사이트 토큰 |
| diboMemberToken | string | 선택 | 로그인한 회원의 member-token. 회원 전용 요청 전 await window._diboMemberReady 로 준비를 기다린 뒤 사용 |
방법 2: config_id 확인
각 익스텐션은 고유한 config_id로 대상을 지정합니다.
(1) 익스텐션 설정에서 코드 복사 (자동)
DIBO 관리 페이지 → 나의 익스텐션 → 익스텐션 설정 → 코드 복사 클릭 시, 복사된 코드에 config_id가 자동으로 내 값으로 치환되어 들어갑니다.
(2) API로 조회
GET /config?site_id={site_id}응답의 각 항목 id가 그 익스텐션의 config_id입니다.
공통 사항
요청 헤더
Content-Type: application/json
access-token: {your_access_token}multipart/form-data를 사용하며, JSON 데이터는 req_body 필드에 JSON 문자열로 전달합니다.응답 형식
모든 응답은 JSON 형식으로 반환됩니다. 목록 조회 API는 기본적으로 최신순으로 정렬되어 반환됩니다.
HTTP 상태 코드
| 코드 | 설명 | 대응 방법 |
|---|---|---|
| 200 OK | 성공 | - |
| 204 No Content | 삭제 성공 | - |
| 400 Bad Request | 잘못된 요청 | 요청 파라미터 확인 |
| 401 Unauthorized | 인증 실패 | access-token 확인 |
| 403 Forbidden | 권한 없음 | 사용자 권한 확인 |
| 404 Not Found | 리소스 없음 | ID 및 경로 확인 |
| 409 Conflict | 중복된 리소스 | 기존 데이터 확인 |
| 500 Internal Server Error | 서버 오류 | 관리자 문의 |
빠른 시작
DIBO 관리 페이지에서 익스텐션을 추가한 뒤, 아래 흐름으로 사이트에 연결합니다.
// 예: 블록(배너/카드) 위젯 데이터를 받아 렌더
const res = await axios.get(`https://api.di-bo.me/block?config_id=copy_config_id`, {
headers: { 'access-token': diboToken }
});
res.data.forEach((item) => {
// item.main_img_url, item.title, item.link 로 카드 렌더
});member-token을 함께 보냅니다. 호출 전 await window._diboMemberReady로 검증 완료를 기다립니다. 회원/게시판 기능은 스탠다드 이상 구독에서 동작합니다.Extension Block API
블록 형태의 콘텐츠 위젯을 관리하는 API입니다. 이미지, 텍스트, 링크를 포함한 카드 형태의 UI 컴포넌트를 생성할 수 있습니다.
config_id 확인데이터 모델
interface ExtensionBlock {
id: string; // 블록 고유 ID
client_id: string; // 클라이언트 ID
config_id: string; // 설정 ID
main_img_url?: string; // 메인 이미지 URL
sub_img_url?: string; // 서브 이미지 URL
title: string; // 제목 (최대 128자)
content?: string; // 내용
link?: string; // 링크 URL
display_order?: number; // 표시 순서
created_at: datetime; // 생성일시
updated_at: datetime; // 수정일시
}엔드포인트
블록 목록 조회
응답: ExtensionBlock[]
블록 생성
Content-Type: multipart/form-data
| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| req_body | JSON string | 필수 | config_id, title, content, link 포함 JSON 문자열 |
| main_image | file | 선택 | 메인 이미지 파일 |
| sub_image | file | 선택 | 서브 이미지 파일 |
curl -X POST https://api.di-bo.me/block \
-H "access-token: your_token" \
-F 'req_body={"config_id":"config_789","title":"새로운 블록","content":"설명","link":"https://example.com"}' \
-F "main_image=@/path/to/main.jpg" \
-F "sub_image=@/path/to/sub.jpg"블록 상세 조회
블록 수정
요청 형식은 생성과 동일 (multipart/form-data)
블록 삭제
Extension Timer API
타이머 기반 이벤트를 관리하는 API입니다. 카운트다운, 이벤트 시작/종료 등의 시간 기반 위젯을 구현할 수 있습니다.
데이터 모델
interface ExtensionTimer {
id: string;
client_id: string;
config_id: string;
started_at: datetime; // 시작 시간
start_title: string; // 시작 제목 (최대 128자)
ended_at?: datetime; // 종료 시간 (선택)
end_title?: string; // 종료 제목 (선택)
display_order?: number;
created_at: datetime;
updated_at: datetime;
}엔드포인트
타이머 목록 조회
타이머 생성
{
"config_id": "config_789",
"started_at": "2024-01-20T09:00:00Z",
"start_title": "이벤트 시작",
"ended_at": "2024-01-20T21:00:00Z",
"end_title": "이벤트 종료"
}타이머 상세 조회
타이머 수정
타이머 삭제
Extension Edit API
사용자 정의 입력폼 데이터를 관리하는 API입니다.
지원 입력 타입
| 타입 | 설명 | 예시 |
|---|---|---|
| single_line | 한 줄 텍스트 | 이름, 제목 |
| multi_line | 여러 줄 텍스트 | 상세 설명, 메시지 |
| single_selection | 단일 선택 | 카테고리 선택 |
| checkbox | 체크박스 | 동의 여부 |
| list_selection | 목록 선택 | 다중 옵션 |
| phone | 전화번호 | 010-1234-5678 |
| 이메일 | user@example.com | |
| date | 날짜 | 2024-01-15 |
| file | 파일 업로드 | 문서, 이미지 |
데이터 모델
interface ExtensionEdit {
id: string;
client_id: string;
config_id: string;
set_id: string; // 폼 설정 ID
column_1: string; // 컬럼1 (필수)
column_2?: string;
column_3?: string;
// ... column_10까지
created_at: datetime;
updated_at: datetime;
}엔드포인트
입력폼 데이터 목록 조회
입력폼 데이터 생성
Content-Type: multipart/form-data
curl -X POST https://api.di-bo.me/edit-set/{set_id}/rows \
-H "access-token: your_token" \
-F 'req_body={"config_id":"config_789"}' \
-F "column_1=홍길동" \
-F "column_2=hong@example.com" \
-F "column_3=010-1234-5678" \
-F "column_4=기술 지원" \
-F "column_5=API 연동 관련 문의드립니다." \
-F "column_6=@/path/to/document.pdf"입력폼 데이터 상세 조회
입력폼 데이터 수정
입력폼 데이터 삭제
Extension Popup API
모달 팝업 데이터를 반환합니다.
데이터 모델
interface ExtensionPopup {
id: string;
status?: 'active' | 'inactive';
schedule?: PopupSchedule;
title: string;
description?: string | null;
image_url?: string | null;
link_url?: string | null;
link_target?: string; // _self | _blank
show_pages?: string[]; // 빈 배열이면 전체 페이지
}
interface PopupSchedule {
type?: 'always' | 'period';
schedule_started_at?: string | null;
schedule_ended_at?: string | null;
}엔드포인트
팝업 목록 조회
응답: ExtensionPopup[]
const res = await axios.get(`https://api.di-bo.me/popup?config_id=copy_config_id`, {
headers: { 'access-token': diboToken }
});
res.data.forEach((popup) => {
if (popup.status !== 'active') return;
// popup.title / popup.image_url / popup.link_url 로 모달 렌더
});Extension Floating API
플로팅 버튼 데이터를 반환합니다. design.mode가 single이면 단일 버튼, expandable이면 클릭 시 메뉴가 펼쳐집니다.
데이터 모델
interface ExtensionFloating {
display: FloatingDisplay;
design: FloatingDesign;
items?: FloatingItem[];
}
interface FloatingDisplay {
show_on?: 'all' | 'specific' | 'exclude';
show_pages?: string[];
show_delay?: number;
hide_on_mobile?: boolean;
hide_on_desktop?: boolean;
}
interface FloatingDesign {
mode?: 'single' | 'expandable';
vertical?: string; // top | bottom
horizontal?: string; // left | right
offset_x?: number;
offset_y?: number;
width?: number;
height?: number;
border_radius?: number;
trigger_icon?: string | null;
trigger_icon_open?: string | null;
}
interface FloatingItem {
id: string;
display_order?: number | null;
label?: string | null;
icon_url?: string | null;
link_url?: string | null;
link_target?: string; // _self | _blank
}엔드포인트
플로팅 버튼 조회
응답: ExtensionFloating. mode=single이면 items[0]만, mode=expandable이면 items 전체를 메뉴로 렌더링합니다.
const res = await axios.get(`https://api.di-bo.me/floating?config_id=copy_config_id`, {
headers: { 'access-token': diboToken }
});
const { design, items } = res.data;
const list = design.mode === 'single' ? items.slice(0, 1) : items;
// design.vertical/horizontal 위치에 list 의 각 항목(icon_url/label/link_url) 렌더Member API
사이트 방문자(end-user)의 회원가입, 로그인, 본인 정보 관리 API입니다.
인증
| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| access-token | header | 필수 | 사이트 토큰 (모든 회원 API 공통) |
| member-token | header | 선택 | 로그인 응답으로 받은 회원 토큰 (본인 정보/탈퇴/비밀번호 변경 등) |
데이터 모델
interface MemberToken {
member_token: string;
pwd_change_required?: boolean;
email_verified?: boolean;
}
interface MemberDetailWithCustom {
id: string;
site_id: string;
group_ids?: string[] | null;
email: string;
user_id?: string | null;
member_type: 'general' | 'business';
profile_img?: string | null;
name?: string | null;
phone_num?: string | null;
birth_date?: string | null;
status: string;
email_verified?: boolean | null;
created_at: string;
updated_at: string;
// 그룹 설정에 따라 business_* 또는 custom_1~5 추가될 수 있음
}엔드포인트
회원가입
Content-Type: multipart/form-data. req_body에 email, pwd, member_type, group_ids, 약관 동의 등 JSON 문자열 전달. 파일 필드: profile_image, business_file, custom_file_1~5.
로그인
{ "email": "member@example.com", "pwd": "Password1234!" }응답: MemberToken
이메일 인증
아이디 찾기
비밀번호 재설정
member-token 유효성 확인
비밀번호 변경 (로그인 회원)
회원 탈퇴
회원 본인 정보 조회 / 수정 / 삭제
multipart/form-data로 변경 필드를 req_body에 담아 전달합니다.Member Group API
회원가입 폼을 구성하기 위해 그룹 설정을 조회합니다. 스탠다드 이상 구독에서 동작합니다.
데이터 모델
interface MemberGroup {
id: string;
site_id: string;
name: string;
group_type: 'general' | 'business';
login_type?: 'email' | 'id';
join_process?: 'approval' | 'auto';
pw_min_length?: number;
pw_policy?: { upper?: boolean; number?: boolean; special?: boolean };
profile_field?: { use?: boolean; required?: boolean };
terms_enabled?: boolean;
terms_content?: { service?: string; privacy?: string; marketing?: string };
general_fields?: object | null;
business_fields?: object | null;
custom_fields?: CustomFieldSetting[] | null;
created_at: string;
updated_at: string;
}
interface CustomFieldSetting {
type?: string;
name?: string;
options?: string[];
use?: boolean;
required?: boolean;
}엔드포인트
회원 그룹 목록 조회
응답: MemberGroup[]
const res = await axios.get(`https://api.di-bo.me/member-group?site_id=SITE_ID`, {
headers: { 'access-token': diboToken }
});
const group = res.data[0];
// group.login_type(email/id), group.custom_fields, group.terms_content 에 맞춰 폼 렌더회원 그룹 단건 조회
Board API
게시판 글, 댓글, 대댓글과 좋아요/신고, 이미지 업로드, 내 활동 조회 API입니다. 스탠다드 이상 구독에서 동작합니다.
인증
| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| access-token | header | 필수 | 사이트 토큰 |
| member-token | header | 선택 | 회원 작성/투표/내 활동 시 필요 |
author와 password로 작성/수정/삭제가 가능합니다.데이터 모델
interface Post {
id: number;
board_id: string;
slug: string;
category?: string | null;
title: string;
content: string; // HTML
author: string;
views?: number;
thumbnail?: string | null;
tags?: string[];
likes?: number;
dislikes?: number;
my_vote?: string | null; // member-token 있을 때 본인 투표 상태
comments_enabled?: boolean;
is_guest_post?: boolean;
created_at: string;
updated_at: string;
}
interface Comment {
id: number;
post_id: number;
author: string;
content: string;
images?: string[];
likes?: number;
secret?: boolean;
replies?: Reply[];
created_at: string;
}엔드포인트
게시판 목록
게시글 목록
| 이름 | 타입 | 필수 | 설명 |
|---|---|---|---|
| category | string | 선택 | 카테고리 필터 |
| q | string | 선택 | 검색어 |
| page | number | 선택 | 페이지 번호 |
| limit | number | 선택 | 페이지당 결과 수 |
| sort | latest | popular | 선택 | 정렬 방식 |
게시글 작성
// 회원 글 작성 (member-token)
await window._diboMemberReady;
await axios.post(`https://api.di-bo.me/board/boards/${boardId}/posts`,
{ title: '문의합니다', content: '<p>내용</p>', category: '일반' },
{ headers: { 'access-token': diboToken, 'member-token': diboMemberToken } }
);
// 비회원 글 작성 (비회원 허용 게시판)
await axios.post(`https://api.di-bo.me/board/boards/${boardId}/posts`,
{ title: '문의', content: '<p>내용</p>', author: '홍길동', password: '1234' },
{ headers: { 'access-token': diboToken } }
);게시글 상세
게시글 수정 / 삭제
게시글 투표 / 신고
댓글
대댓글
이미지 업로드
Content-Type: multipart/form-data. 응답: { urls: string[] }
내 활동 (member-token 필요)
Extension Catalog API
설치 가능한 위젯(익스텐션) 목록과 복사용 기본 코드, 그리고 내 사이트에 설치된 익스텐션(config) 목록을 조회합니다.
데이터 모델
interface Extension {
id: string;
extension_type: 'free' | 'block' | 'timer' | 'edit' | 'popup' | 'floating' | 'rolling_banner';
status: 'approved' | 'disapproved' | 'deleted';
title: string;
content?: string | null;
keyword?: string[] | null;
thumbnail_url?: string | null;
image_urls?: string[] | null;
created_at: string;
updated_at: string;
}
interface ExtensionConfig {
id: string; // config_id
site_id: string;
extension_id: string;
status: 'approved' | 'disapproved';
title: string;
extension_type: string;
thumbnail_url?: string | null;
created_at: string;
updated_at: string;
}엔드포인트
위젯 목록 / 단건
위젯 기본 코드
copy_config_id는 실제 config_id로 치환해 사용합니다.내 사이트 익스텐션 (config) 목록
응답: ExtensionConfig[]. 각 항목의 id가 위젯 데이터 API에서 사용하는 config_id입니다.
const res = await axios.get(`https://api.di-bo.me/config?site_id=SITE_ID`, {
headers: { 'access-token': diboToken }
});
const popup = res.data.find((c) => c.extension_type === 'popup');
// popup.id 를 popup 위젯 API 호출 시 config_id 로 사용에러 처리
에러 응답 형식
{ "detail": "에러 메시지" }주요 에러 코드
| 코드 | 설명 | 대응 방법 |
|---|---|---|
| 400 | 잘못된 요청 | 요청 파라미터 확인 |
| 401 | 인증 실패 | access-token 확인 |
| 403 | 권한 없음 | 사용자 권한 확인 |
| 404 | 리소스 없음 | ID 및 경로 확인 |
| 409 | 중복된 리소스 | 기존 데이터 확인 |
| 500 | 서버 오류 | 관리자 문의 |
예제 코드
JavaScript (Axios)
공통 설정
// DIBO 관리 페이지에서 제공된 토큰
const diboToken = 'eyJhbGciOiJIUzI1NiIsInR...'
// 코드 복사에서 확인한 config_id
const configId = 'CFYEDHZSP5ZT'Block API 예제
// 블록 목록 조회
async function getBlocks(configId) {
const response = await axios.get(`https://api.di-bo.me/block?config_id=${configId}`, {
headers: { 'access-token': diboToken }
});
return response.data;
}
// 블록 생성
async function createBlock(configId, title, content, link, mainImage) {
const formData = new FormData();
formData.append('req_body', JSON.stringify({ config_id: configId, title, content, link }));
if (mainImage) formData.append('main_image', mainImage);
const response = await axios.post('https://api.di-bo.me/block', formData, {
headers: { 'access-token': diboToken }
});
return response.data;
}Timer API 예제
async function createTimer(configId, startTime, startTitle, endTime, endTitle) {
const response = await axios.post('https://api.di-bo.me/timer', {
config_id: configId,
started_at: startTime,
start_title: startTitle,
ended_at: endTime,
end_title: endTitle
}, {
headers: { 'access-token': diboToken }
});
return response.data;
}Edit API 예제
async function submitFormData(setId, configId, fields) {
const formData = new FormData();
formData.append('req_body', JSON.stringify({ config_id: configId }));
// 텍스트 필드 (관리 페이지 설정의 컬럼 순서에 맞춰 매핑)
Object.entries(fields).forEach(([key, value]) => {
if (value instanceof File) formData.append(key, value);
else if (value != null) formData.append(key, String(value));
});
const response = await axios.post(`https://api.di-bo.me/edit-set/${setId}/rows`, formData, {
headers: { 'access-token': diboToken }
});
return response.data;
}Python 예제
import requests, json
class DiboAPI:
def __init__(self, access_token):
self.base_url = "https://api.di-bo.me"
self.headers = { "access-token": access_token }
def get_blocks(self, config_id):
res = requests.get(f"{self.base_url}/block?config_id={config_id}", headers=self.headers)
res.raise_for_status()
return res.json()
def create_block(self, config_id, title, content=None, link=None, main_image_path=None):
files = { 'req_body': (None, json.dumps({"config_id": config_id, "title": title, "content": content, "link": link})) }
if main_image_path:
files['main_image'] = open(main_image_path, 'rb')
res = requests.post(f"{self.base_url}/block", headers=self.headers, files=files)
res.raise_for_status()
return res.json()
# 사용 예시
api = DiboAPI(access_token="eyJhbGciOiJIUzI1NiIsInR...")
blocks = api.get_blocks("CFYEDHZSP5ZT")- 파일 업로드 최대 크기: 50MB
- 블록 제목 최대 길이: 128자
- 타이머 제목 최대 길이: 128자
- Edit 입력폼 최대 컬럼 수: 10개