API 레퍼런스
APost 공개 API를 사용하여 외부 웹사이트나 앱에서 발행된 콘텐츠를 가져올 수 있습니다.
개요
APost API는 REST 방식으로 동작합니다. 모든 요청은 https://apost.soviss.com/api/v1을 기준으로 합니다.
article
GET /posts
발행된 글 목록 조회
description
GET /posts/{slug}
단일 글 상세 조회
folder
GET /categories
카테고리 목록 조회
image
GET /media/{path}
이미지 프록시
인증 (API Key)
모든 API 요청에는 API Key가 필요합니다.Authorization 헤더에 Bearer 토큰 형태로 전달합니다.
GET /api/v1/posts
Authorization: Bearer apost_sk_여러분의_API_KEYkey
API Key 발급: APost 대시보드 → 설정 → API Key 메뉴에서 발급할 수 있습니다. API Key는
apost_sk_로 시작합니다.warning
보안 주의: API Key는 서버 측에서만 사용하세요. 프론트엔드 자바스크립트에 직접 노출하지 마세요.
Rate Limit
과도한 요청을 방지하기 위해 아래와 같은 제한이 적용됩니다:
| 엔드포인트 | 제한 | 기준 |
|---|---|---|
| 공개 API (GET) | 60회/분 | API Key당 |
| AI 생성 (POST) | 10회/분 | 사용자당 |
제한 초과 시 429 Too Many Requests 응답이 반환됩니다. 응답 헤더의 X-RateLimit-Remaining으로 남은 횟수를 확인할 수 있습니다.
에러 형식
모든 에러는 동일한 JSON 형식으로 반환됩니다:
{
"error": {
"message": "에러 설명",
"code": "ERROR_CODE",
"status": 400
}
}| 코드 | HTTP | 설명 |
|---|---|---|
UNAUTHORIZED | 401 | API Key 누락 또는 유효하지 않음 |
FORBIDDEN | 403 | 접근 권한 없음 |
NOT_FOUND | 404 | 리소스를 찾을 수 없음 |
VALIDATION_ERROR | 400 | 요청 파라미터 오류 |
RATE_LIMITED | 429 | Rate Limit 초과 |
DB_ERROR | 500 | 서버 내부 오류 |
GET /posts — 글 목록
발행된 글의 페이지네이션(쪽 나누기) 목록을 반환합니다.
엔드포인트
GET /api/v1/posts쿼리 파라미터
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
page | number | 1 | 페이지 번호 |
per_page | number | 10 | 페이지당 글 수 (최대 100) |
category | string | - | 카테고리 slug(주소 코드)로 필터 |
locale | string | - | 언어 코드로 필터 (ko, en 등) |
search | string | - | 제목 검색 |
channel_id | string | - | 특정 채널에 발행된 글만 필터 (UUID) |
응답 예시
{
"data": [
{
"id": "uuid",
"title": "블로그 SEO 완벽 가이드",
"slug": "blog-seo-guide",
"excerpt": "블로그 SEO의 핵심 전략을...",
"locale": "ko",
"word_count": 2500,
"reading_time_min": 10,
"published_at": "2026-03-10T09:00:00Z",
"seo_title": "블로그 SEO 가이드 | 2026년",
"seo_description": "초보자를 위한...",
"seo_keywords": ["SEO", "블로그"],
"category": { "id": "uuid", "name": "SEO" },
"featured_image": {
"id": "uuid",
"cdn_url": "https://...",
"alt_text": "SEO 가이드 대표 이미지",
"width": 1200,
"height": 630
}
}
],
"pagination": {
"page": 1,
"per_page": 10,
"total": 45,
"total_pages": 5
}
}GET /posts/{slug} — 단일 글
slug(주소 코드)로 단일 글의 전체 내용을 조회합니다.
엔드포인트
GET /api/v1/posts/{slug}쿼리 파라미터
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
image_base | string | /img | HTML 내 이미지 경로 프리픽스(접두어). 사이트 구조에 맞게 변경 |
응답 필드
| 필드 | 타입 | 설명 |
|---|---|---|
content_html | string | HTML 형식의 글 본문 |
seo.title | string | SEO 최적화된 제목 |
seo.description | string | 메타 설명 |
seo.keywords | string[] | 키워드 배열 |
images | array | 본문에 포함된 이미지 목록 |
image_base | string | 적용된 이미지 경로 프리픽스 |
tips_and_updates
이미지 URL 자동 변환: 글 본문의 이미지 URL이
image_base 값에 맞게 자동으로 치환(변경)됩니다. 예: /img/userId/2026-03/image.webpGET /categories — 카테고리 목록
사용자의 카테고리 목록을 반환합니다.
엔드포인트
GET /api/v1/categories응답 예시
{
"data": [
{
"id": "uuid",
"name": "SEO",
"description": "검색엔진최적화 관련 글",
"parent_id": null,
"sort_order": 0
},
{
"id": "uuid",
"name": "마케팅",
"description": "디지털 마케팅 전략",
"parent_id": null,
"sort_order": 1
}
]
}GET /media/{path} — 이미지 프록시
발행된 글에 포함된 이미지를 외부 사이트에서 표시할 때 사용하는 프록시(중계) 엔드포인트입니다.
엔드포인트
GET /api/v1/media/{userId}/{date}/{filename}사용 방법
외부 사이트에서 APost 이미지를 표시하려면, 웹 서버에 rewrite(경로 재작성) 규칙을 설정하세요.
# Next.js (next.config.js)
{
source: '/img/:path*',
destination: 'https://apost.soviss.com/api/v1/media/:path*'
}
# Nginx
location /img/ {
proxy_pass https://apost.soviss.com/api/v1/media/;
proxy_set_header Authorization "Bearer YOUR_API_KEY";
}cached
이미지 응답은 1년 캐시가 적용되어 빠르게 로드됩니다.
CORS 설정
모든 공개 API는 CORS(Cross-Origin Resource Sharing, 교차 출처 리소스 공유)가 활성화되어 있습니다. 브라우저에서 직접 호출할 수 있지만, API Key 노출에 주의하세요.
- 서버 측 호출 (권장): Next.js의
getServerSideProps, API Routes, 또는 백엔드에서 호출 - 클라이언트 호출: API Key를 환경 변수로 관리하고, 프록시를 통해 전달
활용 예시
Next.js에서 블로그 목록 페이지
// app/blog/page.tsx
async function getBlogPosts(page = 1) {
const res = await fetch(
`https://apost.soviss.com/api/v1/posts?page=${page}&per_page=10`,
{
headers: {
Authorization: `Bearer ${process.env.APOST_API_KEY}`,
},
next: { revalidate: 60 }, // 1분 캐시
}
);
return res.json();
}
export default async function BlogPage() {
const { data: posts, pagination } = await getBlogPosts();
return (
<ul>
{posts.map(post => (
<li key={post.id}>
<a href={`/blog/${post.slug}`}>
{post.title}
</a>
</li>
))}
</ul>
);
}WordPress에서 REST API 연동
// functions.php
function get_apost_posts() {
$response = wp_remote_get(
'https://apost.soviss.com/api/v1/posts?per_page=5',
[
'headers' => [
'Authorization' => 'Bearer ' . APOST_API_KEY,
],
]
);
if (is_wp_error($response)) return [];
$body = json_decode(
wp_remote_retrieve_body($response),
true
);
return $body['data'] ?? [];
}멀티 채널 — 채널별 글 분리 조회
하나의 계정에 여러 채널(사이트)을 연결한 경우, channel_id 파라미터로 특정 채널에 발행된 글만 가져올 수 있습니다.
// 사이트 A 채널의 글만 조회
const res = await fetch(
`https://apost.soviss.com/api/v1/posts?channel_id=${CHANNEL_A_ID}`,
{
headers: {
Authorization: `Bearer ${process.env.APOST_API_KEY}`,
},
next: { revalidate: 60 },
}
);
// 사이트 B 채널의 글만 조회
const resB = await fetch(
`https://apost.soviss.com/api/v1/posts?channel_id=${CHANNEL_B_ID}`,
{
headers: {
Authorization: `Bearer ${process.env.APOST_API_KEY}`,
},
}
);tips_and_updates
채널 ID 확인: APost 대시보드 → 채널 관리에서 각 채널의 ID를 확인할 수 있습니다.
channel_id를 생략하면 모든 발행 글이 반환됩니다.