# Conectar Shopify

En un par de minutos los pedidos pagos de una tienda Shopify empiezan a llegar a Ruta como entregas, y Shopify muestra al comprador el **link de seguimiento de Ruta** cuando el pedido sale. No hay claves que copiar: autorizás la app de Ruta en tu tienda y listo.

Necesitás entrar a la tienda como **dueño** (o con permiso para administrar apps) y al panel de Ruta como administrador de tu courier.

> [!NOTE]
> Ruta usa la API GraphQL Admin de Shopify, versión **2026-10**. Los pedidos con envío local (*local delivery*) y con envío a domicilio se importan; los retiros en tienda no.

## Antes de empezar

| Requisito | Dónde se ve |
| --- | --- |
| La dirección **`tienda.myshopify.com`** de la tienda. | Shopify → **Configuración → Dominios**. Es la que termina en `.myshopify.com`, aunque tus clientes vean otra. También sirve la dirección del admin (`admin.shopify.com/store/tienda`). |
| Sos el **dueño** de la tienda o tenés permiso para **administrar apps**. | Shopify → **Configuración → Usuarios**. |
| Tu plan de Ruta incluye integraciones (**Pro**). | Ruta → **Mi cuenta → Tu plan**. |

## 1. Conectá con Shopify

<div class="steps">

1. En Ruta, andá a **Integraciones (en la barra de arriba del panel)** y elegí **Shopify** (en **Tiendas online**, o buscala).
2. Tocá **Conectar**, escribí la dirección de tu tienda y tocá **Conectar con Shopify**.
3. Shopify te muestra la app **Ruta** y los permisos que pide. Tocá **Instalar**.
4. Volvés a Ruta con el aviso **«Tienda tienda.myshopify.com conectada»**. La conexión aparece en la página de **Shopify** y pasa a **Conectada** en cuanto Ruta hace la primera consulta.

</div>

Eso es todo. Ruta se suscribe sola a los avisos de la tienda (pedido creado, pagado y cancelado): cada pedido llega segundos después de pagarse, y Ruta igual revisa la tienda cada 15 minutos por si un aviso se pierde.

> [!TIP]
> Si la autorización tarda más de 5 minutos o tocás **Atrás** en el navegador, Ruta te pide empezar de nuevo («La autorización venció o ya se usó»). Es una protección: cada autorización sirve una sola vez y sólo para la tienda que escribiste.

### Qué permisos pide Ruta y por qué

| Permiso en Shopify | Para qué |
| --- | --- |
| Ver pedidos (`read_orders`) | Traer los pedidos pagos y saber si se cancelaron. |
| Preparar pedidos (`write_merchant_managed_fulfillment_orders`) | Marcar el pedido como **enviado** con el link de seguimiento de Ruta. |
| Seguimiento de envíos (`write_fulfillments`) | Agregar al envío los estados **en camino** y **entregado**. |
| Nombre, dirección y teléfono del comprador (datos protegidos) | Crear la entrega con el destinatario y la dirección de envío. |

Ruta no cambia precios, productos, stock ni clientes de tu tienda.

> [!TIP]
> En **Ajustes de la conexión** elegís qué pedidos importar (entrega local, envío a domicilio, sólo pagos), el comercio de retiro y la zona, y si las entregas se asignan solas al entrar. Ver [Ajustes de cada conexión](integraciones.html#ajustes-de-cada-conexion).

## 2. Avisar a Shopify

Como en otros sistemas de reparto, Ruta le cuenta a Shopify cómo va cada pedido. Viene **encendido** en las conexiones nuevas:

| En Ruta | En Shopify |
| --- | --- |
| La entrega **sale** (el repartidor la inicia) | El pedido pasa a **Preparado** con un envío de la empresa **Ruta**, el número de seguimiento (los 8 caracteres del código de la entrega) y el **link de seguimiento** de Ruta. El envío queda **En camino**. |
| La entrega se **entrega** | El envío pasa a **Entregado**. |

El comprador ve el link en la página de estado de su pedido (y en su cuenta, si la tienda las usa). Shopify **no** le manda su propio email de envío: los avisos al destinatario los manda Ruta.

- Si el pedido ya estaba preparado a mano en Shopify, o se canceló, Ruta no lo toca.
- Si el pedido tiene una parte para retirar en el local, Ruta marca como enviada sólo la parte con envío a domicilio.
- Si Shopify rechaza el aviso (por ejemplo, el pedido está **en espera**), **la entrega sigue igual** en Ruta. La conexión muestra **Requiere revisión** con el motivo; corregilo en Shopify y tocá **Reintentar**.
- Para apagarlo, abrí los **Ajustes de la conexión** y desactivá **Avisar a Shopify**. Lo que pase mientras está apagado no se le cuenta a Shopify después: al volver a encenderlo, Ruta avisa sólo los cambios nuevos.
- El aviso sale apenas cambia el estado de la entrega (en menos de un minuto).

> [!NOTE]
> Una conexión creada antes de octubre de 2026 tenía sólo permiso de lectura: **Avisar a Shopify** queda apagado. Para encenderlo, tocá **Volver a autorizar en Shopify** en la conexión y aceptá los permisos nuevos.

## 3. Verificá que funciona

<div class="steps">

1. Hacé un pedido de prueba con envío a domicilio o envío local y pagalo. En una tienda de desarrollo sirve el pago de prueba de Shopify (*Bogus Gateway*).
2. En Ruta aparece la entrega nueva en **Entregas** con el nombre y la dirección de envío del pedido (si tarda, en la conexión tocá **Buscar pedidos ahora**).
3. Iniciá la entrega desde la app del repartidor: en Shopify, el pedido pasa a **Preparado** con el link de Ruta.

</div>

## Qué datos se usan

| En Ruta | Sale del pedido de Shopify |
| --- | --- |
| Destinatario | Dirección de envío → nombre y apellido |
| Dirección | Dirección de envío → dirección, línea 2 y ciudad (`Av. Italia 1234 apto 5, Montevideo`) |
| Teléfono | Dirección de envío → teléfono; si no tiene, el teléfono del pedido |
| Instrucciones | Nota del pedido |
| Referencia del pedido | El número del pedido sin `#` (`#1001` → `1001`) |

| Pedido en Shopify | Qué hace Ruta |
| --- | --- |
| **Pagado** (o **Autorizado**), sin preparar, con **envío** o **envío local** | Crea la entrega. |
| **Sin envío** (por ejemplo, un pedido borrador sin línea de envío) o sólo con productos digitales | Lo ignora: no hay nada que entregar. |
| **Pendiente** con el pago manual **Cash on Delivery (COD)** de Shopify (o su traducción con «(COD)») | Crea la entrega con **monto a cobrar = saldo pendiente del pedido** en pesos uruguayos: el que vio el comprador al pagar o, si no, el de la tienda. Si el pedido no está en pesos para ninguno de los dos pero sí en **dólares**, la entrega se cobra en dólares. Ruta no convierte monedas: en cualquier otra moneda el pedido no se importa y figura en **Pedidos que no se importaron** con el motivo. |
| Con **retiro en tienda**, punto de retiro o venta en el local | Lo ignora: no es un envío. |
| **Pendiente** con otro medio de pago (transferencia…) | Lo ignora. Cuando se marca **Pagado**, se importa. |
| **Preparado** o **Preparado parcialmente** | Lo ignora: ya salió por otro lado. |

Al conectar, Ruta trae los pedidos **creados desde una semana antes** de la conexión: los pedidos viejos sin preparar no se convierten en entregas de golpe. Un pedido más viejo que se paga después igual entra por el aviso de pago.

Un pedido se importa una sola vez, aunque Shopify lo avise de nuevo. Si un pedido no se puede importar (por ejemplo, no tiene dirección de envío), Ruta importa los demás igual y la ejecución lo marca con `INTEGRATION_PAYLOAD_INVALID`.

Si tu sistema ya creó la entrega por la [API](entregas.html) con `externalReference` igual al número del pedido (`1001`), Ruta la **vincula** en lugar de crear otra. Las entregas que crea Ruta llevan ese número como referencia, así la API tampoco puede duplicarlas.

### Si cancelás o reembolsás un pedido que ya es una entrega

Cuando un pedido importado se **cancela**, se **reembolsa** completo o se **anula** el pago, Ruta se entera por el aviso de cancelación o en la revisión siguiente (cada 15 minutos):

| La entrega en Ruta | Qué hace Ruta |
| --- | --- |
| Todavía no salió (creada, asignada o con un intento fallido) | La cancela, igual que si la cancelaras en el panel. |
| Ya está en camino o entregada | **No la toca.** La marca con un aviso en su detalle y en **Últimas búsquedas de pedidos** («Pedido #1001 cancelado en la tienda…») para que decidas con el repartidor. Ya no le avisa nada más a Shopify sobre ese pedido. |

Cada cancelación se aplica una sola vez. Un reembolso parcial no cancela nada.

## Desinstalar y datos personales

- **Pausar**: **Pausar conexión** en Ruta deja de traer pedidos sin tocar la tienda.
- **Desinstalar**: en Shopify → **Configuración → Apps**, desinstalá **Ruta**. Ruta deja de poder leer la tienda al instante, borra su permiso y la conexión muestra **Requiere revisión** con **Volver a autorizar en Shopify**. Las entregas ya creadas quedan en Ruta.
- **Pedidos de datos de un comprador** (Shopify los manda por pedido del comprador o de la tienda): Ruta los registra y el soporte de tu courier responde dentro de los 30 días.
- **Borrado de un comprador** o **de la tienda** (48 horas después de desinstalar): en las entregas ya cerradas Ruta reemplaza el nombre y la dirección del comprador por «Cliente anonimizado» / «Dirección anonimizada» y borra su teléfono, email, notas y ubicación; la entrega queda como registro del courier (fecha, estado, repartidor, montos). Una entrega todavía en curso no se toca. Con el borrado de la tienda, la conexión queda pausada y sin permisos.

## Opción avanzada: conectar con una app propia

Si tu courier todavía no activó la app de Ruta, o preferís usar una app tuya, podés conectar con las claves de una app creada por el comercio. En la ventana de Shopify, abrí **Opción avanzada: conectar con una app propia**.

<div class="steps">

1. En el admin de la tienda, andá a **Configuración → Apps → Desarrollar apps** y tocá **Crear apps en el Dev Dashboard** (o entrá a `dev.shopify.com` con la misma cuenta de la tienda).
2. Tocá **Crear app** y llamala `Ruta`.
3. En la versión de la app, elegí los permisos de la **API Admin**: `read_orders` y `read_merchant_managed_fulfillment_orders` para importar; para **Avisar a Shopify**, en lugar del segundo, `write_merchant_managed_fulfillment_orders`, y además `write_fulfillments`.
4. Si Shopify te pide **datos protegidos de clientes**, marcá **nombre**, **dirección** y **teléfono**.
5. Publicá la versión, instalala en tu tienda y copiá el **ID del cliente** y el **Secreto del cliente** de **Configuración**.
6. En Ruta, escribí la dirección de la tienda, abrí **Avanzado**, elegí **App nueva (Dev Dashboard)** y pegá el ID y el secreto. Con una app creada en el admin antes de 2026, elegí **App creada antes de 2026** y pegá su token `shpat_…`.

</div>

> [!WARNING]
> Tratá el secreto como una contraseña: no lo mandes por mail ni por chat. Pegalo directo en Ruta.

Con una app propia, los avisos de pedidos se crean a mano: en Shopify, **Configuración → Notificaciones → Webhooks → Crear webhook**, tres webhooks JSON versión 2026-10 («Creación de pedido», «Pago de pedido» y «Cancelación de pedido») con la URL que te muestra Ruta (en **Para que lleguen al instante (opcional)**), y la clave con la que Shopify los firma en **Clave secreta de los avisos**. Sin ellos igual funciona: Ruta revisa la tienda cada 15 minutos.

```text
https://<tu-courier>/api/integrations/sources/<id-de-la-conexion>/webhooks/shopify
```

Ruta acepta un aviso sólo si la firma `X-Shopify-Hmac-Sha256` (HMAC-SHA256 en base64 del cuerpo) se hizo con la clave de firma de la tienda o con el secreto de la app que lo envió, la tienda `X-Shopify-Shop-Domain` es la de la conexión y el evento es `orders/create`, `orders/paid`, `orders/cancelled` u `orders/updated`. El aviso sólo dice **qué pedido** cambió: Ruta lo vuelve a consultar en Shopify antes de crear o cancelar la entrega.

## Límites

Shopify limita las consultas de cada app (en el plan estándar, 100 puntos por segundo). Ruta pide los pedidos de a 25 y, si Shopify le pide esperar, espera y sigue; si persiste, reintenta sola en unos minutos (`RATE_LIMITED`). Shopify sólo deja leer los pedidos de los **últimos 60 días**.

## Problemas frecuentes

| Lo que ves | Causa probable | Solución |
| --- | --- | --- |
| «La autorización venció o ya se usó» | Pasaron más de 5 minutos, recargaste la página de vuelta o la autorización era para otra tienda. | Tocá **Conectar con Shopify** de nuevo. |
| **Requiere revisión** con `INTEGRATION_CREDENTIALS_REJECTED` | La app de Ruta se desinstaló (o, con una app propia, las claves se copiaron mal o se rotaron). | Tocá **Volver a autorizar en Shopify** (o cargá las claves de nuevo). |
| `INTEGRATION_SCOPE_MISSING` | Shopify no dio un permiso que Ruta necesita (por ejemplo, una app propia de sólo lectura con **Avisar a Shopify** encendido). | Volvé a autorizar aceptando los permisos, o apagá **Avisar a Shopify**. |
| `INTEGRATION_STORE_UPDATE_REJECTED` | Shopify no aceptó marcar un pedido como enviado (en espera, sin artículos por preparar). La entrega sigue igual. | Revisá el pedido en Shopify y tocá **Reintentar**. |
| `INTEGRATION_DESTINATION_BLOCKED` | La dirección no es una tienda Shopify (`tienda.myshopify.com`). | Conectá la dirección `.myshopify.com` que ves en **Configuración → Dominios**. |
| `SERVICE_UNAVAILABLE` repetido | Shopify no responde, o la tienda está congelada o bloqueada por falta de pago. | Revisá el estado de la tienda en Shopify. Ruta reintenta sola. |
| Conectada, pero un pedido no llegó | El pedido es de retiro en tienda, no tiene envío, no está pagado, ya se marcó preparado, no tiene dirección de envío, es contra reembolso en otra moneda o se creó más de una semana antes de conectar. | Mirá **Pedidos que no se importaron** en la conexión: dice el motivo de cada pedido. Revisá el pago, el método de entrega y la dirección del pedido en Shopify. |

¿Seguís con problemas? Mandale al soporte de tu courier la hora del pedido y el código que muestra la conexión: **nunca** el ID, el secreto ni el token.
