Amplitude HTTP API 트래킹

Amplitude HTTP API 트래킹

Amplitude는 사용자 행동 데이터를 수집하는 제품 분석(Product Analytics) 플랫폼이에요. 앱이나 웹사이트에서 일어나는 이벤트(event)를 Amplitude로 보내면, 퍼널이나 리텐션 같은 지표를 바로 분석할 수 있죠. 이벤트를 보내는 방법은 크게 두 가지예요. 클라이언트·서버 SDK를 쓰거나, 이 문서에서 다룰 **HTTP API(HTTP V2 API)**를 직접 호출하는 방식이에요. SDK가 자동 배치·재시도를 처리해 주는 반면, HTTP API는 서버에서 POST 요청 하나로 이벤트를 바로 전송하기 때문에 커스텀 서버나 백엔드 파이프라인에 붙이기 좋아요. 기존에 쓰던 HTTP API(V1)는 더 이상 사용이 권장되지 않고, 지금은 이 HTTP V2 API가 그 자리를 대체하고 있어요.

출처: 문서

본문

핵심 개념: 트래킹 SDK와 HTTP 이벤트 전송

Amplitude로 데이터를 보내는 가장 직접적인 방법은 서버에서 HTTP V2 API로 이벤트를 전송하는 거예요. SDK를 쓰면 배치(batch)와 재시도 같은 세부 처리를 라이브러리가 알아서 해 주지만, HTTP API는 그 대신 요청이 성공했는지, 어떤 이벤트가 몇 개 들어갔는지 응답으로 직접 확인할 수 있어요. 그래서 SDK를 쓰기 어려운 환경이거나, 이벤트 전송 흐름을 완전히 제어하고 싶을 때 특히 유용해요.

엔드포인트(Endpoint) — 이벤트 수집용 호스트는 프로젝트의 데이터 상주(Data Residency) 지역에 따라 달라져요. 기본(Default)은 api2.amplitude.com, EU 데이터 센터를 쓰는 프로젝트는 api.eu.amplitude.com을 사용해요.

데이터 상주 Base URL
Default https://api2.amplitude.com
EU https://api.eu.amplitude.com

전송 URL은 아래와 같아요.

POST https://api2.amplitude.com/2/httpapi

이벤트를 보내려면 Content-Type 헤더를 application/json으로 설정해야 해요.

이벤트와 사용자 데이터 보내기

요청 본문(body)에는 프로젝트의 API 키(api_key)와 이벤트 배열(events)이 들어가요. 각 이벤트에는 event_type(이벤트 이름)이 반드시 필요하고, user_id(사용자 ID) 또는 device_id(기기 ID) 중 하나는 꼭 포함해야 해요.

Body parameters

이름 설명
api_key 필수. String. Amplitude 프로젝트 API 키.
events 필수. []. 업로드할 이벤트 배열.
options 선택. Object.

Event array keys (이벤트 객체에 담을 수 있는 주요 키)

  • user_iddevice_id를 안 쓰면 필수. String. 사용자 ID. 기본 최소 길이는 5자.
  • device_iduser_id를 안 쓰면 필수. String. 기기 전용 식별자(예: iOS의 Identifier for Vendor). 안 보내면 user_id를 해시한 값으로 설정돼요.
  • event_type — 필수. String. 이벤트를 구분하는 고유 식별자. Amplitude가 내부용으로 예약한 이름([Amplitude] Start Session, [Amplitude] Revenue 등)은 사용할 수 없어요.
  • user_agent — 선택. 사용자 기기의 조합되지 않은 원본 user agent 문자열.
  • time — 선택. 이벤트 타임스탬프(epoch 이후 밀리초). 안 보내면 요청 업로드 시각으로 설정돼요.
  • event_properties — 선택. Object. 이벤트와 함께 보낼 데이터의 키-값 쌍 사전.
  • user_properties — 선택. Object. 사용자에게 묶이는 데이터의 키-값 쌍 사전.
  • groups — 선택. Object. 사용자 그룹을 나타내는 키-값 사전(Growth/Enterprise + Accounts 추가 기능).
  • session_id — 선택. Long. 세션 시작 시각(epoch 이후 밀리초). 특정 세션과 이벤트를 묶고 싶을 때 필요해요.
  • insert_id — 선택. String. 이벤트의 고유 식별자. 같은 device_idinsert_id로 보낸 이후 이벤트는 7일 이내 중복 제거돼요.

참고 — 최상위 속성(top-level properties): session_id 같은 속성은 반드시 이벤트 payload의 최상위 레벨에 넣어야 해요. 그렇지 않으면 Amplitude가 값을 제대로 매핑하지 못해요.

이벤트 속성 vs 사용자 속성

이벤트와 함께 보내는 데이터는 어디에 묶이느냐에 따라 달라져요.

  • event_properties: "이벤트가 발생한 시점"의 문맥이에요. 예를 들어 load_time, source처럼 그 이벤트에만 적용되는 값을 담아요.
  • user_properties: "사용자"에게 묶이는 장기적인 값이에요. 나이, 성별, 관심사처럼 사용자 프로필에 남는 데이터를 담아요.

이 구분이 중요한 이유는, 이벤트 속성은 특정 행동을 분석할 때 쓰고 사용자 속성은 사용자 세그먼트를 나눌 때 쓰이기 때문이에요.

사용 예시 (이벤트 보내기)

아래는 사용자 12345watch_tutorial 이벤트를 cURL로 보내는 가장 간단한 예시예요. 사용자 속성(Cohort), 국가, IP, 시각을 함께 담고 있어요.

curl --location --request POST 'https://api2.amplitude.com/2/httpapi' \
--header 'Content-Type: application/json' \
--data-raw '{
    "api_key": "YOUR_API_KEY",
    "events": [
        {
            "user_id": "12345",
            "event_type": "watch_tutorial",
            "user_properties": {
                "Cohort": "Test A"
            },
            "country": "United States",
            "ip": "127.0.0.1",
            "time": 1396381378123
        }
    ]
}'

이벤트 속성과 사용자 속성, 그룹, 기기·앱 정보까지 함께 담는 더 풍부한 요청 예시도 확인해 볼게요.

curl --location --request POST 'https://api2.amplitude.com/2/httpapi' \
--header 'Content-Type: application/json' \
--data-raw '{
  "api_key": "YOUR_API_KEY",
  "events": [
    {
      "user_id": "[email protected]",
      "device_id": "C8F9E604-F01A-4BD9-95C6-8E5357DF265D",
      "event_type": "watch_tutorial",
      "time": 1396381378123,
      "event_properties": {
        "load_time": 0.8371,
        "source": "notification",
        "dates": [
          "monday",
          "tuesday"
        ]
      },
      "user_properties": {
        "age": 25,
        "gender": "female",
        "interests": [
          "chess",
          "football",
          "music"
        ]
      },
      "groups": {
        "team_id": "1",
        "company_name": [
          "Amplitude",
          "DataMonster"
        ]
      },
      "app_version": "2.1.3",
      "platform": "iOS",
      "os_name": "Android",
      "os_version": "4.2.2",
      "device_brand": "Verizon",
      "device_manufacturer": "Apple",
      "device_model": "iPhone 9,1",
      "country": "United States",
      "region": "California",
      "city": "San Francisco",
      "ip": "127.0.0.1",
      "event_id": 23,
      "session_id": 1396381378123,
      "insert_id": "5f0adeff-6668-4427-8d02-57d803a2b841"
    }
  ]
}'

업로드 제한 (Upload limit)

  • Free 플랜 고객: 초당 100개 배치, 초당 1000개 이벤트로 제한돼요. 업로드에 이벤트를 묶을 수 있지만 Amplitude는 배치당 10개 이하를 권장해요.
  • Growth/Enterprise 고객: 요청 크기를 1MB 미만, 요청당 이벤트 2000개 미만으로 유지해야 해요. 이 제한을 넘기면 413 에러가 나요.
  • 프로젝트당 HTTP API·HTTP V2 엔드포인트의 처리 상한은 초당 50,000개 이벤트예요 (SDK 엔드포인트는 프로젝트당 초당 150,000개).

응답 확인과 재시도 (Response)

200 OK 응답을 받으면 이벤트 업로드가 성공적으로 처리된 거예요. 응답으로 몇 개 이벤트가 들어갔는지(events_ingested), payload 크기(payload_size_bytes), 서버 업로드 시각(server_upload_time)을 확인할 수 있어요.

{
  "code": 200,
  "events_ingested": 50,
  "payload_size_bytes": 50,
  "server_upload_time": 1396381378123
}

400 Bad Request는 잘못된 요청을 의미해요. 응답의 error 필드로 원인을 확인할 수 있는데, 예를 들어 JSON 본문이 유효하지 않으면 "Invalid JSON request body", 필수 필드가 빠지면 "Request missing required field"가 반환돼요.

{
  "code": 400,
  "error": "Request missing required field",
  "missing_field": "api_key",
  "events_with_missing_fields": {
    "event_type": [3]
  }
}

Amplitude는 재시도(retry) 로직을 직접 구현하고 이벤트마다 insert_id를 보낼 것을 권장해요. 재시도와 insert_id를 함께 쓰면 API가 일시적으로 응답하지 않거나 요청이 실패했을 때, 이벤트가 유실되거나 중복되는 것을 막을 수 있어요. 또 200이 아닌 응답을 따로 로깅해 두면 문제를 빨리 발견할 수 있어요.

더 알아두면 좋은 고려 사항

  • 모든 문자열 제한: user_id, 이벤트, 사용자 속성 값 등 모든 문자열 값은 1024자 제한이 있어요.
  • 날짜 값: Amplitude는 날짜를 문자열로 비교하므로 ISO 8601 형식(YYYY-MM-DDTHH:mm:ss)을 사용해요.
  • 시간 값: 각 이벤트의 time은 epoch 이후 밀리초로 보내야 해요. 다른 형식(예: ISO)은 400 에러가 나요.
  • 중복 이벤트 방지: 각 이벤트에 insert_id를 보내는 걸 강력히 권장해요. 같은 device_idinsert_id로 7일 내에 다시 보낸 이벤트는 무시돼요.
  • ID 최소 길이: device_iduser_id는 기본 최소 5자 이상이어야 해요. min_id_length 옵션으로 기본값을 바꿀 수도 있어요. user_iddevice_id가 없는 이벤트는 400으로 거부될 수 있어요.
  • 403: Amplitude의 Web Application Firewall(WAF)이 요청을 차단한 경우예요. 헤더/본문/URI에 보안 필터와 일치하는 잘못된 값이 있거나, Amplitude가 수락하지 않는 지역에서 온 요청일 수 있어요.

더 알아보기 (Learn more)