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

# GET /v1/functions

> List the webhook functions of your company, with secret values masked.

Lists the webhook functions an assistant can call. Each one is an HTTPS endpoint of yours: you describe what it does, the model decides when to call it, and Keebai makes the request.

Header and query-string **values come back masked** as `***`; the keys stay visible so you can see the shape of the request. See [webhook security](/dev/assistants/webhook-security#secrets-are-write-only).

## Endpoint

```
GET https://api.keebai.com/v1/functions
```

## Required scope

`assistants:read`

## Headers

| Header          | Required | Value                    |
| --------------- | -------- | ------------------------ |
| `Authorization` | Yes      | `Bearer kbai_pk_<token>` |

## Query parameters

| Parameter     | Type      | Default | Description                                   |
| ------------- | --------- | ------- | --------------------------------------------- |
| `active_only` | `boolean` | `false` | Return only functions with `is_active: true`. |
| `limit`       | `integer` | `50`    | Records per page, 1–200.                      |
| `offset`      | `integer` | `0`     | Records to skip.                              |

## Example request

<CodeGroup>
  ```bash curl theme={null}
  curl -s "https://api.keebai.com/v1/functions?active_only=true" \
    -H "Authorization: Bearer kbai_pk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  ```

  ```js JavaScript theme={null}
  const params = new URLSearchParams({ active_only: "true" });
  const resp = await fetch(`https://api.keebai.com/v1/functions?${params}`, {
    headers: { Authorization: `Bearer ${process.env.KEEBAI_API_TOKEN}` },
  });
  const { data, total } = await resp.json();
  ```

  ```python Python theme={null}
  import os, requests

  resp = requests.get(
      "https://api.keebai.com/v1/functions",
      headers={"Authorization": f"Bearer {os.environ['KEEBAI_API_TOKEN']}"},
      params={"active_only": True},
      timeout=10,
  )
  resp.raise_for_status()
  functions = resp.json()["data"]
  ```
</CodeGroup>

## Response

### 200 OK

```json theme={null}
{
  "data": [
    {
      "_id": "6650cccc3333dddd4444eeee",
      "name": "consultar_stock",
      "display_name": "Consultar stock",
      "description": "Devuelve el stock disponible de un SKU en el ERP.",
      "type": "webhook",
      "tool_params": [
        {
          "name": "sku",
          "description": "Código del producto",
          "type": "string",
          "required": true
        }
      ],
      "context": {
        "url": "https://erp.example.com/stock/{{sku}}",
        "method": "GET",
        "headers": { "Authorization": "***" },
        "params": {},
        "timeout": 30
      },
      "tags": ["erp"],
      "is_active": true,
      "used_by_blocks": [
        {
          "block_id": "6650bbbb2222cccc3333dddd",
          "name": "Reserva",
          "type": "steps"
        }
      ],
      "created_at": "2026-07-22T08:12:04.221Z",
      "updated_at": "2026-07-25T16:30:19.008Z"
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}
```

### 401 Unauthorized

Missing, invalid, revoked, or expired token.

### 403 Forbidden

The token does not have the `assistants:read` scope.

### 502 Bad Gateway

The assistant service is unreachable.

## Operational notes

* **Functions are company-wide, not project-scoped.** Unlike assistants and blocks, two tokens on two projects of the same company see the same list. A name collision is a company-level collision.
* **Only webhook functions appear here.** Keebai also has calendar, ecommerce and block-generated functions; none of them are exposed, and asking for one by id returns `404`. See [why](/dev/assistants/webhook-security#only-webhook-functions-are-exposed).
* **`used_by_blocks` is what makes a delete recoverable.** While it is non-empty, [deleting the function](/dev/endpoints/functions-delete) returns `409` — this field names the blocks to unbind first.
* **`context.body` is not masked.** It is the request template the model fills in, not a place credentials normally live, and hiding it would remove the main reason to read a function.
* **`total` is a real count**, unlike the block endpoints: the upstream returns the full set, so the page is sliced here.


## OpenAPI

````yaml GET /v1/functions
openapi: 3.0.0
info:
  title: Keebai Public API
  description: Superficie pública REST autenticada con Personal Access Tokens (PAT).
  version: 1.0.0
  contact: {}
servers:
  - url: https://api.keebai.com
    description: Production
security: []
tags: []
paths:
  /v1/functions:
    get:
      tags:
        - functions
      summary: Listar funciones de webhook
      description: >-
        Devuelve las funciones de webhook de la company. Las funciones son de
        company, no de proyecto. Los valores de headers y de query string
        vuelven enmascarados; las claves se ven.
      operationId: PublicFunctionsController_list
      parameters:
        - name: limit
          required: false
          in: query
          schema:
            minimum: 1
            maximum: 200
            default: 50
            type: number
        - name: offset
          required: false
          in: query
          schema:
            minimum: 0
            default: 0
            type: number
        - name: active_only
          required: false
          in: query
          description: Devuelve solo las funciones activas.
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicFunctionListResponseDto'
      security:
        - PAT: []
components:
  schemas:
    PublicFunctionListResponseDto:
      type: object
      properties:
        total:
          type: number
        limit:
          type: number
        offset:
          type: number
        data:
          type: array
          items:
            $ref: '#/components/schemas/PublicFunctionDto'
      required:
        - total
        - limit
        - offset
        - data
    PublicFunctionDto:
      type: object
      properties:
        _id:
          type: string
        name:
          type: string
        display_name:
          type: string
        description:
          type: string
        type:
          type: string
          example: webhook
        tool_params:
          type: array
          items:
            $ref: '#/components/schemas/PublicFunctionParamResponseDto'
        context:
          $ref: '#/components/schemas/PublicWebhookContextResponseDto'
        tags:
          type: array
          items:
            type: string
        is_active:
          type: boolean
        used_by_blocks:
          description: >-
            Bloques que referencian esta funcion. Mientras la lista no este
            vacia, borrarla devuelve 409.
          type: array
          items:
            $ref: '#/components/schemas/PublicFunctionUsageDto'
        created_at:
          type: string
        updated_at:
          type: string
      required:
        - _id
        - name
        - display_name
        - description
        - type
        - tool_params
        - context
        - tags
        - is_active
        - used_by_blocks
        - created_at
        - updated_at
    PublicFunctionParamResponseDto:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
        type:
          type: string
          enum:
            - string
            - number
            - boolean
            - array
            - object
        required:
          type: boolean
      required:
        - name
        - type
        - required
    PublicWebhookContextResponseDto:
      type: object
      properties:
        url:
          type: string
        method:
          type: string
          enum:
            - GET
            - POST
            - PUT
            - PATCH
            - DELETE
        headers:
          type: object
          additionalProperties:
            type: string
          description: >-
            Headers configurados. Las claves se muestran y los valores vuelven
            siempre como '***'.
          example:
            Authorization: '***'
        params:
          type: object
          additionalProperties:
            type: string
          description: >-
            Query string configurada, con los valores enmascarados igual que
            headers.
        body:
          type: object
          additionalProperties: true
          description: >-
            Body de la request. No se enmascara: es la plantilla que rellena el
            modelo.
        timeout:
          type: number
        response_path:
          type: string
      required:
        - url
        - method
        - headers
        - params
        - timeout
    PublicFunctionUsageDto:
      type: object
      properties:
        block_id:
          type: string
        name:
          type: string
        type:
          type: string
          enum:
            - personification
            - objective
            - response_format
            - steps
            - cases_possible
            - do_not
            - product_info
            - store_info
            - reservation_info
            - tables_info
            - tags
            - response_policy
      required:
        - block_id
        - name
        - type
  securitySchemes:
    PAT:
      scheme: bearer
      bearerFormat: kbai_pk_<hex>
      type: http
      description: >-
        Personal Access Token con prefijo `kbai_pk_`. Generar desde el portal
        con permiso `developer.manage_tokens`.

````