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

# Crear o actualizar canales

> Crea o actualiza hasta 100 canales de venta por id externo en una sola solicitud.

Envía un arreglo de canales. Cada ítem crea el canal cuando su `id` no existe, o lo actualiza cuando ya existe. Envía solo los campos a cambiar. El `id` va en cada ítem y no se puede renombrar aquí.

> [!NOTE]
>
> Requiere un access token con el scope `channels:write`. Ver
> [Token](https://firespark.cloud/docs/es/integrations-api/oauth/token/post.md) para obtenerlo.

Un ítem con solo `id` refresca `updated_at` si el canal ya existe. Un `id` nuevo requiere `name` y `type`. Si omites `status` queda `ACTIVE`. Si omites `cms_template_id` queda sin plantilla. `type` solo se guarda al crear; en un canal existente se ignora.

## Solicitud

```bash theme={null}
curl -X PUT "https://firespark.cloud/api/integrations/v1/channels" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    { "id": "app", "name": "Mobile app", "type": "APP", "status": "ACTIVE" },
    { "id": "web", "name": "Website", "type": "WEB" }
  ]'
```

## Cuerpo

Un arreglo de 1 a 100 ítems. Cada ítem acepta estos campos:

| Campo | Tipo | Descripción |
| - | - | - |
| `id` | string | Id externo del canal. Obligatorio. Caracteres alfanuméricos, `_` y `-`, de 1 a 64 caracteres. |
| `name` | string | Nombre visible, 1–100 caracteres. Letras, números y espacios simples. |
| `type` | string | Obligatorio al crear. Uno de `APP`, `WEB`, `KIOSK`, `POS`, `CALL_CENTER` o `AGGREGATOR`. Se ignora si el canal ya existe. |
| `cms_template_id` | string (UUID) | Plantilla CMS a vincular. `null` la quita. |
| `status` | string | `ACTIVE` o `INACTIVE`. |

Si se envían `labels`, `cms`, `settings`, `attributes`, `uid`, `merchant_id` o `env`, se ignoran.

## Respuesta

Zod valida el cuerpo completo antes de guardar. Si algún campo es inválido, responde HTTP `400` y no se guarda ningún ítem. Cuando el cuerpo es válido, los ítems se guardan uno tras otro. El HTTP es `200` solo si todos se guardaron. Si un ítem posterior falla por una regla de negocio, el HTTP es el `status` de ese ítem (`422` o `500`).

| Campo | Descripción |
| - | - |
| `id` | El `id` del ítem. `null` si faltaba o no era válido. |
| `status` | `200` si se guardó. `422` si `name` ya lo usa otro canal, o si un `id` nuevo llegó sin `name` y `type`. `500` por un fallo inesperado. |
| `data` | El canal guardado, con `labels` y `cms`. Solo cuando `status` es `200`. |
| `error` | Mensaje de error. Solo cuando `status` no es `200`. |
| `details` | Detalle del error a nivel de ítem. |

```json Success theme={null}
{
  "data": [
    {
      "id": "app",
      "status": 200,
      "data": {
        "id": "app",
        "uid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "merchant_id": "c1d2e3f4-a5b6-7890-cdef-123456789abc",
        "name": "Mobile app",
        "type": "APP",
        "status": "ACTIVE",
        "cms_template_id": null,
        "cms": null,
        "labels": []
      }
    },
    {
      "id": "web",
      "status": 422,
      "error": "Channel name already exists",
      "details": null
    }
  ]
}
```

```json Campos inválidos theme={null}
{
  "error": "Invalid fields",
  "details": {
    "0.type": "Invalid option"
  }
}
```

## Errores

| Estado | Descripción |
| - | - |
| `400` | El cuerpo no es un arreglo de 1 a 100 ítems, o algún ítem tiene campos inválidos. No se guarda ningún ítem. |
| `401` | Access token ausente o inválido. |
| `403` | El token no incluye el scope `channels:write`. |


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