# Cambios de precio

> Cambios de precio de lista y vista previa de uno, incluyendo lo que pagará un cliente antes y después.

Los cambios masivos, programación y correos electrónicos de cambios de precio para clientes requieren Pro. Free puede publicar importaciones de hojas de cálculo de precios estándar de inmediato sin correos electrónicos. Los precios acordados existentes y los cambios programados publicados continúan aplicándose cuando finaliza Pro.

Los precios de lista nunca cambian de forma silenciosa en TradeCatalog. Los nuevos precios van a un **cambio de precio** para una lista de precios: un borrador que el personal revisa, fecha y publica. Los clientes solo reciben un correo electrónico cuando sus propios precios cambian. Standard es la lista cuando no se nombra otra.

## Cómo se realizan los cambios de precio

- **Desde la API:** [`PUT /products`](/docs/api/products#create-or-update-products) con un nuevo `listPrice` para un producto existente lo agrega a un borrador y devuelve el `priceChangeId` del borrador.
- **Desde la aplicación:** importaciones de hojas de cálculo, y cambios masivos como «+4% en la categoría de Tuercas».

La publicación, programación y cancelación ocurren en la aplicación, bajo **Cambios de precio**. No hay API para ellos: siempre una persona revisa un cambio de precio antes de que los clientes lo vean.

## Estados

| Estado      | Significado                                                       |
| ----------- | ----------------------------------------------------------------- |
| `draft`     | No publicado. No han cambiado precios.                            |
| `scheduled` | Publicado con una fecha futura. Los precios cambian en esa fecha. |
| `live`      | En vigor.                                                         |
| `cancelled` | Cancelado antes de que entrara en vigor.                          |

## El objeto de cambio de precio

```json
{
  "id": "c4d5e6f7-1234-4abc-9def-0123456789ab",
  "source": "import",
  "title": "API import (Sage stock sync)",
  "supplierNote": null,
  "status": "draft",
  "effectiveAt": null,
  "notifyCustomers": true,
  "raiseFixedPrices": false,
  "priceListId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
  "priceListName": "Standard",
  "createdBy": "Fq3L0cZ7tN1pW9aYx2Rk",
  "publishedAt": null,
  "cancelledAt": null,
  "createdAt": "2026-09-27T02:00:14.000Z",
  "items": 38
}
```

| Campo              | Tipo          | Descripción                                                                                                                        |
| ------------------ | ------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `source`           | string        | `import` (hoja de cálculo o API) o `bulk` (un cambio porcentual realizado en la aplicación).                                       |
| `title`            | string        | Mostrado al personal. Los borradores de API tienen el título «Importación de API (nombre de clave)».                               |
| `supplierNote`     | string o nulo | Mensaje a los clientes en el correo electrónico de cambio de precio.                                                               |
| `status`           | string        | Véase [estados](#statuses).                                                                                                        |
| `effectiveAt`      | string o nulo | Cuándo aplican los nuevos precios.                                                                                                 |
| `notifyCustomers`  | booleano      | Si los clientes reciben un correo electrónico con sus nuevos precios.                                                              |
| `raiseFixedPrices` | booleano      | Si los precios acordados aumentan en el mismo porcentaje. Esta opción es independiente de la lista.                                |
| `priceListId`      | string o nulo | La lista a la que se escribe este cambio. Nulo significa Standard, incluyendo cambios realizados antes de que se nombraran listas. |
| `priceListName`    | string        | El nombre de esa lista. `Standard` cuando `priceListId` es nulo.                                                                   |
| `createdBy`        | string o nulo | Id de la persona que lo realizó. Para borradores de API, la persona que creó la clave.                                             |
| `items`            | entero        | Cuántos productos cambia. Solo en la lista.                                                                                        |

## Cambios de precio de lista

**GET** `/api/v1/price-changes`

Más recientes primero. Cubre los **100 cambios de precio más recientes**.

| Nombre   | Tipo   | Requerido | Descripción                                       |
| -------- | ------ | --------- | ------------------------------------------------- |
| `limit`  | entero | no        | 1 a 100. Valor predeterminado 100.                |
| `offset` | entero | no        | Número de filas a omitir. Valor predeterminado 0. |

```bash
curl https://tradecatalog.app/api/v1/price-changes \
  -H "Authorization: Bearer $TRADECATALOG_API_KEY"
```

```js
const res = await fetch('https://tradecatalog.app/api/v1/price-changes', {
  headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` },
})
const { data: changes } = await res.json()
const drafts = changes.filter((change) => change.status === 'draft')
```

## Vista previa de un cambio de precio

**GET** `/api/v1/price-changes/{id}`

Todo lo que el personal ve antes de publicar: cuántos precios suben y bajan, los mayores movimientos, advertencias y cuántos precios acordados afecta. Pase `customer` para ver los precios propios del cliente antes y después.

| Nombre     | En    | Tipo   | Requerido | Descripción                        |
| ---------- | ----- | ------ | --------- | ---------------------------------- |
| `id`       | path  | string | sí        | Id del cambio de precio.           |
| `customer` | query | string | no        | Id del cliente o código de cuenta. |

```bash
curl "https://tradecatalog.app/api/v1/price-changes/c4d5e6f7-1234-4abc-9def-0123456789ab?customer=OAK01" \
  -H "Authorization: Bearer $TRADECATALOG_API_KEY"
```

```js
const res = await fetch(
  `https://tradecatalog.app/api/v1/price-changes/${priceChangeId}?customer=OAK01`,
  { headers: { Authorization: `Bearer ${process.env.TRADECATALOG_API_KEY}` } },
)
const { data: preview } = await res.json()
if (preview.warnings.length)
  console.warn('Check these before publishing', preview.warnings)
```

```json
{
  "data": {
    "change": {
      "id": "c4d5e6f7-1234-4abc-9def-0123456789ab",
      "source": "import",
      "title": "API import (Sage stock sync)",
      "supplierNote": null,
      "status": "draft",
      "effectiveAt": null,
      "notifyCustomers": true,
      "raiseFixedPrices": false,
      "priceListId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
      "priceListName": "Standard",
      "createdBy": "Fq3L0cZ7tN1pW9aYx2Rk",
      "publishedAt": null,
      "cancelledAt": null,
      "createdAt": "2026-09-27T02:00:14.000Z"
    },
    "counts": { "total": 38, "up": 36, "down": 2 },
    "biggest": [
      {
        "productId": "3f8a2c1e-9b4d-4e6f-a7c8-1d2e3f4a5b6c",
        "oldPrice": 1850,
        "newPrice": 1950,
        "sku": "HX-8510",
        "name": "Hex bolt M10 x 50 zinc",
        "changeBp": 541
      }
    ],
    "warnings": [],
    "fixedAffected": 3,
    "customer": {
      "name": "Oakfield Joinery",
      "rows": [
        {
          "sku": "HX-8510",
          "name": "Hex bolt M10 x 50 zinc",
          "before": 1573,
          "after": 1658,
          "label": "Brand discount −15%"
        }
      ]
    }
  },
  "currency": "GBP"
}
```

| Campo           | Descripción                                                                                                                                                                                                         |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `counts`        | Productos en el cambio, y cuántos suben y bajan.                                                                                                                                                                    |
| `biggest`       | Hasta 20 artículos con el mayor porcentaje de cambio. `changeBp` es el cambio en puntos básicos (541 = +5,41%).                                                                                                     |
| `warnings`      | Artículos que cambian más del 30% en cualquier dirección, o llegan a cero. Normalmente errores de escritura.                                                                                                        |
| `fixedAffected` | Precios acordados en estos productos que son válidos ahora. Solo cambian si el cambio eleva los precios acordados.                                                                                                  |
| `customer`      | Con `customer`: los precios unitarios de este cliente antes y después, de su propia lista y luego su ajuste, para los primeros 50 artículos como máximo. Un cliente en otra lista no se ve afectado. `null` sin él. |

`404 not_found` si no hay ningún cambio de precio en este espacio de trabajo.
