# Data model (https://webmetic.de/docs/en/api/datenmodell)

For example, Bergquell Mineralbrunnen GmbH visits your website three times this week. In the API, that is one company with three sessions, and each session holds its page views. People don't appear in the visit data.

The API only returns visits that Webmetic matched to a company and leaves out every other visit.

## Visit data [#visit-data]

1. **Your website**: You choose the website in every request with the `domain` parameter.
2. **Session**: Each visit to this website is a session with its own `session_id` and belongs to exactly one company.
3. **Page view**: Each page the visit opened is a page view in the session's `user_data` field.

These IDs connect the objects:

- `domain`: your website as a domain without `https://`, written exactly as in your account. With any other spelling, the API answers with `API_KEY_NOT_AUTHORIZED`. Visits on subdomains such as `shop.your-website.com` count toward `your-website.com`.
- `company_id`: the ID of a company as a string, which stays the same. Don't read meaning into the ID's format, and store `company_url` as a second key alongside it.
- `session_id`: the ID of a visit with 26 characters, which stays the same and sorts by time.
- `client_id`: the pseudonymized visitor ID, which changes daily and differs per account. So it doesn't connect visits across several days.
- Page view: because it has no ID of its own, you recognize it by `session_id` and `timestamp`.

All timestamps are in UTC, without `Z` in API responses and with `Z` in webhook deliveries. For details, see [Date ranges and time zones](https://webmetic.de/docs/en/api/zeitraeume-und-zeitzonen).

## Objects and connections [#objects-and-connections]

| Object | Connected by | Endpoint |
| --- | --- | --- |
| [Company](https://webmetic.de/docs/en/api/datenmodell/company) | `company_id` | [`/company`](https://webmetic.de/docs/en/api/referenz/visitor-intelligence/company), [`/company-sessions`](https://webmetic.de/docs/en/api/referenz/visitor-intelligence/company-sessions) |
| [Session](https://webmetic.de/docs/en/api/datenmodell/session) | `session_id`, plus the company's `company_id` | [`/session`](https://webmetic.de/docs/en/api/referenz/visitor-intelligence/session) |
| [Page View](https://webmetic.de/docs/en/api/datenmodell/page-view) | `session_id`, without `company_id` | [`/session_user_data`](https://webmetic.de/docs/en/api/referenz/visitor-intelligence/session-user-data) |
| NACE code | `nace_codes` list in the company, in `/company_nace` one row per code with `company_id` | [`/company_nace`](https://webmetic.de/docs/en/api/referenz/visitor-intelligence/company-nace) |
| [Visit types](https://webmetic.de/docs/en/api/datenmodell/besuchsarten) | Companies with the matching sessions | [`/intensive-visits`](https://webmetic.de/docs/en/api/referenz/visitor-intelligence/intensive-visits), [`/returning-visits`](https://webmetic.de/docs/en/api/referenz/visitor-intelligence/returning-visits), [`/new-visits`](https://webmetic.de/docs/en/api/referenz/visitor-intelligence/new-visits) |
| [Contact](https://webmetic.de/docs/en/api/datenmodell/contact) | `company_id` in the request, `contact_id` in the response | [`/contacts/search`](https://webmetic.de/docs/en/api/referenz/contacts/search), [`/contacts/reveal`](https://webmetic.de/docs/en/api/referenz/contacts/reveal) |
| [Credits](https://webmetic.de/docs/en/api/datenmodell/credits) | Your account, not the website | [`/contacts/credits`](https://webmetic.de/docs/en/api/referenz/contacts/credits) |
| [Enrichment list](https://webmetic.de/docs/en/api/datenmodell/enrichment-liste) | Only the company's domain | [`/enrichment/lists`](https://webmetic.de/docs/en/api/referenz/enrichment/lists), [`/enrichment/company`](https://webmetic.de/docs/en/api/referenz/enrichment/company) |
| Webhook event | `data.company.company_id` and `data.visit.session_id` | [Webhooks](https://webmetic.de/docs/en/api/webhooks) |

Contacts carry the name of their company but no `company_id`, so store the `company_id` you searched with. The search only works for companies that visited one of your websites. For any other company, the API answers with `COMPANY_NOT_IDENTIFIED`.

A webhook event contains the company in `data.company` and the visit with its page views in `data.visit`. For `segment.entered`, `data.segment` holds the `id` and `label` of a segment from the dashboard. The API doesn't return segments themselves.

## Nested and flat responses [#nested-and-flat-responses]

`/company-sessions` returns each company with its sessions and, inside them, the page views. Its pages count companies, not sessions, as described under [Pagination](https://webmetic.de/docs/en/api/paginierung). `/company`, `/session`, and `/session_user_data` return the same levels one at a time as flat lists.

No endpoint returns a company by its `company_id` or a session by its `session_id`. You always request a website and a date range and then pick from the list.

```bash tab="cURL" tab-group="lang"
curl "https://hub.webmetic.de/company-sessions?domain=your-website.com&page_size=1" \
  -H "Authorization: wmtc_YOUR_API_KEY"
```

```js tab="JavaScript" tab-group="lang"
const res = await fetch(
  'https://hub.webmetic.de/company-sessions?domain=your-website.com&page_size=1',
  { headers: { Authorization: 'wmtc_YOUR_API_KEY' } },
);
const data = await res.json();
console.log(data.result[0].sessions);
```

```python tab="Python" tab-group="lang"
import requests

res = requests.get(
    "https://hub.webmetic.de/company-sessions",
    params={"domain": "your-website.com", "page_size": 1},
    headers={"Authorization": "wmtc_YOUR_API_KEY"},
)
data = res.json()
print(data["result"][0]["sessions"])
```

```json title="Response (shortened)"
{
  "pagination": [
    {
      "total": 32,
      "page_total": 32,
      "isFirst": true,
      "current": 1,
      "isLast": false,
      "page_size": 1
    }
  ],
  "result": [
    {
      "company_id": "41ea486a9c95",
      "company_name": "Bergquell Mineralbrunnen GmbH",
      "company_url": "www.bergquell.example",
      "nace_codes": [
        {
          "code": "11.07",
          "full_code": "C 11.07",
          "description_de": "Herstellung von Erfrischungsgetränken und Mineralwässern",
          "description_en": "Manufacture of soft drinks and bottled waters"
        }
      ],
      "sessions": [
        {
          "session_id": "01M4WQFX6YM2X5V8T4N6R1C0DZ",
          "client_id": "14e382cf709a614559666137b3d1dfcefa99b1e7ecf93400cc9e2cc4822619d3",
          "timestamp": "2026-10-14T08:12:05.214000",
          "weburl": "https://your-website.com",
          "session_duration": 309.0,
          "user_data": [
            {
              "timestamp": "2026-10-14T08:12:05.214000",
              "document_location": "https://your-website.com/pricing",
              "time_spent": 95.0
            }
          ]
        }
      ]
    }
  ]
}
```

The order of the entries is not fixed. Most endpoints leave out a field when its value is unknown. Only the visit types and `data.visit` in webhooks return every field and set unknown values to `null`. When Webmetic couldn't measure a time, the field holds an estimate of a few seconds, which [Page View](https://webmetic.de/docs/en/api/datenmodell/page-view) describes in more detail.

## Domain in visit data and Enrichment [#domain-in-visit-data-and-enrichment]

The `domain` parameter has two meanings in the API:

- **Visit data**: your website, whose visits you request.
- **Enrichment**: the company whose data you retrieve.

The contact endpoints take no domain, only the `company_id`.

Because Enrichment rows carry no `company_id`, you connect the rows to the visit data by domain. In the visit data, `company_url` can start with `www.` or another subdomain. Shorten the value to the domain before you compare, for example `www.bergquell.example` to `bergquell.example`. [Enrichment list](https://webmetic.de/docs/en/api/datenmodell/enrichment-liste) describes how the other fields also differ in Enrichment.

## Keys, plan, and credits [#keys-plan-and-credits]

Which objects you can read depends on the API key, which you send as described under [Authentication](https://webmetic.de/docs/en/api/authentifizierung). Admins find the keys under [**Menu** > **Integrations** > **API**](https://app.webmetic.de/?menu=api_details):

- **Visitor Intelligence**: companies, sessions, page views, contacts, credits, and webhooks.
- **Enrichment**: Enrichment lists, their rows, and the single lookup. New lists, new domains, and single lookups only work during the trial and on the Growth and Enterprise plans.

On the Free plan, the API also returns companies you can't read. These companies carry only their `company_id`, their sessions with times, a placeholder as the name, and `"blurred": true`. For details, see [Plans](https://webmetic.de/docs/en/konto/plaene).

Only `/contacts/reveal` and `/contacts/find` cost credits. Before you search for contacts, complete [Set up contacts](https://webmetic.de/docs/en/ansprechpartner/einrichten) once in the dashboard. Otherwise, the API answers with `CONTACTS_SETUP_REQUIRED`. Enrichment currently costs no credits. For details, see [Credits in the API](https://webmetic.de/docs/en/api/credits).

## Next steps [#next-steps]

- [Company](https://webmetic.de/docs/en/api/datenmodell/company): Every field of a company with its type and an example.
- [Session](https://webmetic.de/docs/en/api/datenmodell/session): When a visit starts and ends, and which fields it carries.
- [Contact](https://webmetic.de/docs/en/api/datenmodell/contact): What a contact looks like before and after you unlock it.
