---
title: Core concepts
description: The vocabulary every other Retidal doc assumes — project, visitor, user, event, session, campaign, and link.
---

Retidal's data model is small; these seven concepts cover the vocabulary the rest of the docs assume you already know.

## Prerequisites

- A Retidal project — see [Quickstart](/docs/quickstart).

## Glossary

- **Project**: the tenant boundary. Every event, key, and Management API path is scoped to one project (`/api/projects/{projectId}/...`).
- **Visitor**: an anonymous identity, `visitorId`, assigned on first contact — the join key for attribution before a user ever authenticates.
- **User**: an authenticated identity, `userId`, associated with a visitor via [Send data](/docs/sending-data/identify)'s identify call.
- **Event**: a named action (`page_view`, `user_paid`, …) with arbitrary `properties`, attributed to a visitor and optionally a user.
- **Session**: a `sessionId` grouping the events of one visit — used for attribution windows and short-link click stitching.
- **Campaign**: the marketing initiative a click or conversion is attributed to, configured and reported on in the console's campaigns section.
- **Link**: a short link (`GET /s/{code}`) that always `302`-redirects and seeds attribution — never a permanent redirect, so the redirect is never cached and attribution is never lost.

## What this unlocks

Knowing this vocabulary unlocks reading [Sending data](/docs/sending-data/events), [Attribution](/docs/attribution/short-links), and [Authentication](/docs/authentication) without re-deriving what a visitor or project scope means each time.

## Verify it worked

Confirm you can identify your own project's scope in a real request:

```bash
curl -s -X POST "https://api.retidal.com/api/v1/t?sync=1" \
  -H "X-API-Key: $RETIDAL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"eventName": "page_view", "visitorId": "vid_abc123"}'
# expect: { "accepted": 1, ..., "processed": true } — processed:true proves
# the event reached storage under your project's scope, not just an async ack
```

## If it doesn't work

If a concept here doesn't match what you're seeing in the console or in API responses, work through the [health checklist](/docs/troubleshooting/health-checklist).
