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

# Record a browser-side conversion (fallback)

> Reports a sale from the browser, for a cart integration that cannot post server-to-server. No token is required or checked; the endpoint is public, CORS-enabled, and rate-limited per IP instead.

This is a fallback, not a replacement for a real integration postback. Every row it writes is stamped unverified: it is excluded from revenue, EPC, RPV, ROAS, and every other aggregate that only counts server-confirmed sales, and it never fires ad-platform pixels or CRM webhooks. If the same order later arrives through the integration's real postback, the two collapse into one row and the verified postback always wins, regardless of which arrived first.

The integration named in `integration` must have the browser conversion fallback turned on for this workspace, or the call is rejected. Turn it on in TrackPlay under that integration's settings.

Server: `https://e.trackplay.io`



## OpenAPI

````yaml /api-reference/openapi.json post /v1/conversion
openapi: 3.1.0
info:
  title: TrackPlay API
  description: >-
    Send conversions and events to TrackPlay, and read them back. Authenticated
    with scoped tokens you mint in the dashboard.
  version: 1.0.0
servers:
  - url: https://app.trackplay.io/api/v1
    description: App API. Conversions, videos, webhooks.
  - url: https://e.trackplay.io
    description: Events API. High-volume event ingest.
security:
  - bearerAuth: []
tags:
  - name: Videos
    description: Create, read, update, and delete videos, and read workspace metadata.
  - name: Video settings
    description: Save a settings draft, publish it live, and read or restore past deploys.
  - name: Uploads
    description: >-
      Upload a source video file in one request or in resumable chunks, and poll
      its processing status.
  - name: Captions and chapters
    description: >-
      Manage caption tracks, chapter markers, AI-generated segments, and CTA
      cards on a video.
  - name: Playlists
    description: Group videos into a playlist or course, and manage the videos inside it.
  - name: Webhooks
    description: Subscribe a URL to TrackPlay lifecycle events and test deliveries.
  - name: Zapier
    description: >-
      The REST-hook endpoints Zapier calls to connect a workspace and manage
      triggers.
  - name: Analytics
    description: Read play, retention, event, and conversion analytics for a video.
  - name: Exports
    description: Queue and download bulk analytics exports.
  - name: Conversions
    description: Report a sale or a lead, from your own server or from a browser fallback.
  - name: Events
    description: Send a custom event tied to a viewer's session.
  - name: Identity
    description: Resolve a viewer's identity from the page, with no token required.
paths:
  /v1/conversion:
    post:
      tags:
        - Conversions
      summary: Record a browser-side conversion (fallback)
      description: >-
        Reports a sale from the browser, for a cart integration that cannot post
        server-to-server. No token is required or checked; the endpoint is
        public, CORS-enabled, and rate-limited per IP instead.


        This is a fallback, not a replacement for a real integration postback.
        Every row it writes is stamped unverified: it is excluded from revenue,
        EPC, RPV, ROAS, and every other aggregate that only counts
        server-confirmed sales, and it never fires ad-platform pixels or CRM
        webhooks. If the same order later arrives through the integration's real
        postback, the two collapse into one row and the verified postback always
        wins, regardless of which arrived first.


        The integration named in `integration` must have the browser conversion
        fallback turned on for this workspace, or the call is rejected. Turn it
        on in TrackPlay under that integration's settings.


        Server: `https://e.trackplay.io`
      operationId: browserConversion
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BrowserConversionRequest'
            examples:
              sale:
                summary: A sale from a thank-you page
                value:
                  workspace_code: WS123
                  integration: clickbank
                  order_id: ORDER-9001
                  value: 97
                  currency: USD
                  session_id: 3b1e5c90-77aa-4f2d-8c31-6de0a9b41c22
                  customer_email: buyer@example.com
      responses:
        '200':
          description: Recorded as an unverified, browser-sourced conversion.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BrowserConversionResponse'
        '400':
          description: >-
            `INVALID_PAYLOAD`: a field failed validation, or the body carried a
            field outside the schema.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventError'
        '403':
          description: >-
            `FALLBACK_DISABLED`: the browser conversion fallback is not turned
            on for this integration in this workspace.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventError'
        '404':
          description: >-
            `INTEGRATION_NOT_FOUND`: no integration named `integration` is
            configured for this workspace.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventError'
        '429':
          description: Rate limited. 60 requests per minute per IP by default.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventError'
              examples:
                limited:
                  value:
                    error: Too many requests
        '500':
          description: >-
            `WRITE_FAILED`: the conversion could not be written. Retry the call:
            `order_id` keeps the retry from double-counting the sale.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventError'
        '503':
          description: >-
            `UNAVAILABLE`: the integration lookup is temporarily unreachable.
            This is never a rejection of your payload. Retry shortly.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/EventError'
      security: []
      servers:
        - url: https://e.trackplay.io
components:
  schemas:
    BrowserConversionRequest:
      type: object
      additionalProperties: false
      required:
        - workspace_code
        - integration
        - order_id
        - value
      properties:
        workspace_code:
          type: string
          maxLength: 100
          description: Your workspace's public code. Required.
        integration:
          type: string
          maxLength: 60
          description: >-
            Which cart integration this fallback backs, e.g. `clickbank`.
            Required. The integration must have the browser conversion fallback
            turned on for this workspace, or the call is rejected.
        order_id:
          type: string
          maxLength: 190
          description: >-
            Your order ID. Required. This is the dedup key: a server-to-server
            postback for the same integration and order collapses into the same
            row, and the server-confirmed row always wins.
        value:
          type: number
          minimum: 0
          description: The sale amount. Required.
        currency:
          type: string
          maxLength: 3
          default: USD
        conversion_type:
          type: string
          maxLength: 40
          default: purchase
        is_test:
          type: boolean
          default: false
        session_id:
          type: string
          maxLength: 100
          description: >-
            The player session that produced the sale, if you have it. Used to
            attribute the conversion and to pick up the session's video if
            `video_code` is omitted.
        device_id:
          type: string
          maxLength: 100
        video_code:
          type: string
          maxLength: 100
          description: Wins over the session's last video when both are available.
        customer_email:
          type: string
          maxLength: 255
        customer_phone:
          type: string
          maxLength: 64
        customer_name:
          type: string
          maxLength: 255
        product_name:
          type: string
          maxLength: 255
        product_code:
          type: string
          maxLength: 190
        properties:
          type: object
          additionalProperties: true
          description: Extra key/value pairs to keep with the conversion.
      description: >-
        Every row this endpoint writes is stamped `conversion_source: browser`
        and `verified: false`. It never feeds the revenue, EPC, RPV, or ROAS
        numbers your dashboard treats as real: those only count `verified` rows.
        It also never fires ad-platform pixels or CRM webhooks, because an
        unverified sale must not reach a customer's ad account as a confirmed
        Purchase event. Use this only as a fallback for a cart that cannot post
        server-to-server; prefer the real integration postback or `POST
        /conversions` wherever you can reach either one.
    BrowserConversionResponse:
      type: object
      properties:
        ok:
          type: boolean
        id:
          type: string
          description: The conversion's dedup ID, `<integration>:<order_id>`.
        conversion_source:
          type: string
          examples:
            - browser
        verified:
          type: boolean
          examples:
            - false
        attributed:
          type: boolean
          description: True when `session_id` resolved to a known session.
    EventError:
      type: object
      properties:
        error:
          type: string
          description: A stable error code, e.g. `INSUFFICIENT_SCOPE`.
        message:
          type: string
          description: What went wrong, in plain English.
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        A scoped token minted in **Settings → API tokens**. Send it as
        `Authorization: Bearer tplt_…` or `X-API-Key: tplt_…`.

````

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