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

# Submit a conversion event

> Accepts a consent-aware server-side conversion event. Supply either event_id in the JSON body or Idempotency-Key in the request headers to make retries idempotent.



## OpenAPI

````yaml https://plainrouter.com/openapi.json post /events
openapi: 3.1.0
info:
  title: PlainRouter Conversion API
  version: 0.5.0
  description: PlainRouter public Signals Conversion API.
servers:
  - url: https://plainrouter.com/api/v1
    description: Production
security:
  - signalTrackerSecret: []
paths:
  /events:
    post:
      tags:
        - Event
      summary: Submit a conversion event
      description: >-
        Accepts a consent-aware server-side conversion event. Supply either
        event_id in the JSON body or Idempotency-Key in the request headers to
        make retries idempotent.
      operationId: createEvent
      parameters:
        - name: Idempotency-Key
          in: header
          description: >-
            Optional idempotency key. When event_id is omitted, PlainRouter uses
            this value as event_id. If both are supplied, they must match.
          schema:
            type: string
      requestBody:
        required: true
        content:
          application/json:
            schema:
              anyOf:
                - type: object
                  properties:
                    event_id:
                      type: string
                      description: Caller-supplied idempotency key; maximum 128 characters.
                    event_name:
                      type: string
                      description: Signal event name; maximum 100 characters.
                    parent_event_id:
                      type: string
                      description: Optional parent event id; maximum 128 characters.
                    event_time:
                      description: >-
                        Unix timestamp or ISO-8601 date-time. Defaults to
                        receipt time.
                      anyOf:
                        - type: integer
                        - type: string
                    event_source:
                      type: string
                      format: uri
                      description: Optional absolute source URL.
                    action_source:
                      type: string
                      description: >-
                        Optional action source; defaults to website and is
                        limited to 50 characters.
                    visitor_id:
                      type: string
                      description: Optional visitor identifier; maximum 255 characters.
                    consent_basis:
                      type: string
                      description: >-
                        Legal basis for processing. Legitimate-interest revenue
                        lifecycle events are rejected; use an authenticated
                        server adapter.
                      const: consent
                    consent:
                      type: object
                      description: Consent state supplied with the event.
                      additionalProperties: {}
                    consent_mode:
                      type: object
                      description: Consent Mode v2 signal values supplied with the event.
                      additionalProperties: {}
                    tcf:
                      type: object
                      description: TCF v2 data containing string and optional captured_at.
                      additionalProperties: {}
                    user_data:
                      type: object
                      description: Identity fields accepted by the tracker.
                      additionalProperties: {}
                    click_ids:
                      type: object
                      description: Advertising click identifiers.
                      additionalProperties: {}
                    value_data:
                      type: object
                      description: >-
                        Optional commerce data. Contents accepts at most 50
                        items and 16 KB serialized.
                      properties:
                        value:
                          type: string
                        currency:
                          type: string
                        order_id:
                          type: string
                        contents:
                          type: array
                          items: {}
                        num_items:
                          type: integer
                  required:
                    - event_name
                    - consent_basis
                - type: object
                  properties:
                    event_id:
                      type: string
                      description: Caller-supplied idempotency key; maximum 128 characters.
                    event_name:
                      type: string
                      description: Signal event name; maximum 100 characters.
                      enum:
                        - signal_verification
                        - consent_withdrawal
                    parent_event_id:
                      type: string
                      description: Optional parent event id; maximum 128 characters.
                    event_time:
                      description: >-
                        Unix timestamp or ISO-8601 date-time. Defaults to
                        receipt time.
                      anyOf:
                        - type: integer
                        - type: string
                    event_source:
                      type: string
                      format: uri
                      description: Optional absolute source URL.
                    action_source:
                      type: string
                      description: >-
                        Optional action source; defaults to website and is
                        limited to 50 characters.
                    visitor_id:
                      type: string
                      description: Optional visitor identifier; maximum 255 characters.
                    consent_basis:
                      type: string
                      description: >-
                        Legal basis for processing. Legitimate-interest revenue
                        lifecycle events are rejected; use an authenticated
                        server adapter.
                      const: legitimate_interest
                    consent:
                      type: object
                      description: Consent state supplied with the event.
                      additionalProperties: {}
                    consent_mode:
                      type: object
                      description: Consent Mode v2 signal values supplied with the event.
                      additionalProperties: {}
                    tcf:
                      type: object
                      description: TCF v2 data containing string and optional captured_at.
                      additionalProperties: {}
                    user_data:
                      type: object
                      description: Identity fields accepted by the tracker.
                      additionalProperties: {}
                    click_ids:
                      type: object
                      description: Advertising click identifiers.
                      additionalProperties: {}
                    value_data:
                      type: object
                      description: >-
                        Optional commerce data. Contents accepts at most 50
                        items and 16 KB serialized.
                      properties:
                        value:
                          type: string
                        currency:
                          type: string
                        order_id:
                          type: string
                        contents:
                          type: array
                          items: {}
                        num_items:
                          type: integer
                  required:
                    - event_name
                    - consent_basis
      responses:
        '200':
          description: Duplicate event accepted idempotently.
          content:
            application/json:
              schema:
                type: object
                properties:
                  event_id:
                    type: string
                  duplicate:
                    type: boolean
                required:
                  - event_id
                  - duplicate
          headers:
            Location:
              description: Canonical event resource to poll for delivery state.
              schema:
                type: string
                format: uri
            Idempotency-Key:
              description: Echoes the Idempotency-Key supplied by the caller.
              schema:
                type: string
        '202':
          description: New event accepted for processing.
          content:
            application/json:
              schema:
                type: object
                properties:
                  event_id:
                    type: string
                  duplicate:
                    type: boolean
                required:
                  - event_id
                  - duplicate
          headers:
            Location:
              description: Canonical event resource to poll for delivery state.
              schema:
                type: string
                format: uri
            Idempotency-Key:
              description: Echoes the Idempotency-Key supplied by the caller.
              schema:
                type: string
        '401':
          description: Invalid or missing Signal tracker secret.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorMessage'
        '422':
          description: Request validation failed.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ValidationError'
components:
  schemas:
    ErrorMessage:
      type: object
      properties:
        message:
          type: string
      required:
        - message
      title: ErrorMessage
    ValidationError:
      type: object
      properties:
        message:
          type: string
        errors:
          type: object
          additionalProperties:
            type: array
            items:
              type: string
      required:
        - message
        - errors
      title: ValidationError
  securitySchemes:
    signalTrackerSecret:
      type: http
      description: >-
        Per-tracker bearer secret. It authenticates only the Signal tracker
        represented by the credential.
      scheme: bearer

````