Prompt Score v3.0 엔드포인트
v3 스코어링 API는 v2.1 컴포지트(SSE, PES, IE, CRR, FC로 구성한 Speed / Skill / Efficiency)를 대체합니다. 대표 지표는 프롬프트 점수(Prompt Score) — 0–100 척도의 APG(Average Prompt Grade)입니다(자세한 내용은 /insight/summary 참조). 완료율(completion rate) — 목표를 완료(crush)한 자격 서브세션의 비율 — 은 이를 뒷받침하는 보조 숫자로 함께 제공됩니다(/score 엔드포인트(endpoint)의 prism_score 필드).
서브세션이 “완료(crush)“로 인정되는(완료율에 반영되는) 조건은 다음 세 가지가 모두 참일 때입니다.
- 실질 기준(substance floor)을 통과하고(실제 작업이 충분히 일어남), 그리고
- outcome judge가
goal_complete로 판정하며, 그리고 - 이전 시도를 다시 한 재작업(rework)이 아니어야 합니다.
의도(intent) 분류는 완료 조건이 아니라 별도의 자격 게이트입니다. 루브릭 판정기가 유형을 정하지 못한 서브세션은 완료 실패로 세는 대신 점수에서 아예 빠집니다.
스코어링 단위는 prism.score_v3_sub_sessions(하나의 Claude Code 세션 안의 목표 단위)입니다. 이 문서의 점수 및 리포트 엔드포인트는 인증된 개발자(developer) 범위(scope)로 제한됩니다. /v1/model-catalog는 예외로, 신뢰할 수 있는 서비스가 내부 secret으로만 읽는 전역 카탈로그이며 개발자별로 필터링되지 않습니다.
인증 및 개인 범위
섹션 제목: “인증 및 개인 범위”사람 개발자 키는 요청(request)마다 활성 자격 증명 수명 주기와 개발자의 현재 조직 멤버십에 대해 검사됩니다. API는 성공한 권한 부여를 캐시한다고 약속하지 않습니다. 위임된 사용자가 없는 내부 호출은 서비스 주체이며 개인 엔드포인트를 사용할 수 없습니다. 내부적으로 위임된 사용자도 요청한 조직의 현재 멤버여야 합니다.
개인 목록, 상세, 편집, 이의 제기, 실시간 스냅샷, 무결성 엔드포인트는 인증된 조직과 개발자 범위로 제한됩니다. 그 범위 밖의 리소스 ID는 존재 여부를 드러내지 않고 404를 반환합니다. 서브세션(sub-session) 리소스에서는 자식과 부모 세션이 모두 동일한 인증된 조직 및 개발자 범위를 가져야 합니다.
Claude 세션 ID는 전역 고유성을 유지하며, 고유성은 범위-로컬 복합 고유성으로 완화되지 않았습니다. 범위를 넘어 기존 Claude 세션 ID를 재사용하는 요청은 실패 닫힘으로 처리되어 기존 세션을 덮어쓰거나 연결하지 않습니다.
공통 파라미터
섹션 제목: “공통 파라미터”대부분의 v3 엔드포인트는 window 쿼리 파라미터를 받습니다:
| 값 | 의미 |
|---|---|
daily | 현재 캘린더 일 |
weekly | 현재 캘린더 주 (생략 시 기본값) |
monthly | 현재 캘린더 월 |
잘못된 값은 400 Bad Request를 반환합니다.
모델 카탈로그
섹션 제목: “모델 카탈로그”GET /v1/model-catalog
섹션 제목: “GET /v1/model-catalog”내부 소비자는 컴파일된 정확 일치 모델 카탈로그를 위해 이 엔드포인트를 사용합니다. 가장 최신의 검증된 스냅샷을 반환합니다. 최신 저장 리비전이 유효하지 않으면 엔진은 검증된 스냅샷을 찾을 때까지 리비전 이력을 거슬러 내려가며, 유효하지 않은 리비전이나 fixture/default 카탈로그를 절대 제공하지 않습니다.
현재 카탈로그 문서 버전은 schema_version: 1입니다. 성공 응답(response)에는 schema_version, catalog_revision, checksum_sha256, published_at, refreshed_at, stale, exact_lookups가 포함됩니다. 새로 고침이 실패하는 동안에도 마지막 검증된 스냅샷은 stale: true로 계속 제공될 수 있으며, 검증되지 않은 데이터로 교체되지 않습니다.
검증된 스냅샷이 하나도 없으면 엔드포인트는 503 Service Unavailable을 반환합니다:
{ "status": "unavailable", "reason": "no validated catalog snapshot"}같은 조건에서 /health/ready도 503 Service Unavailable을 반환합니다. 준비 상태에는 서비스 라이프사이클과 카탈로그 스냅샷이 모두 필요합니다.
완료 점수
섹션 제목: “완료 점수”GET /v1/score_v3/score
섹션 제목: “GET /v1/score_v3/score”핵심 점수 한 개와 작은 스파크라인.
GET /v1/score_v3/score?window=weeklyAuthorization: Bearer prism_your_key응답:
{ "window": "weekly", "prism_score": 62.5, "letter_grade": "B", "personal_tier": "Proficient", "crushed_count": 5, "total_count": 8, "crush_weight": 0.94, "sparkline": [55.0, 60.0, 58.0, 62.5]}prism_score(와이어 호환성을 위해 필드 이름 유지)는 완료율(completion measure) — 자격을 갖춘 세션 중 목표를 완료한 비율(%) — 입니다. 이것은 대표 지표인 프롬프트 점수가 아닙니다. 대표 지표인 프롬프트 점수(Average Prompt Grade, 0–100)는 GET /v1/score_v3/insight/summary의 apg_current에서 나옵니다. sparkline은 최근 4개 기간를 시간 순으로 담습니다.
Speed 축
섹션 제목: “Speed 축”GET /v1/score_v3/speed
섹션 제목: “GET /v1/score_v3/speed”CSPW(Crushed Sub-sessions Per Window), 이전 기간 대비 변화량, TTC(Time-To-Crush) 중앙값.
GET /v1/score_v3/speed?window=weekly응답:
{ "window": "weekly", "cspw": 2.4, "delta_cspw": 0.3, "ttc_median_seconds": 1420.0, "sparkline": [1.8, 2.0, 2.1, 2.4]}GET /v1/score_v3/speed/sessions
섹션 제목: “GET /v1/score_v3/speed/sessions”Speed 페이지용 세션별 목록 — 기간 내 스코어링된 서브세션마다 한 줄, 루브릭과 결과 필드 포함.
GET /v1/score_v3/sessions/:id/prompts
섹션 제목: “GET /v1/score_v3/sessions/:id/prompts”하나의 v3 서브세션에 대한 프롬프트별 상세. 서브세션 시간 범위에 들어가는 캡처된 프롬프트와 프롬프트별 루브릭 출력을 left join한 결과(루브릭이 없는 프롬프트도 여전히 표시됨).
Tokens 축
섹션 제목: “Tokens 축”GET /v1/score_v3/tokens
섹션 제목: “GET /v1/score_v3/tokens”완료당 토큰, TET(토큰 효율 추세), TPT(턴당 토큰), 그리고 input / output / cache 세부 분해.
GET /v1/score_v3/tokens?window=weekly응답:
{ "window": "weekly", "crush_weight": 0.94, "tet": 1.12, "tpt": 18450.0, "cpcs_estimate": 0.42, "sparkline": [0.88, 0.91, 0.93, 0.94], "breakdown": { "input": 120000, "output": 28000, "cache_read": 410000, "cache_write": 18000 }}GET /v1/score_v3/tokens/trend
섹션 제목: “GET /v1/score_v3/tokens/trend”Tokens 페이지의 트렌드 시계열.
Skill 축
섹션 제목: “Skill 축”GET /v1/score_v3/skill
섹션 제목: “GET /v1/score_v3/skill”습관 기반 Skill Index(0–100)와 역량 티어, 그리고 boolean별 루브릭 평균.
GET /v1/score_v3/skill?window=weekly응답:
{ "window": "weekly", "skill_index": 58.0, "tier": "Expert", "delta_apg": null, "per_boolean": { "goal_explicit": 0.81, "scope_bounded": 0.65, "references_concrete": 0.78, "context_sufficient": 0.7, "verification_requested": 0.55, "root_cause_oriented": 0.62, "plan_first": 0.58 }, "worst_pillar": "verification_requested"}skill_index는 기간 안에 스코어링된 프롬프트가 생기기 전까지 null입니다. tier는 Novice / Practitioner / Proficient / Expert / Elite 중 하나입니다. delta_apg는 응답 형태에 남아 있지만 현재 채워지지 않습니다(항상 null).
Insight (Prompt Grade)
섹션 제목: “Insight (Prompt Grade)”Insight 섹션이 Prompt Grade 페이지를 구동합니다 — 서브세션별 루브릭(불리언 7개 + intent class + judge 상태 + 문자 등급).
GET /v1/score_v3/insight/sessions
섹션 제목: “GET /v1/score_v3/insight/sessions”인증된 개발자의 최근 루브릭 행 목록.
GET /v1/score_v3/insight/sessions?limit=50score_v3_sub_session_id, intent_class, letter_grade, confidence, 7개 boolean, applicability, judge_status, 서브세션 title / summary / title_source를 가진 RubricItem 배열을 반환합니다.
GET /v1/score_v3/insight/summary
섹션 제목: “GET /v1/score_v3/insight/summary”요청 기간에 걸친 집계 요약. 그 apg_current 필드가 대표 지표인 프롬프트 점수 — 해당 범위의 Average Prompt Grade(0–100) — 이며, 함께 apg_previous, sample_count, 등급 distribution, 기간별 points 트렌드를 반환합니다.
GET /v1/score_v3/insight/sessions_range
섹션 제목: “GET /v1/score_v3/insight/sessions_range”명시적인 from / to 범위 안의 루브릭 행 목록.
POST /v1/score_v3/insight/backfill
섹션 제목: “POST /v1/score_v3/insight/backfill”관리용 — 기간 범위에 대해 루브릭 출력을 backfill하는 트리거.
Trivia
섹션 제목: “Trivia”실질 기준을 통과하지 못해 스코어링에서 제외된 세션(너무 짧거나, 실제 작업이 없는 등). 필터된 결과를 개발자가 볼 수 있도록 노출합니다.
GET /v1/score_v3/trivia
섹션 제목: “GET /v1/score_v3/trivia”GET /v1/score_v3/trivia?window=weeklyscore_v3_sub_session_id, reason, created_at, title / summary를 가진 TriviaItem 배열을 반환합니다.
GET /v1/score_v3/trivia/trend
섹션 제목: “GET /v1/score_v3/trivia/trend”제외된 세션의 트렌드 카운트.
Integrity (anti-gaming 플래그)
섹션 제목: “Integrity (anti-gaming 플래그)”GET /v1/score_v3/integrity
섹션 제목: “GET /v1/score_v3/integrity”요청 기간 안에서 종류별로 묶인 플래그.
GET /v1/score_v3/integrity?window=weekly응답:
{ "by_kind": [ { "kind": "auto_retry_storm", "count": 2 }, { "kind": "tiny_prompt_burst", "count": 1 } ]}GET /v1/score_v3/integrity/trend
섹션 제목: “GET /v1/score_v3/integrity/trend”차트용 기간별 합계와 종류별 카운트.
GET /v1/score_v3/integrity/trend?from=2026-04-01T00:00:00Z&to=2026-04-30T00:00:00Z&period=dayGET /v1/score_v3/integrity/recent
섹션 제목: “GET /v1/score_v3/integrity/recent”드릴다운 목록용 최근 플래그 행.
GET /v1/score_v3/integrity/recent?from=2026-04-01T00:00:00Z&limit=50동료 비교
섹션 제목: “동료 비교”GET /v1/score_v3/peer-comparison
섹션 제목: “GET /v1/score_v3/peer-comparison”인증된 개발자에 대해 선택적 from / to 범위(일 단위 버킷팅용 선택적 tz 포함)의 비교를 반환합니다.
myScore는 퍼센트 단위의 완료율입니다: crushed_substantive_sessions / substantive_sessions. Skill 엔드포인트가 보여 주는 APG(Average Prompt Grade)와는 다른 값입니다.
GET /v1/score_v3/peer-comparison?from=2026-04-01T00:00:00Z&to=2026-04-30T00:00:00Z응답 해석:
basis: "peers"는 스코어링된 동료가 최소 4명 있다는 뜻입니다.distribution.peerCount는 호출자를 제외하며,cohortMean,p25,p50,p75는myScore가 있을 경우 호출자를 포함해 범위 내에 점수가 있는 모든 사람을 요약합니다.myPercentile은 점수가 있는 동료 중 호출자 점수 이하인 동료의 비율입니다.basis: "selfHistory"는 동료 분포를 지원할 수 없지만 호출자에게requiredDays개 이상의 스코어링된 일별 값이 있다는 뜻입니다.baseline은 일수, 중앙값(typical), 최신 값,delta를 제공합니다.basis: "insufficient"는 어느 비교에도 뒷받침할 데이터가 충분하지 않다는 뜻입니다. 요청 범위에 호출자에게 스코어링된 실질 세션이 없으면myScore는 여전히null일 수 있습니다.
동료 코호트는 호출자의 활성 팀 멤버십에서 파생되며, 팀 멤버십과 현재 조직 멤버십의 교집합을 취합니다. 비활성 팀과 이전 조직 멤버는 제외됩니다. 클라이언트는 팀을 선택하지 않습니다.
응답에는 동료 이름이나 개인별 행이 없습니다. 하지만 peerCount, 평균, 사분위수, 호출자 점수, 백분위는 노출하므로 소규모 그룹 추론이 여전히 가능할 수 있습니다. 익명성이나 차등 프라이버시 보장은 제공하지 않습니다.
현재 API 응답은 표준 completionRate / percent / crushed_substantive_sessions / substantive_sessions metric / unit / definition 메타데이터를 전송합니다. Dashboard는 세 필드가 모두 없는 레거시 페이로드를 여전히 수용하며, 일부만 있거나 지원되지 않는 메타데이터는 숫자 동료 비교가 아니라 사용 불가/알 수 없음으로 표시합니다.
서브세션 관리
섹션 제목: “서브세션 관리”PATCH /v1/score_v3/sub-sessions/:id
섹션 제목: “PATCH /v1/score_v3/sub-sessions/:id”서브세션 이름(과 옵션으로 요약)을 변경합니다. title_source를 "user_edited"로 올려서 이후 LLM 재작성이 개발자의 선택을 덮어쓰지 않게 합니다. 소유권이 강제됩니다 — 다른 개발자가 소유한 서브세션은 404를 반환합니다.
PATCH /v1/score_v3/sub-sessions/<id>Authorization: Bearer prism_your_keyContent-Type: application/json
{ "title": "Fix auth flow timeout", "summary": "Investigated the 30s timeout in the login redirect and added a retry."}GET /v1/score_v3/realtime/sub-sessions
섹션 제목: “GET /v1/score_v3/realtime/sub-sessions”대시보드가 매 prism.score_v3.sub_session.* SSE 이벤트마다 호출하는 스냅샷 엔드포인트. 인증된 개발자의 최근 v3 서브세션을 started_at DESC 순으로 반환하며, claude_session_id를 위해 부모 score_v3_sessions 행과 join합니다.
GET /v1/score_v3/realtime/sub-sessions?limit=200&from=2026-05-26T00:00:00Zv3 리포트
섹션 제목: “v3 리포트”리포트 생성은 별도의 v3 엔드포인트 계열을 가집니다. 형태는 v2.1 리포트 엔드포인트(자세한 내용은 Insights & Reports)와 같지만 v3 스코어링 데이터로 범위가 한정됩니다.
| 엔드포인트 | 메서드 | 용도 |
|---|---|---|
/v1/score_v3/report | GET | 최신 v3 리포트 |
/v1/score_v3/report/generate | POST | 새 v3 리포트 생성 |
/v1/score_v3/report/history | GET | 과거 리포트 |
/v1/score_v3/report/pending | GET | 진행 중 리포트, 없으면 200 {"report_id": null} |
/v1/score_v3/report/status/:id | GET | 진행 중 작업 상태 |
/v1/score_v3/report/cancel/:id | POST | 진행 중 작업 취소 |
/v1/score_v3/report/:id | GET / DELETE | 단건 조회 / 삭제 |
리포트 생성 실패 상태
섹션 제목: “리포트 생성 실패 상태”실패한 GET /v1/score_v3/report/status/:id 응답에는 additive 컬럼을 사용할 수 있을 때 안정적인 기계 판독용 error_code가 포함됩니다. 리포트 소스를 읽을 수 없으면 값은 정확히 "source_unavailable"입니다:
{ "report_id": "<id>", "status": "failed", "error_code": "source_unavailable", "error_message": "Report data is temporarily unavailable. Please retry."}이 실패에 대해 Dashboard는 리포트 생성을 다시 안전하게 제안할 수 있습니다. 엔드포인트는 원시 내부 소스나 데이터베이스 오류가 아닌 고정된 안전한 error_message를 노출합니다. 다른 실패 상태에서는 error_code: null과 일반적인 안전 재시도 메시지를 가집니다. Additive 컬럼이 적용되기 전에는 호환 경로도 error_code: null과 일반 안전 메시지를 반환합니다. API는 snake_case error_code를 방출하며, Dashboard는 호환 응답을 소비할 때 camelCase 표기도 수용합니다.
일일 섹션의 표준 범위
섹션 제목: “일일 섹션의 표준 범위”GET /v1/score_v3/files, /prompts/top, /task-time, /model-task는 additive 쿼리 파라미터 from_us, to_us, timezone을 받습니다. from_us와 to_us는 함께 제공해야 하며 정확한 반개구간 [from_us, to_us)을 정의합니다. timezone은 Asia/Seoul이나 America/Los_Angeles 같은 IANA 이름이어야 합니다. 각 응답은 수락한 경계를 camelCase range: { fromUs, toUs, timezone }으로 되돌려 줍니다.
일일 리포트 Dashboard는 리포트의 meta.periodStart와 meta.periodEnd에서 하나의 범위를 도출하고, /v1/telemetry/analytics를 포함한 모든 실시간 섹션에 같은 범위를 보내며, 응답의 echo가 다른 섹션은 병합하지 않습니다. 날짜 전용 요청은 호환성을 위해 계속 사용할 수 있으며 제공된 시간대의 현지 자정을 경계로 도출합니다. 범위 echo가 없는 응답은 Dashboard가 NEXT_PUBLIC_SCORE_V3_LEGACY_DAILY_RANGE=true로 명시적으로 빌드된 경우에만 수용됩니다.
팀 대시보드 데이터
섹션 제목: “팀 대시보드 데이터”GET /v1/score_v3/team/cost
섹션 제목: “GET /v1/score_v3/team/cost”이 팀 범위 엔드포인트는 team_id, window(기본값 weekly), 선택적 tz(생략 시 UTC)를 받습니다. Parquet 기반 비용 응답은 isPartial, prevIsPartial, readCoverage, prevReadCoverage, costRankingAvailable, rollup, members를 포함한 camelCase 필드를 사용합니다.
isPartial: true는 제한된 파일 또는 바이트 읽기 예산 때문에 텔레메트리가 누락되었음을 뜻합니다. 이 경우 정확한 집계 및 멤버 숫자 필드는 null이고, 지출 순위와 스파이크 결론을 제공하지 않으며, 양수로 관측된 금액만 rollup.lowerBoundCostUsd에 표시될 수 있습니다. 0은 활동이 없는 완전한 읽기일 때만 정확합니다. readCoverage와 prevReadCoverage는 예산 사유, 읽은 배치 수, 누락 파일 수를 알려 주며, 이전 읽기가 불완전하면 prevCostUsd도 사용할 수 없습니다.
이 계약은 카탈로그 가격 적용 범위와 별개입니다. pricingCoverage는 요청 가격 산정 가능 여부를 나타내므로, 완전한 읽기에도 가격 미확인 요청이 있을 수 있고 rollup.isEstimate는 항상 true입니다. 필드는 additive 또는 nullable이므로 롤백 중 구형 API의 숫자 값도 Dashboard가 계속 수용합니다.
GET /v1/score_v3/team/summary
섹션 제목: “GET /v1/score_v3/team/summary”팀 요약은 team_id, 선택적 date(YYYY-MM-DD, 그 외에는 현재 UTC 날짜), 선택적 lang(기본값 en, ko로 시작하는 값은 한국어), 선택적 tz를 받습니다. tz는 Asia/Seoul과 같은 유효한 IANA timezone이어야 합니다. 생략하거나 빈 값이면 UTC를 사용하고, 잘못된 이름은 400 Bad Request를 반환합니다. 선택한 date는 해당 timezone의 local midnight부터 다음 날 local midnight 전까지를 나타내며, 저장된 timestamp와 비교할 때 UTC로 변환됩니다. 생성에 성공하면 narrative는 정규화되고 길이가 제한된 팀 aggregate 일반 텍스트 요약이며, narrativeSource는 "llm", generatedAt은 해당 텍스트 생성 시각입니다.
{ "narrative": "팀은 재시도 수정과 후속 작업을 완료했습니다.", "structuredNarrative": null, "narrativeSource": "llm", "generatedAt": "2026-08-06T00:00:00Z"}structuredNarrative는 nullable wire compatibility 필드로 유지됩니다. prose 내러티브가 성공해도 이 값은 필요하지 않으며 null일 수 있습니다. Dashboard는 이 경우 narrative를 리터럴 일반 텍스트로 렌더링합니다. 구조화된 값이 있지만 형식이 잘못되었거나 지원되지 않으면 기존처럼 안전하게 실패하며 narrative로 대체하지 않습니다.
모델에는 sanitized abstract task label과 익명 멤버 경계만 전달됩니다. developer ID나 display name, raw prompt, grade, score, rank, 상대 작업량, authorization 데이터는 전달하지 않습니다. 생성 내러티브는 선택 사항이므로 gateway 오류, timeout, content 누락, 정규화 후 빈 출력이 발생해도 live count는 그대로 반환됩니다. 이 실패는 cache하지 않습니다. generatedAt은 콘텐츠의 나이를 보여 줍니다. 변경된 사실은 생성된 내러티브에 최대 4시간까지 늦게 반영될 수 있고, 바뀌지 않은 사실은 이전 콘텐츠를 더 오래 재사용할 수 있습니다. narrativeInputClipped는 내러티브가 반드시 팀 전체가 아니라 가장 바쁜 멤버 또는 작업만 다룰 수 있음을 뜻합니다.