개발자 문서 / REST API
자동화 업무를 하나의 대화로.
메시지를 보내고 답장을 받고, 승인된 업무의 결과까지 확인하세요. Pushyou REST API로 연결할 수 있습니다.
내 연결 설정하기01시작하기 전에
초대받은 Pushyou 내부 테스트 앱에서 계정과 대화방을 먼저 만드세요. 웹 로그인은 해당 앱의 QR 승인이 필요합니다. 연결 설정에서는 대화방을 선택하고 실제 전송을 확인할 수 있습니다.
설정 → 연결 관리에서 프로그램별 연결을 만들고 필요한 대화방과 작업 권한만 허용하세요. 키 원문은 발급 시 한 번 표시됩니다. 특정 방 권한으로 새 방을 만들 수는 없습니다. 모든 대화방 범위와 conversations:write가 필요합니다.
02인증
컴퓨터나 서버의 Bash 또는 zsh에서 실행하세요. 키는 실행 환경의 비밀 설정에 보관하고 브라우저 코드, URL, 게시 화면에 넣지 마세요. MCP OAuth 토큰으로는 REST 요청을 인증할 수 없습니다.
export PUSHYOU_API_URL='https://asia-northeast3-pushyou-prod.cloudfunctions.net/pushyouApi'
export PUSHYOU_MEDIA_URL='https://asia-northeast3-pushyou-prod.cloudfunctions.net/pushyouMedia'printf 'Pushyou API key: ' >&2
IFS= read -r -s PUSHYOU_API_KEY
printf '\n' >&2
export PUSHYOU_API_KEYcurl --fail-with-body --silent --show-error \
-X GET "$PUSHYOU_API_URL/v1/me" \
-H "Authorization: Bearer $PUSHYOU_API_KEY"03첫 메시지 보내기
기존 대화방 선택
계정 응답의 id, permissions, conversation_ids를 확인하세요. conversation_ids가 null이면 모든 대화방 범위입니다. 허용된 방을 조회한 뒤 YOUR_CONVERSATION_ID를 실제 ID로 바꾸세요. 목록 조회에는 conversations:read가 필요합니다.
curl --fail-with-body --silent --show-error \
-X GET "$PUSHYOU_API_URL/v1/conversations?limit=20" \
-H "Authorization: Bearer $PUSHYOU_API_KEY"export PUSHYOU_CONVERSATION_ID='YOUR_CONVERSATION_ID'curl --fail-with-body --silent --show-error \
-X POST "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/messages" \
-H "Authorization: Bearer $PUSHYOU_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"id":"docs-message-01","text":"Pushyou connection verified.","notify":true}'{
"conversation_id": "YOUR_CONVERSATION_ID",
"message_id": "docs-message-01",
"duplicate": false
}같은 메시지에는 안정적인 ID를 사용하세요. 같은 ID와 내용으로 재전송하면 HTTP 200과 duplicate: true를 반환합니다. 같은 ID에 다른 내용은 409입니다. 새 메시지에는 새 ID를 사용하세요.
메시지 필드
| 필드 | 규칙 |
|---|---|
id | 필수. 영문·숫자·밑줄·하이픈 1–80자입니다. |
text | 최대 8,000자. 비어 있지 않은 텍스트 또는 첨부파일이 필요합니다. |
attachment_ids | 같은 대화방에 업로드를 마친 파일 ID를 최대 4개 지정합니다. |
card | 선택 사항. report, actions, html 카드입니다. 카드만으로 텍스트나 첨부파일을 대신할 수 없습니다. |
notify | 불리언, 기본 true. 푸시를 요청하며 실제 수신은 기기 권한과 알림 설정에도 영향을 받습니다. |
대화·메시지·히스토리 목록은 limit(1–100, 기본 50)과 before=next_cursor를 사용합니다. 필터를 유지하고 next_cursor가 null이면 멈추세요. 이벤트는 숫자 after 커서로 오름차순 조회합니다. API 조회는 앱의 읽음 처리와 별개입니다.
04답장 수신과 업무 실행
앱에서 답장한 뒤 이벤트를 조회하세요. 일반 답장·액션의 실제 처리를 마친 후 결과 저장 → ACK → next_cursor 영구 저장 순서로 진행합니다. ACK는 이벤트 삭제나 독점 실행 권한이 아닙니다. 일반 자동 응답은 방마다 한 프로그램을 사용하거나 별도로 조정하세요.
curl --fail-with-body --silent --show-error \
-X GET "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/events?after=0" \
-H "Authorization: Bearer $PUSHYOU_API_KEY"curl --fail-with-body --silent --show-error \
-X POST "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/events/YOUR_EVENT_ID/ack" \
-H "Authorization: Bearer $PUSHYOU_API_KEY" \
-H 'Content-Type: application/json' \
--data '{}'승인 요청
curl --fail-with-body --silent --show-error \
-X POST "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/tasks" \
-H "Authorization: Bearer $PUSHYOU_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"id":"docs-report-01","title":"Review the weekly report","category_id":"reports","fields":[{"id":"notes","label":"Review notes","type":"multiline","required":false}]}'업무는 승인과 실행 결과를 함께 추적합니다. 소유자가 승인하면 작업 프로그램이 task_protocol=1로 이벤트를 조회하고 실행 토큰을 영구 저장한 뒤 해당 시도를 선점합니다. heartbeat로 점유를 유지하고 실제 결과를 저장한 후 complete를 보냅니다. 완료 시 이벤트도 ACK됩니다. 별도 ACK로 미완료 업무를 끝낼 수 없습니다.
업무 필드·선점·결과 계약 (영문) ↗Response receiver
상시 응답에는 REST 프로그램 키로 Node 22+ 수신기를 실행하세요. 수신기는 전송·ACK 전에 결과를 저장합니다. 프로세스가 실행 중이어야 하며 컴퓨터가 잠들면 동작하지 않습니다. Codex 모드는 별도 세션을 시작하며 기존 채팅에 연결하지 않습니다.
Webhooks
서명된 응답 Webhook도 지원합니다. 모바일 설정의 응답 Webhook에서 연결하세요. 원본 본문의 서명을 검증하고 전달 ID로 중복을 막아야 합니다. HTTP 2xx는 수신 확인이며 업무 완료가 아닙니다. 서명과 재시도 규칙은 업무 가이드에서 확인할 수 있습니다.
05파일과 대화방 화면
파일은 별도 미디어 엔드포인트와 media:write 또는 media:read 권한의 REST 키를 사용합니다. 원본 바이트를 먼저 업로드한 뒤 같은 대화방 메시지에 파일 ID를 첨부하세요. 파일 URL은 비공개이며 인증이 필요합니다. 사진은 10 MiB, 영상은 25 MiB까지 지원합니다.
curl --fail-with-body --silent --show-error \
"$PUSHYOU_MEDIA_URL/v1/media/docs-image-01?conversation_id=$PUSHYOU_CONVERSATION_ID" \
-H "Authorization: Bearer $PUSHYOU_API_KEY" \
-H 'Content-Type: application/octet-stream' \
-H 'X-Pushyou-Filename: review.png' \
--data-binary @review.pngcurl --fail-with-body --silent --show-error \
-X POST "$PUSHYOU_API_URL/v1/conversations/$PUSHYOU_CONVERSATION_ID/messages" \
-H "Authorization: Bearer $PUSHYOU_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"id":"docs-attachment-01","text":"Please review this image.","attachment_ids":["docs-image-01"]}'MCP에서는 pushyou_prepare_media_upload에 media_id, filename, content_type, 바이트 크기, SHA-256을 보냅니다. 반환된 upload.url과 파일 전용 헤더 그대로 5분 안에 원본 바이트를 POST한 뒤 attachment_ids로 전송하세요. REST에서도 같은 준비 API를 제공합니다. 업로드 권한을 계정 키나 MCP OAuth 토큰으로 바꾸면 안 됩니다.
PATCH …/view에 {"view": CARD}로 리포트·버튼·HTML 화면을 게시하고 {"view": null}로 제거합니다. 화면은 해당 대화방에서 엽니다. HTML은 외부 네트워크·앱 자격 증명·브라우저 저장소에 접근할 수 없습니다. 액션을 명시적으로 선언하면 같은 방에 이벤트로 전달됩니다.
Card / Field
Card =
{ type: "report", title: string, items: { title: string, body?: string, label?: string }[] }
| { type: "actions", title: string, body?: string, actions: { id: ID, label: string }[] }
| { type: "html", title: string, html: string, height?: integer, actions?: { id: ID, label: string }[] }
Field = { id: ID, label: string, type: "text" | "multiline" | "number" | "date" | "select" | "checkbox", required?: boolean, options?: string[], min?: number, max?: number }06엔드포인트 레퍼런스
경로는 각 그룹에 표시한 기본 주소에 붙입니다. 파일 전용 업로드 권한을 사용하는 경우 외에는 Bearer 프로그램 키가 필요합니다. 항목을 열어 요청 형식을 확인하고 예시 ID를 실제 ID로 바꾸세요.
JSON API
https://asia-northeast3-pushyou-prod.cloudfunctions.net/pushyouApiPOST/v1/conversations/{id}/media/uploads
파일 업로드 준비
파일 ID·이름·유형·바이트 크기·SHA-256으로 5분짜리 파일 전용 전송 권한을 받습니다. media:write 권한이 필요합니다.
{ media_id: ID, filename: string, content_type: string, size: integer, sha256: string }GET/v1/me
계정 확인
API 키가 속한 계정과 권한 범위를 확인합니다.
GET /v1/me
→ { id, key_scope, permissions, conversation_ids }POST/v1/conversations
대화방 생성
id와 name으로 대화방을 만듭니다. 같은 id와 내용으로 재시도해도 중복 생성되지 않습니다.
{ id: ID, name: string, description?: string, kind?: string, view?: Card }GET/v1/conversations
대화방 목록
내 계정의 대화방 목록을 조회합니다.
?limit=20&before=CURSOR
→ { conversations, next_cursor }GET/v1/conversations/{id}
대화방 조회
이름, 설명, 상태와 연결된 대화방 화면을 조회합니다.
GET /v1/conversations/ROOM_ID
→ { conversation }PATCH/v1/conversations/{id}
대화방 수정
이름·설명·즐겨찾기를 수정하고, active로 대화를 일시중지하거나 다시 시작합니다.
{ name?: string, description?: string, pinned?: boolean, active?: boolean, view?: Card | null }POST/v1/conversations/{id}/messages
메시지 보내기
텍스트·카드·첨부파일을 보냅니다. 업로드한 파일 ID를 attachment_ids에 넣고 notify로 푸시 여부를 지정합니다.
{ id: ID, text?: string, attachment_ids?: ID[], card?: Card | null, notify?: boolean }GET/v1/conversations/{id}/messages
대화 내용 조회
수신 메시지와 사용자의 답장을 최신순으로 조회합니다.
?limit=20&before=CURSOR
→ { messages, next_cursor }GET/v1/conversations/{id}/messages/{message_id}
메시지 상세
메시지 하나의 내용과 카드를 조회합니다.
GET /v1/conversations/ROOM_ID/messages/MESSAGE_ID
→ { message }GET/v1/conversations/{id}/events/head
현재 응답 순번
새 수신 프로그램을 시작할 때 현재까지의 마지막 순번을 확인합니다. 읽음이나 처리 완료 상태를 바꾸지 않습니다.
GET /v1/conversations/ROOM_ID/events/head
→ { cursor }GET/v1/conversations/{id}/receiver-status
수신기 상태 조회
프로그램이 최근 보고한 상태와 보고 시각을 확인합니다. 실제 작업 완료나 작업 선점 여부를 뜻하지 않습니다.
GET /v1/conversations/ROOM_ID/receiver-status
→ { receivers, checked_at }PUT/v1/conversations/{id}/receiver-status/{instance_id}
수신기 상태 보고
실행마다 새 UUID와 증가하는 sequence로 상태를 보고합니다. 대화 조회·응답 조회·ACK·메시지 전송 권한이 필요합니다.
{ sequence: positive_integer, state: "starting" | "receiving" | "processing" | "retrying" | "paused" | "stopped" | "needs_review" | "delivery_pending" }
instance_id: UUID v4GET/v1/conversations/{id}/events
사용자 응답 받기
채팅 답장과 사용자가 보낸 버튼 요청을 after 순번 이후부터 조회합니다.
?after=0
?after=0&task_protocol=1
→ { events, next_cursor }POST/v1/conversations/{id}/events/{event_id}/ack
응답 처리 확인
에이전트나 서버가 처리한 이벤트를 완료 표시합니다.
{}
→ { ok: true }GET/v1/conversations/{id}/view
대화방 화면 조회
대화방에 연결된 HTML·컴포넌트 화면을 조회합니다.
GET /v1/conversations/ROOM_ID/view
→ { view: Card | null }PATCH/v1/conversations/{id}/view
대화방 화면 게시
view에 카드를 보내면 해당 대화방 상단에 화면 열기가 나타납니다. null을 보내면 화면을 제거합니다.
{ view: Card | null }GET/v1/history
히스토리 조회
category_id·kind·status_group·conversation_id를 조합해 전체 기록을 페이지로 조회합니다.
?limit=20&before=CURSOR
&category_id=reports&conversation_id=ROOM_ID
&kind=received&status_group=attention
&result_pending=true
kind: received | action | saved
status_group: attention | progress | problems | complete
→ { history, next_cursor }POST/v1/conversations/{id}/tasks
업무 승인 요청
안정적인 업무 ID와 제목·본문·폼을 보냅니다. 사용자가 승인해야 실행 이벤트가 생깁니다.
{ id: ID, title: string, body?: string, category_id?: ID, fields?: Field[], inputs?: object, expires_at?: integer, result_requires_review?: boolean }GET/v1/conversations/{id}/tasks/{task_id}
업무 상태 조회
현재 상태와 시도, 입력, 결과를 확인합니다.
GET /v1/conversations/ROOM_ID/tasks/TASK_ID
→ { task }GET/v1/conversations/{id}/tasks/{task_id}/versions
요청 버전 조회
같은 요청의 이전 버전을 확인합니다.
GET /v1/conversations/ROOM_ID/tasks/TASK_ID/versions
→ { versions: [{revision, title, body, fields, inputs, created_at, change_request}] }POST/v1/conversations/{id}/tasks/{task_id}/revise
요청 수정본 전달
사용자가 승인할 수 있도록 수정된 요청을 전달합니다.
{ request_id: ID, expected_revision: integer, change_request_id?: ID, body: string, title?: string, fields?: Field[], inputs?: object }
Only pending or changes_requested tasks can be revised. Approval is required for every new version.POST/v1/conversations/{id}/tasks/{task_id}/claim
업무 실행 선점
실행 토큰을 먼저 저장한 뒤 해당 시도를 선점합니다. 선점 성공 후에만 외부 작업을 시작하세요.
{ request_id: ID, attempt: integer, execution_token: string }POST/v1/conversations/{id}/tasks/{task_id}/heartbeat
실행 연결 유지
현재 선점의 10분 기한을 갱신합니다. 연결 유실은 확인 필요로 남습니다.
{ request_id: ID, attempt: integer, execution_token: string }POST/v1/conversations/{id}/tasks/{task_id}/complete
업무 결과 기록
결과를 로컬에 저장한 뒤 성공·실패·확인 필요를 보고합니다. 해당 이벤트도 함께 처리됩니다.
{ request_id: ID, attempt: integer, execution_token: string, status: "succeeded" | "failed" | "needs_review", result: string, result_links?: [{label: string, url: HTTPS_URL}] }GET/v1/conversations/{id}/actions
작업 메뉴 조회
대화방의 실행 폼과 현재 버전을 확인합니다.
GET /v1/conversations/ROOM_ID/actions
→ { actions }PUT/v1/conversations/{id}/actions/{action_id}
작업 메뉴 설정
폼을 등록하거나 수정합니다. 수정은 expected_revision이 필요하며 사용자가 직접 제출합니다.
{ title: string, description?: string, fields: Field[], category_id?: ID, active?: boolean, expected_revision?: ID }미디어 API
https://asia-northeast3-pushyou-prod.cloudfunctions.net/pushyouMediaPOST/v1/uploads/{id}
준비한 파일 전송
MCP 업로드 준비에서 받은 URL과 파일 전용 인증 헤더로 원본 바이트를 전송합니다. 기존 API 키나 MCP OAuth 토큰을 대신 넣지 마세요.
POST upload.url
Headers: upload.headers
Body: original file bytesPOST/v1/media/{id}?conversation_id={room}
사진·영상 업로드
파일 원본 바이트와 URI 인코딩한 X-Pushyou-Filename 헤더를 보냅니다. 같은 id와 파일로 재시도할 수 있습니다.
Content-Type: application/octet-stream
X-Pushyou-Filename: URI_ENCODED_FILENAME
Body: original file bytesGET/v1/media/{id}
파일 조회
인증 헤더로 사진·영상을 가져옵니다. 영상은 단일 Range 요청을 지원합니다.
Range: bytes=0-65535 (optional)
→ original file bytesHEAD/v1/media/{id}
파일 정보
파일 본문 없이 MIME·크기·Range 응답 헤더를 확인합니다.
HEAD /v1/media/MEDIA_ID
→ Content-Type, Content-Length, Accept-RangesDELETE/v1/media/{id}
사용하지 않은 업로드 삭제
아직 메시지에 붙이지 않은 파일을 제거합니다. 삭제한 파일 id는 재사용하지 않습니다.
DELETE /v1/media/UNATTACHED_MEDIA_ID07문제 해결
REST 오류는 2xx가 아닌 상태와 {"error": "…"}를 반환합니다. MCP 도구 오류는 클라이언트에 표시됩니다. 구조화된 오류와 연결 권한을 함께 확인하세요.
400 | ID, 필수 필드, 자료형, 커서와 요청 크기를 확인하세요. |
|---|---|
401 | 다시 인증하거나 키의 만료·재발급·폐기 여부를 확인하세요. |
403 | 작업 권한, 허용된 대화방, 방의 일시중지 여부를 확인하세요. |
404 | 리소스 ID와 기본 주소를 확인하세요. /mcp는 웹페이지가 아닌 프로토콜 엔드포인트입니다. |
409 | 다른 내용으로 재사용한 ID, 오래된 리비전, 업무 선점, 이미 첨부된 파일 등 충돌 원인을 확인하세요. 외부 작업을 무작정 반복하지 마세요. |
410 | 대화방 삭제 중이거나 더 이상 사용할 수 없는 리소스입니다. 현재 상태를 확인하세요. |
413 | JSON 본문이나 파일 크기를 줄이고 업로드 한도를 확인하세요. |
415 | 지원되는 사진·영상 형식과 올바른 파일 바이트를 사용하세요. |
416 | 요청한 바이트 구간이 파일 범위 안인지 확인하세요. |
429 | 요청 한도라면 간격을 늘리세요. 미디어 저장 한도라면 미사용 파일을 정리한 뒤 재시도하세요. 새 메시지는 방마다 분당 60건입니다. |
500 | 일시 오류는 안정적인 ID로 간격을 늘려 재시도하세요. 외부 작업이 이미 실행됐을 수 있다면 결과를 먼저 확인하세요. |