> ## 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 tiendas

> Crea o actualiza hasta 100 ubicaciones del comercio por id externo en una sola solicitud.

Envía un arreglo de tiendas. Cada ítem crea la tienda cuando su `id` es nuevo, o actualiza la tienda existente cuando ya pertenece al comercio del access token. Envía solo los campos a cambiar. Cada tienda guardada coincide con [Obtener tienda](https://firespark.cloud/docs/es/integrations-api/stores/\[id]/get).

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

`merchant_id` y `env` salen del token. El `id` va en cada ítem. Las zonas de cobertura, las etiquetas y `cms` no se escriben aquí.

Al crear, `name`, `contact`, `location` y `timezone` son obligatorios. Si omites `status`, queda `ACTIVE`. Si omites `availability`, queda abierta y sin horario. Si omites `tags`, quedan vacíos. Si omites `channel_ids` y `fulfillment_ids`, quedan activos todos los canales y fulfillments que el merchant tenga en ese momento. Los canales y fulfillments que se creen después empiezan desactivados en las tiendas existentes.

## Solicitud

```bash theme={null}
curl -X PUT "https://firespark.cloud/api/integrations/v1/stores" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    {
      "id": "pos-location-01",
      "name": "Main Street",
      "brand_id": null,
      "contact": {
        "email": "main@merchant.com",
        "phone": "+593991234567",
        "name": "Main Street"
      },
      "location": {
        "latitude": -2.1894,
        "longitude": -79.8891,
        "address_line_1": "Calle Principal 456",
        "city": "Guayaquil",
        "country": "Ecuador",
        "postal_code": "090101",
        "business_name": "Main Street Restaurant"
      },
      "timezone": "America/Guayaquil",
      "channel_ids": ["web", "app"],
      "fulfillment_ids": ["delivery", "pickup"],
      "status": "ACTIVE"
    },
    {
      "id": "pos-location-02",
      "status": "INACTIVE"
    }
  ]'
```

El cuerpo es un arreglo de 1 a 100 ítems. Cada ítem acepta estos campos:

| Campo | Descripción |
| - | - |
| `id` | Id externo de la tienda. Obligatorio. Caracteres alfanuméricos, `_` y `-`, de 1 a 64 caracteres. |
| `name` | Nombre de la tienda. Obligatorio al crear. |
| `brand_id` | Id externo de la marca. `null` lo limpia. |
| `contact` | Correo y teléfono. Reemplaza el contacto completo cuando se envía. Obligatorio al crear. |
| `location` | Dirección y coordenadas. Reemplaza la ubicación completa cuando se envía. Obligatorio al crear. |
| `timezone` | Zona horaria IANA. Obligatorio al crear. |
| `instructions` | Notas localizadas de llegada o retiro. `null` las limpia. |
| `availability` | Horario y estado de apertura. Reemplaza el objeto completo cuando se envía. |
| `channel_ids` | Ids externos de los canales desde los que la tienda acepta pedidos. Reemplaza la lista completa cuando se envía. `[]` desactiva todos los canales. |
| `fulfillment_ids` | Ids externos de los fulfillments que ofrece la tienda. Reemplaza la lista completa cuando se envía. `[]` desactiva todos los fulfillments. |
| `tags` | Etiquetas arbitrarias. Reemplazan el objeto completo cuando se envían. |
| `cms_template_id` | UUID de la plantilla CMS. `null` lo limpia. |
| `status` | `ACTIVE` o `INACTIVE`. |

Se ignoran al escribir: `labels`, `cms`, `coverage_zones`, `uid`, `merchant_id`, `env`.

## 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` por un `id` duplicado, o al crear sin `name`, `contact`, `location` y `timezone`. `500` por un fallo inesperado. |
| `data` | La tienda guardada, con etiquetas, cms y zonas de cobertura. 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": "pos-location-01",
      "status": 200,
      "data": {
        "id": "pos-location-01",
        "name": "Main Street",
        "timezone": "America/Guayaquil",
        "status": "ACTIVE"
      }
    },
    {
      "id": "pos-location-02",
      "status": 422,
      "error": "Name, contact, location, and timezone are required",
      "details": null
    }
  ]
}
```

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

## 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 `stores:write`. |


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