Skip to main content

User Analytics

Capture user engagement analytics into the Distinct system via the dedicated user analytics endpoint.

Endpoint

POST https://api.distinct.so/api/v1/user/analytics

Request Headers

KeyValue
Content-Typeapplication/json
x-distinct-api-keyYour shared API key

Request Body

KeyTypeRequiredDescription
userIdStringConditionalUnique internal identifier for the user
emailStringConditionalEmail address of the user
phoneStringConditionalPhone number in E.164 format (e.g. "+14155552671")
featureStringYesHigh-level category (e.g. registration_email, user_collectible)
actionStringYesSpecific interaction event (e.g. sent, opened, delivered)
experienceIdStringYesExperience identifier provided by the Distinct team
capturedAtISOTimestampYesEvent timestamp in ISO 8601 format (e.g. 2026-04-27T13:35:00Z)
metadataObjectNoJSON object containing additional custom data
info

At least one identifier (userId, email, or phone) must be provided. If multiple identifiers are sent, the data is stored against the user record matching any one of them.

Response

Success (200)

{
"statusCode": 200,
"message": "User analytics added successfully.",
"data": null
}

Example Requests

Capture by Email

curl -X POST 'https://api.distinct.so/api/v1/user/analytics' \
-H 'Content-Type: application/json' \
-H 'x-distinct-api-key: <shared-api-key>' \
-d '{
"email": "john.doe@example.com",
"feature": "registration_email",
"action": "opened",
"experienceId": "47Gop5",
"capturedAt": "2026-04-27T13:35:00Z"
}'

Capture by Phone

curl -X POST 'https://api.distinct.so/api/v1/user/analytics' \
-H 'Content-Type: application/json' \
-H 'x-distinct-api-key: <shared-api-key>' \
-d '{
"phone": "+14155552671",
"feature": "registration_sms",
"action": "delivered",
"experienceId": "47Gop5",
"capturedAt": "2026-04-27T13:35:00Z"
}'

Replace the placeholders:

  • <shared-api-key> — your actual shared API key from Distinct

Feature & Action Registry

note

Third-party vendors are required to share the specific list of features and actions they intend to send. This allows the Distinct team to set up and validate identical pairs in our system to ensure data is recorded correctly.

Feature (Module)Action (Event)Use Case
registration_emaildelivered, opened, sentOnboarding email performance
registration_smssent, delivered, failedMobile verification / SMS tracking
user_collectibleviewed, downloadedDigital asset engagement
page_visitviewedWebsite visit

Response Structure

Status CodeDescriptionExample Response
200Data captured successfully{"statusCode": 200, "message": "User analytics added successfully.", "data": null}
400Missing identifiers / user not found{"statusCode": 400, "message": "User not found.", "data": null}
400Invalid feature/action pair{"statusCode": 400, "message": "Invalid feature/action.", "data": null}
400Invalid experienceId{"statusCode": 400, "message": "Invalid experience id.", "data": null}
401Missing or invalid API key{"statusCode": 401, "message": "Unauthorized.", "data": null}
500Internal server error{"statusCode": 500, "message": "Internal server error.", "data": null}

Notes

  1. This endpoint is used exclusively by third-party vendors to send user engagement/analytics data to the Distinct system.
  2. The x-distinct-api-key will be shared with you by the Distinct team and must be included in every API request.
  3. experienceId is provided by the Distinct team and is required on every request.
  4. capturedAt must strictly follow ISO 8601 format.
  5. feature and action strings are case-insensitive but must match a registered pair.
  6. phone must be in E.164 format (e.g. +14155552671) with no spaces or dashes.
  7. metadata must be a valid JSON object. Omit if no additional data is needed.
  8. Optional fields should be omitted from the payload if there are no values — do not send them as empty strings or null.
  9. Optional IP allowlisting — You can share a list of IP addresses with the Distinct team to be whitelisted against your API key for an additional layer of security. When configured, requests from any other IP are rejected with 403.