API 레퍼런스

APost 공개 API를 사용하여 외부 웹사이트나 앱에서 발행된 콘텐츠를 가져올 수 있습니다.

개요

APost API는 REST 방식으로 동작합니다. 모든 요청은 https://apost.soviss.com/api/v1을 기준으로 합니다.

인증 (API Key)

모든 API 요청에는 API Key가 필요합니다.Authorization 헤더에 Bearer 토큰 형태로 전달합니다.

GET /api/v1/posts
Authorization: Bearer apost_sk_여러분의_API_KEY
key
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설명
UNAUTHORIZED401API Key 누락 또는 유효하지 않음
FORBIDDEN403접근 권한 없음
NOT_FOUND404리소스를 찾을 수 없음
VALIDATION_ERROR400요청 파라미터 오류
RATE_LIMITED429Rate Limit 초과
DB_ERROR500서버 내부 오류

GET /posts — 글 목록

발행된 글의 페이지네이션(쪽 나누기) 목록을 반환합니다.

엔드포인트

GET /api/v1/posts

쿼리 파라미터

이름타입기본값설명
pagenumber1페이지 번호
per_pagenumber10페이지당 글 수 (최대 100)
categorystring-카테고리 slug(주소 코드)로 필터
localestring-언어 코드로 필터 (ko, en 등)
searchstring-제목 검색
channel_idstring-특정 채널에 발행된 글만 필터 (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_basestring/imgHTML 내 이미지 경로 프리픽스(접두어). 사이트 구조에 맞게 변경

응답 필드

필드타입설명
content_htmlstringHTML 형식의 글 본문
seo.titlestringSEO 최적화된 제목
seo.descriptionstring메타 설명
seo.keywordsstring[]키워드 배열
imagesarray본문에 포함된 이미지 목록
image_basestring적용된 이미지 경로 프리픽스
tips_and_updates
이미지 URL 자동 변환: 글 본문의 이미지 URL이 image_base 값에 맞게 자동으로 치환(변경)됩니다. 예: /img/userId/2026-03/image.webp

GET /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를 생략하면 모든 발행 글이 반환됩니다.