> ## Documentation Index
> Fetch the complete documentation index at: https://docs.corbado.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Create new events

> Ingests events from your backend using an API key. For browser and native collection, use the
[Observe SDKs](/sdks/overview) and their separate project-scoped transport.

### Server-side enrichment

Attach a user reference or tags, such as a risk or bot verdict, to a flow without sending them
through the browser. Target a flow by event ID or temporal matching; authenticated enrichment
allows a symmetric 10-second matching tolerance.

A request accepts at most 2,000 events and low-level events combined.

Required API key permission: `observe:events:write`.



## OpenAPI

````yaml /api-reference/openapi/observe.yaml post /observe/events
openapi: 3.1.1
info:
  version: 1.0.0
  title: Corbado API
  description: >
    # Introduction

    This documentation gives an overview of all Corbado API calls to implement
    authentication observe.
  contact:
    name: Corbado team
    email: support@corbado.com
    url: https://www.corbado.com
servers:
  - url: https://api.cloud.corbado.io/v1
security:
  - bearerAuth: []
tags:
  - name: ObserveFlow
    description: Flow search and related APIs
    x-group: Journeys and users
  - name: ObserveSubFlow
    description: Subflow search and related APIs
    x-group: Journeys and users
  - name: ObserveUser
    description: User search and related APIs
    x-group: Journeys and users
  - name: ObserveClientEnv
    description: Client environment search APIs
    x-group: Journeys and users
  - name: ObserveTimeSeries
    description: Time series query APIs
    x-group: Metrics and funnels
  - name: ObserveFunnel
    description: Historical funnel metrics, dictionaries and coverage.
    x-group: Metrics and funnels
  - name: ObserveEvent
    description: Event ingestion and event feed APIs
    x-group: Events
  - name: ObserveError
    description: Named authentication errors and recommendations.
    x-group: Error management
  - name: ObserveErrorFlavour
    description: Error variants and their impact on authentication outcomes.
    x-group: Error management
  - name: ObserveAlert
    description: Authentication alert rules, instances and history.
    x-group: Alert management
  - name: ObserveAnnotation
    description: Annotation APIs (dated notes for analytics context)
    x-group: Annotations
  - name: ObserveTableExport
    description: Table export file listing and download APIs
    x-group: Data exports
  - name: ObserveTimeSeriesExport
    description: Time-series export generation and downloads.
    x-group: Data exports
  - name: ObserveDataExport
    description: Data export APIs
    x-group: User data
  - name: ObserveDataDeletionJob
    description: Data deletion job APIs
    x-group: User data
  - name: ObserveFlowTypeDefinition
    description: Flow type definitions used in authentication journeys.
    x-group: Catalogs and labels
  - name: ObserveCatalog
    description: Catalog APIs
    x-group: Catalogs and labels
  - name: OpenAPI
    description: Downloadable API specification
  - name: ProjectOperationExecution
    description: Project-scoped operation history and pipeline health
  - name: ObserveClassification
    description: Flow and subflow classification APIs
  - name: ObserveIntegrationStats
    description: Integration stats APIs
  - name: ObserveTimeSeriesPrecalculation
    description: Time series precalculation APIs
  - name: ObserveIDList
    x-group: Saved ID lists
    description: Stored ID-list selection APIs
  - name: ObserveDataContext
    description: Schema-loose data context APIs for agent and debugging tooling
  - name: ObserveData
    description: Observe data administration APIs
  - name: ObserveTrackingStats
    description: Tracking ingestion stats APIs
  - name: ObserveExperiment
    x-group: Experiments
    description: Experiment catalog and run APIs
  - name: ObserveDataPolicy
    description: >-
      Project data policy catalogue (retention selected by the SDK's
      meta.dataPolicy code)
  - name: ObserveMetadata
    x-group: Metadata
    description: Authenticator metadata APIs (FIDO MDS + passkey AAGUID)
  - name: ObservePasskey
    x-group: Passkey analysis
    description: Observed passkey search and cohort analysis.
paths:
  /observe/events:
    post:
      tags:
        - ObserveEvent
      summary: Create new events
      description: >-
        Ingests events from your backend using an API key. For browser and
        native collection, use the

        [Observe SDKs](/sdks/overview) and their separate project-scoped
        transport.


        ### Server-side enrichment


        Attach a user reference or tags, such as a risk or bot verdict, to a
        flow without sending them

        through the browser. Target a flow by event ID or temporal matching;
        authenticated enrichment

        allows a symmetric 10-second matching tolerance.


        A request accepts at most 2,000 events and low-level events combined.


        Required API key permission: `observe:events:write`.
      operationId: ObserveEventCreateAuthenticated
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/observeEventCreateReq'
      responses:
        '200':
          description: >-
            SDK reliability configuration (returned only when the
            X-Corbado-Observe-Config header is set). The shape depends on the
            requesting SDK: web SDKs receive observeEventCreateRes, native app
            SDKs (request `sdk.name` observe-android/observe-ios) receive the
            app-specific observeSdkConfigApp.
          content:
            application/json:
              schema:
                oneOf:
                  - $ref: '#/components/schemas/observeEventCreateRes'
                  - $ref: '#/components/schemas/observeSdkConfigApp'
        '204':
          $ref: '#/components/responses/204'
        default:
          $ref: '#/components/responses/error'
      security:
        - bearerAuth:
            - observe:events:write
components:
  schemas:
    observeEventCreateReq:
      type: object
      required:
        - sessionID
        - events
      properties:
        deliveryAck:
          type: boolean
          description: >-
            Request synchronous durable ingestion. Only a committed request
            returns X-Corbado-Observe-Accepted=1; temporary persistence failures
            return 503. Legacy delivery is unchanged.
        sessionID:
          type: string
          description: Session ID for the events (UUID format)
          example: 550e8400-e29b-41d4-a716-446655440000
          x-oapi-codegen-extra-tags:
            validate: required,uuid
        events:
          type: array
          description: >-
            Array of events to create. The combined number of events and lows
            must be at least 1 and at most 2000.
          items:
            $ref: '#/components/schemas/observeEvent'
          x-oapi-codegen-extra-tags:
            validate: max=2000,dive
        lows:
          type: array
          description: >-
            Array of low-level events to create. The combined number of events
            and lows must be at least 1 and at most 2000.
          items:
            $ref: '#/components/schemas/observeLow'
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=2000,dive
        telemetry:
          type: array
          description: >
            Diagnostic telemetry entries (SDK/integration-side messages, not
            auth-flow events). They ride along

            with the normal event batch, are tied to the same session, and never
            participate in flow

            classification. A batch may carry telemetry only (no events/lows).
            Capped at 2000 per batch.
          items:
            $ref: '#/components/schemas/observeTelemetry'
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=2000,dive
        meta:
          $ref: '#/components/schemas/observeEventMetaSession'
        sdk:
          $ref: '#/components/schemas/observeSdkInfo'
    observeEventCreateRes:
      type: object
      description: >
        SDK reliability configuration. Returned from the event ingestion
        endpoints only when the client opts in

        by sending the `X-Corbado-Observe-Config` request header carrying the
        config version the client is

        currently running (or `1` when it has none cached). When the sent
        version matches the current one the

        endpoints return `204 No Content` (nothing new); without the header they
        always return `204`, so this is

        a fully backwards-compatible addition. The SDK applies a received config
        on its next page load

        (boot-snapshot model) and stamps the version it ran under into each
        batch's `meta.configVersion`.
      required:
        - version
        - flushIntervalMs
        - durableOutbox
        - durableLowOutbox
        - beaconKeepalive
        - sessionContinuity
        - sessionInactivityMs
        - seqLockTimeoutMs
        - tvc
        - tph
        - td
        - telemetry
        - rawErrors
        - flushOnTelemetry
        - flushOnEventNames
        - flushOnFlowTypeFinished
        - deviceInfoCollectorTimeoutMs
        - deviceInfoTiming
        - aap
        - sourcePathQuery
        - sourcePathQueryAllow
        - retry
      properties:
        version:
          type: string
          description: >
            Content-derived version (hash) of this configuration. Changes
            whenever any value changes. The SDK

            caches it, echoes it in the `X-Corbado-Observe-Config` request
            header, and stamps it into

            `meta.configVersion` of every event batch so analyses can segment by
            the config actually in effect.
          example: 3f2a1b9c0d4e
        flushIntervalMs:
          type: integer
          format: int32
          description: How often the SDK should flush its event queue, in milliseconds.
          example: 500
        durableLowOutbox:
          type: boolean
          description: >-
            Persist lows in a separate bounded outbox and require durable server
            acknowledgement. Default false.
        durableOutbox:
          type: boolean
          description: >-
            Whether the SDK should persist queued events to a durable outbox so
            they survive reloads, redirects and browser-context switches.
        beaconKeepalive:
          type: boolean
          description: >-
            Whether the SDK should use keepalive/sendBeacon transport for
            flushes triggered during page unload.
        sessionContinuity:
          type: boolean
          description: >-
            Whether the SDK should maintain session continuity across
            browser-context switches (e.g. in-app browser to system browser).
        sessionInactivityMs:
          type: integer
          format: int32
          description: >
            Inactivity threshold for continuity sessions, in milliseconds. When
            more time than this has

            passed since the last tracked activity, the SDK rotates to a new
            session id on the next load.

            Only relevant when `sessionContinuity` is enabled.
          example: 1800000
        seqLockTimeoutMs:
          type: integer
          format: int32
          description: >
            Maximum time to wait for the cross-tab sequence Web Lock before
            allocating without it,

            in milliseconds. Clamped to 0–100ms. 0 is a sentinel that disables
            the lock: the SDK then

            allocates the sequence counter without requesting a lock at all,
            giving up cross-tab

            atomicity (two tabs can allocate the same seq) to save a lock
            round-trip per event.
          example: 5
        tvc:
          type: boolean
          description: >
            Flush-trigger switch: flush pending events when the document becomes
            hidden (`visibilitychange`).

            Default true; the SDK treats a missing value as true, so delivery
            can never be disabled by accident.
        tph:
          type: boolean
          description: >-
            Flush-trigger switch: flush pending events on `pagehide`
            (navigation/close). Default true.
        td:
          type: boolean
          description: >-
            Flush-trigger switch: flush pending events when the integrator calls
            `destroy()`. Default true.
        rawErrors:
          type: boolean
          default: true
          description: >
            Enables serialization of explicitly supplied raw error diagnostics
            into stepData.rawError.

            Server default is true; an explicit false disables diagnostics.
            Normalized errors

            are always reported independently. SDK built-in defaults may differ
            (Android defaults off). SDKs apply this using their normal config
            lifecycle;

            disabling affects newly captured diagnostics, not events already
            queued.
        telemetry:
          type: boolean
          description: >
            Master switch for the diagnostic telemetry stream. When true the SDK
            sends buffered telemetry

            entries (`observeTelemetry`) piggybacked on normal event requests;
            when false it collects nothing

            and sends nothing. Lets telemetry be turned off server-side without
            a customer redeploy.
        flushOnTelemetry:
          type: boolean
          description: >
            When true (and `telemetry` is enabled), enqueuing a telemetry entry
            triggers an immediate client

            flush so diagnostics go out promptly (e.g. before a
            crash/navigation). Default false: a telemetry

            entry alone never triggers a flush, it only rides the next flush
            caused by anything else.
        flushOnEventNames:
          type: array
          description: >
            Superseded by `flushOnFlowTypeFinished`; served only for SDK
            versions that predate it (they

            ignore the new field, newer SDKs ignore this one). Event names that
            trigger an immediate

            client-side flush when enqueued (e.g. `flow_finished`,
            `conversion`), so high-value events go

            out while the page is still alive instead of relying on unload
            delivery. Empty = no priority

            events. Capped at 20 names (both sides).
          items:
            type: string
          example:
            - flow_finished
            - conversion
        flushOnFlowTypeFinished:
          type: array
          description: >
            Flow types whose completion triggers an immediate client-side flush
            when enqueued, so the

            highest-value events go out while the page is still alive instead of
            relying on unload

            delivery. Both completion events count — `flow_finished` and
            `flow_auto_finished` — matched

            on their `flowName`; no other event name ever flushes early. Empty =
            no priority flows.

            Capped at 20 entries (both sides). Replaces `flushOnEventNames`,
            which SDKs from the version

            that introduced this field on no longer read.
          items:
            type: string
          example:
            - login
            - enrollment
        deviceInfoCollectorTimeoutMs:
          type: integer
          format: int32
          description: >
            Per-field timeout for the SDK's device info collection, in
            milliseconds. A browser API that does

            not answer within this budget is recorded as a timeout in the
            event's device info collection

            errors and the field stays empty; the other fields are unaffected.
            Clamped to 10–10000ms.

            The SDK reads it per collection run, so a new value takes effect
            from the next device info

            refresh; the first collection of a load without a cached config runs
            on the built-in default.
          example: 1000
        deviceInfoTiming:
          type: boolean
          description: >
            When true (and `telemetry` is enabled), every device info collection
            emits an `info` telemetry

            entry carrying the total duration and each field's duration in
            milliseconds. Default false —

            a diagnostic stream to switch on while investigating slow
            collection, not for permanent use.

            Durations of fields that hit `deviceInfoCollectorTimeoutMs` are
            censored at that value.
        aap:
          type: string
          description: >
            Capability policy token for Corbado frontend SDKs and adapters.
            Values are assigned by

            Corbado per project and select how a capability behaves for that
            project; an SDK that does

            not implement the token it receives ignores it and keeps its
            standard behavior. Empty (the

            default) always means standard behavior. Capped at 16 characters — a
            longer value is served

            as empty.
          example: c1
        sourcePathQuery:
          type: string
          description: >
            Which query values the SDK includes in the page URL it reports as
            `meta.trackingSourcePath`:

            `allowlist` (the default) or `all`. `allowlist` keeps every query
            key and its position but

            replaces each value with `*` unless its key is listed in
            `sourcePathQueryAllow` (empty by

            default, so every value is masked); empty values and keys without a
            value stay as they are.

            `all` sends the query unchanged. The path itself is never changed.
            Any value other than `all`

            (including unset or empty) is served as `allowlist`. Server-side
            email/phone redaction still

            applies to whatever is sent.
          example: allowlist
        sourcePathQueryAllow:
          type: array
          description: >
            Query keys whose values are kept when `sourcePathQuery` is
            `allowlist`. Matched

            case-insensitively and exactly; a trailing `*` matches a key prefix
            (`utm_*`). Empty or

            oversized entries (more than 64 characters) are dropped and the list
            is capped at 50 entries

            (both sides). Empty by default. Ignored in `all` mode.
          items:
            type: string
          example:
            - utm_*
            - section
        retry:
          $ref: '#/components/schemas/observeEventCreateResRetry'
    observeSdkConfigApp:
      type: object
      description: >
        SDK reliability configuration for native app SDKs
        (observe-android/observe-ios). Served from the

        config GET endpoint when `sdkName` names a native SDK, or from event
        ingestion instead of

        observeEventCreateRes when the request's `sdk.name` names a native SDK.
        Contains only native fields —

        web-only flags (beaconKeepalive, seqLockTimeoutMs, tvc/tph/tlf,
        durableOutbox, sessionContinuity)

        never appear. Config GET always returns the current policy and
        content-hash version. Legacy ingestion

        uses the `X-Corbado-Observe-Config` request header and returns 204 when
        the version is current.
      required:
        - version
        - flushIntervalMs
        - sessionInactivityMs
        - telemetry
        - rawErrors
        - flushOnTelemetry
        - flushOnFlowTypeFinished
        - deviceInfoCollectorTimeoutMs
        - flushOnBackground
        - retry
      properties:
        version:
          type: string
          description: >-
            Content-derived version (hash); echoed by the SDK in the request
            header.
        flushIntervalMs:
          type: integer
          format: int32
          description: >-
            How often the SDK flushes its event queue, in milliseconds. Native
            default is 2000 (battery/radio frugality).
        sessionInactivityMs:
          type: integer
          format: int32
          description: >-
            Inactivity threshold after which the session id rotates, in
            milliseconds.
        rawErrors:
          type: boolean
          default: true
          description: >
            Enables serialization of explicitly supplied raw error diagnostics
            into stepData.rawError.

            Server default is true; an explicit false disables diagnostics.
            Normalized errors

            are always reported independently. SDK built-in defaults may differ
            (Android defaults off). SDKs apply this using their normal config
            lifecycle;

            disabling affects newly captured diagnostics, not events already
            queued.
        telemetry:
          type: boolean
          description: Master switch for the diagnostic telemetry stream.
        flushOnTelemetry:
          type: boolean
          description: >-
            When true (and telemetry is enabled), enqueuing a telemetry entry
            triggers an immediate flush.
        flushOnFlowTypeFinished:
          type: array
          items:
            type: string
          description: >-
            Flow types whose completion (flow_finished/flow_auto_finished)
            triggers an immediate flush.
        deviceInfoCollectorTimeoutMs:
          type: integer
          format: int32
          description: Per-field timeout for device info collection, in milliseconds.
        flushOnBackground:
          type: boolean
          description: >-
            Native flush-trigger switch: flush pending events when the app
            leaves the foreground (the last reliable delivery moment before a
            potential process kill). Defaults to true; a missing value can never
            disable delivery.
        retry:
          $ref: '#/components/schemas/observeEventCreateResRetry'
    observeEvent:
      type: object
      additionalProperties: true
      required:
        - type
        - name
        - timestamp
      properties:
        id:
          type: string
          description: >-
            Client-generated unique event ID (UUID) used for idempotent
            ingestion. When provided, the backend deduplicates events with the
            same id within the same session, so safe client retries do not
            create duplicates. Optional for backwards compatibility.
          example: 550e8400-e29b-41d4-a716-446655440000
          x-oapi-codegen-extra-tags:
            validate: omitempty,uuid
        type:
          $ref: '#/components/schemas/observeEventType'
        name:
          type: string
          description: >-
            Name of the event. `flow_enriched` carries a user reference and/or
            tags and is accepted on both unauthenticated and authenticated
            endpoints. Its optional `data` section selects the matching flow and
            controls tag expansion: Explicit targeting uses `{ targetEventId:
            "<client event UUID>" }` and enriches the flows that directly own
            that event in the same project and session, including completed
            flows: every flow a `flow_started` opened, the flow a
            `flow_finished` finished, or the flow of one of its subflow steps —
            never a nested flow's event and never another enrichment — so an
            integration can enrich a flow from the page that finished it.
            `flowStartedEventId` is deprecated: it remains accepted as an alias
            of `targetEventId` for SDKs that predate it, and both may be sent
            together only with the same UUID. Explicit targeting is mutually
            exclusive with `match`; it never falls back to temporal matching,
            advances flow duration, or establishes identity for unrelated later
            flows. Delivery order does not matter once both events are available
            to classification. Without an explicit target, temporal targeting
            uses `{ match: { flowType?: string, at?: "started" | "finished" |
            "during" }, expCh?: boolean, expFol?: boolean }` — defaults
            `flowType` login, `at` finished, `expCh`/`expFol` true. The explicit
            `flowType` value `*` accepts any flow type; omission retains the
            login default. `started` and `finished` select the nearest
            qualifying start or finish; `during` selects the innermost matching
            flow at the event time. Temporal unauthenticated enrichments require
            a flow started or explicitly continued in the emitting session
            before the enrichment and still open when it is emitted. Timestamp
            and sequence determine emission order; delivery time does not affect
            ownership. Matching has no grace period, and these references cannot
            identify earlier flows through late or future-reference fallback.
            Sequences must be non-negative. Authenticated enrichment retains a
            symmetric 10-second matching tolerance. `expCh` and `expFol` control
            tag expansion to child and following flows; user identity propagates
            forward independently. An unmatched enrichment has no flow
            association and its tags are dropped, while its reference remains
            available for forward propagation. The legacy alias
            `session_enriched` remains accepted; on the unauthenticated endpoint
            its `data` must remain empty for compatibility. User references on
            other events remain supported.
          enum:
            - flow_started
            - flow_finished
            - flow_reset
            - flow_decided
            - flow_auto_finished
            - auth_method_decision_started
            - auth_method_decision_finished
            - auth_decision_started
            - auth_decision_finished
            - subflow_started
            - subflow_step_started
            - subflow_step_finished
            - subflow_step_error
            - subflow_trigger
            - subflow_spacer
            - subflow_error
            - conversion
            - session_enriched
            - flow_enriched
          example: flow_started
          x-oapi-codegen-extra-tags:
            validate: >-
              required,oneof=flow_started flow_finished flow_reset flow_decided
              flow_auto_finished auth_method_decision_started
              auth_method_decision_finished auth_decision_started
              auth_decision_finished subflow_started subflow_step_started
              subflow_step_finished subflow_step_error subflow_trigger
              subflow_spacer subflow_error conversion session_enriched
              flow_enriched
        timestamp:
          type: integer
          format: int64
          description: >-
            Unix timestamp of when the event was created (in milliseconds
            elapsed since January 1, 1970, 00:00:00 UTC)
          example: 1752738240000
          x-oapi-codegen-extra-tags:
            validate: required
        data:
          type: object
          description: Additional event data (arbitrary JSON)
          additionalProperties: true
        meta:
          $ref: '#/components/schemas/observeEventMetaEvent'
        deviceInfo:
          $ref: '#/components/schemas/observeDevicesInfo'
        user:
          $ref: '#/components/schemas/observeUserReference'
        tags:
          type: object
          additionalProperties:
            type: string
        experiments:
          type: object
          description: >
            Experiment assignments active for this event, as a map of experiment
            key to variant value (e.g. {"button_color": "blue"}). First-class,
            prefix-free representation of A/B-test exposure; the backend
            attributes the flow to these. The SDK sends the full active set on
            every event, so the latest change is the complete truth.
          additionalProperties:
            type: string
        seq:
          type: integer
          description: >
            Sequence number to order events within the same session (must be
            strictly increasing for each subsequent event in the same session).
            It belongs to the SDK's counter, so a server sending events into a
            browser session does not share it: on the authenticated endpoint the
            value is moved into negative space at ingest, where it orders that
            sender's own events only and is excluded from gap detection. Send -1
            (or any negative value, which is stored unchanged) to state
            explicitly that the event carries no sequence information. Never try
            to force sort order with an out-of-band positive value such as
            100000 — relative to the client's counter it means "everything in
            between was lost in transit".
    observeLow:
      required:
        - lowType
        - ts
      properties:
        captureSeq:
          type: integer
          format: int64
          minimum: 0
          maximum: 4294967295
          description: >-
            Unsigned per-page capture order, reserved at observation start and
            retained through retries. Zero or missing means unavailable.
          x-oapi-codegen-extra-tags:
            validate: omitempty,min=0,max=4294967295
        captureVersion:
          type: integer
          format: int32
          description: Capture contract version. Missing means legacy v0.
          x-oapi-codegen-extra-tags:
            validate: omitempty,min=0,max=255
        pageId:
          type: string
          description: Document capture UUID, retained through retries.
          x-oapi-codegen-extra-tags:
            validate: omitempty,uuid
        initiator:
          type: string
          description: Semantic initiating control when observed; unknown otherwise.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=32
        id:
          type: string
          description: Immutable client low-event UUID for retry deduplication.
          x-oapi-codegen-extra-tags:
            validate: omitempty,uuid
        subflowStartEventId:
          type: string
          description: >-
            Client UUID of the owning subflow_started, scoped to this project
            and session.
          x-oapi-codegen-extra-tags:
            validate: omitempty,uuid
        sourceKind:
          type: string
          description: Capture source category. Unknown future values are stored as NULL.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=32
        fieldRole:
          type: string
          description: >-
            Logical field role (password, identifier, otp, data). Unknown values
            are stored as NULL.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=32
        inputEffect:
          type: string
          description: >-
            Observed value effect (fill, modify, clear); unknown values are
            ignored.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=32
        lowType:
          type: string
        ts:
          type: integer
          format: int64
        durationMs:
          type: integer
          format: int64
        fieldType:
          type: string
          description: >-
            Semantic field the low relates to, named by subflow-type vocabulary
            (e.g. provide-identifier, password-login). Native SDK extension;
            free-form on the wire — the backend stores known values and drops
            unknown ones.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=64
        actor:
          type: string
          description: >-
            Who caused the observed effect, when known (password-manager, app).
            Native SDK extension; free-form on the wire — the backend stores
            known values and drops unknown ones.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=64
    observeTelemetry:
      type: object
      description: >
        A single diagnostic telemetry entry (a level + free-form message) tied
        to the batch's session.

        Used for SDK/integration-side diagnostics; it is never classified as an
        auth-flow event.
      required:
        - level
        - message
        - ts
      properties:
        id:
          type: string
          description: >-
            Client-generated idempotency id (uuidv7). Lets safe resends
            (retry/beacon/outbox) dedupe server-side.
          x-oapi-codegen-extra-tags:
            validate: omitempty,uuid
        level:
          type: string
          description: Severity of the telemetry message.
          enum:
            - info
            - error
          x-oapi-codegen-extra-tags:
            validate: required,oneof=info error
        message:
          type: string
          description: >-
            Free-form diagnostic message. Truncated server-side. Must not
            contain credentials or PII.
          x-oapi-codegen-extra-tags:
            validate: required,max=1000
        ts:
          type: integer
          format: int64
          description: >-
            Client capture time (unix ms). Corrected against batch send time
            like low events.
          x-oapi-codegen-extra-tags:
            validate: required
    observeEventMetaSession:
      type: object
      required:
        - sent
        - transport
      properties:
        sent:
          type: integer
          format: int64
        transport:
          type: string
          description: Transport used by the client to send events
        flushReason:
          type: string
          description: >-
            What triggered the flush this batch was sent in (timer, backoff,
            recovery, flow-finished, telemetry, visibility-change, pagehide,
            low-event-teardown, destroy, manual). Deliberately not an enum: a
            newer SDK must never have its batch rejected for reporting a trigger
            this backend does not know yet. Absent for legacy SDKs.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=32
        configVersion:
          type: string
          description: >-
            Version of the SDK reliability configuration the client was running
            when it captured this batch. Absent for legacy SDKs or when no
            config was cached yet.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=64
        retryCount:
          type: integer
          format: int32
          description: >-
            Number of prior failed delivery attempts for this batch; absent on
            the first attempt.
          x-oapi-codegen-extra-tags:
            validate: omitempty,min=0
        dataPolicy:
          type: integer
          format: int32
          description: >
            Project-scoped data policy code (0..255) the tracker is running
            under, as set through the SDK's

            `setDataPolicy(code)` / `init({ dataPolicy })`. Sent on every batch
            once known, including an

            explicit 0; absent for legacy SDKs and before the first call. Codes
            are opaque project-scoped

            selectors of the project's data policies (0 = default). Stored as-is
            on the batch and copied onto

            the session (last write wins); never validated at ingestion (unknown
            codes are reported by

            classification).
          x-oapi-codegen-extra-tags:
            validate: omitempty,min=0,max=255
    observeSdkInfo:
      type: object
      description: >-
        Identity of the SDK that produced the batch. Clients have always sent
        this; it is declared here so the backend can branch on it (e.g. serve
        the app-specific reliability config to native SDKs). Optional for
        backwards compatibility.
      required:
        - name
        - version
      properties:
        name:
          type: string
          description: SDK wire name, e.g. "@corbado/observe" (web) or "observe-android".
          x-oapi-codegen-extra-tags:
            validate: max=64
        version:
          type: string
          description: SDK version, e.g. "0.2.0".
          x-oapi-codegen-extra-tags:
            validate: max=32
    observeEventCreateResRetry:
      type: object
      description: >-
        Client-side retry configuration (exponential backoff) for failed event
        flushes.
      required:
        - maxAttempts
        - baseDelayMs
        - maxDelayMs
      properties:
        maxAttempts:
          type: integer
          format: int32
          description: Maximum number of send attempts, including the first one.
          example: 5
        baseDelayMs:
          type: integer
          format: int32
          description: Base delay for exponential backoff, in milliseconds.
          example: 500
        maxDelayMs:
          type: integer
          format: int32
          description: Maximum backoff delay between attempts, in milliseconds.
          example: 15000
    errorRspV2:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - message
          properties:
            message:
              description: Error message
              type: string
              example: Validation failed
            details:
              description: Validation error details per field
              type: array
              items:
                type: object
                required:
                  - field
                  - message
                properties:
                  field:
                    description: Field name that failed validation
                    type: string
                    example: projectID
                  message:
                    description: Validation error message
                    type: string
                    example: required
    observeEventType:
      type: string
      description: Type of the tracking event
      enum:
        - predefined
        - custom
      x-oapi-codegen-extra-tags:
        validate: oneof=predefined custom
    observeEventMetaEvent:
      type: object
      properties:
        captureVersion:
          type: integer
          format: int32
          description: Capture contract version. Missing means legacy v0.
          x-oapi-codegen-extra-tags:
            validate: omitempty,min=0,max=255
        pageId:
          type: string
          description: Document capture UUID, retained through retries.
          x-oapi-codegen-extra-tags:
            validate: omitempty,uuid
        initiator:
          type: string
          description: Semantic initiating control when observed; unknown otherwise.
          x-oapi-codegen-extra-tags:
            validate: omitempty,max=32
        subflowStartEventId:
          type: string
          description: >-
            Client UUID of the owning start event; preserved on each step event
            through retries.
          x-oapi-codegen-extra-tags:
            validate: omitempty,uuid
        trackingSourcePath:
          type: string
          description: >-
            Tracking source path of the event including query string ("where"
            was this event created). Web SDKs send it (page path); native app
            SDKs send the host-provided screen name and omit the field when no
            screen is set. The backend stores it ONCE PER BATCH — on the first
            event of the batch that reports one; later events of the batch are
            stored without it and resolve the batch's path on read — so an SDK
            may omit it on all but the first event of a batch. Email addresses
            and phone numbers are redacted before storage.
        tabId:
          type: string
          description: >
            Per-tab id (sessionStorage-scoped) of the tab that CREATED this
            event, stamped at track() time. Distinguishes tabs that share one
            localStorage-backed session; late-flushed events keep the tab they
            originated in, regardless of which page delivers them. Native app
            SDKs send their per-process id here on every event (the
            process-incarnation marker used for stream splitting and seq
            disambiguation).
    observeDevicesInfo:
      type: object
      required:
        - type
        - clientEnvHandle
        - clientEnvHandleMeta
      properties:
        type:
          type: string
          enum:
            - web
            - app
        clientEnvHandle:
          type: string
        clientEnvHandleMeta:
          $ref: '#/components/schemas/observeClientEnvHandleMeta'
        tabId:
          type: string
          description: >-
            Per-tab id (sessionStorage-scoped) distinguishing tabs that share
            one localStorage-backed session.
        data:
          oneOf:
            - $ref: '#/components/schemas/observeDeviceInfoWeb'
            - $ref: '#/components/schemas/observeDeviceInfoApp'
        collectionErrors:
          type: array
          items:
            $ref: '#/components/schemas/observeDeviceInfoCollectionError'
    observeUserReference:
      type: object
      properties:
        userId:
          type: string
          description: User ID
        identifier:
          type: string
          description: User identifier (e.g. email)
        crossEnvironmentTransactionIDStart:
          type: string
          description: >-
            Cross-environment transaction ID used to correlate events across
            sessions/devices
        crossEnvironmentTransactionIDFinish:
          type: string
          description: >-
            Cross-environment transaction ID used to correlate events across
            sessions/devices
        crossEnvironmentTransactionID:
          type: string
          description: >-
            Generic transaction ID that links any sessions sharing the same
            value so they are classified together (independent of subflow type)
    observeClientEnvHandleMeta:
      type: object
      required:
        - ts
        - source
      properties:
        ts:
          type: integer
          format: int64
        source:
          type: string
          enum:
            - ls
            - cookie
            - storage
    observeDeviceInfoWeb:
      type: object
      properties:
        bluetoothAvailable:
          type: boolean
        userVerifyingPlatformAuthenticatorAvailable:
          type: boolean
        conditionalMediationAvailable:
          type: boolean
        javaScriptHighEntropy:
          $ref: '#/components/schemas/observeJavaScriptHighEntropy'
        webDriver:
          type: boolean
        privateMode:
          type: boolean
        clientCapabilities:
          type: object
          additionalProperties:
            type: string
        maxTouchPoints:
          type: integer
          description: >-
            navigator.maxTouchPoints, the maximum number of simultaneous touch
            contact points. Stored raw. Values outside 0-255 are ignored.
    observeDeviceInfoApp:
      type: object
      required:
        - osName
        - osVersion
      properties:
        osName:
          type: string
        osVersion:
          type: string
        model:
          type: string
          description: >-
            Device model (e.g. "iPhone15,3", "Pixel 8"). Optional; older SDKs
            omit it.
        brand:
          type: string
          description: >-
            Device manufacturer/brand (e.g. "Apple", "Google"). Optional; older
            SDKs omit it.
        appName:
          type: string
          description: >-
            Host application name (e.g. "Acme Banking"). Optional; older SDKs
            omit it.
        appVersion:
          type: string
          description: >-
            Host application version (e.g. "3.2.1"). Optional; older SDKs omit
            it.
        deviceOwnerAuth:
          type: string
          enum:
            - none
            - code
            - bio-face
            - bio-touch
            - bio-strong
            - bio-weak
            - bio
          description: >-
            Device owner authentication / screen-lock method. iOS reports
            bio-face/bio-touch, Android reports bio-strong/bio-weak, bio is a
            catch-all for other biometrics. Optional; older SDKs omit it.
        isBluetoothAvailable:
          type: boolean
          description: >-
            Whether Bluetooth is available on the device. Optional; older SDKs
            omit it.
        androidGooglePlayServicesVersion:
          type: string
          description: >-
            Google Play Services version (Android only; null on iOS). Optional;
            older SDKs omit it.
        locale:
          type: string
          description: Device locale (BCP-47, e.g. "en-US"). Optional; older SDKs omit it.
        screen:
          $ref: '#/components/schemas/observeAppScreen'
    observeDeviceInfoCollectionError:
      type: object
      required:
        - field
        - source
        - error
      properties:
        field:
          type: string
          enum:
            - bluetoothAvailable
            - conditionalMediationAvailable
            - userVerifyingPlatformAuthenticatorAvailable
            - clientCapabilities
            - javaScriptHighEntropy
            - privateMode
            - webdriver
            - maxTouchPoints
        source:
          type: string
        error:
          $ref: '#/components/schemas/observeDeviceInfoCollectionErrorDetail'
    observeJavaScriptHighEntropy:
      type: object
      required:
        - platform
        - platformVersion
        - mobile
      properties:
        platform:
          type: string
        platformVersion:
          type: string
        mobile:
          type: boolean
        model:
          type: string
          description: >-
            Device model from the UA-CH model hint (only populated on Android
            browsers).
    observeAppScreen:
      type: object
      description: >-
        Native app screen geometry in logical points plus the backing scale
        factor.
      properties:
        widthPoints:
          type: number
          format: float
        heightPoints:
          type: number
          format: float
        scale:
          type: number
          format: float
    observeDeviceInfoCollectionErrorDetail:
      type: object
      required:
        - message
      properties:
        name:
          type: string
        message:
          type: string
  responses:
    '204':
      description: Operation succeeded without content
    error:
      description: Error
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/errorRspV2'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Use an Observe API key from the management console. The key selects the
        project and must grant the permission listed on the operation. Keep this
        key on your server.

````