Sending Events
Track pageviews, custom events, performance, and errors from any platform using the HTTP API.
POST /api/trackTrack pageviews, custom events, performance, and errors from server-side applications, mobile apps, or any platform. An API key is optional but recommended for server-side tracking — it bypasses bot detection and domain validation. IP addresses are resolved to geolocation and user agents are parsed for browser/OS/device info.
Request Body
All parameters are sent in the request body as JSON.
Prop
Type
Pageview
Standard page view tracking. Set type: "pageview" (default).
Custom Event
Track custom events with optional properties. Set type: "custom_event".
Prop
Type
Performance
Track Core Web Vitals. Set type: "performance".
Prop
Type
Outbound
Track outbound link clicks. Set type: "outbound". Pass details in the properties JSON string.
Prop
Type
Error
Track JavaScript errors. Set type: "error". event_name is the error type and properties carries the error details as a JSON string.
Prop
Type
Response
Prop
Type
Rate Limiting
API keys are limited to 500 requests per 10 minutes. Exceeding the limit returns a 429 status code.
curl -X POST "https://app.rybbit.io/api/track" \
-H "Authorization: Bearer your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"site_id": "1",
"type": "custom_event",
"pathname": "/checkout",
"event_name": "purchase",
"properties": "{\"amount\": 99.99, \"currency\": \"USD\"}"
}'const response = await fetch('https://app.rybbit.io/api/track', {
method: 'POST',
headers: {
'Authorization': 'Bearer your_api_key_here',
'Content-Type': 'application/json'
},
body: JSON.stringify({
site_id: '1',
type: 'custom_event',
pathname: '/checkout',
event_name: 'purchase',
properties: JSON.stringify({ amount: 99.99, currency: 'USD' })
})
});
const data = await response.json();import requests
import json
response = requests.post(
'https://app.rybbit.io/api/track',
json={
'site_id': '1',
'type': 'custom_event',
'pathname': '/checkout',
'event_name': 'purchase',
'properties': json.dumps({'amount': 99.99, 'currency': 'USD'})
},
headers={
'Authorization': 'Bearer your_api_key_here'
}
)
data = response.json()$body = [
'site_id' => '1',
'type' => 'custom_event',
'pathname' => '/checkout',
'event_name' => 'purchase',
'properties' => json_encode(['amount' => 99.99, 'currency' => 'USD'])
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://app.rybbit.io/api/track');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Authorization: Bearer your_api_key_here',
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
$data = json_decode($response, true);require 'net/http'
require 'json'
uri = URI('https://app.rybbit.io/api/track')
request = Net::HTTP::Post.new(uri)
request['Authorization'] = 'Bearer your_api_key_here'
request['Content-Type'] = 'application/json'
request.body = {
site_id: '1',
type: 'custom_event',
pathname: '/checkout',
event_name: 'purchase',
properties: { amount: 99.99, currency: 'USD' }.to_json
}.to_json
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
http.request(request)
end
data = JSON.parse(response.body)body := map[string]interface{}{
"site_id": "1",
"type": "custom_event",
"pathname": "/checkout",
"event_name": "purchase",
"properties": `{"amount": 99.99, "currency": "USD"}`,
}
jsonBody, _ := json.Marshal(body)
req, _ := http.NewRequest("POST", "https://app.rybbit.io/api/track", bytes.NewBuffer(jsonBody))
req.Header.Set("Authorization", "Bearer your_api_key_here")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, _ := client.Do(req)
defer resp.Body.Close()
var data map[string]interface{}
json.NewDecoder(resp.Body).Decode(&data)let body = serde_json::json!({
"site_id": "1",
"type": "custom_event",
"pathname": "/checkout",
"event_name": "purchase",
"properties": r#"{"amount": 99.99, "currency": "USD"}"#
});
let client = reqwest::Client::new();
let res = client
.post("https://app.rybbit.io/api/track")
.header("Authorization", "Bearer your_api_key_here")
.json(&body)
.send()
.await?;
let data: serde_json::Value = res.json().await?;String json = """
{
"site_id": "1",
"type": "custom_event",
"pathname": "/checkout",
"event_name": "purchase",
"properties": "{\"amount\": 99.99, \"currency\": \"USD\"}"
}
""";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://app.rybbit.io/api/track"))
.header("Authorization", "Bearer your_api_key_here")
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());var body = new
{
site_id = "1",
type = "custom_event",
pathname = "/checkout",
event_name = "purchase",
properties = JsonSerializer.Serialize(new { amount = 99.99, currency = "USD" })
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer your_api_key_here");
var content = new StringContent(
JsonSerializer.Serialize(body),
Encoding.UTF8,
"application/json");
var response = await client.PostAsync("https://app.rybbit.io/api/track", content);
var data = await response.Content.ReadAsStringAsync();{
"success": true
}{
"success": false,
"error": "Invalid payload",
"details": {
"fieldErrors": {},
"formErrors": ["Custom events require event_name"]
}
}