공개 API & API 키

워크스페이스에 프로그래밍 방식으로 접근합니다 — 프로젝트, 세션, 맞춤 이벤트 및 세그먼트를 읽고 세션에 고객 ID를 연결하며 — 워크스페이스 범위의 API 키로 보호됩니다.

1. 개요

MousePlayer API로 워크스페이스의 데이터를 자체 대시보드, 데이터 웨어하우스 또는 내부 도구로 가져올 수 있습니다. 세션에 고객 ID를 연결하는 기능(identify, 쓰기 범위의 키 필요, 키 범위 참조)을 제외하면 읽기 전용입니다. API로 데이터를 수정하거나 삭제할 수 없습니다.

  • 기본 URL: https://www.mouseplayer.com/api/v1/
  • 모든 응답은 JSON입니다.
  • 모든 요청은 API 키로 인증되며, 해당 키가 속한 워크스페이스로 범위가 자동 제한됩니다 — 한 워크스페이스의 키로 다른 워크스페이스의 데이터를 보는 것은 실수로도 불가능합니다.
  • 전체 세션 재생 녹화(마우스 이동, DOM 스냅샷)는 API를 통해 제공되지 않습니다 . 세션 메타데이터, 페이지 조회, 맞춤 이벤트 및 세그먼트를 받습니다 — 원시 재생 데이터를 옮기지 않고도 보고서와 대시보드를 만들기에 충분합니다.

2. 인증

계정 메뉴의 API 키 에서 API 키를 생성하고 관리하세요(/api-keys). 워크스페이스 소유자와 관리자만 키를 생성하거나 폐기할 수 있습니다.

키를 비밀로 유지하세요. 키는 워크스페이스의 모든 항목에 대한 읽기 권한을 부여합니다. 전체 키는 생성 직후 정확히 한 번만 표시됩니다 — 비밀번호 관리자나 비밀 저장소에 보관하세요. 잃어버리면 폐기하고 새로 만드세요.

모든 요청의 Authorization 헤더에 키를 Bearer 토큰으로 전송하세요.

# List projects in your workspace curl -H "Authorization: Bearer mp_live_..." \ https://www.mouseplayer.com/api/v1/projects

누락되거나 형식이 잘못되었거나 폐기된 키에는 401 응답이 반환됩니다.

{ "error": "Invalid or missing API key. Use: Authorization: Bearer <key>" }

요금제 요구 사항

REST API는 Business 및 Enterprise 요금제에 포함됩니다. 요금제는 워크스페이스의 소유자 를 기준으로 적용되므로 초대받은 팀원도 이를 따릅니다. 확인은 키 생성 시뿐 아니라 모든 요청에서 실행됩니다 — 워크스페이스 요금제가 낮아지면 기존 키가 작동을 멈추고 403을 반환합니다.

키 범위

각 키는 접두사에 자체 범위를 표시하므로 보는 것만으로 어떤 작업을 하는지 알 수 있습니다 — 예를 들어 .env파일이나 티켓, 터미널에서 확인할 수 있습니다.

접두사의미
mp_ro_읽기 전용. 프로젝트, 세션, 이벤트 및 세그먼트를 읽습니다. 어떤 항목도 변경할 수 없습니다.
mp_rw_읽기 및 쓰기. 위의 모든 기능에 더해 식별 엔드포인트로 고객 ID를 연결할 수 있습니다.
키를 만들 때 범위를 선택하세요. 기본값은 읽기 전용입니다. 쓰기 엔드포인트에 읽기 전용 키를 사용하면 403 과 함께 키의 범위와 엔드포인트가 요구하는 범위를 명시한 메시지가 반환됩니다. 범위는 나중에 변경할 수 없습니다 — 새 키를 만들고 기존 키를 폐기하세요.

3. 요청 한도

각 API 키에는 분당 60개 요청의 한도가 적용되며 이동 시간 창으로 집계합니다. 이를 초과하면 시간 창이 해소될 때까지 요청에 429 응답이 반환됩니다.

{ "error": "Rate limit exceeded. Max 60 requests per minute." }

더 높은 한도가 필요한 기능을 만들고 있나요? 지원 을 통해 사용 사례를 알려 주세요.

4. 엔드포인트

GET/api/v1/projects

워크스페이스의 모든 프로젝트(추적 속성)를 나열합니다.

{ "data": [ { "channelid": "955a45df5ee842cb", "domain": "yourdomain.com", "status": "active", "total_traffic_bytes": 27304765, "created_at": "2026-07-19 22:06:39", "last_used": "2026-08-05 01:12:55" } ] }

GET/api/v1/projects/{channelid}/sessions

프로젝트에서 녹화된 방문자 세션을 최신순으로 나열합니다. 페이지 나누기를 지원합니다.

쿼리 매개변수설명
page페이지 번호. 기본값: 1.
per_page페이지당 결과 수. 기본값: 25, 최댓값: 100.
since이 날짜 이후 또는 당일에 시작한 세션만 표시(YYYY-MM-DD).
until이 날짜 이전 또는 당일에 시작한 세션만 표시.
{ "data": [ { "session_id": "s_kfmist058_1785795295504", "visitor_id": "v_sv90jdpzo_1785795296042", "custom_user_id": null, "country": "DE", "device_type": "desktop", "is_bot": 0, "start_time": "2026-08-04 00:14:56", "end_time": "2026-08-04 00:16:41", "duration_seconds": 105 } ], "pagination": { "page": 1, "per_page": 25, "total": 142, "total_pages": 6 } }

GET/api/v1/sessions/{session_id}

단일 세션의 메타데이터와 페이지 조회입니다. 전체 재생 데이터는 의도적으로 제외합니다 — 녹화 재생에는 대시보드의 플레이어를 사용하세요.

{ "data": { "session_id": "s_kfmist058_1785795295504", "channelid": "955a45df5ee842cb", "visitor_id": "v_sv90jdpzo_1785795296042", "country": "DE", "asn_org": "Deutsche Telekom AG", "referrer": "https://duckduckgo.com/", "device_type": "desktop", "start_time": "2026-08-04 00:14:56", "end_time": "2026-08-04 00:16:41", "duration_seconds": 105, "pageviews": [ { "pageview_id": 1199, "url": "https://yourdomain.com/pricing", "page_title": "Pricing", "start_time": "2026-08-04 00:14:56", "end_time": "2026-08-04 00:16:41" } ] } }

GET/api/v1/sessions/{session_id}/events

세션 중 발생한 맞춤 이벤트( mp('event', ...)로 전송하는 것과 같은 이벤트)와 해당 매개변수입니다.

{ "data": [ { "event_id": 61, "pageview_id": 1199, "event_name": "add_to_cart", "created_at": "2026-08-04 00:14:59", "params": { "item_id": "SKU_98765", "price": 299.99 } } ] }

GET/api/v1/projects/{channelid}/segments

프로젝트에 정의된 방문자 세그먼트를 나열합니다(프로젝트별 세그먼트와 워크스페이스 전체 세그먼트 모두).

{ "data": [ { "segment_id": 4, "name": "High Intent Visitors", "description": "Pageviews > 5", "badge_color": "cyan", "is_global": 0, "created_at": "2026-08-03 00:00:43" } ] }

5. 백엔드에서 고객 ID 연결

브라우저는 사용자가 누구인지 모르는 경우가 많습니다. B2B 제품에서는 로그인 후 신원이 결정됩니다 — 백엔드에서 결정되는 것입니다. 쇼핑몰에서는 주문 확인 시점입니다. 이 엔드포인트는 바로 그 순간을 위한 것입니다.

POST /api/v1/sessions/{session_id}/identify
Authorization: Bearer mp_live_xxxxxxxxxxxx
Content-Type: application/json

{"user_id": "customer-4711"}

// 200 OK
{"data": {"session_id": "s_a1b2c3", "user_id": "customer-4711",
          "changed": true, "previous": null, "webhook_queued": true}}

그러면 ID가 세션 목록에 표시되어 검색할 수 있게 되며, session_identified 웹훅이 실행됩니다 — 이를 통해 CRM에 전달됩니다.

같은 ID로 두 번 호출해도 안전합니다. 응답에 "changed": false 가 포함되며 웹훅은 전송되지 않습니다. 주문이 반복되어도 두 번째 리드를 만들지 않습니다.
상태조건
400필드가 누락되었거나, user_id 가 128자를 초과하거나 제어 문자를 포함하는 경우. 잘라내는 대신 거부합니다 — 아무 알림 없이 줄어든 ID는 CRM의 어떤 항목과도 일치하지 않으면서 성공한 것처럼 보이기 때문입니다.
404세션이 존재하지 않는 경우 또는 워크스페이스에 속하지 않는 경우. 두 경우에 의도적으로 같은 응답을 반환합니다.
403워크스페이스 요금제에 API가 포함되지 않은 경우.

6. 웹훅: 서명 검증

웹훅은 프로젝트별로 연동에서 설정하며, 서명용 비밀 값도 여기서 확인할 수 있습니다. 모든 전송에는 다음 헤더가 포함됩니다.

헤더의미
X-MousePlayer-Event이벤트 이름. 예: session_identified
X-MousePlayer-TimestampUnix 초 — 서명되는 텍스트의 일부
X-MousePlayer-Attempt첫 번째 시도는 1, 재시도할수록 증가
X-MousePlayer-Signaturesha256=<hex>

서명은 프로젝트의 서명용 비밀 값을 키로 사용하여 timestamp + "." + raw body에 대해 계산한 HMAC-SHA256입니다.

// PHP
$erwartet = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $rawBody, $secret);
if (!hash_equals($erwartet, $signature)) { http_response_code(401); exit; }

// Node
const expected = 'sha256=' + crypto.createHmac('sha256', secret)
                                     .update(timestamp + '.' + rawBody).digest('hex');
JSON 파싱 전에 원시 본문으로 서명하세요. 다시 직렬화하면 키 순서와 공백이 바뀌므로 서명이 절대 일치하지 않습니다. 또한 타임스탬프가 몇 분 이상 지난 요청은 거부하세요 — 이것이 타임스탬프의 목적입니다.

전송 및 재시도

전송에 실패하면 1분, 5분, 15분, 1시간 및 6시간의 간격으로 재시도한 뒤 포기합니다. 4xx 응답 중 408 및 429 이외의 응답은 재시도하지 않습니다 — 이는 "지금은 안 됨"이 아니라 "이 방식은 안 됨"을 뜻합니다. 응답은 2xx 를 신속히 반환하고 작업은 그 뒤에 수행하세요. 전송은 10초 후 시간 초과됩니다.

사용 가능한 이벤트

이벤트실행 시점
session_identified브라우저 또는 API에서 세션에 처음 고객 ID가 부여될 때 — 최초 한 번
session_ended세션 종료 시 한 번
goal_reached맞춤 이벤트가 목표 하나를 달성했을 때 세션당 한 번. “event” 유형 목표만 해당 — URL, 지속 시간, 페이지 조회 및 퍼널 목표는 평가하지 않습니다. 포함되는 값: goal_id, goal_name, goal_value 및 currency.
high_value_session특정 날짜에 방문자가 이 프로젝트의 가치 임계값을 처음 넘을 때. 임계값은 자체 점수 분포에서 산출합니다 (최근 90일의 90백분위수). 고정된 숫자가 아니며, 최소 20명의 방문자에게 점수가 매겨져야 생성됩니다. 포함되는 값: visitor_id, value_score, threshold 및 해당 날짜에 시청 가치가 가장 높은 세션.
funnel_dropoff퍼널 하나에 진입했지만 완료하지 않은 세션이 끝날 때. 중단한 단계를 명시합니다(dropped_at). 중도 이탈은 이벤트가 없다는 뜻이므로 세션이 끝나야 알 수 있습니다. 퍼널에 진입하지 않은 세션은 중도 이탈이 아니며 이벤트도 발생시키지 않습니다.
high_friction_session마찰 점수가 처음 임계값(기본값: 100점 중 60점)에 도달했을 때 세션당 한 번. 포함되는 값: friction_score, 그 배경 신호(reasons) 및 임계값을 넘게 한 신호(trigger).
element_broken추적 요소가 며칠 동안 확인한 모든 페이지 조회에서 아무것도 찾지 못했을 때 한 번 — 보통 사이트 개편 후입니다. 표시가 다시 일치했다가 또 깨져야 다시 발생합니다. 이 이벤트는 어떤 세션에도 속하지 않습니다: session_id 및 session_url 값은 null이며, link_url 은 대신 표시를 열고, subject_id 는 표시를 식별합니다 — 모든 버전에서 같으므로 새 선택자가 다시 깨지면 열린 인시던트에 합쳐집니다. 포함되는 값: rule_id, rule_name, selector, page, checked_page_views, window_days 및 last_matched. 방문자 데이터는 없습니다.
element_recovered다음 이벤트의 해제 알림: element_broken. 표시가 실제로 요소를 다시 찾았을 때 발생합니다 — 페이지 조회가 너무 적다는 이유만으로는 발생하지 않습니다. element_broken 이벤트가 웹훅으로 전송된 경우에만 전송하며, 별도 스위치는 없습니다. element_broken 을 구독하면 함께 포함됩니다. 동일한 subject_id를 사용하므로 PagerDuty가 인시던트를 해결하고 Opsgenie가 알림을 닫습니다. 추가로 matched_page_views 및 checked_page_views 를 포함합니다.
anomaly_detected어제가 이전 28일과 뚜렷하게 달랐을 때 하루 한 번. 세션 수 급감 또는 급증, 목표 달성률 감소, 마찰이나 JS 오류가 있는 세션 증가 등이 해당합니다. 같은 지표와 방향은 일주일 동안 알리지 않습니다(조정 가능). 이 이벤트는 어떤 세션에도 속하지 않습니다: session_id 및 session_url 값은 null이며, link_url 은 프로젝트 개요를 열고, subject_id 는 지표, 방향 및 날짜를 식별합니다. 포함되는 값: metric (sessions, goal_rate, friction_rate, js_error_rate, lcp_p75, inp_p75, cls_p75), direction, day, value, expected, sessions, robust_z, z_score 및 사람이 읽을 수 있는 summary 와 hint. 방문자 데이터는 없습니다. Web Vitals의 경우 measurements 가 sessions를 대체하며, page (전체 사이트인 경우 빈 값) 및 device (desktop 또는 mobil)가 발생 위치를 나타냅니다. link_url 은 이때 Web Vitals 탭을 엽니다.
rage_click분노 클릭이 감지될 때
error_detected프런트엔드 예외 발생 시
ce자체 맞춤 이벤트의 일괄 구독입니다. 위 이벤트는 포함하지 않습니다 — 각각 별도의 스위치가 있습니다.

7. 오류 & 상태 코드

상태의미
200성공.
401누락되거나 형식이 잘못되었거나 폐기된 API 키.
404요청한 프로젝트 또는 세션이 존재하지 않거나 워크스페이스에 속하지 않습니다.
429요청 한도 초과 — 이 키로 분당 60개를 초과하는 요청을 전송하고 있습니다.
403워크스페이스 요금제에 REST API가 포함되지 않습니다. 메시지에는 필요한 요금제와 현재 요금제가 모두 명시됩니다.

8. 보안 참고 사항

  • 읽기 전용 키(mp_ro_)는 어떤 항목도 변경할 수 없습니다. 쓰기 키(mp_rw_)는 고객 ID 연결만 할 수 있으며, 어떤 키도 데이터를 삭제하거나 원시 재생 데이터를 내보낼 수 없습니다.
  • 모든 요청은 키가 속한 워크스페이스로 범위가 자동 제한됩니다 — 다른 워크스페이스 ID를 전달하여 다른 사람의 데이터를 볼 방법은 없습니다.
  • 다음 위치에서 언제든지 키를 폐기할 수 있습니다. /api-keys폐기는 즉시 적용됩니다.
  • API 키를 비밀번호처럼 취급하세요. 실수로 공개 저장소에 커밋했다면 즉시 폐기하고 새로 만드세요.

제한된 이벤트 페이지(API v1, 2026년 10월 14일)

GET /api/v1/sessions/{session_id}/events는 기본적으로 최대 100개 이벤트를 반환합니다. per_page에는 1부터 100까지의 정수를 지정하세요. 다음 요청에 cursor를 변경 없이 전송하여 pagination.next_cursor를 따라가고, 같은 세션과 워크스페이스를 유지하세요. 이벤트는 created_at과 event_id순으로 정렬됩니다. 커서는 서명되며 해당 세션과 워크스페이스에 연결됩니다. 전체 개수나 숫자 페이지 번호는 반환하지 않습니다.

기존 data 배열과 params 맵은 계속 사용할 수 있습니다. pagination.returned는 실제 반환된 개수이며, pagination.has_more는 다음 페이지가 있음을 나타냅니다. 완료되면 next_cursor는 null입니다. 응답은 524288바이트로 제한되므로 페이지에 per_page보다 적은 이벤트가 포함될 수 있습니다. 이벤트당 매개변수 행은 최대 128개까지 반환하며, 더 있으면 params_truncated가 true입니다. 개별 문자열 매개변수에는 데이터베이스의 255자 제한이 그대로 적용됩니다. 잘린 매개변수는 이 엔드포인트로 가져올 수 없습니다. per_page를 줄여도 매개변수 한도가 늘어나지 않습니다.

잘못된 페이지 크기, 변경된 커서 및 다른 세션/워크스페이스의 커서는 400을 반환합니다. 개별 이벤트 데이터가 너무 크면 413을 반환합니다. 기존 접근 검사는 해당 조건에 따라 계속 401, 403, 404 또는 409를 반환합니다.

한도는 API 키당 분당 인증된 요청 60개로 유지됩니다. 한도를 소진하면 Retry-After: 60과 함께 429를 반환합니다. Redis 또는 요청 제한기를 사용할 수 없으면 Retry-After: 5와 함께 503을 반환합니다. 한도 없이 요청을 허용하는 일은 없습니다. Retry-After를 준수하고 무작위 대기 시간을 추가하세요. 짧은 반복문으로 재시도하지 마세요. 이벤트 데이터베이스 장애도 503을 반환합니다. 커서는 스냅샷을 고정하지 않습니다. 과거 타임스탬프를 가진 데이터가 동시에 삽입되면 새로 스캔해야 할 수 있습니다.

GET /api/v1/sessions/s_example/events?per_page=25
GET /api/v1/sessions/s_example/events?per_page=25&cursor=SIGNED_CURSOR

/api/v1/native는 네이티브 SDK 미리보기용 Dev 전용 백엔드 제어 경로입니다. 프로덕션에서는 계속 비활성화됩니다. 백엔드 Bearer 키에는 list/replay를 위한 읽기 범위와 register/grant/delete/disable을 위한 쓰기 범위가 필요합니다. 네이티브 미리보기 가용성 추가 검사도 적용됩니다. 모바일 앱에 영구 워크스페이스 API 키를 절대 삽입하지 마세요.