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

# Report what visitors did in a Workflow, as counts

> Public report of counts for a workflow, sent by the embed. No API key. Each event is one id and a number: a visitor reached a block (`n`), took a connection (`e`), or could not be moved on (`f`). Nothing else is kept: no visitor, no value a visitor typed, no address. A batch carries at most 100 events and 16 KB. The same report may carry `heights`: how tall a step settled at in the browser, which the embed code of the workflow uses to start its box at a real height (a composition, a whole number of pixels, nothing about the visitor).
A report is accepted only with the `token` the workflow's own read handed out for that `versionId`, so a page that never read the workflow cannot raise its numbers. An expired token (`EVENT_TOKEN_EXPIRED`) is refused with 401: read the workflow again for a new one. Counts for ids that are not in that version, or for a workflow that is not live, are not recorded and the answer says so (`recorded: false`) with 200: the visitor's page has nothing to fix.
The body is JSON, sent as `application/json` or as `text/plain` (a "simple" cross-origin request, which is what lets a report leave a page that is being closed).
**Address.** `https://api.widgetic.com/embed/workflows/{workflowId}/events`: the root of the API host, NOT under `/v1`. A client generated from this description for `https://api.widgetic.com/v1` must be given the base address `https://api.widgetic.com` for the calls of the `Public Embed` tag.



## OpenAPI

````yaml /openapi/widgetic-api-public.json post /embed/workflows/{workflowId}/events
openapi: 3.0.0
info:
  title: Widgetic API Gateway
  version: 1.0.0
  description: API documentation for the Widgetic API Gateway
  license:
    name: Widgetic Integration License
    url: https://docs.widgetic.com/resources/license
servers:
  - url: https://api.widgetic.com/v1
    description: Production server
    variables:
      env:
        default: production
        description: Environment
      apiUrl:
        default: https://api.widgetic.com
        description: API URL
      apiVersion:
        default: /v1
        description: API Version path prefix
security: []
tags: []
paths:
  /embed/workflows/{workflowId}/events:
    servers:
      - url: https://api.widgetic.com
        description: >-
          The public embed routes are served at the root of the API host, not
          under /v1.
    post:
      tags:
        - Public Embed
      summary: Report what visitors did in a Workflow, as counts
      description: >-
        Public report of counts for a workflow, sent by the embed. No API key.
        Each event is one id and a number: a visitor reached a block (`n`), took
        a connection (`e`), or could not be moved on (`f`). Nothing else is
        kept: no visitor, no value a visitor typed, no address. A batch carries
        at most 100 events and 16 KB. The same report may carry `heights`: how
        tall a step settled at in the browser, which the embed code of the
        workflow uses to start its box at a real height (a composition, a whole
        number of pixels, nothing about the visitor).

        A report is accepted only with the `token` the workflow's own read
        handed out for that `versionId`, so a page that never read the workflow
        cannot raise its numbers. An expired token (`EVENT_TOKEN_EXPIRED`) is
        refused with 401: read the workflow again for a new one. Counts for ids
        that are not in that version, or for a workflow that is not live, are
        not recorded and the answer says so (`recorded: false`) with 200: the
        visitor's page has nothing to fix.

        The body is JSON, sent as `application/json` or as `text/plain` (a
        "simple" cross-origin request, which is what lets a report leave a page
        that is being closed).

        **Address.**
        `https://api.widgetic.com/embed/workflows/{workflowId}/events`: the root
        of the API host, NOT under `/v1`. A client generated from this
        description for `https://api.widgetic.com/v1` must be given the base
        address `https://api.widgetic.com` for the calls of the `Public Embed`
        tag.
      operationId: reportPublicWorkflowEvents
      parameters:
        - in: path
          name: workflowId
          required: true
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PublicWorkflowEventsRequest'
          text/plain:
            schema:
              type: string
              description: The same JSON, as text.
      responses:
        '200':
          description: Nothing was counted or kept (`recorded` is false, with the reason)
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                  - data
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/PublicWorkflowEventsAccepted'
                  meta:
                    $ref: '#/components/schemas/ResponseMeta'
        '202':
          description: The counts were recorded
          content:
            application/json:
              schema:
                type: object
                required:
                  - success
                  - data
                properties:
                  success:
                    type: boolean
                  data:
                    $ref: '#/components/schemas/PublicWorkflowEventsAccepted'
                  meta:
                    $ref: '#/components/schemas/ResponseMeta'
        '400':
          description: >-
            The body is not what the door reads (`EVENTS_BODY_INVALID`, or a
            field that is not valid)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
        '401':
          description: >-
            The token is missing, wrong, or expired (`EVENT_TOKEN_REQUIRED`,
            `EVENT_TOKEN_INVALID`, `EVENT_TOKEN_EXPIRED`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
        '404':
          description: >-
            The workflow's owner is not being served, so no count is taken
            (`SUSPENDED` for a partner whose agreement is not in force,
            `NOT_FOUND` with the subscription sentence for a plan that lapsed).
            Dropping the counts is fine.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
        '413':
          description: Body too large (`PAYLOAD_TOO_LARGE`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
        '415':
          description: Not JSON or plain text (`UNSUPPORTED_MEDIA_TYPE`)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
        '429':
          description: Rate limited (`RATE_LIMITED`), always with `Retry-After`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
        '503':
          description: >-
            Counts cannot be recorded right now (`EVENT_TOKEN_UNAVAILABLE`, or
            `SERVICE_UNAVAILABLE`). Dropping them is fine.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicEmbedFailure'
components:
  schemas:
    PublicWorkflowEventsRequest:
      type: object
      description: >
        One report from a visitor's browser: counts (`events`), the heights
        steps settled at (`heights`), or both. A report

        with neither is refused.
      required:
        - versionId
        - token
      properties:
        versionId:
          type: string
          format: uuid
        token:
          type: string
          description: The `eventToken` of the workflow, read for the same version.
        events:
          type: array
          maxItems: 100
          description: >-
            The counts of what visitors did. At least one of `events` and
            `heights` is needed.
          items:
            type: object
            required:
              - k
              - id
            properties:
              k:
                type: string
                enum:
                  - 'n'
                  - e
                  - f
                description: >-
                  `n` a visitor reached a block, `e` a visitor took a
                  connection, `f` moving a visitor on failed.
              id:
                type: string
                pattern: ^[A-Za-z0-9_-]{1,64}$
                description: The block or connection counted.
              c:
                type: integer
                minimum: 1
                maximum: 50
                description: How many times (1 when not given).
              r:
                type: string
                enum:
                  - t
                  - e
                  - b
                  - o
                description: >
                  Only on an `f` event: why moving the visitor on failed. `t`
                  the composition did not appear in time,

                  `e` the widget in it reported an error, `b` the composition
                  could not be built, `o` another reason (a

                  step was already on its way, or the page was going away). Left
                  out by an embed that does not say why;

                  a letter this server does not know is read as left out, and
                  the failure is still counted. On an `n` or

                  an `e` event it is ignored. Never a message: one letter, so
                  that nothing a visitor typed can ride on it.
        heights:
          type: array
          maxItems: 10
          description: >
            How tall steps of this version settled in the visitor's browser, so
            that the embed code of the workflow can

            start its box at the height visitors saw instead of a guess. The
            Embed SDK sends one for a visitor who has no

            remembered height for the step. The gateway keeps the latest few for
            each composition (the median is what the

            code gets); a composition that this version does not show is left
            out. At least one of `events` and `heights`

            is needed.
          items:
            type: object
            required:
              - compositionId
              - height
            properties:
              compositionId:
                type: string
                format: uuid
                description: The composition the step shows.
              height:
                type: integer
                minimum: 1
                maximum: 100000
                description: >-
                  The height the step settled at, in pixels. One under 100 is
                  not kept, one over 2000 is kept as 2000.
      example:
        versionId: 3fa85f64-5717-4562-b3fc-2c963f66afa6
        token: Example token
        events: []
        heights: []
    PublicWorkflowEventsAccepted:
      type: object
      required:
        - recorded
      properties:
        recorded:
          type: boolean
          description: >-
            False when nothing was counted or kept (the workflow is not live any
            more, or the ids are not in that version).
        counters:
          type: integer
          description: How many counters were raised (0 for a report of heights alone).
        reason:
          type: string
          description: Why nothing was counted or kept, when `recorded` is false.
      example:
        recorded: true
        counters: 42
        reason: Example reason
    ResponseMeta:
      type: object
      description: >-
        Extra information about the answer: where a page sits in a list, the
        cursor of the next page, or warnings about a call that succeeded with a
        caveat.
      additionalProperties: true
      properties:
        page:
          type: integer
          description: The page that was read, counting from 1.
          example: 1
        size:
          type: integer
          description: How many items one page holds.
          example: 20
        total:
          type: integer
          description: How many items the whole list has.
          example: 135
        limit:
          type: integer
          description: The same as `size`.
          example: 20
        offset:
          type: integer
          description: How many items come before this page.
          example: 0
        hasNextPage:
          type: boolean
          example: true
        hasPreviousPage:
          type: boolean
          example: false
        nextCursor:
          type: string
          nullable: true
          description: >-
            Pass this as `cursor` to read the next page of a list that is read
            by cursor. `null` on the last page.
        warnings:
          type: array
          items:
            type: string
          description: >-
            Things the call did not do, though it succeeded (for example a table
            that could not be created just now).
    PublicEmbedFailure:
      type: object
      required:
        - success
        - message
        - error
        - code
      description: >-
        What a public embed route answers when it refuses or fails. It is the
        standard error answer of the API (`success`, `message`, `error`), and
        the short `code` (with `details` and `correlationId` when the route has
        them) is also at the top level, because a page that embeds a composition
        branches on it there. `error.code` is the same word in the codes of the
        rest of the API where those have it: `NOT_FOUND` is
        `RESOURCE_NOT_FOUND`, `RATE_LIMITED` is `RATE_LIMIT_EXCEEDED`, and the
        others (`DOMAIN_NOT_ALLOWED`, `UNPUBLISHED`, `SUSPENDED`, the codes of
        the entry route) are the same in both places.
      properties:
        success:
          type: boolean
          enum:
            - false
        message:
          type: string
          description: What happened, for a person.
        code:
          type: string
          description: >-
            The short code a page branches on: `DOMAIN_NOT_ALLOWED`,
            `UNPUBLISHED`, `SUSPENDED`, `NOT_FOUND`, `RATE_LIMITED`, and for the
            entry route the codes listed with its answers.
          example: NOT_FOUND
        details:
          type: object
          additionalProperties: true
          description: >-
            What tells the cases of one code apart, such as `reason` of
            `DOMAIN_NOT_ALLOWED`.
          properties:
            reason:
              type: string
              description: For `DOMAIN_NOT_ALLOWED`, why the website was refused.
              enum:
                - domain_not_allowed
                - opaque_origin
            hasDomainsConfigured:
              type: boolean
              description: >-
                For `DOMAIN_NOT_ALLOWED`, always true (an owner who listed
                nothing is never refused).
        correlationId:
          type: string
          description: The id of the request, for the routes that carry it.
        error:
          type: object
          required:
            - code
            - message
            - timestamp
          properties:
            code:
              type: string
              example: RESOURCE_NOT_FOUND
            message:
              type: string
            details:
              type: object
              additionalProperties: true
            correlationId:
              type: string
            retryAfter:
              type: integer
              description: Seconds to wait before asking again, for a rate-limit refusal.
            timestamp:
              type: string
              format: date-time
      example:
        success: true
        message: Example message
        code: NOT_FOUND
        details: {}
        correlationId: Example correlationId
        error: {}

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.