Skip to main content

/i

Endpoint

/i

Overview

Primary SDK ingestion endpoint for sessions, events, metrics, and user updates.

Authentication

  • Uses SDK app authentication (app_key).
  • Dashboard api_key / auth_token is not used for this endpoint.

Permissions

  • Access is controlled by valid app write access (app_key).

Request Parameters

ParameterTypeRequiredDescription
app_keyStringYesApp key for ingestion authorization.
device_idStringYesStable device identifier.
old_device_idStringNoPrevious device ID to merge into the current device_id. When different from device_id, ingestion triggers app-user merge before continuing.
timestampNumberNoEvent/request timestamp.
hourNumberNoUser local hour (0-23). Used by some time-bucketed features and can be overridden per event item.
dowNumberNoUser local day of week (0-6, Sunday = 0). Used by some time-bucketed features and can be overridden per event item.
begin_sessionNumber or BooleanNoStarts a session for this request.
end_sessionNumber or BooleanNoEnds current session for this request.
session_durationNumberNoSession duration (seconds).
eventsArray or JSON String (Array)NoEvent list for this request.
metricsObject or JSON String (Object)NoDevice/session metrics payload.
user_detailsObject or JSON String (Object)NoUser profile update payload.
crashObject or JSON String (Object)NoCrash payload when crash reporting is sent.
consentObject or JSON String (Object)NoConsent payload when consent updates are sent.
locationStringNoGPS coordinates as lat,lng. On begin_session, an empty string indicates location tracking opt-out.
ip_addressStringNoIP override for geo resolution.
country_codeStringNoCountry override for geo resolution.
regionStringNoRegion override for geo resolution.
cityStringNoCity override for geo resolution.
token_sessionNumber or BooleanNoIndicates this request carries push-token registration data.
ios_tokenStringNoiOS push token used with token_session.
android_tokenStringNoAndroid push token used with token_session.
test_modeNumberNoPush token environment selector. Current push code uses 0, 1, or 2.
token_providerStringNoOptional push provider selector for Android, such as FCM, HMS, or HPK.

events Array Structure

FieldTypeRequiredDescription
keyStringYesEvent key.
countNumberNoEvent count increment (default 1 if omitted by sender logic).
sumNumberNoOptional sum value.
durNumberNoOptional duration value.
segmentationObjectNoOptional segmentation map.
timestampNumberNoOptional per-event timestamp override.
hourNumberNoOptional per-event local hour override.
dowNumberNoOptional per-event local day-of-week override.

Example event item:

{
"key": "Purchase",
"count": 1,
"sum": 19.99,
"segmentation": {
"plan": "pro",
"currency": "USD"
}
}

Plugin-Specific Payloads

The main /i endpoint also processes several internal event structures and auxiliary objects added by Countly plugins. These are accepted either directly in the request or are converted into internal events during ingestion.

Views: [CLY]_view

The Views plugin consumes [CLY]_view events from the events array.

FieldTypeRequiredDescription
keyStringYesMust be [CLY]_view.
countNumberNoUsually 1.
durNumberNoView duration increment in seconds. Can also be provided as segmentation.dur; ingestion moves it to event-level dur.
segmentation.nameStringYesView name. Copied to internal event name.
segmentation.visitNumber or BooleanNoMarks a view start.
segmentation.startNumber or BooleanNoMarks the first event for the current view visit.
segmentation.exitNumber or BooleanNoMarks the view as exited.
segmentation.bounceNumber or BooleanNoMarks the view as bounced.
segmentation._idvStringNoView-instance identifier used to correlate repeated updates for the same started view.
segmentation.*AnyNoAdditional view segments such as platform, segment, or domain.

Example:

{
"key": "[CLY]_view",
"count": 1,
"segmentation": {
"name": "Pricing",
"visit": 1,
"start": 1,
"domain": "docs.count.ly"
}
}

Notes:

  • A later [CLY]_view event with the same segmentation.name in the same request can contribute dur and additional segments to the started view.
  • segmentation.dur is normalized into top-level dur.
  • [CLY]_action events related to web scroll tracking are also processed by the Views plugin, but they are separate from [CLY]_view.

Crashes: crash object and generated [CLY]_crash

Crash reports are sent through the top-level crash parameter, not directly as a user-supplied event. When valid, ingestion converts the object into an internal [CLY]_crash event and appends it to events.

Minimum required crash fields:

FieldTypeRequiredDescription
crash._errorStringYesStack trace or crash body.
crash._app_versionStringYesApp version for grouping and segmentation.
crash._osStringYesOS name.

Common supported crash fields:

FieldTypeRequiredDescription
crash._os_versionStringNoOS version.
crash._manufactureStringNoDevice manufacturer.
crash._deviceStringNoDevice model.
crash._resolutionStringNoScreen resolution.
crash._cpuStringNoCPU architecture or type.
crash._openglStringNoOpenGL version.
crash._viewStringNoScreen/view/page where the crash occurred.
crash._browserStringNoBrowser name when applicable.
crash._ram_currentNumberNoCurrent RAM usage.
crash._ram_totalNumberNoTotal RAM.
crash._disk_currentNumberNoCurrent free/used disk value reported by SDK.
crash._disk_totalNumberNoTotal disk size.
crash._bat / crash._bat_currentNumberNoBattery level.
crash._orientationStringNoDevice orientation.
crash._rootBooleanNoRooted/jailbroken state.
crash._onlineBooleanNoConnectivity state.
crash._mutedBooleanNoDevice muted state.
crash._signalBooleanNoCellular signal present.
crash._backgroundBooleanNoWhether app was in background.
crash._nameStringNoCrash name. Defaults to first line of _error.
crash._typeStringNoError type.
crash._nonfatalBooleanNotrue for handled exceptions.
crash._logsString or ArrayNoSupplemental logs.
crash._runNumberNoSeconds since app start.
crash._customObjectNoCustom crash key-values. Nested keys are flattened and sanitized.

Example:

{
"_error": "TypeError: Cannot read properties of undefined\n at main.js:42:13",
"_app_version": "2.4.0",
"_os": "Android",
"_os_version": "14",
"_device": "Pixel 8",
"_manufacture": "Google",
"_nonfatal": true,
"_view": "Checkout",
"_custom": {
"order_id": "A-1042",
"step": "payment"
}
}

Notes:

  • Valid crash payloads are converted to a generated [CLY]_crash event with count: 1.
  • The generated event name is the computed crash group hash, and segmentation contains normalized crash data.
  • Custom fields are flattened into custom_<key> style segment keys after sanitization.

Star Rating: [CLY]_star_rating

Star rating submissions are ingested as [CLY]_star_rating events, either directly through /i or via the convenience wrapper /i/feedback/input.

FieldTypeRequiredDescription
keyStringYesMust be [CLY]_star_rating.
countNumberYesUsually 1.
sumNumberNoCommonly 1.
segmentation.ratingNumberYesRating value.
segmentation.widget_idStringYesFeedback widget ID.
segmentation.commentStringNoOptional free-text comment.
segmentation.emailStringNoOptional contact email.
segmentation.contactMeBooleanNoContact opt-in flag.
segmentation.platformStringNoPlatform name. Defaults to undefined.
segmentation.app_versionStringNoApp version. Defaults to undefined.

Server-computed fields:

FieldDescription
segmentation.ratingSumNumeric cast of rating.
segmentation.platform_version_rateComposite key {platform}**{app_version}**{rating}**{widget_id}**.
nameSet to widget_id.

NPS: [CLY]_nps

NPS submissions are ingested as [CLY]_nps events, either directly through /i or via the wrapper endpoint /i/feedback/inputs.

FieldTypeRequiredDescription
keyStringYesMust be [CLY]_nps.
countNumberNoUsually 1.
sumNumberNoUsually 1 for answered submissions.
segmentation.widget_idStringYesNPS widget ID.
segmentation.platformStringNoPlatform name. Defaults to undefined.
segmentation.app_versionStringNoApp version. Dots are normalized to : during ingestion.
segmentation.shownNumber or BooleanNoMarks the widget as shown.
segmentation.closedNumber or BooleanNoMarks the widget as closed without answer.
segmentation.ratingNumberNoNPS score. Required for an answered submission.
segmentation.commentStringNoOptional respondent comment.

Server-computed fields:

FieldDescription
nameSet to widget_id.
segmentation.typeDerived from rating: detractor, passive, or promoter.
segmentation.answeredSet to "true" for answered submissions; set to false for pure shown events before drill storage.
Event key rewriteWhen only shown is present, the event is rewritten to [CLY]_nps_shown.

Example:

{
"key": "[CLY]_nps",
"count": 1,
"sum": 1,
"segmentation": {
"widget_id": "67a3d2f5c1a23b0f4d6c0201",
"rating": 9,
"comment": "Very easy to use",
"platform": "Android",
"app_version": "1.22"
}
}

Surveys: [CLY]_survey

Survey responses are ingested as [CLY]_survey events, either directly through /i or via /i/feedback/inputs.

FieldTypeRequiredDescription
keyStringYesMust be [CLY]_survey.
countNumberNoUsually 1.
sumNumberNoUsually 1 for answered submissions.
segmentation.widget_idStringYesSurvey widget ID.
segmentation.platformStringNoPlatform name. Defaults to undefined.
segmentation.app_versionStringNoApp version. Dots are normalized to : during ingestion.
segmentation.shownNumber or BooleanNoMarks the survey as shown.
segmentation.closedNumber or BooleanNoMarks the survey as closed.
segmentation.answ-<question_id>String or NumberNoAnswer value for a question. The exact type depends on question type.

Server-computed fields:

FieldDescription
nameSet to widget_id.
segmentation.answeredSet to "true" when at least one answer field is present and the survey is not closed.
Event key rewriteWhen only shown is present, the event is rewritten to [CLY]_survey_shown.

Example:

{
"key": "[CLY]_survey",
"count": 1,
"sum": 1,
"segmentation": {
"widget_id": "67a3d2f5c1a23b0f4d6c0202",
"shown": 1,
"platform": "Android",
"app_version": "1.24",
"answ-67a3d2f5c1a23b0f4d6c1001": "Answer0",
"answ-67a3d2f5c1a23b0f4d6c1002": 5,
"answ-67a3d2f5c1a23b0f4d6c1003": "choice_a"
}
}

Push: [CLY]_push_action and [CLY]_push_sent

The Push plugin uses internal events for message delivery and interaction tracking.

[CLY]_push_action

This event can be ingested through /i and is validated by the Push ingestor.

FieldTypeRequiredDescription
keyStringYesMust start with [CLY]_push_action.
countNumberYesMust be 1 for validated action tracking.
segmentation.iStringYesPush message ID. Must be a 24-character object ID string.
segmentation.bNumberNoPush button/action index, commonly 0, 1, or 2.
segmentation.pStringNoPlatform key such as a, i, or h. May be inferred from User-Agent.

Server-enriched fields:

FieldDescription
segmentation.aBoolean indicating an automatic trigger (cohort or event).
segmentation.tBoolean indicating an API trigger.
segmentation.apComposite of a + platform.
segmentation.tpComposite of t + platform.

Example:

{
"key": "[CLY]_push_action",
"count": 1,
"segmentation": {
"i": "67a3d2f5c1a23b0f4d6c0203",
"b": 1,
"p": "a"
}
}

[CLY]_push_sent

This event is normally generated internally by Countly when push delivery results are processed. It is included here because it is part of the same ingestion event model.

FieldTypeDescription
keyString[CLY]_push_sent
countNumberNumber of successful sends in the batch being recorded.
segmentation.iStringPush message ID.
segmentation.aBooleanAutomatic trigger flag.
segmentation.tBooleanAPI trigger flag.
segmentation.pStringPlatform key.
segmentation.apStringComposite of a + platform.
segmentation.tpStringComposite of t + platform.

Consent updates are sent through the top-level consent parameter. When values change, ingestion generates a [CLY]_consent event and appends it to events.

The consent object is a key-value map where each key is a consent group and each value is a boolean.

Example request object:

{
"sessions": true,
"events": true,
"push": false
}

Generated event behavior:

Generated segmentation fieldDescription
<consent_key>Current value as string ("true" or "false").
<consent_key>_bfPrevious value before the update, or null if none existed.
_type"i" for opt-in, "o" for opt-out, or ["i","o"] when both happen in the same update.

Notes:

  • A [CLY]_consent event is only generated when at least one consent value actually changes.
  • The generated event is stored as a drill event even though the source request uses the top-level consent object.

Parameter Semantics

  • events string parsing failures do not fail the request; events are treated as empty.
  • device_id and app_key are required to process ingestion.
  • Request payload may include multiple ingestion actions in one call (for example begin_session + events).
  • old_device_id triggers user merge behavior when it differs from the current device_id.
  • session_duration is capped by the server-side api.session_duration_limit configuration when the provided value exceeds the configured maximum.
  • hour and dow can be supplied at request level and overridden per event item.
  • location=lat,lng is accepted for explicit GPS coordinates; location="" on begin_session is treated as location-tracking opt-out.
  • Feedback convenience endpoints /i/feedback/input and /i/feedback/inputs both proxy into the main /i ingestion flow.

Configuration Impact

SettingDefaultAffectsUser-visible impact
api.trim_trailing_ending_spacesfalseRequest normalizationWhen enabled, trims leading/trailing spaces from incoming values.
api.prevent_duplicate_requestsfalseDuplicate suppressionDuplicate payloads can be ignored when enabled.

Response

Success Response

Standard success:

{
"result": "Success"
}

Ignored request success (for example duplicate/validation-cancelled request path):

{
"result": "Success",
"info": "Request ignored: Duplicate request"
}

Response Fields

FieldTypeDescription
resultString"Success" when request is accepted or intentionally ignored.
infoStringPresent only in ignored/redirected success paths; explains why request was skipped.

Error Responses

Status Code: 400 Bad Request

{
"result": "Missing parameter \"app_key\" or \"device_id\""
}

Status Code: 400 Bad Request

{
"result": "App does not exist"
}

Status Code: 400 Bad Request

{
"result": "App is currently not accepting data"
}

Status Code: 403 Forbidden

{
"result": "App is locked"
}

Behavior/Processing

Behavior Modes

ModeTriggerProcessing PathResponse Shape
Valid ingestion modeRequired identifiers and app validation passProcesses session/events/metrics/user payload through standard ingestion flow.Wrapped success string (optionally with info)
Ignored/redirected modeRequest is intentionally skipped by ingestion guardsReturns success plus informational info reason.Wrapped object { "result": "Success", "info": "..." }
Validation failure modeMissing required identifiers or app restrictionsFails early with validation/authorization error.Wrapped string error

Impact on Other Data

  • Updates ingestion-backed aggregates and user state depending on payload content.

Audit & System Logs

  • No /systemlogs action is emitted by this endpoint itself.

Database Collections

CollectionUsed forData touched by this endpoint
countly.appsApp-key validation and app-state checksReads app configuration and lock/acceptance flags during ingestion validation.
countly.app_users{appId}User profile/session stateCreates/updates app user state and profile fields.
countly.users{appId}Session/user aggregatesUpdates aggregate counters and time-based usage metrics.
countly.device_details{appId}Device/platform aggregatesUpdates OS/version/device/resolution metrics.
countly.events_dataEvent aggregatesUpdates event counts/sums/durations and segment aggregates.
countly.metric_changes{appId}Metric change trackingTracks historical metric transitions used by corrections.
countly_drill.drill_eventsDrill/raw event pipelineWrites or forwards detailed event-level records.

Examples

Example 1: Begin session with metrics

/i?
app_key=YOUR_APP_KEY&
device_id=device-123&
begin_session=1&
metrics={"_os":"iOS","_device":"iPhone","_app_version":"2.1.0"}

Example 2: Send events

/i?
app_key=YOUR_APP_KEY&
device_id=device-123&
events=[{"key":"Purchase","count":1,"sum":19.99,"segmentation":{"plan":"pro"}}]

Example 3: End session

/i?
app_key=YOUR_APP_KEY&
device_id=device-123&
end_session=1&
session_duration=245

Example 4: Register push token

/i?
app_key=YOUR_APP_KEY&
device_id=device-123&
token_session=1&
test_mode=0&
android_token=YOUR_PUSH_TOKEN

Example 5: Merge device IDs

/i?
app_key=YOUR_APP_KEY&
device_id=user-authenticated&
old_device_id=user-anonymous

Operational Considerations

  • Keep payloads minimal and valid to reduce ingestion overhead.
  • High-frequency clients should use /i/bulk where batching is appropriate.

Limitations

  • Per-request payload validation can skip/ignore data paths that fail validation checks.
  • Success response does not include per-field ingestion processing details.

Last Updated

2026-04-01