# Grupos (Products) --- - [Grupos (Products)](#groups) - [¿Qué es un grupo?](#overview) - [Listar grupos](#get) - [Crear grupo](#create) - [Actualizar grupo](#update) - [Eliminar grupo](#delete) - [Alias `product`](#alias) ## ¿Qué es un grupo? [#overview] Los **grupos** son el paso inicial y opcional para organizar tus suscripciones: te permiten **agrupar planes** relacionados y darles orden. Un grupo puede contener varios planes (precios). Son ideales cuando manejas varios negocios o productos distintos: creas un grupo por cada uno y asocias sus planes al grupo correspondiente. :::note **Nombre alternativo (estilo Stripe).** Cada ruta de esta página existe también bajo `product`, con el mismo comportamiento y la misma respuesta. Usa el que prefieras: | Nombre original | Alias | | - | - | | `GET /api/v1/subscriptions/group` | `GET /api/v1/subscriptions/product` | | `POST /api/v1/subscriptions/group` | `POST /api/v1/subscriptions/product` | | `PUT /api/v1/subscriptions/group/{id}` | `PUT /api/v1/subscriptions/product/{id}` | | `DELETE /api/v1/subscriptions/group/{id}` | `DELETE /api/v1/subscriptions/product/{id}` | ::: ## Listar grupos [#get] **Descripción:** Devuelve **todos** tus grupos. `GET /api/v1/subscriptions/group` :::caution A diferencia de casi todos los listados de la API, este **no está paginado** y **no viene envuelto en `data`**: la respuesta es directamente el arreglo de grupos, en `snake_case`. Tampoco separa por ambiente: verás los grupos de prueba y los de producción juntos. ::: `GET /api/v1/subscriptions/group` ```bash curl -X GET \ '/api/v1/subscriptions/group' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -H 'Accept: application/json' ``` :::tip Respuesta satisfactoria ::: Código de respuesta: 200 ```json [ { "id": "9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f", "name": "Streaming", "description": "Planes de streaming", "active": true, "user_id": 42, "office_id": 1, "commerce_id": 315, "created_at": "2026-07-31 10:15:00" } ] ``` Es el mismo alias en el listado: `GET /api/v1/subscriptions/product` devuelve exactamente esto. `GET /api/v1/subscriptions/product` ## Crear grupo [#create] **Descripción:** Crea un grupo con nombre y sucursal. Opcionalmente puedes darle una `description`. `POST /api/v1/subscriptions/group` | Nombre del campo | Descripción | Reglas | | - | - | - | | name | Nombre del grupo. Lo verás al organizar tus planes. No puede repetirse dentro de tu comercio | `['required', 'string', 'max:255', 'unique:subscription_groups,name']` | | description | Para qué es el grupo. Solo de uso interno | `['nullable', 'string', 'max:500']` | | office | Sucursal a la que pertenece el grupo. Debe ser una de [tus sucursales](/commercio) | `['required', 'exists:offices,id']` | `POST /api/v1/subscriptions/group` Cuerpo de ejemplo: ```json { "name": "Streaming", "description": "Planes de streaming", "office": 1 } ``` ```bash curl -X POST \ '/api/v1/subscriptions/group' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -H 'Content-type: application/json' \ -H 'Idempotency-Key: 9b1f0e34-6b2a-4a7e-9d0a-000000000001' \ -d '{ "name": "Streaming", "description": "Planes de streaming", "office": 1 }' ``` :::tip Respuesta satisfactoria ::: Código de respuesta: 200 ```json { "saved": true, "group": { "id": "9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f", "name": "Streaming", "description": "Planes de streaming", "plansCount": 0, "createdAt": "2026-07-31 10:15:00" } } ``` :::danger El nombre ya existe en tu comercio, o la sucursal no es tuya ::: Código de respuesta: 422 ```json { "message": "El campo name ya está en uso.", "errors": { "name": ["El campo name ya está en uso."], "office": ["El office seleccionado no es válido."] } } ``` :::note El objeto `group` de la respuesta viene en **camelCase** (`plansCount`, `createdAt`), mientras que el listado devuelve `snake_case`. No es un error: son dos serializaciones distintas del mismo recurso. ::: ## Actualizar grupo [#update] **Descripción:** Cambia el nombre o la descripción del grupo. El nuevo nombre no puede repetirse dentro de tu comercio. La sucursal del grupo no se puede cambiar. `PUT /api/v1/subscriptions/group/{group-id}` | Nombre del campo | Descripción | Reglas | | - | - | - | | name | Nuevo nombre. Único dentro de tu comercio, ignorando este mismo grupo | `['required', 'string', 'max:255', 'unique:subscription_groups,name']` | | description | Nueva descripción. Envía `null` para borrarla | `['sometimes', 'nullable', 'string', 'max:500']` | `PUT /api/v1/subscriptions/group/your-group-id` Cuerpo de ejemplo: ```json { "name": "Streaming", "description": "Planes de streaming mensual" } ``` ```bash curl -X PUT \ '/api/v1/subscriptions/group/9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -H 'Content-type: application/json' \ -d '{ "name": "Streaming", "description": "Planes de streaming mensual" }' ``` :::tip Respuesta satisfactoria ::: Código de respuesta: 200 ```json { "saved": true, "group": { "id": "9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f", "name": "Streaming", "description": "Planes de streaming mensual", "plansCount": 3, "createdAt": "2026-07-31 10:15:00" } } ``` :::danger El grupo no es de tu comercio ::: Código de respuesta: 403 ## Eliminar grupo [#delete] **Descripción:** Elimina un grupo por su `id`. `DELETE /api/v1/subscriptions/group/{group-id}` :::caution No podrás eliminar un grupo que tenga planes asociados. Elimina o reasigna primero sus [planes](/plan). ::: `DELETE /api/v1/subscriptions/group/your-group-id` ```bash curl -X DELETE \ '/api/v1/subscriptions/group/9b0f2a13-2c44-4a1a-9f2e-1d3b4c5d6e7f' \ -H 'Authorization: Bearer ACCESS_TOKEN' \ -H 'Accept: application/json' ``` :::tip Respuesta satisfactoria ::: Código de respuesta: 200 ```json { "deleted": true } ``` :::danger El grupo todavía tiene planes ::: Código de respuesta: 400 ```json { "deleted": false, "message": "El grupo tiene planes asociados y no puede eliminarse." } ``` ## Alias `product` [#alias] Las mismas operaciones, con el nombre de Stripe. Comportamiento, parámetros y respuestas son idénticos a los de arriba. **Crear** — `POST /api/v1/subscriptions/product` `POST /api/v1/subscriptions/product` Cuerpo de ejemplo: ```json { "name": "Streaming", "description": "Planes de streaming", "office": 1 } ``` **Actualizar** — `PUT /api/v1/subscriptions/product/{product-id}` `PUT /api/v1/subscriptions/product/your-group-id` Cuerpo de ejemplo: ```json { "name": "Streaming", "description": "Planes de streaming mensual" } ``` **Eliminar** — `DELETE /api/v1/subscriptions/product/{product-id}` `DELETE /api/v1/subscriptions/product/your-group-id`