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

# Simular una suma de puntos

> Devuelve cuántos puntos se acreditarían, con el desglose, **sin acreditar nada**. Sirve para mostrarle al cliente lo que va a sumar antes de cerrar la venta.

Mandá **uno** de estos tres: `amount` (monto de la compra), `initialPointsToGive` (puntos directos) o `pointItems` (ítems de puntos con sus cantidades, cuyos IDs salen de `GET /external/point-items`).

A diferencia de `POST /external/tags/add`, el cliente se identifica por `clientId` y tiene que existir: previsualizar no da de alta a nadie.

**No reserva nada.** El resultado es el de este momento: si cambian las bonificaciones, el nivel del cliente o el catálogo de ítems, la suma real puede dar distinto. Mandá el mismo `branch_id` que vas a usar después, porque hay bonificaciones por sucursal.

**Cómo pasar de la simulación a la suma real**: `POST /external/tags/add` acepta `amount` o `pointItems`, pero con otro formato: allá `pointItems` es un array de ids donde la cantidad se expresa repitiendo el id (`[{ "id": 12, "quantity": 2 }]` acá equivale a `[12, 12]` allá). La suma real no acepta `initialPointsToGive`: si simulás por ese modo, no hay una acreditación equivalente por esta API.



## OpenAPI

````yaml /api-reference/openapi.json post /external/tags/add/preview
openapi: 3.0.0
info:
  title: API de Tienda de Puntos
  description: >-
    API pública de Tienda de Puntos. Permite sumar puntos por compra, consultar
    clientes, validar canjes y consumir cupones desde tu POS, ERP o e-commerce.


    Todas las llamadas se autentican con el header `x-api-key`.
  version: 0.0.1
  contact: {}
servers:
  - url: https://api.tiendadepuntos.com
    description: Producción
  - url: https://apidev.tiendadepuntos.com
    description: QA
security:
  - ApiKeyAuth: []
tags: []
paths:
  /external/tags/add/preview:
    post:
      tags:
        - Puntos
      summary: Simular una suma de puntos
      description: >-
        Devuelve cuántos puntos se acreditarían, con el desglose, **sin
        acreditar nada**. Sirve para mostrarle al cliente lo que va a sumar
        antes de cerrar la venta.


        Mandá **uno** de estos tres: `amount` (monto de la compra),
        `initialPointsToGive` (puntos directos) o `pointItems` (ítems de puntos
        con sus cantidades, cuyos IDs salen de `GET /external/point-items`).


        A diferencia de `POST /external/tags/add`, el cliente se identifica por
        `clientId` y tiene que existir: previsualizar no da de alta a nadie.


        **No reserva nada.** El resultado es el de este momento: si cambian las
        bonificaciones, el nivel del cliente o el catálogo de ítems, la suma
        real puede dar distinto. Mandá el mismo `branch_id` que vas a usar
        después, porque hay bonificaciones por sucursal.


        **Cómo pasar de la simulación a la suma real**: `POST
        /external/tags/add` acepta `amount` o `pointItems`, pero con otro
        formato: allá `pointItems` es un array de ids donde la cantidad se
        expresa repitiendo el id (`[{ "id": 12, "quantity": 2 }]` acá equivale a
        `[12, 12]` allá). La suma real no acepta `initialPointsToGive`: si
        simulás por ese modo, no hay una acreditación equivalente por esta API.
      operationId: ExternalTagsController_previewPointOperation
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ExternalDirectSumPreviewDto'
      responses:
        '200':
          description: Desglose de los puntos que se acreditarían.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  status:
                    type: integer
                    example: 200
                  message:
                    type: string
                    example: Request was successful
                  data:
                    $ref: '#/components/schemas/ExternalDirectSumPreviewOutputDto'
                required:
                  - success
                  - status
                  - message
        '400':
          description: >-
            Faltan los tres modos de carga, vinieron más de uno, o el valor
            enviado no alcanza para otorgar ni un punto.
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: integer
                    example: 400
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-07-31T14:05:12.431Z'
                  path:
                    type: string
                    example: /external/tags/add
                  method:
                    type: string
                    example: POST
                  message:
                    type: string
                    example: >-
                      La operación no otorga ningún punto: el valor enviado no
                      alcanza para sumar ni un punto con la configuración del
                      comercio.
                  errors:
                    type: array
                    nullable: true
                    items:
                      type: object
                  data:
                    type: object
                    nullable: true
        '401':
          description: >-
            Falta el header `x-api-key` (`Api Key is required`), o está presente
            pero no corresponde a ningún comercio (`Api key is invalid`).
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: integer
                    example: 401
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-07-31T14:05:12.431Z'
                  path:
                    type: string
                    example: /external/tags/add
                  method:
                    type: string
                    example: POST
                  message:
                    type: string
                    example: Api key is invalid
                  errors:
                    type: array
                    nullable: true
                    items:
                      type: object
                  data:
                    type: object
                    nullable: true
        '403':
          description: >-
            El cliente está suspendido, así que la suma real tampoco se
            acreditaría.
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: integer
                    example: 403
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-07-31T14:05:12.431Z'
                  path:
                    type: string
                    example: /external/tags/add
                  method:
                    type: string
                    example: POST
                  message:
                    type: string
                    example: >-
                      El cliente al que estás intentando sumar puntos se
                      encuentra suspendido
                  errors:
                    type: array
                    nullable: true
                    items:
                      type: object
                  data:
                    type: object
                    nullable: true
        '404':
          description: >-
            El cliente, la sucursal o alguno de los ítems no existe para este
            comercio.
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: integer
                    example: 404
                  timestamp:
                    type: string
                    format: date-time
                    example: '2026-07-31T14:05:12.431Z'
                  path:
                    type: string
                    example: /external/tags/add
                  method:
                    type: string
                    example: POST
                  message:
                    type: string
                    example: Client not found
                  errors:
                    type: array
                    nullable: true
                    items:
                      type: object
                  data:
                    type: object
                    nullable: true
      security:
        - ApiKeyAuth: []
components:
  schemas:
    ExternalDirectSumPreviewDto:
      type: object
      properties:
        clientId:
          type: number
          description: >-
            ID del cliente en Tienda de Puntos. A diferencia de `POST
            /external/tags/add`, acá es obligatorio y el cliente tiene que
            existir: previsualizar no da de alta a nadie.
          example: 84512
        amount:
          type: number
          description: >-
            Monto de la compra en pesos. Se convierte a puntos con la regla del
            comercio, igual que en `POST /external/tags/add`. Tiene que ser
            mayor a cero: el preview no simula restas.
          example: 4000
        initialPointsToGive:
          type: number
          description: Puntos base, sin convertir. Se usan tal cual llegan.
          example: 50
        pointItems:
          description: >-
            Ítems de puntos de la venta, con sus cantidades. Cada ítem aporta
            sus puntos fijos o su equivalencia en pesos, según cómo lo haya
            configurado el comercio.
          type: array
          items:
            $ref: '#/components/schemas/ExternalPointItemLineDto'
        branch_id:
          type: number
          description: >-
            Sucursal de la venta. Cambia el resultado: hay bonificaciones que
            aplican solo a ciertas sucursales. Mandá la misma que vas a usar
            después en la suma real.
          example: 1972
      required:
        - clientId
    ExternalDirectSumPreviewOutputDto:
      type: object
      properties:
        points:
          description: Desglose de los puntos.
          allOf:
            - $ref: '#/components/schemas/ExternalPreviewPointsDto'
        calculatedAt:
          format: date-time
          type: string
          description: >-
            Momento del cálculo. El preview no reserva ni congela nada: si entre
            la simulación y la suma real cambian las bonificaciones, el nivel
            del cliente o el catálogo de ítems, el resultado puede variar.
          example: '2026-09-21T14:32:11.000Z'
      required:
        - points
        - calculatedAt
    ExternalPointItemLineDto:
      type: object
      properties:
        id:
          type: number
          description: ID del ítem de puntos. Sale de `GET /external/point-items`.
          example: 87
        quantity:
          type: number
          description: Unidades de ese ítem en la venta. Si se omite, se asume 1.
          example: 2
          default: 1
      required:
        - id
    ExternalPreviewPointsDto:
      type: object
      properties:
        initialPointsToGive:
          type: number
          description: Puntos base, antes de cualquier bonificación.
          example: 40
        levelBonusPoints:
          type: number
          description: >-
            Puntos extra por el nivel del cliente. `0` si no tiene nivel o no
            multiplica.
          example: 8
        pointRulesBonusPoints:
          type: number
          description: Puntos extra por las bonificaciones activas del comercio.
          example: 12
        totalPointsToGive:
          type: number
          description: 'Total que se acreditaría: la suma de los tres anteriores.'
          example: 60
      required:
        - initialPointsToGive
        - levelBonusPoints
        - pointRulesBonusPoints
        - totalPointsToGive
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: x-api-key
      description: >-
        API key del comercio. Se genera desde el panel de Tienda de Puntos, en
        Configuración → Integraciones.

````