Resumir ventas de Shopify
Ventas de Shopify de un período, por moneda.
| Tool ID | shopify.ventas.resumir |
| Nombre MCP | shopify__ventas__resumir |
| Conector | shopify |
| Plano | action |
| Scope (permiso) | shopify:pedidos |
| Auth | connection_credentials |
| Versión | 1 |
| Sensible | no |
| Deprecado | no |
| Comportamiento | readOnly=true, destructive=false, idempotent=true, openWorld=true |
Requiere conexión. Indica cuál en cada llamada: header
X-Connect-Connectionen REST y campoconnectionIden elexecutede MCP. No hay resolución implícita, ni siquiera con una sola conexión activa: la conexión es la empresa. El id sale deconexiones.estado.consultar.
Qué hace
Suma con decimales exactos los pedidos creados en el rango: subtotal, descuentos, impuestos, envío, bruto, reembolsado y neto (bruto − reembolsado). Excluye pedidos cancelados y de prueba. cobertura.completa es true solo si se leyeron todos los pedidos del rango y el historial alcanza; si no, cobertura.motivos dice por qué y, con mas_paginas, sigue con cobertura.siguientePagina y suma tú los resultados. Son pedidos, no cobros liquidados. Connect consulta Shopify en vivo y no guarda nada: cada llamada lee la tienda de la conexión.
Entrada
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
desde | string `^\d4-\d2-\d2T\d2:\d2(?::\d2(?:.\d9)?)?(?:Z | [+-]\d2:\d2)$` | sí |
hasta | string `^\d4-\d2-\d2T\d2:\d2(?::\d2(?:.\d9)?)?(?:Z | [+-]\d2:\d2)$` | sí |
pagina | string | no | El valor cobertura.siguientePagina de una respuesta anterior con el MISMO rango. |
JSON Schema de entrada
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"desde": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?(?:Z|[+-]\\d{2}:\\d{2})$",
"description": "Pedidos creados desde este instante (inclusive). Instante ISO 8601 con zona, por ejemplo `2026-10-01T00:00:00-03:00`."
},
"hasta": {
"type": "string",
"pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{1,9})?)?(?:Z|[+-]\\d{2}:\\d{2})$",
"description": "Pedidos creados antes de este instante (exclusive). Instante ISO 8601 con zona, por ejemplo `2026-10-01T00:00:00-03:00`."
},
"pagina": {
"description": "El valor `cobertura.siguientePagina` de una respuesta anterior con el MISMO rango.",
"type": "string",
"minLength": 1,
"maxLength": 4096
}
},
"required": [
"desde",
"hasta"
],
"additionalProperties": false
}Ejemplo
curl -X POST https://connect.emisso.ai/api/v1/tools/shopify.ventas.resumir/execute \
-H "Authorization: Bearer connect_sk_…" \
-H "X-Connect-Connection: conn_9tKfR2mQx4Vb" \
-H "Content-Type: application/json" \
-d '{"input":{"desde":"2026-10-01T00:00:00-03:00","hasta":"2026-10-16T00:00:00-03:00"}}'{
"tool": "shopify.ventas.resumir",
"params": {
"desde": "2026-10-01T00:00:00-03:00",
"hasta": "2026-10-16T00:00:00-03:00"
},
"connectionId": "conn_9tKfR2mQx4Vb"
}Salida esperada (200):
{
"data": {
"desde": "2026-10-01T03:00:00.000Z",
"hasta": "2026-10-16T03:00:00.000Z",
"moneda": "CLP",
"pedidos": 2,
"cancelados": 1,
"totales": {
"subtotal": "41970.0",
"descuentos": "2000.0",
"impuestos": "6701.0",
"envio": "3990.0",
"bruto": "45960.0",
"reembolsado": "12990.0",
"neto": "32970.0",
"actual": "32970.0"
},
"cobertura": {
"completa": true,
"motivos": [],
"siguientePagina": null,
"paginasLeidas": 1
},
"historial": {
"completo": false,
"diasDisponibles": 60
}
},
"meta": {
"request_id": "req_…",
"tool_id": "shopify.ventas.resumir",
"plane": "action",
"latency_ms": 7410,
"audit_status": "recorded"
}
}Si
cobertura.completaes false, no informes los totales como las ventas del período.
Salida
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
desde | string | sí | Inicio del rango pedido, en UTC (Z). |
hasta | string | sí | Fin del rango pedido, en UTC (Z). |
moneda | string ^[A-Z]{3}$ | sí | Moneda de la tienda: la de todos los totales. |
pedidos | entero | sí | Pedidos no cancelados ni de prueba que suman en esta respuesta. |
cancelados | entero | sí | Pedidos cancelados del rango leído; no suman. |
totales | objeto | sí | Sumas exactas como texto decimal, en la moneda de la tienda. |
totales.subtotal | string ^-?[0-9]{1,19}(?:\.[0-9]{1,9})?$ | sí | Suma de subtotales (después de descuentos). |
totales.descuentos | string ^-?[0-9]{1,19}(?:\.[0-9]{1,9})?$ | sí | Suma de descuentos. Informativa: ya está restada del subtotal y del bruto. |
totales.impuestos | string ^-?[0-9]{1,19}(?:\.[0-9]{1,9})?$ | sí | Suma de impuestos. |
totales.envio | string ^-?[0-9]{1,19}(?:\.[0-9]{1,9})?$ | sí | Suma de envíos. |
totales.bruto | string ^-?[0-9]{1,19}(?:\.[0-9]{1,9})?$ | sí | Suma de los totales de los pedidos antes de devoluciones (total). |
totales.reembolsado | string ^-?[0-9]{1,19}(?:\.[0-9]{1,9})?$ | sí | Suma de lo reembolsado de esos pedidos, a la fecha de la consulta. |
totales.neto | string ^-?[0-9]{1,19}(?:\.[0-9]{1,9})?$ | sí | bruto − reembolsado. Lo reembolsado se descuenta una sola vez. |
totales.actual | string ^-?[0-9]{1,19}(?:\.[0-9]{1,9})?$ | sí | Suma de los totales actuales (currentTotalPriceSet): ya descuenta devoluciones y quitas de líneas. Es otra medida que neto; no le restes reembolsado. |
cobertura | objeto | sí | Qué cubren estas sumas. |
cobertura.completa | booleano | sí | true solo si ESTA respuesta sumó TODOS los pedidos del rango que la conexión puede ver y el historial alcanza. Una respuesta pedida con pagina nunca es completa por sí sola: suma solo el tramo desde ese cursor. |
cobertura.motivos | lista de "mas_paginas" · "tope_paginas" · "tiempo_agotado" · "cupo_shopify" · "continuacion" · "historial_limitado" · … | sí | Por qué no es completa: mas_paginas (quedan pedidos; sigue con siguientePagina y suma tú los resultados), tope_paginas, tiempo_agotado o cupo_shopify (por qué paró esta llamada antes de terminar; siempre van con mas_paginas), continuacion (se pidió con pagina: los totales son solo de ese tramo; la serie está completa cuando la última respuesta ya no trae mas_paginas ni motivos de historial), historial_limitado (el rango empieza antes de los 60 días visibles sin read_all_orders) o historial_desconocido (Shopify no informó los permisos). |
cobertura.siguientePagina | string | null | sí |
cobertura.paginasLeidas | entero | sí | Páginas de Shopify leídas en esta llamada. |
historial | objeto | sí | Cuánto historial de pedidos alcanza esta conexión según los permisos concedidos en Shopify. |
historial.completo | booleano | null | sí |
historial.diasDisponibles | entero | null | sí |
JSON Schema de salida
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"desde": {
"type": "string",
"description": "Inicio del rango pedido, en UTC (Z)."
},
"hasta": {
"type": "string",
"description": "Fin del rango pedido, en UTC (Z)."
},
"moneda": {
"type": "string",
"pattern": "^[A-Z]{3}$",
"description": "Moneda de la tienda: la de todos los totales."
},
"pedidos": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991,
"description": "Pedidos no cancelados ni de prueba que suman en esta respuesta."
},
"cancelados": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991,
"description": "Pedidos cancelados del rango leído; no suman."
},
"totales": {
"type": "object",
"properties": {
"subtotal": {
"type": "string",
"pattern": "^-?[0-9]{1,19}(?:\\.[0-9]{1,9})?$",
"description": "Suma de subtotales (después de descuentos)."
},
"descuentos": {
"type": "string",
"pattern": "^-?[0-9]{1,19}(?:\\.[0-9]{1,9})?$",
"description": "Suma de descuentos. Informativa: ya está restada del subtotal y del bruto."
},
"impuestos": {
"type": "string",
"pattern": "^-?[0-9]{1,19}(?:\\.[0-9]{1,9})?$",
"description": "Suma de impuestos."
},
"envio": {
"type": "string",
"pattern": "^-?[0-9]{1,19}(?:\\.[0-9]{1,9})?$",
"description": "Suma de envíos."
},
"bruto": {
"type": "string",
"pattern": "^-?[0-9]{1,19}(?:\\.[0-9]{1,9})?$",
"description": "Suma de los totales de los pedidos antes de devoluciones (`total`)."
},
"reembolsado": {
"type": "string",
"pattern": "^-?[0-9]{1,19}(?:\\.[0-9]{1,9})?$",
"description": "Suma de lo reembolsado de esos pedidos, a la fecha de la consulta."
},
"neto": {
"type": "string",
"pattern": "^-?[0-9]{1,19}(?:\\.[0-9]{1,9})?$",
"description": "bruto − reembolsado. Lo reembolsado se descuenta una sola vez."
},
"actual": {
"type": "string",
"pattern": "^-?[0-9]{1,19}(?:\\.[0-9]{1,9})?$",
"description": "Suma de los totales actuales (`currentTotalPriceSet`): ya descuenta devoluciones y quitas de líneas. Es otra medida que `neto`; no le restes `reembolsado`."
}
},
"required": [
"subtotal",
"descuentos",
"impuestos",
"envio",
"bruto",
"reembolsado",
"neto",
"actual"
],
"additionalProperties": false,
"description": "Sumas exactas como texto decimal, en la moneda de la tienda."
},
"cobertura": {
"type": "object",
"properties": {
"completa": {
"type": "boolean",
"description": "true solo si ESTA respuesta sumó TODOS los pedidos del rango que la conexión puede ver y el historial alcanza. Una respuesta pedida con `pagina` nunca es completa por sí sola: suma solo el tramo desde ese cursor."
},
"motivos": {
"type": "array",
"items": {
"type": "string",
"enum": [
"mas_paginas",
"tope_paginas",
"tiempo_agotado",
"cupo_shopify",
"continuacion",
"historial_limitado",
"historial_desconocido"
]
},
"description": "Por qué no es completa: `mas_paginas` (quedan pedidos; sigue con `siguientePagina` y suma tú los resultados), `tope_paginas`, `tiempo_agotado` o `cupo_shopify` (por qué paró esta llamada antes de terminar; siempre van con `mas_paginas`), `continuacion` (se pidió con `pagina`: los totales son solo de ese tramo; la serie está completa cuando la última respuesta ya no trae `mas_paginas` ni motivos de historial), `historial_limitado` (el rango empieza antes de los 60 días visibles sin `read_all_orders`) o `historial_desconocido` (Shopify no informó los permisos)."
},
"siguientePagina": {
"anyOf": [
{
"type": "string",
"maxLength": 4096
},
{
"type": "null"
}
],
"description": "Pásalo en `pagina` para sumar el resto del rango; null si no quedan pedidos."
},
"paginasLeidas": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991,
"description": "Páginas de Shopify leídas en esta llamada."
}
},
"required": [
"completa",
"motivos",
"siguientePagina",
"paginasLeidas"
],
"additionalProperties": false,
"description": "Qué cubren estas sumas."
},
"historial": {
"type": "object",
"properties": {
"completo": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"description": "true si la tienda concedió `read_all_orders` y se ve todo el historial; false si solo se ven los últimos 60 días; null si Shopify no informó los permisos."
},
"diasDisponibles": {
"anyOf": [
{
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
{
"type": "null"
}
],
"description": "60 cuando el historial está limitado; null en otro caso."
}
},
"required": [
"completo",
"diasDisponibles"
],
"additionalProperties": false,
"description": "Cuánto historial de pedidos alcanza esta conexión según los permisos concedidos en Shopify."
}
},
"required": [
"desde",
"hasta",
"moneda",
"pedidos",
"cancelados",
"totales",
"cobertura",
"historial"
],
"additionalProperties": false
}Errores de esta tool
| Código | HTTP | Reintentable | Qué hacer |
|---|---|---|---|
connection_disabled | 403 | no | Reactívala en /connections o usa otra conexión del mismo sistema. |
connection_not_found | 404 | no | Usa uno de los connectionId que lista el error, o revisa la conexión en /connections. No hace falta reactivar nada. |
connection_credential_required | 428 | no | Crea un enlace con conexiones.enlace.crear (modo reconectar si la conexión ya existe) y pide a la persona que entregue la credencial de nuevo. No reintentes con la credencial anterior. |
connection_busy | 409 | sí | Espera unos segundos y reintenta. Es una espera transitoria: no necesitas volver a conectar ni ingresar la credencial otra vez. |
upstream_error | 502 | sí | Reintenta más tarde. Si persiste, el problema está en el sistema externo, no en tu integración. |
timeout | 504 | sí | Reintenta. Para sincronizaciones largas usa la vía asíncrona y consulta el estado del trabajo. |
connector_onboarding_required | 428 | no | Lee el mensaje: dice qué falta. Se completa en el portal de ese sistema, no en Connect, y después la llamada funciona sin cambios. |
connection_scope_not_enabled | 403 | no | Pide a un owner/admin que habilite el scope en /connections para esa conexión, o usa otra que ya lo tenga activo. Cambiar la credencial del actor no resuelve este error. |
rate_limited | 429 | sí | Espera y reintenta con backoff exponencial. |
upstream_unexpected_response | 502 | no | No reintentes: la respuesta es determinista. Repórtalo con el request_id para que actualicemos el conector. |
external_resource_not_found | 404 | no | Verifica el identificador con la tool de búsqueda del mismo sistema. Reintentar con el mismo identificador da el mismo resultado. |
Toda llamada puede devolver además los códigos transversales (validation_error, unauthorized, scope_not_granted, rate_limited, entre otros): el detalle vive en el catálogo de errores.