> ## 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.

# List links

> Filter and paginate through the links available to your workspace API key.

Retrieve links from the workspace bound to your API key. Each item uses the
same complete, safe resource format returned by [Retrieve a link](/docs/api-reference/links/get),
including configuration and aggregate performance data.

## Authentication and permission

Send a workspace API key with **Links: Read** (`links.view`):

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

`links.view` is the only API key permission this endpoint needs. It includes
aggregate clicks, leads, sales, normalized USD revenue, and the most recent
click time. You do not need a separate analytics permission or additional read
permissions for the public folder, tag, pixel, and domain IDs contained in each
link.

You do not send a workspace ID. The key determines the workspace. The user who
created the key must still have workspace access; their current workspace role
also determines whether they can see every workspace link or only their own.

## List the first page

```bash theme={null}
curl --request GET \
  --url 'https://biq.li/api/v1/link?page_size=50' \
  --header 'Authorization: Bearer biqli_your_workspace_api_key' \
  --header 'Accept: application/json'
```

Links are ordered newest first using `created_at` and an internal tie-breaker.
The tie-breaker is never exposed. `page_size` defaults to `50` and accepts
values from `1` through `100`.

## Filter links

All filters are optional. When you combine filters, a link must satisfy every
filter. When you provide multiple `tag_ids`, a link may match any supplied tag.

| Query parameter  | Type                | Behavior                                                                                                                                    |
| ---------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `search`         | string              | Case-insensitive partial search across public link ID, external ID, name, short alias or slug, and destination URL. Maximum 255 characters. |
| `domain_id`      | string              | Public `biq_dom_...` custom-domain ID. Use `default` for links on the default Biqli domain.                                                 |
| `folder_id`      | string              | Public `biq_fld_...` folder ID.                                                                                                             |
| `tag_ids`        | string or string\[] | One or more public `biq_tag_...` IDs. Accepts a comma-separated value or array query parameters. Maximum 100 unique IDs.                    |
| `external_id`    | string              | Exact match against your workspace-unique external ID.                                                                                      |
| `active`         | boolean             | Filter by the requested active state using `true` or `false`.                                                                               |
| `safety_status`  | string              | `clear`, `pending`, or `quarantined`. Pending and quarantined links do not redirect.                                                        |
| `starting_after` | string              | Return the next, older page after this public `biq_lnk_...` cursor.                                                                         |
| `ending_before`  | string              | Return the previous, newer page before this public `biq_lnk_...` cursor.                                                                    |
| `page_size`      | integer             | Number of links to return. Defaults to `50`; maximum `100`.                                                                                 |

The endpoint rejects unknown query parameters. Internal numeric IDs,
`workspaceId`, `workspace_id`, `userId`, arbitrary relation loading, and raw
database filters or sorting are not supported.

### Search by destination or alias

```bash theme={null}
curl --get 'https://biq.li/api/v1/link' \
  --header 'Authorization: Bearer biqli_your_workspace_api_key' \
  --header 'Accept: application/json' \
  --data-urlencode 'search=summer-product' \
  --data-urlencode 'page_size=25'
```

### Filter by workspace resources

```bash theme={null}
curl --get 'https://biq.li/api/v1/link' \
  --header 'Authorization: Bearer biqli_your_workspace_api_key' \
  --header 'Accept: application/json' \
  --data-urlencode 'domain_id=biq_dom_01M14C6KQ6SG2GKMCV7HQ9A1QT' \
  --data-urlencode 'folder_id=biq_fld_01M14C93RJD7W46PFJX9B1TVYH' \
  --data-urlencode 'tag_ids[]=biq_tag_01M14CC1TW7AQ6DWZG9TMRH0PQ' \
  --data-urlencode 'tag_ids[]=biq_tag_01M14CD3CA47DTEGTZX90B61QB'
```

You can also send the tags as one comma-separated value:

```text theme={null}
tag_ids=biq_tag_01M14CC1TW7AQ6DWZG9TMRH0PQ,biq_tag_01M14CD3CA47DTEGTZX90B61QB
```

### Find a link by external ID

```bash theme={null}
curl --get 'https://biq.li/api/v1/link' \
  --header 'Authorization: Bearer biqli_your_workspace_api_key' \
  --header 'Accept: application/json' \
  --data-urlencode 'external_id=campaign-link-1842'
```

An exact external-ID filter returns either an empty list or the single matching
link because `external_id` is unique within a workspace.

## Response

A successful request returns `200 OK`. `links` contains zero or more complete
link resources. No internal link, user, domain, folder, tag, pixel, or workspace
numeric IDs are returned.

```json theme={null}
{
  "links": [
    {
      "id": "biq_lnk_01M14D2M8VFKYQCE7Z3A6HRXWP",
      "external_id": "campaign-link-1842",
      "short_url": "https://go.example.com/summer-product",
      "long_url": "https://example.com/product",
      "name": "Summer campaign",
      "domain_id": "biq_dom_01M14C6KQ6SG2GKMCV7HQ9A1QT",
      "alias": "summer-product",
      "active": true,
      "has_password": false,
      "activates_at": null,
      "expires_at": null,
      "exp_clicks_rule": null,
      "utm": "source=newsletter&medium=email&campaign=summer",
      "geo_rules": [],
      "device_rules": [],
      "platform_rules": [],
      "folder_ids": ["biq_fld_01M14C93RJD7W46PFJX9B1TVYH"],
      "pixel_ids": [],
      "tag_ids": ["biq_tag_01M14CC1TW7AQ6DWZG9TMRH0PQ"],
      "conversion_tracking_enabled": true,
      "allow_search_engine_indexing": false,
      "proxy": false,
      "title": null,
      "description": null,
      "image": null,
      "qr_code": null,
      "clicks_count": 2841,
      "leads_count": 93,
      "sales_count": 27,
      "revenue": 4148.5,
      "revenue_currency": "USD",
      "clicked_at": "2026-08-29T10:42:11+00:00",
      "safety_status": "clear",
      "created_at": "2026-08-28T16:42:19+00:00",
      "updated_at": "2026-08-29T09:20:03+00:00"
    }
  ],
  "pagination": {
    "page_size": 50,
    "has_more": true,
    "next_cursor": "biq_lnk_01M14D2M8VFKYQCE7Z3A6HRXWP",
    "previous_cursor": null
  },
  "status": "success"
}
```

The API never returns the password, password hash, quarantine reason, or other
private operational data. `has_password` only tells you whether protection is
enabled. Deleted links are excluded.

## Cursor pagination

Cursor pagination remains stable when links are added while you are traversing
results. Do not construct or alter cursor values: use the public link IDs
returned in `pagination`.

### Get the next page

When `next_cursor` is not `null`, pass it as `starting_after` while keeping all
other filters and `page_size` unchanged:

```bash theme={null}
curl --get 'https://biq.li/api/v1/link' \
  --header 'Authorization: Bearer biqli_your_workspace_api_key' \
  --header 'Accept: application/json' \
  --data-urlencode 'page_size=50' \
  --data-urlencode 'starting_after=biq_lnk_01M14D2M8VFKYQCE7Z3A6HRXWP'
```

`has_more` indicates whether another older page exists. When it is `false`,
`next_cursor` is `null`.

### Return to the previous page

When `previous_cursor` is not `null`, pass it as `ending_before`:

```bash theme={null}
curl --get 'https://biq.li/api/v1/link' \
  --header 'Authorization: Bearer biqli_your_workspace_api_key' \
  --header 'Accept: application/json' \
  --data-urlencode 'page_size=50' \
  --data-urlencode 'ending_before=biq_lnk_01M14E5PF9DGK20HAZ48Q7V3SW'
```

You cannot send `starting_after` and `ending_before` together. A correctly
formatted cursor that is deleted or unavailable in the key's workspace returns
`404 resource_not_found`.

## Empty result

No matches is a successful response, not an error:

```json theme={null}
{
  "links": [],
  "pagination": {
    "page_size": 50,
    "has_more": false,
    "next_cursor": null,
    "previous_cursor": null
  },
  "status": "success"
}
```

## Errors

| HTTP status | Error code              | Meaning                                                                                        |
| ----------- | ----------------------- | ---------------------------------------------------------------------------------------------- |
| `401`       | `invalid_token`         | The workspace API key is missing, malformed, invalid, or revoked.                              |
| `403`       | `insufficient_scope`    | The key lacks `links.view` or its user lost workspace access.                                  |
| `404`       | `resource_not_found`    | A pagination cursor is deleted or unavailable in this workspace.                               |
| `422`       | `validation_error`      | A query parameter is unknown, malformed, out of range, or incompatible with another parameter. |
| `429`       | `rate_limit_exceeded`   | The workspace exceeded its plan's API request limit.                                           |
| `500`       | `internal_server_error` | An unexpected server error occurred.                                                           |

Validation responses include `error.details.errors` keyed by query parameter.
Every error contains a `request_id`, also returned in the `X-Biq-Request-Id`
response header for tracing and support.

## Related link workflows

* Use [Count links](/docs/api-reference/links/count) with the same filters when you
  only need the number of matches.
* Use [Bulk create links](/docs/api-reference/links/bulk-create) to create up to 100
  complete link configurations in request order.
* Use [Bulk update links](/docs/api-reference/links/bulk-update) to apply one shared
  partial update to up to 100 public or external IDs.
* Use [Bulk delete links](/docs/api-reference/links/bulk-delete) to permanently
  remove up to 100 public IDs with idempotent retry behavior.

## Shared API behavior

Authentication is workspace-scoped; see [Authentication](/docs/api-reference/authentication). Errors use the standard envelope and request IDs described in [Errors](/docs/api-reference/errors), and requests are subject to [Rate limits](/docs/api-reference/rate-limits). This endpoint uses cursor pagination; see [Pagination](/docs/api-reference/pagination).


## OpenAPI

````yaml GET /v1/link
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/link:
    get:
      tags:
        - Links
      summary: List links
      description: >-
        Returns a cursor-paginated list of complete link resources from the
        workspace bound to the API key. Requires links.view.
      operationId: link.index
      parameters:
        - name: search
          in: query
          description: >-
            Partial search across public ID, external ID, name, alias or slug,
            and destination URL.
          schema:
            type: string
            minLength: 1
            maxLength: 255
        - name: domain_id
          in: query
          description: Public custom-domain ID, or default for the default Biqli domain.
          schema:
            type: string
            pattern: ^(default|biq_dom_[0-9A-HJKMNP-TV-Z]{26})$
        - name: folder_id
          in: query
          description: Public folder ID.
          schema:
            type: string
            pattern: ^biq_fld_[0-9A-HJKMNP-TV-Z]{26}$
        - name: tag_ids
          in: query
          description: Public tag IDs. A link may match any supplied tag.
          style: form
          explode: false
          schema:
            type: array
            minItems: 1
            maxItems: 100
            uniqueItems: true
            items:
              type: string
              pattern: ^biq_tag_[0-9A-HJKMNP-TV-Z]{26}$
        - name: external_id
          in: query
          description: Exact match for the caller-controlled, workspace-unique external ID.
          schema:
            type: string
            minLength: 1
            maxLength: 255
        - name: active
          in: query
          description: Filter by the requested active state.
          schema:
            type: boolean
        - name: safety_status
          in: query
          description: Filter by the current link safety state.
          schema:
            type: string
            enum:
              - clear
              - pending
              - quarantined
        - name: starting_after
          in: query
          description: >-
            Return the next, older page after this public link cursor. Mutually
            exclusive with ending_before.
          schema:
            type: string
            pattern: ^biq_lnk_[0-9A-HJKMNP-TV-Z]{26}$
        - name: ending_before
          in: query
          description: >-
            Return the previous, newer page before this public link cursor.
            Mutually exclusive with starting_after.
          schema:
            type: string
            pattern: ^biq_lnk_[0-9A-HJKMNP-TV-Z]{26}$
        - name: page_size
          in: query
          description: Number of links to return.
          schema:
            type: integer
            minimum: 1
            maximum: 100
            default: 50
      responses:
        '200':
          description: Links returned successfully.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ListLinksResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    ListLinksResponse:
      type: object
      required:
        - links
        - pagination
        - status
      properties:
        links:
          type: array
          items:
            $ref: '#/components/schemas/CreatedLink'
        pagination:
          $ref: '#/components/schemas/LinkListPagination'
        status:
          type: string
          const: success
    CreatedLink:
      type: object
      required:
        - id
        - external_id
        - short_url
        - long_url
        - name
        - domain_id
        - alias
        - active
        - has_password
        - activates_at
        - expires_at
        - exp_clicks_rule
        - utm
        - folder_ids
        - pixel_ids
        - tag_ids
        - conversion_tracking_enabled
        - allow_search_engine_indexing
        - proxy
        - title
        - description
        - image
        - qr_code
        - geo_rules
        - device_rules
        - platform_rules
        - clicks_count
        - leads_count
        - sales_count
        - revenue
        - revenue_currency
        - clicked_at
        - safety_status
        - created_at
        - updated_at
      properties:
        id:
          type: string
          description: Public link ID. Internal numeric IDs are never returned.
          pattern: ^biq_lnk_[0-9A-HJKMNP-TV-Z]{26}$
        external_id:
          type:
            - string
            - 'null'
          description: Caller-controlled identifier, unique within the workspace.
        short_url:
          type: string
          format: uri
        long_url:
          type: string
        name:
          type:
            - string
            - 'null'
        domain_id:
          type:
            - string
            - 'null'
          pattern: ^biq_dom_[0-9A-HJKMNP-TV-Z]{26}$
        alias:
          type:
            - string
            - 'null'
        active:
          type: boolean
        has_password:
          type: boolean
        activates_at:
          type:
            - string
            - 'null'
          format: date-time
        expires_at:
          type:
            - string
            - 'null'
          format: date-time
        exp_clicks_rule:
          oneOf:
            - $ref: '#/components/schemas/ClickExpirationRule'
            - type: 'null'
        utm:
          type:
            - string
            - 'null'
        geo_rules:
          type: array
          items:
            $ref: '#/components/schemas/TargetingRule'
        device_rules:
          type: array
          items:
            $ref: '#/components/schemas/TargetingRule'
        platform_rules:
          type: array
          items:
            $ref: '#/components/schemas/TargetingRule'
        folder_ids:
          type: array
          items:
            type: string
        pixel_ids:
          type: array
          items:
            type: string
        tag_ids:
          type: array
          items:
            type: string
        conversion_tracking_enabled:
          type: boolean
        allow_search_engine_indexing:
          type: boolean
        proxy:
          type: boolean
        title:
          type:
            - string
            - 'null'
        description:
          type:
            - string
            - 'null'
        image:
          type:
            - string
            - 'null'
        qr_code:
          oneOf:
            - $ref: '#/components/schemas/AttachedQrCode'
            - type: 'null'
        clicks_count:
          type: integer
          minimum: 0
          description: Total recorded clicks.
        leads_count:
          type: integer
          minimum: 0
          description: Total attributed lead events.
        sales_count:
          type: integer
          minimum: 0
          description: Total attributed sale events.
        revenue:
          type: number
          minimum: 0
          description: Attributed sales amount normalized to USD.
        revenue_currency:
          type: string
          const: USD
        clicked_at:
          type:
            - string
            - 'null'
          format: date-time
          description: Time of the most recent recorded click.
        safety_status:
          type: string
          enum:
            - clear
            - pending
            - quarantined
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    LinkListPagination:
      type: object
      required:
        - page_size
        - has_more
        - next_cursor
        - previous_cursor
      properties:
        page_size:
          type: integer
          minimum: 1
          maximum: 100
        has_more:
          type: boolean
          description: Whether another older page is available through next_cursor.
        next_cursor:
          type:
            - string
            - 'null'
          description: >-
            Pass this public link ID as starting_after to retrieve the next,
            older page.
          pattern: ^biq_lnk_[0-9A-HJKMNP-TV-Z]{26}$
        previous_cursor:
          type:
            - string
            - 'null'
          description: >-
            Pass this public link ID as ending_before to retrieve the previous,
            newer page.
          pattern: ^biq_lnk_[0-9A-HJKMNP-TV-Z]{26}$
    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
                - 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.
    ClickExpirationRule:
      type: object
      additionalProperties: false
      required:
        - key
      properties:
        key:
          type: integer
          minimum: 1
          description: Number of clicks after which the link expires.
        value:
          type:
            - string
            - 'null'
          description: Optional URL to use after the click threshold is reached.
          maxLength: 1000
    TargetingRule:
      type: object
      additionalProperties: false
      required:
        - key
        - value
      properties:
        key:
          type: string
          description: Match value, such as a country code, device, or platform.
          maxLength: 250
        value:
          type: string
          description: Destination URL used when the rule matches.
          maxLength: 1000
    AttachedQrCode:
      type: object
      required:
        - url
        - format
        - logo
      properties:
        url:
          type: string
          format: uri
        format:
          type: string
          const: svg
        logo:
          type: string
          enum:
            - app
            - none
  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.
    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_.

````