> For the complete documentation index, see [llms.txt](https://docs.reo.dev/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.reo.dev/integrations/input-sources/api-based-integration/telemetry/unauthenticated-telemetry-events.md).

# Unauthenticated Telemetry Events

This guide covers how to send product telemetry to Reo.dev from your own domain.

### How it works

1. Point a custom domain at the Reo.dev telemetry endpoint
2. Send one <mark style="color:red;">`GET`</mark> request per event with your fields as query parameters
3. You don't need to install an SDK, add an auth header, or agree on a payload format.
4. Setting the domain up takes two CNAME records on your side:
   1. One to route the hostname
   2. One so the TLS certificate can be issued
5. After that, requests terminate at Reo.dev, which records the event and returns immediately
6. You'll need to register the <mark style="color:red;">`activity_type`</mark> under [Product Usage configuration](https://docs.reo.dev/configurations/product-usage#step-2-add-meta-parameters).&#x20;
7. Wait for 15 minutes before you start sending the events, so that system can sync.&#x20;

```
telemetry.yourcompany.com  ->  yourcompany.telemetry.reo.dev
```

<figure><img src="https://2705882080-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fx46P5sAHxDG7PqOdVLxI%2Fuploads%2FCs2IPoSV9ktoE8um5KxI%2Ftelemetry-flow-v4.png?alt=media&amp;token=61167b24-064c-4047-818c-696c267b8b52" alt=""><figcaption></figcaption></figure>

That request goes through the following 4 steps:

1. Your app, CLI, or agent sends <mark style="color:red;">`GET /data?...`</mark> to your telemetry hostname
2. <mark style="color:red;">`telemetry.yourcompany.com`</mark> resolves to <mark style="color:red;">`yourcompany.telemetry.reo.dev`</mark> via CNAME
3. Reo.dev receives the request and returns <mark style="color:red;">`200`</mark> right away
4. The event is forwarded and recorded asynchronously - after which, It goes through the enrichment flow

***

### Send events

One <mark style="color:red;">`GET`</mark> to <mark style="color:red;">`/data`</mark>, with your fields as query parameters:

```
GET <https://telemetry.yourcompany.com/data?activity_type=><event>&<key>=<value>&<key>=<value>
```

Example:

```
GET <https://telemetry.yourcompany.com/data?activity_type=cli-run&package=yourtool&version=1.4.0&platform=Linux&python=3.12&arch=x86_64>
```

***

### What you send

<table><thead><tr><th width="143.01171875">Field</th><th width="205.3984375">Required</th><th>Notes</th></tr></thead><tbody><tr><td><mark style="color:red;"><code>activity_type</code></mark></td><td>Strongly recommended</td><td><ul><li>The event name, for example <mark style="color:red;"><code>cli-run</code></mark> or <mark style="color:red;"><code>cli-import</code></mark></li><li>This is the primary way events get grouped, so keep the list of names small and consistent</li></ul></td></tr><tr><td>Anything else</td><td>Optional</td><td><ul><li>Add as many <mark style="color:red;"><code>key=value</code></mark> pairs as you want</li><li>All of them are stored together under the event's <mark style="color:red;"><code>meta</code></mark></li></ul></td></tr></tbody></table>

Two things worth knowing about values:

* They're always stored as strings, even if you send a number
* If you repeat a key in the same URL, only the first value is kept

***

### What Reo.dev adds

Reo.dev populates these fields as soon as the event occurs:

| Field                                       | What it is                                                                       |
| ------------------------------------------- | -------------------------------------------------------------------------------- |
| <mark style="color:red;">`user_id`</mark>   | An anonymous identifier                                                          |
| <mark style="color:red;">`event_id`</mark>  | A unique ID for the request                                                      |
| <mark style="color:red;">`ip_addr`</mark>   | Read directly from the request, not from a field you set, so it can't be spoofed |
| <mark style="color:red;">`timestamp`</mark> | Server time on arrival                                                           |

***

### What you need to do

There are 5 steps in total:

* **Steps 1-3** set up DNS and TLS for your domain
* **Step 4** registers your domain with Reo.dev, so events actually land
* **Step 5** is where you start sending events and seeing data come through

{% stepper %}
{% step %}

### **Choose the hostname you want to publish**

1. <mark style="color:red;">`telemetry.yourcompany.com`</mark> is the usual shape
2. Any subdomain you control works
   {% endstep %}

{% step %}

### Add the routing CNAME record

1. Reo.dev provisions an endpoint for your account
2. They give you the exact target value to point at

```
telemetry.yourcompany.com. CNAME yourcompany.telemetry.reo.dev.
```

{% endstep %}

{% step %}

### Add the certificate validation CNAME record

1. Reo.dev issues and installs the TLS certificate for your hostname. There's nothing to purchase, upload, or renew yourself
2. Issuance requires domain validation, so Reo.dev gives you a second record for that
3. Add it alongside the routing record and leave it in place. The certificate re-validates against it on every renewal
   {% endstep %}

{% step %}

### Ask Reo.dev to register the domain as a tenant

1. This is the step that makes events actually land
2. It's separate from DNS and TLS, so everything else about the integration can look correct without it
3. Until it's done, the endpoint returns <mark style="color:red;">`200`</mark> for every request and silently drops every one of them

{% hint style="info" icon="exclamation" %}
**Don't skip this step:** DNS resolving and a valid certificate only mean requests can reach Reo.dev, not that they're being kept. Ask Reo.dev to register your domain before you rely on any data showing up.
{% endhint %}
{% endstep %}

{% step %}

### Start sending events

1. Pick your <mark style="color:red;">`activity_type`</mark> names before you ship
2. They're how every event gets grouped later
3. Renaming one after the fact doesn't relabel your history, it starts a new one alongside the old
   {% endstep %}
   {% endstepper %}

***

### Sending telemetry for more than one product

If your company ships more than one product, each with its own owner, you have two ways to set this up.

{% stepper %}
{% step %}

### **Option A: one hostname and a product field**

* Keep a single telemetry domain for the company, like <mark style="color:red;">`telemetry.yourcompany.com`</mark>
* Add a custom field to every event to say which product it came from
* Keep <mark style="color:red;">`activity_type`</mark> as one shared taxonomy across every product, like <mark style="color:red;">`cli-run`</mark>, <mark style="color:red;">`cli-import`</mark>, <mark style="color:red;">`api-call`</mark>
* Let the product field do the work of separating them

***What this gets you:***

* Each product owner filters to their own <mark style="color:red;">`package`</mark> value and gets a clean view of just their numbers
* Leadership filters to nothing and sees every product at once, in one place
  {% endstep %}

{% step %}

### **Option B: a separate hostname per product**

* Set up <mark style="color:red;">`telemetry.product-a.com`</mark> and <mark style="color:red;">`telemetry.product-b.com`</mark> as their own integrations
* Each one follows the five setup steps above and gets registered as its own tenant
* Worth it when products need to stay fully isolated: different teams need different access to the raw data, or a product might get spun out on its own later

{% hint style="info" %}
**Default to Option A:** unless you have a specific reason to isolate the data. It's one integration instead of several, and a single dashboard beats stitching multiple ones together later.
{% endhint %}
{% endstep %}
{% endstepper %}

***

### Things to get right the first time

<details>

<summary><strong>A </strong><mark style="color:red;"><strong><code>200</code></strong></mark><strong> response doesn't mean the event was recorded:</strong></summary>

The call is fire-and-forget by design. Reo.dev returns <mark style="color:red;">`200`</mark> before the event is written, not after. If you're testing the integration, check for the event in Reo.dev, not just the response code.

</details>

<details>

<summary><strong>Nothing arrives until your domain is registered as a tenant:</strong></summary>

DNS and TLS being correct isn't enough on its own. If events aren't showing up, this is the first thing to check.

</details>

<details>

<summary><strong>Decide your </strong><mark style="color:red;"><strong><code>activity_type</code></strong></mark><strong> names before you launch:</strong></summary>

They define how your event history gets grouped. Changing a name later doesn't rename the old events, it starts tracking a new one alongside them.

</details>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.reo.dev/integrations/input-sources/api-based-integration/telemetry/unauthenticated-telemetry-events.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
