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

# WhatsApp tools workflow

> Create and manage company WhatsApp bot tools the same way Configuración > Equipo y acceso > Tools de WhatsApp does.

# WhatsApp tools workflow

WhatsApp **tools** are company templates the bot uses to prepare operation drafts. They are the same `WhatsAppOperationTool` rows as **Configuración → WhatsApp → Tools**. Authenticate with `x-api-key`.

The dashboard employee session API stays at `/api/kapso/tools`. This public integrator surface is `/api/whatsapp/tools` so it matches other company-scoped catalogs (`/api/tags`, `/api/operation-types`).

Delete is a **soft-delete** (`deleted_at` + `enabled=false`), same as the dashboard. List never returns soft-deleted tools; it **does** include disabled ones.

`operationTypeId` lives inside `fixed_config` (dashboard field). There is no top-level `operation_type_id`. Cross-company IDs are rejected.

## List tools (including disabled)

```bash theme={null}
curl --request GET \
  --url "https://finsync.ar/api/whatsapp/tools" \
  --header "x-api-key: YOUR_API_KEY"
```

The response is an array of tools (`id`, `name`, `slug`, `enabled`, `company_operation_type_id`, `fixed_config`, `parameter_schema`, …).

## Create a tool

Body shape matches the dashboard form: `name`, optional `slug` / `description` / `enabled`, required `fixed_config`, optional `parameter_schema` (defaults to no dynamic fields).

`fixed_config.toolKind` must match the company operation type: `up`/`down` → `up_down`, `other` → `other`, `exchange` → `exchange`, `budget` → `budget`.

```bash theme={null}
curl --request POST \
  --url "https://finsync.ar/api/whatsapp/tools" \
  --header "Content-Type: application/json" \
  --header "x-api-key: YOUR_API_KEY" \
  --data '{
    "name": "Subida USD",
    "enabled": true,
    "fixed_config": {
      "toolKind": "up_down",
      "operationTypeId": 3,
      "mode": "standard",
      "source": {
        "accountType": "internal",
        "accountId": 10,
        "transactionTypeId": 1
      },
      "destination": {
        "accountType": "external",
        "currency": "USD",
        "transactionTypeId": 2
      },
      "matchAmountsWhenSameCurrency": false,
      "commissions": []
    },
    "parameter_schema": {
      "parameters": [
        {
          "key": "cliente_destino",
          "label": "Cliente destino",
          "field": "destinationClient",
          "kind": "external_client",
          "required": true
        },
        {
          "key": "monto_origen",
          "label": "Monto origen",
          "field": "sourceAmount",
          "kind": "amount",
          "required": true
        }
      ]
    }
  }'
```

A duplicate `slug` for the same company returns `409`. Invalid `fixed_config` or an `operationTypeId` that is not this company's (or the wrong base type) returns `400`.

### OTHER example

```bash theme={null}
curl --request POST \
  --url "https://finsync.ar/api/whatsapp/tools" \
  --header "Content-Type: application/json" \
  --header "x-api-key: YOUR_API_KEY" \
  --data '{
    "name": "Pase de saldo",
    "fixed_config": {
      "toolKind": "other",
      "operationTypeId": 8,
      "operationDescriptionMode": "fixed",
      "legs": [
        {
          "clientType": 0,
          "clientMode": "dynamic",
          "accountMode": "dynamic",
          "currencyMode": "fixed",
          "amountMode": "dynamic",
          "transactionTypeMode": "fixed",
          "transactionTypeId": 4,
          "descriptionMode": "fixed"
        }
      ]
    },
    "parameter_schema": {
      "parameters": [
        {
          "key": "monto_0",
          "label": "Monto",
          "legIndex": 0,
          "field": "amount",
          "kind": "amount",
          "required": true
        }
      ]
    }
  }'
```

### EXCHANGE example

```bash theme={null}
curl --request POST \
  --url "https://finsync.ar/api/whatsapp/tools" \
  --header "Content-Type: application/json" \
  --header "x-api-key: YOUR_API_KEY" \
  --data '{
    "name": "Cambio interno",
    "fixed_config": {
      "toolKind": "exchange",
      "operationTypeId": 12,
      "clientMode": "internal",
      "debitAccountId": 31,
      "creditAccountId": 32,
      "debitTransactionTypeId": 5,
      "creditTransactionTypeId": 6,
      "commissions": []
    },
    "parameter_schema": { "parameters": [] }
  }'
```

### BUDGET example

Budget tools do **not** send up/down `mode`, `source`, or `destination`. Direction defaults to `expense` (same as the dashboard budget form). `paymentSourceMode` defaults to `internal` (caja). Expense + `external` drafts the same Gastos op as the dashboard: credit `payerClientId` (type=1, not the center client), no caja debit. Source, centro, amount, and description can each be fixed or a param. If `internalAccountId` is omitted on internal, confirm uses the cost center default caja.

```bash theme={null}
curl --request POST \
  --url "https://finsync.ar/api/whatsapp/tools" \
  --header "Content-Type: application/json" \
  --header "x-api-key: YOUR_API_KEY" \
  --data '{
    "name": "Gasto de centro",
    "fixed_config": {
      "toolKind": "budget",
      "operationTypeId": 15,
      "costCenterId": 7,
      "amount": 250
    },
    "parameter_schema": {
      "parameters": [
        {
          "key": "descripcion",
          "label": "Descripción",
          "field": "description",
          "kind": "text",
          "required": false
        }
      ]
    }
  }'
```

Personal expense (cuenta corriente, no caja):

```bash theme={null}
curl --request POST \
  --url "https://finsync.ar/api/whatsapp/tools" \
  --header "Content-Type: application/json" \
  --header "x-api-key: YOUR_API_KEY" \
  --data '{
    "name": "Gasto personal",
    "fixed_config": {
      "toolKind": "budget",
      "operationTypeId": 15,
      "costCenterId": 7,
      "paymentSourceMode": "external",
      "amount": 250
    },
    "parameter_schema": {
      "parameters": [
        {
          "key": "cliente_paga",
          "label": "Cliente que paga",
          "field": "payerClient",
          "kind": "external_client",
          "required": true
        },
        {
          "key": "descripcion",
          "label": "Descripción",
          "field": "description",
          "kind": "text",
          "required": false
        }
      ]
    }
  }'
```

A budget operation type with `toolKind=up_down` returns **400**.

## Enable, rename, or update config

```bash theme={null}
curl --request PATCH \
  --url "https://finsync.ar/api/whatsapp/tools/21" \
  --header "Content-Type: application/json" \
  --header "x-api-key: YOUR_API_KEY" \
  --data '{
    "enabled": false,
    "name": "Subida USD (off)"
  }'
```

## Soft-delete

```bash theme={null}
curl --request DELETE \
  --url "https://finsync.ar/api/whatsapp/tools/21" \
  --header "x-api-key: YOUR_API_KEY"
```

Returns `204`. Soft-deleted tools disappear from GET and return `404` on later PATCH/DELETE.

## Company agent prompt (prompt base del bot)

House rules appended **after** the global WhatsApp agent prompt. They never replace accounting or safety rules. This is the same value as the dashboard card in **Configuración → WhatsApp → Tools** (employee route `/api/kapso/system-prompt-extra`), just with `x-api-key`.

### Read

```bash theme={null}
curl --request GET \
  --url "https://finsync.ar/api/whatsapp/system-prompt-extra" \
  --header "x-api-key: YOUR_API_KEY"
```

Response: `{ "system_prompt_extra": "..." }`, or `null` when unset.

### Set or clear

Send the text to replace it, or `null` / `""` to clear it (the bot falls back to the global prompt). The value is trimmed and capped at **12.000 characters**; longer bodies return `400`.

```bash theme={null}
curl --request PATCH \
  --url "https://finsync.ar/api/whatsapp/system-prompt-extra" \
  --header "Content-Type: application/json" \
  --header "x-api-key: YOUR_API_KEY" \
  --data '{
    "system_prompt_extra": "Cuando pidan varias operaciones iguales en un mensaje, llamá la tool una vez por cada una con batch_key distinto. Si un borrador no coincide, descartalo con discard_operation_draft."
  }'
```

Use it for company vocabulary, habitual multi-step requests, or the multi-draft / discard conventions described in [WhatsApp](/docs/ayuda/whatsapp).

## Related endpoints

* `GET /api/whatsapp/tools`
* `POST /api/whatsapp/tools`
* `GET /api/whatsapp/tools/{id}`
* `PATCH /api/whatsapp/tools/{id}`
* `DELETE /api/whatsapp/tools/{id}`
* `GET /api/whatsapp/system-prompt-extra`
* `PATCH /api/whatsapp/system-prompt-extra`
* `GET /api/operation-types` — resolve `fixed_config.operationTypeId`
* Dashboard catalog/apply (employee session, `whatsapp.manage`): `GET /api/kapso/tool-templates`, `POST /api/kapso/tool-templates/apply`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.