Notion API 페이지 생성
Notion API 페이지 생성
새 노트를 만들고 싶을 때, Notion API의 POST /v1/pages 엔드포인트를 사용해요. 이 엔드포인트는 기존 페이지나 데이터 소스(데이터베이스)의 하위 페이지로 새 페이지를 만들어 줘요. parent로 어디에 넣을지, properties로 어떤 속성을 가질지, children으로 어떤 콘텐츠(블록)를 담을지 지정할 수 있어요. 이번 글에서 페이지 생성 요청의 구조와 실제 사용 예시를 하나씩 살펴볼게요.
출처: 문서
본문
핵심 기능
요청 방식
POST /v1/pages
POST /v1/pages는 새 페이지 객체를 생성하고 반환해요. 요청 본문에는 크게 세 가지 파라미터가 필요해요.
parent— 새 페이지가 들어갈 위치를 지정해요.properties— 새 페이지의 속성(제목, 셀렉트 등)을 지정해요.children— 새 페이지에 담을 콘텐츠 블록을 지정해요.
parent: 페이지가 들어갈 위치 정하기
대부분의 경우 기존 페이지 또는 데이터 소스 아래에 페이지를 만들기 위해 parent에 page_id나 data_source를 넣어요.
{
"parent": {
"page_id": "f7f5e8c0a9b3401f8c4b5a7c9d1e2f3a"
}
}
데이터베이스에 넣을 때는 database_id를 쓰거나, 데이터 소스 ID를 넣어요.
{
"parent": {
"database_id": "a1b2c3d4e5f6478a9b0c1d2e3f4a5b6c"
}
}
공용 커넥션(public connection)이나 개인 액세스 토큰(PAT)을 쓰는 경우에는 parent를 아예 생략하거나 parent[workspace]=true로 설정해서 워크스페이스 레벨의 비공개 페이지를 만들 수도 있어요. 반면 내부 커넥션(internal connection)에서는 페이지나 데이터 소스의 parent가 필수예요. 새 비공개 페이지를 소유할 특정 Notion 사용자가 없기 때문이에요.
properties: 페이지 속성 설정하기
새 페이지가 기존 페이지의 하위일 때는 title 속성만 유효해요. 데이터 소스(데이터베이스)의 하위일 때는 properties 객체의 키가 부모 데이터 소스의 속성과 일치해야 해요.
{
"properties": {
"이름": {
"title": [
{
"text": {
"content": "새 페이지 제목"
}
}
]
}
}
}
주의할 점이 하나 있어요. rollup, created_by, created_time, last_edited_by, last_edited_time 값은 API를 통해 생성하거나 수정할 수 없어요. 이 값들이 properties에 포함되면 오류를 반환해요. Notion이 자동으로 생성하는 값이라서요.
children: 페이지 콘텐츠(블록) 구조
이 엔드포인트는 children 옵션으로 콘텐츠를 포함하거나 포함하지 않은 채 페이지를 만들 수 있어요. children은 블록 객체(block object)들의 배열이고 최대 100개까지 담을 수 있어요. 페이지를 만든 뒤 콘텐츠를 추가하려면 Append block children 엔드포인트를 사용하면 돼요.
블록 구조 예시 — 제목과 문단 블록을 페이지에 함께 넣는 요청이에요.
{
"parent": {
"page_id": "f7f5e8c0a9b3401f8c4b5a7c9d1e2f3a"
},
"properties": {
"title": {
"title": [
{
"text": {
"content": "Groceries"
}
}
]
}
},
"children": [
{
"object": "block",
"type": "heading_2",
"heading_2": {
"rich_text": [
{
"text": {
"content": "My grocery list"
}
}
]
}
},
{
"object": "block",
"type": "paragraph",
"paragraph": {
"rich_text": [
{
"text": {
"content": "Milk, eggs, and bread"
}
}
]
}
}
]
}
사용 예시 (cURL)
POST /v1/pages를 cURL로 호출하는 기본 예시예요. 인증 헤더(Authorization)와 버전 헤더(Notion-Version)를 반드시 포함해야 해요.
curl -X POST 'https://api.notion.com/v1/pages' \
-H 'Authorization: Bearer secret_your_token' \
-H 'Notion-Version: 2022-06-28' \
-H 'Content-Type: application/json' \
-d '{
"parent": {
"database_id": "a1b2c3d4e5f6478a9b0c1d2e3f4a5b6c"
},
"properties": {
"이름": {
"title": [
{
"text": {
"content": "New page"
}
}
]
}
}
}'
템플릿(template)으로 만들기
children을 일일이 구성하는 대신 template 파라미터로 기존 데이터 소스 템플릿을 지정해서 새 페이지의 콘텐츠와 속성을 채울 수도 있어요. 값을 생략하면 기본값인 template[type]=none이 적용돼요.
default— 데이터 소스의 기본 템플릿을 적용해요. Notion 앱에서 기본 템플릿이 설정된 데이터 소스 아래에서만 사용할 수 있어요.template_id— 특정template_id를 청사진으로 사용해요. API 봇이 템플릿 페이지에 접근할 수 있어야 하고, 같은 워크스페이스 안에 있어야 해요.
템플릿을 적용할 때는 children 파라미터를 쓸 수 없어요. API 응답에서는 페이지가 처음에 빈 상태로 반환되고, 요청이 끝난 뒤 Notion 시스템이 비동기적으로 템플릿을 적용해요. 선택적으로 template[timezone]으로 @now, @today 같은 템플릿 변수를 해석할 때 쓸 시간대를 지정할 수 있어요.
마크다운(markdown)으로 만들기
markdown 본문 파라미터로 Notion flavored 마크다운을 직접 전달해서 페이지를 만들 수도 있어요. 이 경우 JSON 문자열에서 줄바꿈은 \n으로 인코딩해야 해요. 예를 들어 "# Heading\n\nParagraph"처럼요. cURL을 쓸 때는 --data 본문을 작은따옴표('...')로 감싸서 \n이 JSON 파서에 그대로 전달되도록 해야 해요.
큰 마크다운 요청은 일반적인 HTTP 클라이언트 타임아웃을 넘길 수 있어요. 이때 allow_async: true를 설정하면 페이지 생성 완료를 기다리는 대신 async_task 객체를 담은 HTTP 202 응답을 받을 수 있어요. 이후 Retrieve an async task로 작업 상태를 폴링하면 돼요.
권한과 오류
이 엔드포인트를 호출하려면 대상 부모 페이지 또는 데이터베이스에 대해 커넥션이 Insert Content(콘텐츠 삽입) 기능을 갖고 있어야 해요. 권한이 없으면 403 응답을 반환해요. 커넥션의 기능을 바꾸려면 Developer portal에서 커넥션을 선택하고 Configuration 탭의 Capabilities 섹션을 수정하면 돼요.
그 외에도 요청 파라미터가 잘못되면 400, 인증이 없으면 401 등 다양한 오류 코드가 반환될 수 있어요. 자세한 내용은 Status codes 문서를 참고하세요.