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

# Track a sale

> Track a sale for a short link.

<Note>
  Conversions endpoints require a [Business plan](https://codeqr.io/pricing)
  subscription or higher.
</Note>


## OpenAPI

````yaml post /track/sale
openapi: 3.0.3
info:
  title: CodeQR.io API
  description: >-
    SaaS platform for creating dynamic QR Codes, trackable short links, and
    interactive pages, focused on automation, analytics, and engagement.
  version: 0.0.1
  contact:
    name: CodeQR.io Support
    email: contact@codeqr.io
    url: https://codeqr.io/api
  license:
    name: AGPL-3.0 license
servers:
  - url: https://api.codeqr.io
    description: Production API
security: []
paths:
  /track/sale:
    post:
      tags:
        - Track
      summary: Track a sale
      description: Track a sale for a short link.
      operationId: trackSale
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                customerExternalId:
                  type: string
                  minLength: 1
                  maxLength: 100
                  description: >-
                    The unique ID of the customer in your system. Will be used
                    to identify and attribute all future events to this
                    customer.
                amount:
                  type: integer
                  minimum: 0
                  description: >-
                    The amount of the sale in the smallest unit of `currency` —
                    cents for two-decimal currencies, the full integer for
                    zero-decimal ones (e.g. `1437` JPY), thousandths for
                    three-decimal ones (e.g. `1437` KWD fils).
                currency:
                  type: string
                  default: usd
                  description: >-
                    The currency of the sale, as an ISO 4217 code. Reporting is
                    always in USD: non-USD sales are converted at the exchange
                    rate of the day the sale is recorded, and the original
                    amount and currency are kept on the event. The rate is not
                    re-applied later, so reported totals do not move with the
                    exchange rate.
                eventName:
                  type: string
                  maxLength: 255
                  default: Purchase
                  description: >-
                    The name of the sale event. Recommended format: `Invoice
                    paid` or `Subscription created`.
                  example: Invoice paid
                paymentProcessor:
                  type: string
                  enum:
                    - stripe
                    - shopify
                    - polar
                    - paddle
                    - revenuecat
                    - custom
                    - manual
                  default: custom
                  description: The payment processor via which the sale was made.
                invoiceId:
                  type: string
                  nullable: true
                  default: null
                  description: >-
                    The invoice ID of the sale. Can be used as a idempotency key
                    – only one sale event can be recorded for a given invoice
                    ID.
                metadata:
                  type: object
                  nullable: true
                  additionalProperties: {}
                  default: null
                  description: >-
                    Additional metadata to be stored with the sale event. Max
                    10,000 characters when stringified.
                leadEventName:
                  type: string
                  nullable: true
                  default: null
                  description: >-
                    The name of the lead event that occurred before the sale
                    (case-sensitive). This is used to associate the sale event
                    with a particular lead event (instead of the latest lead
                    event for a link-customer combination, which is the default
                    behavior). For direct sale tracking, this field can also be
                    used to specify the lead event name.
                  example: Cloned template 1481267
                clickId:
                  type: string
                  nullable: true
                  description: >-
                    [For direct sale tracking]: The unique ID of the click that
                    the sale conversion event is attributed to. You can read
                    this value from `cq_id` cookie.
                customerName:
                  type: string
                  nullable: true
                  maxLength: 100
                  default: null
                  description: >-
                    [For direct sale tracking]: The name of the customer. If not
                    passed, a random name will be generated (e.g. “Big Red
                    Caribou”).
                customerEmail:
                  type: string
                  nullable: true
                  format: email
                  maxLength: 100
                  default: null
                  description: >-
                    [For direct sale tracking]: The email address of the
                    customer.
                customerAvatar:
                  type: string
                  nullable: true
                  default: null
                  description: '[For direct sale tracking]: The avatar URL of the customer.'
              required:
                - customerExternalId
                - amount
      responses:
        '200':
          description: A sale was tracked.
          content:
            application/json:
              schema:
                type: object
                properties:
                  eventName:
                    type: string
                  customerId:
                    type: string
                  amount:
                    type: number
                  paymentProcessor:
                    type: string
                  invoiceId:
                    type: string
                    nullable: true
                  currency:
                    type: string
                  metadata:
                    type: object
                    nullable: true
                    additionalProperties: {}
                required:
                  - eventName
                  - customerId
                  - amount
                  - paymentProcessor
                  - invoiceId
                  - currency
                  - metadata
        '400':
          $ref: '#/components/responses/400'
        '401':
          $ref: '#/components/responses/401'
        '403':
          $ref: '#/components/responses/403'
        '404':
          $ref: '#/components/responses/404'
        '409':
          $ref: '#/components/responses/409'
        '410':
          $ref: '#/components/responses/410'
        '422':
          $ref: '#/components/responses/422'
        '429':
          $ref: '#/components/responses/429'
        '500':
          $ref: '#/components/responses/500'
      security:
        - token: []
      x-codeSamples:
        - lang: JavaScript
          source: >-
            import CodeQR from '@codeqr/ts';


            const client = new CodeQR({
              apiKey: process.env['CODEQR_API_KEY'], // This is the default and can be omitted
            });


            const response = await client.track.trackSale({ amount: 0,
            customerExternalId: 'x' });


            console.log(response.amount);
components:
  responses:
    '400':
      description: >-
        The server cannot or will not process the request due to something that
        is perceived to be a client error (e.g., malformed request syntax,
        invalid request message framing, or deceptive request routing).
      content:
        application/json:
          schema:
            x-speakeasy-name-override: BadRequest
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - bad_request
                    description: A short code indicating the error code returned.
                    example: bad_request
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: https://docs.codeqr.io/api-reference/errors#bad-request
                required:
                  - code
                  - message
            required:
              - error
    '401':
      description: >-
        Although the HTTP standard specifies "unauthorized", semantically this
        response means "unauthenticated". That is, the client must authenticate
        itself to get the requested response.
      content:
        application/json:
          schema:
            x-speakeasy-name-override: Unauthorized
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - unauthorized
                    description: A short code indicating the error code returned.
                    example: unauthorized
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: https://docs.codeqr.io/api-reference/errors#unauthorized
                required:
                  - code
                  - message
            required:
              - error
    '403':
      description: >-
        The client does not have access rights to the content; that is, it is
        unauthorized, so the server is refusing to give the requested resource.
        Unlike 401 Unauthorized, the client's identity is known to the server.
      content:
        application/json:
          schema:
            x-speakeasy-name-override: Forbidden
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - forbidden
                    description: A short code indicating the error code returned.
                    example: forbidden
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: https://docs.codeqr.io/api-reference/errors#forbidden
                required:
                  - code
                  - message
            required:
              - error
    '404':
      description: The server cannot find the requested resource.
      content:
        application/json:
          schema:
            x-speakeasy-name-override: NotFound
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - not_found
                    description: A short code indicating the error code returned.
                    example: not_found
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: https://docs.codeqr.io/api-reference/errors#not-found
                required:
                  - code
                  - message
            required:
              - error
    '409':
      description: >-
        This response is sent when a request conflicts with the current state of
        the server.
      content:
        application/json:
          schema:
            x-speakeasy-name-override: Conflict
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - conflict
                    description: A short code indicating the error code returned.
                    example: conflict
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: https://docs.codeqr.io/api-reference/errors#conflict
                required:
                  - code
                  - message
            required:
              - error
    '410':
      description: >-
        This response is sent when the requested content has been permanently
        deleted from server, with no forwarding address.
      content:
        application/json:
          schema:
            x-speakeasy-name-override: InviteExpired
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - invite_expired
                    description: A short code indicating the error code returned.
                    example: invite_expired
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: https://docs.codeqr.io/api-reference/errors#invite-expired
                required:
                  - code
                  - message
            required:
              - error
    '422':
      description: >-
        The request was well-formed but was unable to be followed due to
        semantic errors.
      content:
        application/json:
          schema:
            x-speakeasy-name-override: UnprocessableEntity
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - unprocessable_entity
                    description: A short code indicating the error code returned.
                    example: unprocessable_entity
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: >-
                      https://docs.codeqr.io/api-reference/errors#unprocessable-entity
                required:
                  - code
                  - message
            required:
              - error
    '429':
      description: >-
        The user has sent too many requests in a given amount of time ("rate
        limiting")
      content:
        application/json:
          schema:
            x-speakeasy-name-override: RateLimitExceeded
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - rate_limit_exceeded
                    description: A short code indicating the error code returned.
                    example: rate_limit_exceeded
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: >-
                      https://docs.codeqr.io/api-reference/errors#rate-limit_exceeded
                required:
                  - code
                  - message
            required:
              - error
    '500':
      description: The server has encountered a situation it does not know how to handle.
      content:
        application/json:
          schema:
            x-speakeasy-name-override: InternalServerError
            type: object
            properties:
              error:
                type: object
                properties:
                  code:
                    type: string
                    enum:
                      - internal_server_error
                    description: A short code indicating the error code returned.
                    example: internal_server_error
                  message:
                    x-speakeasy-error-message: true
                    type: string
                    description: A human readable explanation of what went wrong.
                    example: The requested resource was not found.
                  doc_url:
                    type: string
                    description: >-
                      A link to our documentation with more details about this
                      error code
                    example: >-
                      https://docs.codeqr.io/api-reference/errors#internal-server_error
                required:
                  - code
                  - message
            required:
              - error
  securitySchemes:
    token:
      type: http
      description: Default authentication mechanism
      scheme: bearer

````