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

# Productos

> Agrupa y categoriza tus cobros por producto o servicio. Opcional.

Un **producto** (`Product`) sirve para **agrupar y categorizar** tus cobros (deudas, suscripciones y ligas de pago). Su uso es **completamente opcional**: puedes cobrar sin asociar ningún producto.

Lo usas cuando quieres reportar tus cobros por línea de producto o servicio, por ejemplo "Plan Premium", "Cuota mensual gimnasio" o "Internet 100MB".

## Llave natural: `name`

El `name` es la llave natural del producto y es **único por organización**. Crear un producto con un `name` que ya existe **no** genera un duplicado ni un error: devuelve el producto existente.

<Note>
  Por eso `POST /products` es idempotente por diseño: repetir el mismo `name` siempre te devuelve el mismo producto. No necesitas verificar de antemano si ya existe.
</Note>

## Crear un producto

```bash theme={null}
curl --request POST \
  --url 'https://tapipay-facade.dev.tapila.cloud/products' \
  --header 'x-api-key: TU_API_KEY' \
  --header 'x-authorization-token: TU_TOKEN_TAPI' \
  --header 'Content-Type: application/json' \
  --data '{ "name": "Plan Premium" }'
```

```json theme={null}
{
  "data": {
    "productId": "42",
    "name": "Plan Premium",
    "active": true,
    "createdAt": "2026-06-03T18:00:00Z",
    "updatedAt": "2026-06-03T18:00:00Z"
  },
  "requestId": "req_a1b2c3d4"
}
```

<Note>
  El `productId` es el identificador en el sistema, expuesto como string **sin prefijo**.
</Note>

## Creación en línea (`productName`)

No necesitas crear el producto por adelantado. Puedes enviarlo **en línea** al crear una deuda, suscripción o liga de pago con el campo `productName`. Si el nombre no existe, se crea; si ya existe, se reutiliza sin duplicarlo.

```bash theme={null}
curl --request POST \
  --url 'https://tapipay-facade.dev.tapila.cloud/debts' \
  --header 'x-api-key: TU_API_KEY' \
  --header 'x-authorization-token: TU_TOKEN_TAPI' \
  --header 'Content-Type: application/json' \
  --data '{
    "externalClientId": "CLI-00042",
    "amount": 2500.00,
    "dueDate": "2026-07-10",
    "productName": "Plan Gimnasio"
  }'
```

En la respuesta del cobro, el producto viene embebido con cuatro campos:

```json theme={null}
{
  "product": {
    "productId": "42",
    "name": "Plan Gimnasio",
    "active": true,
    "createdInline": true
  }
}
```

El campo `createdInline` es `true` si el producto se creó en esa misma petición, y `false` si ya existía y se reutilizó.

## Activar y desactivar

<ResponseField name="active" type="boolean" default="true">
  Estado del producto. Un producto inactivo no puede asociarse a nuevos cobros.
</ResponseField>

`DELETE /products/{id}` hace un **soft-delete**: pone `active: false` sin eliminar el producto, de modo que el historial se conserva. Asociar un producto inactivo a un nuevo cobro devuelve `422 BUSINESS_RULE_VIOLATION`.

## Endpoints

| Método   | Ruta             | Descripción                                                 |
| -------- | ---------------- | ----------------------------------------------------------- |
| `POST`   | `/products`      | Crear un producto (o devolver el existente con ese `name`). |
| `GET`    | `/products/{id}` | Consultar un producto.                                      |
| `GET`    | `/products`      | Listar productos (filtros `name`, `active`).                |
| `PATCH`  | `/products/{id}` | Actualizar `name` o `active`.                               |
| `DELETE` | `/products/{id}` | Soft-delete (pone `active: false`).                         |

<Card title="Pruébalo en el API Reference" icon="play" href="/api-reference">
  Explora cada endpoint con su playground interactivo.
</Card>
