cURL
curl -X POST https://api.retain.so/track \
-H "Content-Type: application/json" \
-H "Authorization: Basic $RETAIN_WRITE_KEY" \
-d '{
"userId": "user_123",
"event": "report_exported",
"properties": { "format": "csv" }
}'import { Retain } from '@retain-so/sdk';
const retain = new Retain(process.env.RETAIN_WRITE_KEY);
retain.track({
userId: 'user_123',
event: 'report_exported',
properties: { format: 'csv' },
});import os
import requests
requests.post(
'https://api.retain.so/track',
headers={
'Content-Type': 'application/json',
'Authorization': f'Basic {os.environ["RETAIN_WRITE_KEY"]}',
},
json={
'userId': 'user_123',
'event': 'report_exported',
'properties': {'format': 'csv'},
},
)<?php
$payload = json_encode([
'userId' => 'user_123',
'event' => 'report_exported',
'properties' => ['format' => 'csv'],
]);
$ch = curl_init('https://api.retain.so/track');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Basic ' . getenv('RETAIN_WRITE_KEY'),
],
CURLOPT_POSTFIELDS => $payload,
]);
curl_exec($ch);
curl_close($ch);require 'net/http'
require 'json'
uri = URI('https://api.retain.so/track')
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
req['Authorization'] = "Basic #{ENV.fetch('RETAIN_WRITE_KEY')}"
req.body = {
userId: 'user_123',
event: 'report_exported',
properties: { format: 'csv' },
}.to_json
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
String json = """
{
"userId": "user_123",
"event": "report_exported",
"properties": { "format": "csv" }
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.retain.so/track"))
.header("Content-Type", "application/json")
.header("Authorization", "Basic " + System.getenv("RETAIN_WRITE_KEY"))
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());{
"success": true
}{
"message": "event is required",
"statusCode": 400,
"name": "validation_error"
}{
"message": "Missing or invalid Project Token.",
"statusCode": 401,
"name": "invalid_write_key"
}{
"message": "User not found, please identify the user first using the /identify endpoint.",
"statusCode": 404,
"name": "not_found"
}{
"message": "Too many requests. Please limit the number of requests per second.",
"statusCode": 429,
"name": "rate_limit_exceeded"
}{
"message": "An unexpected error occurred, please try again later.",
"statusCode": 500,
"name": "application_error"
}API documentation
Track an event
Records an event for a user. The user must have been identified first using the /identify endpoint. Events are used to calculate engagement, health scores, and churn risk.
POST
/
track
cURL
curl -X POST https://api.retain.so/track \
-H "Content-Type: application/json" \
-H "Authorization: Basic $RETAIN_WRITE_KEY" \
-d '{
"userId": "user_123",
"event": "report_exported",
"properties": { "format": "csv" }
}'import { Retain } from '@retain-so/sdk';
const retain = new Retain(process.env.RETAIN_WRITE_KEY);
retain.track({
userId: 'user_123',
event: 'report_exported',
properties: { format: 'csv' },
});import os
import requests
requests.post(
'https://api.retain.so/track',
headers={
'Content-Type': 'application/json',
'Authorization': f'Basic {os.environ["RETAIN_WRITE_KEY"]}',
},
json={
'userId': 'user_123',
'event': 'report_exported',
'properties': {'format': 'csv'},
},
)<?php
$payload = json_encode([
'userId' => 'user_123',
'event' => 'report_exported',
'properties' => ['format' => 'csv'],
]);
$ch = curl_init('https://api.retain.so/track');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Basic ' . getenv('RETAIN_WRITE_KEY'),
],
CURLOPT_POSTFIELDS => $payload,
]);
curl_exec($ch);
curl_close($ch);require 'net/http'
require 'json'
uri = URI('https://api.retain.so/track')
req = Net::HTTP::Post.new(uri)
req['Content-Type'] = 'application/json'
req['Authorization'] = "Basic #{ENV.fetch('RETAIN_WRITE_KEY')}"
req.body = {
userId: 'user_123',
event: 'report_exported',
properties: { format: 'csv' },
}.to_json
Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
String json = """
{
"userId": "user_123",
"event": "report_exported",
"properties": { "format": "csv" }
}
""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.retain.so/track"))
.header("Content-Type", "application/json")
.header("Authorization", "Basic " + System.getenv("RETAIN_WRITE_KEY"))
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());{
"success": true
}{
"message": "event is required",
"statusCode": 400,
"name": "validation_error"
}{
"message": "Missing or invalid Project Token.",
"statusCode": 401,
"name": "invalid_write_key"
}{
"message": "User not found, please identify the user first using the /identify endpoint.",
"statusCode": 404,
"name": "not_found"
}{
"message": "Too many requests. Please limit the number of requests per second.",
"statusCode": 429,
"name": "rate_limit_exceeded"
}{
"message": "An unexpected error occurred, please try again later.",
"statusCode": 500,
"name": "application_error"
}Authorizations
Your organization's Project Token (starts with rk-). Get it from Settings.
Body
application/json
User ID (must match the userId used in /identify)
Event name (e.g. report_exported, video_watched, meeting_scheduled, post_created, etc)
Optional event metadata
Optional. When to record the event in ISO 8601 format (e.g., 2024-01-01T00:00:00Z or 2024-01-01). Use for backfilling past events. Defaults to now in the organizion timezone when omitted.
Response
Event tracked successfully. Response body: { "success": true }.
Indicates the request was successful
⌘I