본문으로 건너뛰기

API

엔드포인트​

메서드 · 경로하는 일
POST /api/v1/query읽기 질의. 전체 결과를 JSON 배열로. 상한에 걸리면 truncated 플래그
POST /api/v1/query/stream같은 질의를 NDJSON 으로 — 행마다 한 줄
POST /api/v1/update쓰기 질의 (TQL 은 거부)
POST /api/v1/format질의문 정렬 · 들여쓰기
POST /api/v1/cache인메모리 현재값 하나 조회
GET·POST·DELETE /api/v1/keys · /keys/{id}API 키 목록 · 발행 · 폐기
GET·POST /api/v1/login콘솔 로그인 — /api/v1 아래에서 키 없이 통과하는 유일한 경로
GET /api/v1/openapi.jsonOpenAPI 3.0.3 문서 (인증 필요)
GET /api/health익명 readiness — DB · 인메모리 · 질의로그
GET /admin/metrics · /ping · /healthcheck · /threads운영 지표 (인증 필요)
인증되지 않은 경로는 401 입니다 — 익명이 아닙니다

목록에 없는 경로는 fail-closed 로 401 입니다. 익명으로 여는 것은 / · /index.html · /api/health · 정적 자원, 그리고 /api/v1/login 하나뿐입니다 — 키를 내주는 문이라 키를 요구할 수 없기 때문입니다.

헤더​

헤더필수값
X-API-KeyO발행된 키 또는 설정의 기본 키
X-LangOPQL · CQL · SQL · TQL — 그 밖은 400
X-Params파라미터 바인딩. URL 인코딩된 JSON 객체
Content-TypeOapplication/json

질의문은 요청 본문 그 자체입니다. JSON 으로 감싸지 않습니다.

읽기 — POST /api/v1/query​

curl -X POST -H "X-API-Key: ${PP_DATA_GATEWAY_API_KEY}" -H "X-Lang: PQL" \
-H "Content-Type: application/json" \
-d "SELECT tablename FROM pg_tables WHERE schemaname='pp'" \
https://host:5501/api/v1/query
{"result":"SUCCESS","message":"","truncated":false,
"data":[{"tablename":"mm_asset"},{"tablename":"mm_tag"}]}
truncated 를 무시하지 마십시오

결과가 상한(기본 100,000행)에 도달하면 게이트웨이는 더 읽지 않고 끊습니다. truncated 가 true 인데 그것을 안 보면, 잘린 결과를 전체로 착각한 채로 집계하게 됩니다.

스트림 — POST /api/v1/query/stream​

큰 결과는 이쪽입니다. 서버가 전체를 메모리에 올리지 않고, 클라이언트도 첫 행을 바로 받습니다.

curl -X POST -H "X-API-Key: ${PP_DATA_GATEWAY_API_KEY}" -H "X-Lang: PQL" \
-H "Content-Type: application/json" \
-d "SELECT tablename FROM pg_tables WHERE schemaname='pp'" \
https://host:5501/api/v1/query/stream
{"row":{"tablename":"mm_asset"}}
{"row":{"tablename":"mm_tag"}}
{"end":{"count":43,"exec_ms":42,"truncated":false}}

응답은 application/x-ndjson 이고, 스트림 중간에 오류가 나면 마지막 줄이 end 가 아니라 error 입니다.

{"error":{"message":"..."}}
end 줄을 반드시 확인하십시오

인증은 헤더 단계에서 끝나므로 이 응답은 언제나 200 으로 시작합니다. 그 뒤의 실패는 본문 안에서만 보입니다 — end 를 못 받았으면 결과가 끝난 것이 아니라 연결이 끊긴 것이고, end.truncated 가 true 면 상한에서 잘린 것입니다.

파라미터 바인딩 — X-Params​

질의문에 :이름 으로 자리를 만들고, X-Params 에 URL 인코딩된 JSON 객체를 넣습니다.

PARAMS=$(python3 -c "import urllib.parse,json;print(urllib.parse.quote(json.dumps({
'site_id': 'SITE_00001',
'from:ts-long': 1772041960266,
'limit:int': 500
})))")

curl -X POST -H "X-API-Key: ${PP_DATA_GATEWAY_API_KEY}" -H "X-Lang: PQL" \
-H "X-Params: ${PARAMS}" -H "Content-Type: application/json" \
-d "SELECT * FROM pp.mm_tag WHERE site_id = :site_id AND created_at >= :from LIMIT :limit" \
https://host:5501/api/v1/query

키에 :타입 을 붙여 변환을 지정합니다. 붙이지 않으면 JSON 의 타입 그대로 들어갑니다.

접미뜻
:int · :long · :float · :double수
:string문자열
:epoch · :ts-longepoch 밀리초 → 타임스탬프
:ts-string날짜 문자열 → 타임스탬프

모르는 타입 접미는 400 PARAM_MISSING 입니다 — 조용히 무시하지 않습니다.

X-Params 가 깨져 있으면 400 이지 500 이 아닙니다

디코딩할 수 없는 값(%zz)이나 JSON 이 아닌 값은 클라이언트 오류입니다. 예전에는 이것이 500 INTERNAL_ERROR 로 새어 나가 「서버가 고장났다」로 읽혔습니다.

쓰기 — POST /api/v1/update​

curl -X POST -H "X-API-Key: ${PP_DATA_GATEWAY_API_KEY}" -H "X-Lang: PQL" \
-H "Content-Type: application/json" \
-d "UPDATE pp.mm_tag SET description = 'reactor inlet' WHERE tag_id = 'TAG_001'" \
https://host:5501/api/v1/update

TQL 은 이 경로에서 거부됩니다 — 시계열 엔진은 게이트웨이를 통한 쓰기를 받지 않습니다.

오류 계약​

모든 오류가 같은 봉투로 옵니다.

{"result":"ERROR","error_code":"QUERY_SYNTAX",
"message":"DDL statements are not allowed: DROP"}
error_codeHTTP뜻
AUTH_MISSING401X-API-Key 헤더가 없다
AUTH_INVALID401키가 맞지 않는다
PARAM_MISSING400헤더 · 언어 · 파라미터 타입 변환 실패
QUERY_SYNTAX400DDL 거부 · 다중 구문 · 문법 오류
QUERY_DATA400데이터 제약 위반
QUERY_CONSTRAINT409무결성 제약
QUERY_DEADLOCK409교착
QUERY_AUTH401백엔드 저장소의 인증 실패
QUERY_CONNECTION503백엔드에 연결하지 못했다
QUERY_TIMEOUT504백엔드 응답이 늦었다
QUERY_ERROR500그 밖의 실행 실패
QUERY_UNSUPPORTED400그 언어가 지원하지 않는 요청
NOT_FOUND404경로 없음
METHOD_NOT_ALLOWED405메서드 없음
UNSUPPORTED_MEDIA_TYPE415Content-Type 불일치
API_KEY_NOT_CONFIGURED503마스터 키가 설정되지 않았다 — 자격증명 실패가 아닙니다
LOGIN_NOT_CONFIGURED503콘솔 계정 두 키가 설정되지 않았다
4xx 와 5xx 를 가른 것이 핵심입니다

문법 · 제약 · 데이터 · 인증은 클라이언트 원인(4xx) 이고, 연결 · 타임아웃은 인프라 원인(5xx) 입니다. 하나로 뭉개면 「내 질의가 틀렸나 저장소가 죽었나」를 호출자가 구별할 수 없습니다. 서버 로그도 같은 기준으로 4xx 는 WARN, 5xx 는 ERROR 로 갈라 남깁니다.

API 키는 둘입니다​

종류어디 있나수명
기본 키설정 파일 data.gateway.api.key (렌더됨)설정이 바뀔 때까지
발행 키POST /api/v1/keys 로 만든다. 저장은 salt + SHA-256 다이제스트만프로세스 안에만 삽니다 — 재기동에 사라집니다

비교는 언제나 상수 시간입니다.

콘솔 로그인은 «키를 발행하지» 않습니다

로그인에 성공하면 설정의 기본 키를 그대로 돌려줍니다. 이유는 부트스트랩입니다 — 클린 설치에서 키 저장소는 비어 있고, 키를 만드는 모든 경로가 이미 키를 요구합니다. 최초 진입자는 저장소보다 «먼저» 존재하는 자격증명을 들고 와야 하고, 그것은 설정 파일의 키뿐입니다.

그래서 이 경로는 키 저장소를 읽지도 쓰지도 않습니다. DB 가 죽어도 반드시 열려야 할 문이기 때문입니다.

관련 문서​