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

# Track a lead

> Record an idempotent server-side lead and attribute it to a Biqli click.

Use this endpoint from a trusted server when a customer signs up, submits a
qualified form, starts a trial, or completes another lead event.

## Authentication and permission

Send a secret `biqli_...` workspace API key with **Conversions: Write**
(`conversions.create`). Do not use a browser publishable key or call this
endpoint from frontend code.

```http theme={null}
Authorization: Bearer biqli_your_workspace_api_key
Content-Type: application/json
Accept: application/json
```

The key selects the workspace. Do not send a workspace ID. Server tracking does
not use browser origins or the allowed-hostname list.

## Request

```bash theme={null}
curl --request POST \
  --url https://biq.li/api/v1/track/lead \
  --header "Authorization: Bearer $BIQLI_API_KEY" \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --header 'Idempotency-Key: lead_signup_customer_1842' \
  --header 'X-Biq-Client: acme-backend' \
  --header 'X-Biq-Client-Version: 1.4.0' \
  --data '{
    "clickId": "fGQimsCLcpoa",
    "eventId": "lead_signup_customer_1842",
    "eventName": "Signed up",
    "customerExternalId": "customer_1842",
    "customerName": "Ada Lovelace",
    "customerEmail": "ada@example.com",
    "eventQuantity": 1,
    "metadata": {
      "plan": "pro"
    },
    "occurredAt": "2026-09-12T22:35:02Z"
  }'
```

| Field                | Required    | Description                                                                                                                               |
| :------------------- | :---------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
| `clickId`            | Conditional | Biqli click ID from `bq_id` or client click tracking. You may omit it only when this workspace customer already has eligible attribution. |
| `eventName`          | Yes         | Lead name, from 1 to 255 characters.                                                                                                      |
| `customerExternalId` | Yes         | Stable customer ID from your system, from 1 to 100 characters.                                                                            |
| `customerName`       | No          | Customer display name, up to 255 characters.                                                                                              |
| `customerEmail`      | No          | Valid customer email, up to 254 characters.                                                                                               |
| `customerAvatar`     | No          | HTTP or HTTPS avatar URL, up to 2,048 characters.                                                                                         |
| `eventId`            | No          | Stable event identifier. Use 1 to 100 safe identifier characters.                                                                         |
| `eventQuantity`      | No          | Positive integer from 1 to 100. Defaults to `1`.                                                                                          |
| `metadata`           | No          | JSON object, up to 16 KB, 50 keys, 100 values, and five nested levels. Keys contain 1 to 64 characters and cannot be numeric-only.        |
| `occurredAt`         | No          | ISO 8601 event time. It must be within seven days in the past and five minutes in the future.                                             |

The attributed click must be active, unexpired, and belong to the API key's
workspace. A click from another workspace returns `404 resource_not_found`.

## Idempotency

Send a stable `Idempotency-Key` on every retry. Also send a stable `eventId`
when your system has one. Repeating the same identifier and payload returns the
original `201` response with `Idempotency-Replayed: true` and creates no new
event, realtime update, or webhook delivery.

Reusing an idempotency or event identifier with different data returns
`409 idempotency_conflict`. Idempotency records are retained for seven days;
the event identifier remains durably unique within its workspace and source.

## Response

```json theme={null}
{
  "event": {
    "id": "biq_lev_01M2BW50V1MJDD4KPZ394GXGC5",
    "eventName": "Signed up",
    "type": "lead",
    "occurredAt": "2026-09-12T22:35:02+00:00"
  },
  "click": {"id": "fGQimsCLcpoa"},
  "link": {
    "id": "biq_lnk_01M2BVVED2HDH0JVM5HV9WQ2F6",
    "shortUrl": "https://biq.li/3bKxigL",
    "destinationUrl": "https://example.com/signup"
  },
  "customer": {
    "id": "biq_cus_01M2BW50TQD96C0QPCM6Z6WZNF",
    "externalId": "customer_1842",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "avatar": null
  },
  "request_id": "8259fc91-99f4-4f96-bfc0-1be9c208a91e"
}
```

The response uses public IDs only. Deleted links continue to resolve through
their preserved conversion snapshot.

## Errors

| Status | Code                   | Meaning                                                                           |
| :----- | :--------------------- | :-------------------------------------------------------------------------------- |
| `401`  | `invalid_token`        | The workspace API key is missing, invalid, revoked, or the wrong credential type. |
| `403`  | `insufficient_scope`   | The key lacks `conversions.create`.                                               |
| `403`  | `tracking_disabled`    | Conversion tracking is unavailable or disabled for the workspace.                 |
| `404`  | `resource_not_found`   | The click is expired, missing, or belongs to another workspace.                   |
| `405`  | `method_not_allowed`   | This endpoint only accepts `POST`.                                                |
| `409`  | `idempotency_conflict` | An idempotency or event identifier was reused with different data.                |
| `422`  | `attribution_required` | Neither a valid `clickId` nor existing customer attribution was available.        |
| `422`  | `validation_error`     | The JSON body, fields, metadata, or event time is invalid.                        |
| `429`  | `rate_limit_exceeded`  | The workspace exceeded its API request allowance.                                 |

Authentication, errors, rate-limit headers, and request IDs follow the shared
[API conventions](/docs/api-reference/introduction).


## OpenAPI

````yaml POST /v1/track/lead
openapi: 3.1.0
info:
  title: Biqli API
  version: 1.0.0
  description: Workspace-scoped REST API for Biqli.
servers:
  - url: https://biq.li/api
security:
  - bearerAuth: []
paths:
  /v1/track/lead:
    post:
      tags:
        - Conversions
      summary: Track a lead
      description: >-
        Records a server-side lead against a redirect or client click. Requires
        conversions.create.
      operationId: tracking.lead
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/ApiClient'
        - $ref: '#/components/parameters/ApiClientVersion'
        - $ref: '#/components/parameters/RequestId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/TrackLeadRequest'
      responses:
        '201':
          description: Lead created or idempotently replayed.
          headers:
            X-Biq-Request-Id:
              $ref: '#/components/headers/RequestId'
            Idempotency-Replayed:
              $ref: '#/components/headers/IdempotencyReplayed'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/TrackEventResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  parameters:
    IdempotencyKey:
      name: Idempotency-Key
      in: header
      required: false
      description: Stable retry key. Reuse only for the same logical request and payload.
      schema:
        type: string
        minLength: 1
        maxLength: 255
    ApiClient:
      name: X-Biq-Client
      in: header
      required: false
      description: Integration name recorded in API diagnostics.
      schema:
        type: string
        maxLength: 64
    ApiClientVersion:
      name: X-Biq-Client-Version
      in: header
      required: false
      description: Integration version recorded in API diagnostics.
      schema:
        type: string
        maxLength: 64
    RequestId:
      name: X-Biq-Request-Id
      in: header
      required: false
      description: Caller-generated request identifier for tracing.
      schema:
        type: string
        minLength: 1
        maxLength: 100
        pattern: ^[A-Za-z0-9._:-]+$
  schemas:
    TrackLeadRequest:
      type: object
      additionalProperties: false
      required:
        - eventName
        - customerExternalId
      properties:
        clickId:
          type:
            - string
            - 'null'
          minLength: 1
          maxLength: 100
          pattern: ^[A-Za-z0-9_-]+$
        eventName:
          type: string
          minLength: 1
          maxLength: 255
        customerExternalId:
          type: string
          minLength: 1
          maxLength: 100
        customerName:
          type:
            - string
            - 'null'
          maxLength: 255
        customerEmail:
          type:
            - string
            - 'null'
          format: email
          maxLength: 254
        customerAvatar:
          type:
            - string
            - 'null'
          format: uri
          pattern: ^https?://
          maxLength: 2048
        eventId:
          type:
            - string
            - 'null'
          minLength: 1
          maxLength: 100
          pattern: ^[A-Za-z0-9](?:[A-Za-z0-9._:-]*[A-Za-z0-9])?$
        eventQuantity:
          type:
            - integer
            - 'null'
          minimum: 1
          maximum: 100
          default: 1
        metadata:
          type:
            - object
            - 'null'
          maxProperties: 50
          propertyNames:
            pattern: ^(?=.*[^0-9])[^\u0000-\u001F\u007F]{1,64}$
          additionalProperties: true
        occurredAt:
          type:
            - string
            - 'null'
          format: date-time
          pattern: Z$
    TrackEventResponse:
      type: object
      required:
        - event
        - click
        - link
        - customer
        - request_id
      properties:
        event:
          $ref: '#/components/schemas/TrackEvent'
        click:
          $ref: '#/components/schemas/TrackClickReference'
        link:
          $ref: '#/components/schemas/TrackLinkReference'
        customer:
          $ref: '#/components/schemas/TrackCustomer'
        request_id:
          type: string
    TrackEvent:
      type: object
      required:
        - id
        - eventName
        - type
        - occurredAt
      properties:
        id:
          type: string
          pattern: ^biq_(?:lev|sev)_[0-9A-HJKMNP-TV-Z]{26}$
        eventName:
          type: string
        type:
          type: string
          enum:
            - lead
            - sale
        occurredAt:
          type: string
          format: date-time
    TrackClickReference:
      type: object
      required:
        - id
      properties:
        id:
          type: string
    TrackLinkReference:
      type:
        - object
        - 'null'
      properties:
        id:
          type:
            - string
            - 'null'
          pattern: ^biq_lnk_[0-9A-HJKMNP-TV-Z]{26}$
        shortUrl:
          type:
            - string
            - 'null'
          format: uri
        destinationUrl:
          type:
            - string
            - 'null'
          format: uri
    TrackCustomer:
      type: object
      required:
        - id
        - externalId
        - name
        - email
        - avatar
      properties:
        id:
          type:
            - string
            - 'null'
          pattern: ^biq_cus_[0-9A-HJKMNP-TV-Z]{26}$
        externalId:
          type:
            - string
            - 'null'
        name:
          type:
            - string
            - 'null'
        email:
          type:
            - string
            - 'null'
          format: email
        avatar:
          type:
            - string
            - 'null'
          format: uri
    ApiError:
      type: object
      required:
        - error
        - request_id
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              enum:
                - invalid_token
                - insufficient_scope
                - upgrade_required
                - quota_exceeded
                - resource_not_found
                - tracking_disabled
                - attribution_required
                - currency_unavailable
                - idempotency_conflict
                - domain_taken
                - alias_taken
                - external_id_taken
                - folder_name_taken
                - tag_name_taken
                - pixel_name_taken
                - biolink_name_taken
                - method_not_allowed
                - url_blocked
                - dns_verification_failed
                - validation_error
                - rate_limit_exceeded
                - internal_server_error
            message:
              type: string
            details:
              type: object
              additionalProperties: true
        request_id:
          type: string
          description: Request identifier to include when contacting support.
  headers:
    RequestId:
      description: Request identifier for tracing and support.
      schema:
        type: string
    IdempotencyReplayed:
      description: Present with value true when the original successful result is replayed.
      schema:
        type: string
        const: 'true'
  responses:
    Unauthorized:
      $ref: '#/components/responses/ApiErrorResponse'
      description: The workspace API key is missing, invalid, or revoked.
    Forbidden:
      $ref: '#/components/responses/ApiErrorResponse'
      description: >-
        The key lacks a required scope, the workspace must upgrade, or its quota
        is exhausted.
    NotFound:
      $ref: '#/components/responses/ApiErrorResponse'
      description: >-
        The requested resource or referenced public ID is unavailable in the
        key's workspace.
    MethodNotAllowed:
      description: The endpoint does not support the requested HTTP method.
      headers:
        Allow:
          description: HTTP methods supported by this endpoint.
          schema:
            type: string
            const: POST
        X-Biq-Request-Id:
          $ref: '#/components/headers/RequestId'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    Conflict:
      $ref: '#/components/responses/ApiErrorResponse'
      description: >-
        A unique alias, external ID, custom domain, or workspace resource name
        is already in use.
    UnprocessableEntity:
      $ref: '#/components/responses/ApiErrorResponse'
      description: >-
        The payload is invalid, a destination was blocked, or domain DNS
        verification is not ready.
    RateLimited:
      description: The workspace exceeded its plan's API rate limit.
      headers:
        RateLimit-Policy:
          description: Current IETF HTTPAPI quota policy as a structured field.
          schema:
            type: string
            example: '"workspace-api";q=1000;w=60'
        RateLimit:
          description: Current IETF HTTPAPI service limit as a structured field.
          schema:
            type: string
            example: '"workspace-api";r=0;t=17'
        Retry-After:
          description: Seconds to wait before retrying the request.
          schema:
            type: integer
            minimum: 0
            example: 17
        X-RateLimit-Limit:
          description: Legacy maximum request count for the current window.
          schema:
            type: integer
            minimum: 1
            example: 1000
        X-RateLimit-Remaining:
          description: Legacy remaining request count.
          schema:
            type: integer
            minimum: 0
            example: 0
        X-RateLimit-Reset:
          description: Legacy reset time as a UTC Unix timestamp.
          schema:
            type: integer
            format: int64
            example: 1788126519
        X-Biq-Request-Id:
          description: Request identifier for support and tracing.
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
    InternalError:
      $ref: '#/components/responses/ApiErrorResponse'
      description: The request failed unexpectedly.
    ApiErrorResponse:
      description: API error.
      headers:
        X-Biq-Request-Id:
          description: Request identifier for support and tracing.
          schema:
            type: string
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ApiError'
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: Workspace API key
      description: A workspace API key beginning with biqli_.

````