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

# Track an event

> Records a behavior event for a user. Unseen users are created; an unknown event name registers a definition on first use; built-in Usertour event names are refused.



## OpenAPI

````yaml /api-reference-v2/openapi.json post /v2/projects/{projectId}/environments/{environmentId}/events
openapi: 3.0.0
info:
  title: Usertour API v2
  description: >-
    Project-scoped v2 API. Authenticate with a personal API token — an opaque
    `utp_...` string (NOT a JWT: do not try to decode it), created in the
    Usertour app under Settings → API, sent as `Authorization: Bearer utp_...`.
  version: '2.0'
  contact: {}
servers:
  - url: https://api.usertour.io
security: []
tags: []
paths:
  /v2/projects/{projectId}/environments/{environmentId}/events:
    post:
      tags:
        - Events
      summary: Track an event
      description: >-
        Records a behavior event for a user. Unseen users are created; an
        unknown event name registers a definition on first use; built-in
        Usertour event names are refused.
      operationId: ApiEventsController_track
      parameters:
        - name: environmentId
          required: true
          in: path
          description: Environment ID
          schema: {}
        - name: projectId
          required: true
          in: path
          description: Project ID
          schema: {}
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TrackEventBodyDto'
      responses:
        '201':
          description: The recorded event
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventDto'
        '400':
          description: >-
            Invalid request — E1017 validation (may carry `issues`; an invalid
            orderBy/limit is also E1017), E1015 invalid scope, E0003 invalid
            against current domain state.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '401':
          description: Missing or expired API key — E1010, E1020.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '403':
          description: >-
            Refused — E1000 invalid key, E1011 project not in token scope, E1012
            insufficient scope, E1029 environment not in token scope, E1032
            environment creation needs a token without env-targeted capabilities
            (its allowlist cannot cover a not-yet-existing environment), E0043
            the project's plan does not include the feature (e.g. webhooks
            require a paid plan on cloud).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
        '429':
          description: >-
            Rate limit exceeded — E1013. The limit follows the project's plan
            (100/500/1000/3000 requests per minute); unknown credentials share a
            per-IP bucket. Every response also carries X-RateLimit-Limit /
            -Remaining / -Reset for pacing; a 429 adds the standard Retry-After
            header (seconds to back off).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponseDto'
      security:
        - bearer: []
components:
  schemas:
    TrackEventBodyDto:
      type: object
      properties:
        userId:
          type: string
          minLength: 1
          maxLength: 200
          description: >-
            The user's external ID — the same value passed to
            usertour.identify(). Unseen users are created.
        companyId:
          description: >-
            External ID of the company to associate the event with. Must already
            exist — an unknown id records the event without the association.
          type: string
          minLength: 1
          maxLength: 200
        name:
          type: string
          minLength: 2
          maxLength: 100
          pattern: ^[a-zA-Z][a-zA-Z0-9_]*$
          description: >-
            The event code name. An unknown name creates the event definition on
            first use; built-in Usertour event names are refused.
        attributes:
          description: >-
            Event attribute values. Unknown attribute names register on the
            event definition automatically.
          type: object
          additionalProperties: {}
        occurredAt:
          description: When the event actually happened (ISO 8601); defaults to now.
          type: string
          format: date-time
          pattern: >-
            ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d(?::[0-5]\d(?:\.\d+)?)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
      required:
        - userId
        - name
      additionalProperties: false
    EventDto:
      type: object
      properties:
        id:
          type: string
        object:
          type: string
          enum:
            - event
        codeName:
          type: string
        eventDefinitionId:
          type: string
        createdAt:
          type: string
        userId:
          type: string
        companyId:
          type: string
          nullable: true
        sessionId:
          type: string
          nullable: true
        contentId:
          type: string
          nullable: true
        versionId:
          type: string
          nullable: true
        attributes:
          type: object
          additionalProperties: {}
      required:
        - id
        - object
        - codeName
        - eventDefinitionId
        - createdAt
        - userId
        - companyId
        - sessionId
        - contentId
        - versionId
        - attributes
    ErrorResponseDto:
      type: object
      properties:
        error:
          type: object
          properties:
            code:
              type: string
              description: >-
                Stable machine-readable code (e.g. E1017). Match on this, never
                on `message`.
            message:
              type: string
              description: Human-readable summary. Wording may change between releases.
            issues:
              description: >-
                Validation errors (E1017) may carry one entry per problem so
                every field can be fixed in a single round-trip. Absent on other
                errors.
              type: array
              items:
                type: object
                properties:
                  rule:
                    type: string
                    description: >-
                      Which validation layer rejected it: schema |
                      reactive_condition | action_not_allowed | step_shape |
                      reference_target | auto_start | media_url. New values may
                      be added; treat an unknown value as a generic validation
                      failure.
                  message:
                    type: string
                  path:
                    description: >-
                      Path into the request body (e.g.
                      `steps[0].triggers[0].when[1]`).
                    type: string
                required:
                  - rule
                  - message
            doc_url:
              type: string
              description: Base URL of the API documentation.
      required:
        - error
  securitySchemes:
    bearer:
      scheme: bearer
      bearerFormat: utp_... personal API token (opaque)
      type: http

````