본문으로 건너뛰기

공개 API

헬프데스크는 하나의 공개 API를 제공합니다. GraphQL 엔드포인트입니다. 스키마의 모든 작업은 개인 액세스 토큰(Personal Access Token, PAT)으로 브라우저 밖에서 호출할 수 있습니다.

이 페이지는 계약 그 자체입니다. 무엇이 안정적인지, 어떻게 인증하는지, 스코프가 무엇을 허용하는지, 오류가 어떤 형태인지를 정합니다. hdmx CLI는 그 위에 구축되어 있고, API 버전 관리는 이 표면이 어떻게 발전하는지를 다룹니다.

엔드포인트​

POST https://<your-host>/backend/<subdomain>/api/<version>/graphql
  • <subdomain>은 계정을 식별합니다(로그인할 때 쓰는 것과 같은 핸들입니다).
  • <version>은 2026-07과 같은 날짜 기반 API 버전입니다 — API 버전 관리를 참고하세요. 버전 구간을 생략하고 …/backend/<subdomain>/graphql을 호출할 수도 있습니다. 이 경우 요청은 지원되는 가장 오래된 버전이 처리하며, 어떤 버전이 응답했는지는 모든 응답이 알려 줍니다.

인증​

개인 액세스 토큰을 Bearer 자격 증명으로 보냅니다.

Authorization: Bearer hdmx_<random>

PAT는 수명이 길고(단, 만료일은 필수), 스코프를 가지며, IP로 제한되고, 취소할 수 있습니다. 하나의 계정에 묶여 있어, 다른 계정의 서브도메인에 토큰을 제시하면 HTTP 401로 거부됩니다.

토큰 만들기​

토큰은 에이전트 앱의 Settings → API tokens에서 직접 만들고 관리합니다.

  1. New token을 클릭합니다.
  2. 나중에 알아볼 수 있는 이름을 붙입니다.
  3. 만료 기간을 고릅니다(최대 365일 — "무기한"은 없습니다).
  4. 접근 정책을 설정합니다. 이 토큰에 꼭 필요한 리소스만 읽기 또는 읽기·쓰기로 켜 주세요. 기본값은 아무 접근 권한도 없는 상태입니다.
  5. 허용 목록에 IP 주소 또는 CIDR을 하나 이상 추가합니다(필수 — IP 허용 목록 참고). 양식에서 현재 IP를 대신 추가해 줄 수 있습니다.
  6. 확인하고 생성합니다. 전체 토큰은 딱 한 번만 표시됩니다. 즉시 복사하세요. 저장되는 것은 해시뿐이라 다시 보여 줄 수 없습니다. 잃어버렸다면 토큰을 교체(rotate)해 새로 발급받으세요.

이후에도 토큰의 접근 정책과 허용 목록을 수정하고, 교체하고(새 비밀값을 발급하되 기존 값은 짧은 유예 기간 동안 계속 동작하므로 무중단으로 전환할 수 있습니다), 취소할 수 있습니다. 각 토큰에는 마지막으로 언제 어디에서 사용됐는지와 최근 활동 로그가 표시됩니다.

스코프​

접근 권한은 굵은 단위이며 리소스 계열별로 나뉩니다. 토큰은 고정된 스코프 집합을 갖고, 모든 최상위 작업이 그중 하나를 확인합니다.

스코프허용 범위
tickets:read티켓, 메시지, 임시 저장 글, 이력, 첨부 파일, 리포트 읽기
tickets:write티켓 생성 / 수정 / 삭제, 메시지 게시, 첨부 파일 업로드. tickets:read 포함
chat:read채팅, 대화, 메시지, 세션 읽기
chat:write상담원 메시지 전송, 대화 참여 / 나가기 / 종료 / 재오픈. chat:read 포함
customers:read고객 레코드 읽기
customers:write고객 레코드 생성 / 수정 / 병합. customers:read 포함
settings:read계정 설정 읽기(부서, 상태, 우선순위, 메일함 — 비밀값 제외)

메일함 자격 증명 필드(IMAP/SMTP 사용자 이름, 비밀번호, 호스트)는 스코프와 무관하게 토큰에 절대 반환되지 않습니다. 이 비밀값들은 이메일 제공업체의 것이며 공개 API의 손이 닿지 않는 곳에 남습니다.

오류 분류 체계​

GraphQL 응답은 errors[].extensions.code를 사용합니다.

코드의미HTTP
SCOPE_DENIED토큰에 필요한 스코프가 없습니다. extensions.valid_values에 해당 작업을 충족하는 스코프가 나열됩니다200
RATE_LIMITED토큰별 요청 한도를 모두 소진했습니다. extensions.retryAfter는 초기화까지 남은 초이며, Retry-After 헤더도 같은 숫자를 담습니다429
INVALID_API_TOKEN토큰을 찾을 수 없거나 형식이 잘못됐거나 그 밖의 이유로 사용할 수 없습니다200

취소된 토큰, 만료된 토큰, 계정 불일치, IP 허용 목록에 의한 거부는 쿼리가 실행되기 전에 차단되어 GraphQL 본문 없이 HTTP 401로 나타납니다. 토큰 요청에서의 401은 "이 토큰은 이 요청에 더 이상 유효하지 않음 — 만료일, 스코프, IP 허용 목록을 확인하라"는 뜻으로 다루세요.

요청 한도​

토큰을 사용한 모든 요청에는 다음 헤더가 실립니다.

X-RateLimit-Limit: 120
X-RateLimit-Remaining: 96
X-RateLimit-Reset: 1715692800

기본 한도는 토큰당 분당 120건입니다. 읽기든 쓰기든 요청 하나의 비용은 1입니다. 한도를 넘으면 Retry-After 헤더와 extensions.code = "RATE_LIMITED"를 담은 HTTP 429가 반환됩니다. 예의 바른 클라이언트는 초기화 시점까지 기다립니다.

IP 허용 목록​

셀프서비스로 만든 모든 토큰은 반드시 최소 하나의 IP 또는 CIDR을 가져야 합니다. "모든 IP" 토큰은 없습니다. 각 요청의 출발지 IP가 토큰의 목록과 대조되며, 일치하지 않으면 HTTP 401과 extensions.sub_code = "ip_not_allowed"로 거부됩니다.

  • IPv4, IPv6, CIDR 범위를 모두 받아들입니다. 단일 호스트에는 /32(IPv4) 또는 /128(IPv6)을 쓰세요.
  • 범위는 저장할 때 검증되고 정규화됩니다.
  • 허용 목록은 생성 후에도 수정할 수 있으며, 수정해도 비밀값은 바뀌지 않습니다.

토큰은 안정적인 송신 지점에서 사용하세요. CI 러너, 예약 작업, 고정된 사무실 NAT, 또는 알려진 IP 대역에 있는 자체 서버 등입니다. 유출된 토큰은 허용 목록 밖 어디에서도 쓸모가 없습니다.

토큰 활동​

토큰이 수행한 모든 인증된 요청이 기록됩니다. 시각, 작업 이름, 출발지 IP, 결과(성공, 오류, 한도 초과, 스코프 거부, 취소됨, 만료됨), 왕복 지연 시간입니다. 토큰이 예상과 다르게 동작할 때 확인해야 할 기록입니다.

버전 관리와 지원 중단​

API는 YYYY-MM 형식의 날짜 기반 버전으로 관리됩니다. URL에 버전을 고정하면 최소 12개월 동안 안정적으로 유지되며, 지원 중단은 사용 중인 것이 사라지기 전에 응답 안에서 알려집니다. 전체 정책은 API 버전 관리를 참고하세요.

스키마 탐색​

스키마는 스스로를 설명합니다. 버전이 지정된 엔드포인트에 표준 GraphQL 인트로스펙션을 사용하면 타입을 생성하고 API 전반을 살펴볼 수 있습니다. 대화형 GraphQL Playground는 …/backend/<subdomain>/playground에서 이용할 수 있습니다.

curl 빠른 시작​

아래 예시는 호스트 helpdesk.example.com, 서브도메인 acme, 버전 2026-07, 그리고 $TOKEN에 담긴 토큰을 전제로 합니다.

현재 사용자 조회(스코프 무관)​

curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"query":"{ currentUser { id email firstname lastname } }"}'

최근 티켓 목록 조회(tickets:read)​

curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "query ($first: Int!) {
ticketList(first: $first) {
edges { node { code subject status { name } updatedAt } }
}
}",
"variables": { "first": 10 }
}'

공개 답변 게시(tickets:write)​

curl -sS https://helpdesk.example.com/backend/acme/api/2026-07/graphql \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"query": "mutation ($input: SaveTicketInput!) {
saveTicket(input: $input) {
ticket { code }
error { code message }
}
}",
"variables": {
"input": {
"id": "TICKET-UUID-HERE",
"message": "Thanks — fixing this now.",
"messageType": "PUBLIC"
}
}
}'

일상적인 사용에는 hdmx CLI가 이 전체 표면을 편리한 명령으로 감싸 줍니다.