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

# Create a biolink

> Create a bio page and configure its public URL and access settings.

Create a bio page in the workspace bound to your API key. The endpoint creates
the page itself. Design, widgets, and page content remain managed in the Biqli
dashboard.

<Note>
  Do not send a workspace ID. Every `biqli_` API key belongs to one workspace,
  and the new biolink is always created there.
</Note>

## Authentication and permission

Send the API key as a Bearer token. The key needs **Biolinks: Write** with the
`biolinks.create` permission. A request containing `domain_id` also needs
**Custom domains: Read** (`custom_domains.view`).

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

## Minimal request

Only `name` is required. Biqli generates an available alias on the default
domain when you omit `alias` and `domain_id`.

```bash theme={null}
curl --request POST \
  --url https://biq.li/api/v1/bio \
  --header 'Authorization: Bearer biqli_your_workspace_api_key' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Acme profile"
  }'
```

## Request fields

| Field                          | Type                       | Required | Behavior                                                                                                          |
| ------------------------------ | -------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `name`                         | string                     | Yes      | Internal page name. Between 3 and 250 characters.                                                                 |
| `external_id`                  | string or null             | No       | Your integration's identifier. Maximum 255 characters and unique in the workspace.                                |
| `description`                  | string or null             | No       | Page description and basic search metadata. Maximum 250 characters.                                               |
| `alias`                        | string                     | No       | Custom path for the short URL. The workspace alias length and character rules apply.                              |
| `domain_id`                    | string or null             | No       | Public `biq_dom_...` ID of a domain available in this workspace. Omit or use `null` for the default Biqli domain. |
| `active`                       | boolean                    | No       | Whether visitors can open the page. Defaults to `true`.                                                           |
| `password`                     | string or null             | No       | Visitor password. Maximum 250 characters. It is never returned by the API.                                        |
| `activates_at`                 | ISO 8601 date-time or null | No       | Time at which the page becomes available.                                                                         |
| `expires_at`                   | ISO 8601 date-time or null | No       | Time at which the page expires.                                                                                   |
| `allow_search_engine_indexing` | boolean                    | No       | Whether search engines may index the page. Defaults to `false`.                                                   |

Use public resource IDs only. Numeric database IDs are not accepted. The
selected domain must belong to, or be attached to, the API key's workspace.
When both schedules are set, `expires_at` must be later than `activates_at`.

## Complete example

```bash theme={null}
curl --request POST \
  --url https://biq.li/api/v1/bio \
  --header 'Authorization: Bearer biqli_your_workspace_api_key' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "Acme profile",
    "external_id": "creator-page-1842",
    "description": "Official links for Acme.",
    "alias": "acme",
    "domain_id": "biq_dom_01M14C6KQ6SG2GKMCV7HQ9A1QT",
    "active": true,
    "password": "preview-2026",
    "activates_at": "2026-09-01T08:00:00Z",
    "expires_at": "2027-01-01T00:00:00Z",
    "allow_search_engine_indexing": false
  }'
```

## Successful response

Success returns `201 Created` and the complete public API representation of the
page.

```json theme={null}
{
  "biolink": {
    "id": "biq_bio_01M19R8Q6G4S2PT7VNZ5K0W3CX",
    "external_id": "creator-page-1842",
    "name": "Acme profile",
    "description": "Official links for Acme.",
    "short_url": "https://go.example.com/acme",
    "alias": "acme",
    "domain_id": "biq_dom_01M14C6KQ6SG2GKMCV7HQ9A1QT",
    "active": true,
    "has_password": true,
    "activates_at": "2026-09-01T08:00:00+00:00",
    "expires_at": "2027-01-01T00:00:00+00:00",
    "allow_search_engine_indexing": false,
    "links_count": 0,
    "clicks_count": 0,
    "clicked_at": null,
    "created_at": "2026-08-30T11:42:19+00:00",
    "updated_at": "2026-08-30T11:42:19+00:00"
  },
  "status": "success"
}
```

`has_password` tells you whether protection is enabled. Biqli never returns the
plaintext password or its hash. It also does not return widgets, page content,
appearance settings, internal workspace IDs, or internal database IDs.

## Conflicts and validation

* Names are unique across the workspace's folder and biolink resources.
* Aliases are unique per domain across links, folders, and biolinks.
* `external_id` can be used to prevent duplicate integration records.
* Unknown fields are rejected. This includes `workspaceId`, `workspace_id`,
  `content`, `widgets`, and `appearance`.

| HTTP status | Error code            | Meaning                                                                                                                                 |
| ----------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `401`       | `invalid_token`       | The API key is missing, invalid, or revoked.                                                                                            |
| `403`       | `insufficient_scope`  | The key lacks `biolinks.create`, lacks `custom_domains.view` when selecting a domain, or its user cannot create pages in the workspace. |
| `404`       | `resource_not_found`  | The supplied domain is not available in the key's workspace.                                                                            |
| `409`       | `alias_taken`         | The alias is already used on the selected domain.                                                                                       |
| `409`       | `external_id_taken`   | The external ID is already used in the workspace.                                                                                       |
| `409`       | `biolink_name_taken`  | A biolink already uses the name.                                                                                                        |
| `409`       | `folder_name_taken`   | A folder already uses the name.                                                                                                         |
| `422`       | `validation_error`    | A field is missing, invalid, or unsupported.                                                                                            |
| `429`       | `rate_limit_exceeded` | The workspace exceeded its API request limit.                                                                                           |

<Warning>
  This endpoint does not accept an idempotency key. For retry-safe creation,
  provide a unique `external_id` or a caller-controlled `alias` and handle a
  possible `409` response.
</Warning>

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


## OpenAPI

````yaml POST /v1/bio
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/bio:
    post:
      tags:
        - Biolinks
      summary: Create a biolink
      description: >-
        Creates a bio page. Page design and content remain dashboard-managed.
        Requires biolinks.create.
      operationId: bio.store
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BiolinkWrite'
      responses:
        '201':
          description: Biolink created.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BiolinkResponse'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/UnprocessableEntity'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
components:
  schemas:
    BiolinkWrite:
      allOf:
        - $ref: '#/components/schemas/BiolinkFields'
        - type: object
          required:
            - name
    BiolinkResponse:
      type: object
      required:
        - biolink
        - status
      properties:
        biolink:
          $ref: '#/components/schemas/Biolink'
        status:
          type: string
          const: success
    BiolinkFields:
      type: object
      additionalProperties: false
      properties:
        name:
          type: string
          minLength: 3
          maxLength: 250
        external_id:
          type:
            - string
            - 'null'
          minLength: 1
          maxLength: 255
        description:
          type:
            - string
            - 'null'
          maxLength: 250
        alias:
          type: string
        domain_id:
          type:
            - string
            - 'null'
          pattern: ^biq_dom_[0-9A-HJKMNP-TV-Z]{26}$
        active:
          type: boolean
        password:
          type:
            - string
            - 'null'
          maxLength: 250
          writeOnly: true
        activates_at:
          type:
            - string
            - 'null'
          format: date-time
        expires_at:
          type:
            - string
            - 'null'
          format: date-time
        allow_search_engine_indexing:
          type: boolean
    Biolink:
      type: object
      additionalProperties: false
      description: >-
        Stable page-level settings and aggregate counts. Frontend-owned content,
        widgets, layout, and appearance are omitted.
      required:
        - id
        - external_id
        - name
        - description
        - short_url
        - alias
        - domain_id
        - active
        - has_password
        - activates_at
        - expires_at
        - allow_search_engine_indexing
        - links_count
        - clicks_count
        - clicked_at
        - created_at
        - updated_at
      properties:
        id:
          type: string
          pattern: ^biq_bio_[0-9A-HJKMNP-TV-Z]{26}$
        external_id:
          type:
            - string
            - 'null'
        name:
          type: string
        description:
          type:
            - string
            - 'null'
        short_url:
          type: string
          format: uri
        alias:
          type: string
        domain_id:
          type:
            - string
            - 'null'
          pattern: ^biq_dom_[0-9A-HJKMNP-TV-Z]{26}$
        active:
          type: boolean
        has_password:
          type: boolean
        activates_at:
          type:
            - string
            - 'null'
          format: date-time
        expires_at:
          type:
            - string
            - 'null'
          format: date-time
        allow_search_engine_indexing:
          type: boolean
        links_count:
          type: integer
          minimum: 0
        clicks_count:
          type: integer
          minimum: 0
        clicked_at:
          type:
            - string
            - 'null'
          format: date-time
        created_at:
          type:
            - string
            - 'null'
          format: date-time
        updated_at:
          type:
            - string
            - 'null'
          format: date-time
    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.
  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.
    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_.

````