Skip to main content
The API and the exports use the same model as the management console. Events from your integration are classified into flows, and each flow contains the subflows a user went through. This page describes how that model appears as tables. For the events you send, see the event model reference.

1. How the model fits together

2. Exported tables

Table exports contain 43 tables. They fall into five groups: ob_flow already includes the client environment fields of each flow, so most journey analysis starts there and joins subflows by flow ID. ob_time_series_data holds pre-calculated KPI data. Both this table and ob_time_series_experiment_data export a rolling calendar month ending at the export cutoff, so successive snapshots overlap. For reports that match the console, use time-series exports with the same interval, dimensions and filters. Recalculate from flows and subflows for questions the series do not cover. ob_tracking_password_manager stores one browser-extension detection per session and manager. Its export window uses server-side ingested, when the row was first stored. first_detected_at is the earliest reported client time and can move earlier after a later report; that update does not rewrite an existing export. Accumulated client-environment sightings, including passkey evidence, are available through client environment search and are not a standalone table export. The optional integration_version on ob_tracking_event_batch identifies the web integration revision separately from the SDK version. See integration revision.

3. Types, keys and identifiers

  • IDs: unsigned 64-bit integers. Preserve the full unsigned range. If your platform only supports signed 64-bit integers, use a lossless decimal or string representation and apply it consistently to join keys.
  • Timestamps: UTC with microsecond precision.
  • JSON columns: exported as strings. Parse them in your platform where needed.
  • Nullable columns: exported as nullable fields.
  • Joins: flows reference their session, subflows reference their flow and events map to flows through ob_event_flow.
  • Row grain: newly generated ob_flow and ob_email_link_sub_flow files contain one row per flow or email-link subflow. Older files can repeat a row for each device snapshot in its session; deduplicate by id before counting or joining them. See existing export files for reload guidance.
  • Identifiers and user IDs: initially stored as sent by your integration, in clear text or hashed. Data policies can later hash clear values or delete their references. Use the representation present in each export for joins. See security and privacy.
Identifier submissions are stored in ob_subflow_identifier, one row per subflow step that carried a submitted identifier, with its flow, subflow and session. The value lives in the per-project dictionary ob_identifier, initially with the value and type your integration sent and subject to policy-driven hashing or deletion. linked_user_id on a submission is the identifier-to-user link: it is set only when a completed login in the same flow verified that identifier. See Users and identifiers for the rule and examples across devices and authentication methods.
Inside one Observe project, alice@example.com is recorded as a submitted identifier on Flow F2, which contains a failed password attempt followed by a successful one. The host supplies user_42 as the authenticated user. A separate verified link connects the identifier to that user because the successful password login confirms the entered account. Hashing changes the values while preserving these relationships. Deleting references removes their links while retained journeys remain.Inside one Observe project, alice@example.com is recorded as a submitted identifier on Flow F2, which contains a failed password attempt followed by a successful one. The host supplies user_42 as the authenticated user. A separate verified link connects the identifier to that user because the successful password login confirms the entered account. Hashing changes the values while preserving these relationships. Deleting references removes their links while retained journeys remain.

The submitted identifier records the account targeted; the host's user ID identifies the authenticated user. The identifier-to-user link requires a login that verifies that identifier.

Neither table is part of table exports yet; use identifier search or the user data export. The submitted value is also contained in the raw step event, so it appears in the data column of exported ob_tracking_event rows. Keep these relationships separate when joining authentication data to your customer tables:
  • Attempt lookup: A submitted identifier finds attempts against that account, including attempts by an unknown person.
  • User activity: Use the flow’s user reference and authentication outcome to distinguish authenticated activity from attempts that merely named an account.
  • Expanded lookup: An established identifier-to-user link can make other attempts discoverable. Preserve that match reason; do not replace an attempt’s user reference with the user reached through the link.
  • Join cardinality: One flow can contain several submissions, and one identifier can have several user links. Preserve individual submissions for investigation and deduplicate flow IDs when counting journeys.
Use matching identifier types, normalization and hashing on both sides of a join. Equal values in different namespaces are not ownership evidence. Hashing preserves these relationships; deleting identifier or user ID references removes the corresponding links. Exports are snapshots: a file downloaded before hashing or deletion can still contain the earlier values. Apply your own retention rules to copies in your platform.

4. Time columns

Each table is exported by its own time column. Subflows use their start time, flows their creation time and events their event time. A journey that starts shortly before midnight can therefore have rows in two export dates. Join across the relevant export dates rather than assuming all related rows share one date. A one-day lookback can cover a midnight boundary, but is not a completeness guarantee for late events or reclassification. Tags and user references also have their own export time columns, which can use server ingestion time.

5. Re-classification and snapshots

Observe classifies a session a few minutes after its last event and classifies it again when later events arrive, for example when a user returns to the same session. An exported day is a snapshot of that day at export time. Classification changes after the export are not reflected in files that were already written. Agree the historical regeneration and reload process when your warehouse must reflect these corrections; downloading an unchanged snapshot again does not refresh its contents.

6. Schema changes

The export schema follows the data model and grows as Observe adds fields. Configure your loader to accept new columns rather than failing on them, and write transformations that select the columns they need instead of relying on column order.

Exports

Schedules, formats and how to download exports.

Connect your data platform

Loading pattern and platform notes.