API de PriceZag — Conecta los datos de precios con tus sistemas

Utiliza la API JSON de PriceZag para consultar precios y existencias de competidores, gestionar productos y reglas de repricing, descargar informes y automatizar tareas.

Ejemplo rápido con curl

Sabemos que a los desarrolladores les gusta ver código funcional desde el principio. Estos comandos crean un producto de prueba y después lo consultan. Sustituye MYAPIKEY por la clave de tu cuenta (consulta Clave API).
Crear un producto de prueba:
curl -vX POST 'https://pricezag.com/api/v3/MYAPIKEY' -d '{"actions":[{"a":"productCreate","code":"000-SOME-TEST-PRODUCT","name":"Some Test Product created via PriceZag API","price":12.34,"currency":"USD"}]}'
(si ejecutas el comando por segunda vez, obtendrás un error porque el producto ya existe)
Ahora puedes consultar ese producto:
curl -X POST 'https://pricezag.com/api/v3/MYAPIKEY' -d '{"actions":[{"a":"productGet","code":"000-SOME-TEST-PRODUCT"}]}' | python -mjson.tool
(elimina | python -mjson.tool si no tienes esa herramienta para dar formato a la respuesta JSON en tu terminal)

Descripción general

Qué puedes hacer con la API de PriceZag

La API JSON de PriceZag permite que tus scripts y sistemas trabajen directamente con los precios y las existencias que monitorizamos. Consulta datos de productos, gestiona productos y categorías, calcula importes a partir de las reglas de repricing, configura alertas y descarga hojas de cálculo personalizadas. Puedes utilizar la API con cualquier plataforma de ecommerce o lenguaje de programación que permita enviar solicitudes HTTPS y procesar JSON.

También puedes pedir a tu asistente de IA favorito que escriba los scripts por ti. Facilítale la URL de esta documentación (https://pricezag.com/integrations/api), explica qué quieres automatizar e indica qué lenguaje de programación o plataforma de ecommerce utilizas. Mantén tu clave API en privado: no la pegues en una conversación con una IA.

PriceZag se encarga de la monitorización en nuestra plataforma, por lo que la API es opcional. Es útil cuando necesitas conectar tus propios sistemas con esos datos. Shopify y WooCommerce también disponen de integraciones directas.

Clave API y permisos

En tu cuenta de PriceZag, abre Automation > API. Haz clic en Reveal the current API key para ver la clave actual, o en Change the API key para sustituirla. Ambas operaciones solicitan la contraseña de tu cuenta. Tu usuario debe tener los permisos correspondientes para ver o generar claves API. Si no los tiene, consulta con un administrador de la cuenta.

Mantén la clave API en secreto. Puede permitir cambios importantes en los datos de la cuenta, incluso eliminaciones. No la incluyas en repositorios públicos, código del navegador ni conversaciones con IA. Si alguien te ayuda a crear una integración, asígnale un usuario de PriceZag con los permisos necesarios y cambia la clave API cuando corresponda.

El acceso mediante API depende de tu suscripción. Con acceso completo, tus scripts pueden trabajar con todos tus productos. Sin él, la API solo puede acceder a los 10 primeros productos ordenados alfanuméricamente por código de referencia. Por ejemplo, si tienes 1.000 productos con códigos desde SKU0001 hasta SKU1000, la API puede acceder desde SKU0001 hasta SKU0010. La prueba gratuita de 14 días incluye acceso completo a la API. También puedes activar el acceso completo como opción de tu suscripción.

Registro de actividad de la API y última solicitud

La página Automation > API de tu cuenta muestra la hora de la última solicitud a la API y un botón API Activity Log. Consúltalos si un script no funciona: así podrás comprobar si las solicitudes llegaron a PriceZag e investigar fallos o cambios inesperados.

Los cambios realizados mediante API también aparecen en el History of Edits de toda la cuenta, con el nombre de usuario API. Por ejemplo, en el historial de un producto podría aparecer Price edited by API en lugar de Price edited by JOHN. PriceZag admite varios usuarios en una misma cuenta, por lo que puedes distinguir los cambios automáticos de los realizados por miembros concretos de tu equipo.

URL y métodos de solicitud

Todas las solicitudes a la API utilizan la misma URL HTTPS. Envía solicitudes POST a esa dirección, sustituyendo MYAPIKEY por tu clave:

https://pricezag.com/api/v3/MYAPIKEY

Lo que quieres hacer con la API (las "actions") y sus parámetros se indica en el cuerpo JSON de la solicitud, no en la URL.
Envía un objeto JSON con una o varias acciones en el cuerpo de la solicitud POST. La URL es exactamente la misma tanto para consultar un producto como para actualizar precios o descargar una hoja de cálculo.

¿No puedes enviar POST?
Como último recurso puedes enviar una solicitud GET con el cuerpo JSON codificado en base64 en el parámetro de URL ?data=. Las URL tienen límites de longitud, así que es preferible utilizar POST.

Cómo funcionan las acciones

Lo que llamamos una acción es una operación que realizas en tu cuenta, como editar campos de un producto, modificar una regla de repricing o consultar los precios de todos los competidores de un producto.
La API y la interfaz de usuario (UI) ejecutan las mismas funciones en nuestros servidores, así que casi cualquier operación disponible en la interfaz también puede realizarse por API.
Cuando envías una solicitud a la API, el JSON contiene un array con todas las acciones que quieres ejecutar, de 1 a un máximo de 1.000 por solicitud. Puedes, por ejemplo, cambiar el nombre de tres productos y crear una categoría nueva con una sola solicitud de cuatro acciones. También puedes consultar 1.000 productos de una vez con 1.000 acciones "productGet".
Las acciones se ejecutan en el orden del array. Si creas una regla de repricing y después asignas productos a ella, debes enviar las acciones en ese orden para que la regla exista antes de editar los productos.
Desplázate hacia abajo para ver la lista de todas las acciones disponibles.

Tu objeto de solicitud JSON

Para scripts y código generado por IA: Los ejemplos de esta referencia contienen // comentarios y ... marcadores de posición para explicar los campos. Son ejemplos ilustrativos, no JSON válido para enviar sin cambios. Elimina los comentarios y marcadores antes de enviar una solicitud. Los dos ejemplos de curl anteriores sí contienen cuerpos JSON válidos.

Todos los datos POST deben formar un único objeto JSON {...} que contenga el array de acciones que se ejecutarán.
{
	"stopOnFailure"	: 1,  // (opcional) Por defecto seguimos con la siguiente acción aunque falle. Usa 1 para detener la ejecución.

	// Array con todas las acciones:
	"actions" : [
		// Acción 1:
		{
			"a"	: "someActionName",  // El nombre de la acción siempre es la variable "a" de cada objeto.
			"xx"	: "some parameter this action needs"	// Todo lo demas depende de los parámetros que necesite la acción.
		},
		// Acción 2:
		{
			"a"	: "anotherActionName",
			"abc"	: "some parameter this action needs",
			"xyz"	: {"x":"some object this action needs", "y":5, "z":6}
		},
		// Acción 3:
		{
			"a"	: "aThirdAction",
			"xyz"	: ["some array this action needs", "..."]
		}
	]
}

Respuesta del servidor y códigos HTTP

El servidor devuelve text/plain para errores relacionados con el formato de la solicitud o, por ejemplo, cuando la cuenta está desactivada. En esos casos, el texto contiene el mensaje de error.
Si la solicitud es correcta, normalmente recibirás un objeto JSON como respuesta, salvo algunas acciones marcadas como excepciones (por ejemplo, descargar una hoja de cálculo). Lo identificarás por la cabecera de respuesta Content-Type: application/json.
El código de respuesta HTTP es:
► 200 cuando todas las acciones se han ejecutado correctamente (ok=0 también se considera un resultado correcto)
► 406 cuando algunas acciones han funcionado y otras han fallado.
► 422 cuando todas las acciones han fallado, pero no por los motivos indicados a continuación.
► 400 cuando no se pudo decodificar el objeto JSON recibido.
► 403 cuando falla la autenticación (normalmente por una clave API incorrecta).
Si quieres simplificar tus scripts, puedes basarte en estos códigos de respuesta. Si necesitas más información, el objeto JSON devuelto contiene más detalles:
{
	"ok"		: 15,  // número de acciones ejecutadas correctamente (ok>0)
	"errors"	: 0,  // número de acciones que generaron un error (ok<0)
	"actionsCount"	: 20,  // total de acciones solicitadas inicialmente (longitud del array "actions")
	// NOTA: deducimos que 5 acciones devolvieron ok=0 (no fallaron, pero no cambiaron nada).
	
	// Array con todas las acciones solicitadas (en el mismo orden):
	"actions" : [
		...
		// Objeto de respuesta de cada acción:
		{
			"a"	: "someActionName",
			"ok"	: 4,		// Resultado: >0 = éxito, 0 = sin cambios, <0 = error
						// Por ejemplo, 0 si cambias un precio por el mismo que ya tenía.
						// -1 si el producto no existe.
						// >0 depende de la acción. Suele ser el número de campos o elementos modificados.
			"error"	: "...",  // Mensaje de error, si ok < 0
						// Nuestros mensajes de error siempre son detallados. Guárdalos en los registros
						// porque contienen la información necesaria para diagnosticar el problema.
			...	// Otros datos específicos devueltos por esta acción
		},
		...
	]
}

¿Ejemplos?

A veces resulta más fácil entenderlo con ejemplos. Consulta más ejemplos al final de esta página.

Límites de solicitudes y programación

Disponemos de un firewall que nos protege a nosotros y a ti frente a ataques o grandes volúmenes de solicitudes. Si bloquea un servidor, puede parecer que nuestro sitio está caído: sin conexión, respuesta ni ping.
Para evitar que tus solicitudes legítimas se bloqueen:
► No utilices una clave API incorrecta; el firewall tolera muy pocos intentos con claves erróneas (igual que con contraseñas incorrectas en nuestra web).
► Agrupa varias acciones en una sola solicitud y objeto JSON (máximo 1.000). Por ejemplo, para crear 1.000 productos envía una solicitud, no 1.000.
► Si necesitas muchas solicitudes, espera 500 ms entre ellas y reutiliza la misma conexión HTTPS. Abrir una conexión nueva por solicitud es un error habitual. Solo suele ser necesario hacer muchas solicitudes para modificar cientos de miles de productos, con 1.000 acciones por solicitud.
No existe un límite fijo de solicitudes por segundo; nuestro firewall decide según decenas de parámetros. En este caso, lo mejor es actuar con sentido común.
 
Solicitudes programadas:
Si programas solicitudes a intervalos regulares, añade una espera aleatoria para enviarlas en un segundo no habitual. Muchos clientes hacen solicitudes exactamente al principio del minuto (segundo 0). Así reducirás los tiempos de espera y el riesgo de agotamiento del tiempo de respuesta.

Todas las acciones de API disponibles

Cada acción se documenta a continuación con sus parámetros y ejemplos de solicitud y respuesta. El menú izquierdo enlaza directamente a cada acción.

Productos

AcciónFunción
productCreateCrear un producto nuevo
productEditEditar un producto existente
productCompetitorsEditar las URL de competidores de un producto (sin tener que sustituirlas todas)
productCategoriesEditar las categorías de uno o varios productos (sin tener que sustituirlas todas)
productRepricingAsignar muchos productos a una regla de repricing
productDeleteEliminar uno o varios productos
productGetConsultar un producto (y los datos de sus competidores)
productGetAllConsultar todos los productos (y los datos de sus competidores)

Categorías

AcciónFunción
categoryCreateCrear una categoría nueva
categoryEditEditar una categoría existente
categoryDeleteEliminar una o varias categorías
categoryCopyCopiar o mover productos entre categorías
categoryGetConsultar una categoría
categoryGetAllConsultar todas las categorías

Alertas

AcciónFunción
alertRecipientCreateCrear un destinatario de alertas
alertRecipientEditEditar un destinatario y/o sus reglas de alertas
alertRecipientDeleteEliminar un destinatario de alertas
alertRuleEditEditar una regla de alerta existente
alertRuleCreate ?Esa acción no existe. Usa alertRecipientEdit con un array "rulesAdd".
alertRuleDelete ?Esa acción no existe. Usa alertRecipientEdit con un array "rulesRemove".
alertGetAllConsultar todos los destinatarios y sus reglas de alertas

Reglas de repricing

AcciónFunción
repricingCreateCrear una regla de repricing
repricingEditEditar una regla de repricing existente
repricingDeleteEliminar una regla de repricing
repricingGetAllConsultar todas las reglas de repricing

Hojas de cálculo

AcciónFunción
spreadsheetDownloadDescargar una hoja de cálculo
spreadsheetPresetEditCambiar el nombre o eliminar un ajuste predefinido de exportación
spreadsheetAutoCreateCrear un envío automático de hojas de cálculo
spreadsheetAutoEditEditar un envío automático de hojas de cálculo

Competidores y más

AcciónFunción
competitorDeleteAllEliminar un competidor de todos los productos o categorías
mathEditDefinir o editar los cálculos de precios de un dominio competidor

Productos

productCreate - Crear un producto nuevo

Esta es la misma función que utiliza la interfaz en la página New Product.
{ "actions" : [
	...
	{
		"a"		: "productCreate",
		"code"		: "UNIQUE-REF-CODE",  // entre 1 y 80 ([a-z\d][a-z\d_-]{0,78}[a-z\d]); no distingue mayúsculas (se convierte a mayúsculas)
		"name"		: "The Product Name",  // entre 1 y 200
		"price"		: 1234.90,  // Cuidado con comas y puntos. Sin separador de miles; el decimal usa punto.
		"currency"	: "USD",
		"cost"		: 1234.90,  // (opcional)
		"costCurrency"	: "USD",  // obligatorio si hay coste
		"repricingRule"	: "The Rule Name",  // (opcional) Regla de repricing asignada (vacía = desactivada, inexistente = error)
		"myWebsite"	: "https://...",  // (opcional) URL o shopify:productId:variantId, o woocommerce:productId(:variationId)
		"competitors"	: ["https://...", "https://..."],  // (opcional)
		"categories"	: ["The Category 1", "The Category 2"],  // (opcional) categorías del producto (si no existen se crean)
		"comments"	: "Some comments\nAnd another line",  // (opcional) máximo 1000 caracteres UTF-8
		"custom_someFieldName1"	: "Value of custom field",		// (opcional)
		"custom_someFieldName2"	: "Value of other\nCustom\tField",  // (opcional)
		// Los campos personalizados son para tu uso interno. Pueden aparecer en muchos lugares, por ejemplo como columnas al exportar hojas de cálculo.
		// Hasta 20 campos personalizados por producto. Nombre de máximo 40 letras/cifras/guiones bajos (distingue mayúsculas), sin prefijo "custom_" (47 en total).
		// Valor máximo 500 bytes (normalmente caracteres). Puedes asignar un número (custom_varname:123),
		// pero siempre devolvemos cadenas (custom_varname:"123"); convierte los valores al leerlos si hace falta.
		// Para eliminar un campo personalizado, asigna "". No ocurre en productCreate, sino en productEdit.
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "productCreate",
			"ok"	: 1,
			"code"	: "REF-CODE",  // Código final en base de datos (podemos modificar caracteres especiales de tu código)
		},
		...
	]
}

productEdit - Editar un producto existente

Es la misma función que utiliza la interfaz al editar un campo de un producto. Sin embargo, la interfaz envía cada campo por separado, mientras que la API permite modificar, por ejemplo, el nombre y el precio en una sola llamada.
{ "actions" : [
	...
	{
		"a"		: "productEdit",
		"code"		: "REF-CODE",
		...		// Usa los parámetros de productCreate, todos opcionales.
		"newCode"	: "REF-CODE-RENAMED",  // (opcional)
		"competitors"	: ["https://...", "https://..."],  // Si se proporciona, SUSTITUYE todas las URL de competidores existentes.
		// Si solo quieres añadir o eliminar competidores de los existentes, utiliza en su lugar la acción productCompetitors.
		"categories"	: ["The Category 1", "The Category 2"],  // Si se proporciona, SUSTITUYE las categorías actuales. Como alternativa, usa productCategories o categoryEdit.
		"custom_someFieldName"	: "New value or empty to delete that custom field",
		// Máximo 20 campos personalizados por producto. Para añadir otros, quita antes algunos asignando "".
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "productEdit",
			"ok"	: 3,  // Número de cambios (p. ej. mi precio + 2 URLs de competidores = 3)
			"code"	: "REF-CODE",  // Código final nuevo en la base de datos (podemos adaptar caracteres especiales)
		},
		...
	]
}

productCompetitors - Editar las URL de competidores de un producto

Modifica las URL de competidores de un producto sin tener que sustituirlas todas (a diferencia de la acción productEdit ).
{ "actions" : [
	...
	{
		"a"			: "productCompetitors",
		"code"			: "REF-CODE",
		"competitorsAdd"	: ["https://...", "https://..."],  // (opcional) Añadir estas URL a las existentes
		"competitorsRemove"	: ["https://...", "example.com/a0ff80...5f00", "example.net"],  // (opcional) Quitar estos competidores. Cada elemento puede ser:
		// > La URL (incluido el modificador hashtag). Las etiquetas son opcionales.
		// > El "ref" del competidor (devuelto por otras acciones: dominio raíz y hash md5 de 32 caracteres)
		// > Dominio raíz o hostname completo; se quitaran todas las URL de ese dominio del producto.
		// NOTA: "competitorsAdd" y "competitorsRemove" también pueden ser cadenas en vez de arrays de un elemento.
		// Primero se quita y luego se añade: puedes quitar un dominio entero y añadir una URL suya.
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "productCompetitors",
			"ok"			: 3,  // Número de URL de competidores modificadas
			"competitorsAdded"	: 2,  // Número de URL de competidores añadidas al producto
			"competitorsRemoved"	: 1,  // Número de URL de competidores quitadas del producto
			// ERRORES:
			// > Añadir una URL ya existente NO genera error (ok = 0)
			// > Quitar una URL o "ref" inexistente genera error (ok = -1)
			// > Quitar todas las URL de un dominio inexistente NO genera error (ok = 0)
		},
		...
	]
}

productCategories - Editar las categorías de uno o varios productos

Modifica las categorías de uno o varios productos sin tener que sustituirlas todas (a diferencia de la acción productEdit).
Es la misma función que utiliza la interfaz cuando vas a All Products, seleccionas uno o varios productos y haces clic en Selected Products > Edit Categories. Puedes consultar esa pantalla para obtener una explicación más detallada.
También puedes revisar la acción categoryEdit para elegir cuál te conviene.
{ "actions" : [
	...
	{
		"a"			: "productCategories",
		"code"			: "REF-CODE",  // no distingue mayúsculas (cadena), O:
		"code"			: ["REF-CODE-1", "REF-CODE-2"],  // también puede ser un array con varios productos (máximo 100.000)
		"categoriesRemove"	: ["The Category 1", "The Category 2"],  // (opcional) Primero se quitan de estas categorías.
		"categoriesRemoveAll"	: 1,  // (opcional) Primero se quitan de todas las categorías (como productEdit).
		"deleteEmptyCategories"	: 1,  // Con esto cualquier categoría que quede vacía
		// como resultado de quitar productos se eliminara.
		"categoriesAdd"		: ["The Category 1", "The Category 2"],  // (opcional) Después añadir a estas categorías (si no existen, se crean)
		"categoriesAddClear"	: 1,  // (opcional) Primero vaciar las categorías a las que se añaden los productos
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "productCategories",
			"ok"	: 3,  // Número de productos modificados
		},
		...
	]
}

productRepricing - Asignar muchos productos a una regla de repricing

Asigna hasta 100.000 productos a una regla de repricing.
Hace lo mismo que la acción productEdit, pero cada solicitud admite un máximo de 1.000 acciones. Por eso, para asignar 50.000 productos con productEdit necesitarías 50 solicitudes y el proceso sería mucho más lento.
Si solo necesitas modificar unos pocos productos, puedes utilizar productEdit en su lugar.
{ "actions" : [
	...
	{
		"a"			: "productRepricing",
		"repricingRule"		: "The Rule Name",  // no distingue mayúsculas; "" (cadena vacía existente) significa sin regla (desactivar repricing)
		"products"		: ["REF-CODE-1", "REF-CODE-2"],  // no distingue mayúsculas (máximo 100.000)
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "productRepricing",
			"ok"		: 10,  // Número de productos modificados
			// Si todos los productos ya tenian esa regla, obtendras ok=0.
		},
		...
	]
}

productDelete - Eliminar uno o varios productos

ADVERTENCIA: el producto y sus URL de competidores se eliminan inmediatamente de tu cuenta y no se pueden recuperar.
Es la misma función que utiliza la interfaz cuando vas a All Products, seleccionas uno o varios productos y haces clic en Selected Products > Delete.
{ "actions" : [
	...
	{
		"a"	: "productDelete",
		"code"	: "REF-CODE",  // no distingue mayúsculas (cadena), O:
		"code"	: ["REF-CODE-1", "REF-CODE-2"],  // también puede ser un array para eliminar varios productos (máximo 100.000)
		"deleteEmptyCategories"	: 1,  // Con esto cualquier categoría que quede vacía
		// así se borran también las categorías que queden vacias
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "productDelete",
			"ok"	: 2,  // Número de productos eliminados correctamente
		},
		...
	]
}

productGet - Consultar un producto

{ "actions" : [
	...
	{
		"a"			: "productGet",
		"code"			: "REF-CODE",  // no distingue mayúsculas
		"currency"		: "EUR",  // (opcional) convierte todos los importes a esta moneda en lugar de la moneda del producto
		"withStats"		: 1,  // (opcional) devolver el objeto de estadísticas
		"noCompetitors"		: 1,  // (opcional) no devolver el array de competidores (respuesta más pequeña)
		"noComments"		: 1,  // (opcional) no devolver los comentarios (...)
		"withScreenshots"	: 1,  // (opcional) devolver la URL de la última captura para cada competidor
		"sickMax"		: 2,  // (opcional, predeterminado 1) 0-3; devolver solo URL con nivel de error hasta N
	},
	...
] }
Devuelve toda la información de un producto, incluidos los precios y las existencias actuales de sus competidores.
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "productGet",
			"ok"			: 1,
			"code"			: "REF-CODE",
			"name"			: "The Product Name",
			"price"			: 1234.90,  // Tu propio precio, siempre en la moneda original
			"currency"		: "USD",  // Moneda original de "price"
			"convCurrency"		: "EUR",  // Moneda de los importes convertidos ("currency" proporcionada o moneda original del producto)
			"priceConv"		: 1234.90,  // Precio propio convertido a "convCurrency", o igual que "price"
			"cost"			: 1234.90,
			"costCurrency"		: "USD",
			"costPriceConv"		: 1234.90,  // Coste propio convertido a la moneda de "currency"
			"costConv"		: 1234.90,  // Coste propio convertido a "convCurrency"
			"margin"		: 10.5,  // Porcentaje (puede ser negativo)
			"repricingRule"		: "The Rule Name",  // Estas 3 variables de repricing NO EXISTEN si no hay repricing.
			"reprice"		: 1234.90,  // Importe de repricing actual calculado según repricingRule
			"repriceCurrency"	: "USD",  // Igual que "convCurrency", solo para mayor claridad
			"myWebsite"		: "https://...",
			"created"		: 1234567890,  // Tiempo Epoch de creación del producto
			"createdBy"		: "SOMEUSER",  // Nombre del usuario o "API"
			"edited"		: 1234567890,  // Tiempo Epoch de la última edición (si la hubo)
			"editedBy"		: "SOMEUSER",  // Nombre del usuario o "API"
			"comments"		: "Some comments\nAnd another line",
			"commentsLast"		: 1234567890,  // Tiempo Epoch de la última edición de comentarios (si la hubo)
			"commentsLastBy"	: "SOMEUSER",  // Nombre del usuario o "API"
			"categories"		: ["The Category 1", "The Category 2"],
			"stats"		: {
				// Solo cuentan competidores de nivel 0 o 1 para estadísticas, independientemente de "sickMax".
				// Todos los importes están en "convCurrency", es decir "currency" o la moneda original del producto.
				// ADVERTENCIA: si no hay importe (p. ej. compIn* sin competidores con stock), el valor es 0.
				"rank"			: 1.23,  // Tu posición en precio (1 = nadie por debajo)
				"rankIn"		: 1.23,  // Tu posición entre competidores con stock
				"compCount"		: 3,  // Número de competidores con precio válido
				"compInCount"		: 3,  // Número de competidores con stock...
				"compOutCount"		: 3,  // Número de competidores sin stock ...
				"compAvg"		: 123.56,  // Media de todos los competidores
				"compAvgVsMe"		: 123.56,  // Diferencia (en convCurrency) entre tu precio y la media (negativo = eres más barato)
				"compInAvg"		: 123.56,  // Media de competidores con stock
				"compInAvgVsMe"		: 123.56,  // Como "compAvgVsMe", pero solo con stock
				"compLowest"		: 123.56,  // Competidor más barato
				"compLowestVsMe"	: 123.56,  // Como "compAvgVsMe", pero usando el mínimo en vez de la media
				"compInLowest"		: 123.56,  // Competidor más barato con stock
				"compInLowestVsMe"	: 123.56,  // Como "compInAvgVsMe", pero ...
				"compHighest"		: 123.56,  // Competidor más caro
				"compHighestVsMe"	: 123.56,  // Como "compAvgVsMe", pero ...
				"compInHighest"		: 123.56,  // Competidor más caro con stock
				"compInHighestVsMe"	: 123.56,  // Como "compInAvgVsMe", pero ...
			},
			"competitors"	: [
				// Array de competidores (más barato primero), cada uno es un objeto:
				...
				{
					"url"		: "https://...",  // Incluye cualquier modificador hashtag
					"ref"		: "example.com/123abc...def",
					// Referencia de URL (dominio raíz + md5 de 32 caracteres); así identificamos URL internamente.
					"domain"	: "example.com",  // Dominio raíz de este competidor
					"price"		: 1234.90,  // Ultimo importe encontrado (tras aplicar cálculos configurados)
					"currency"	: "USD",  // Moneda encontrada en el sitio
					"priceConv"	: 1234.90,  // Precio convertido a "convCurrency"
					"stock"		: "5",  // Inventario (cadena). "A" = disponible, "2" = 2 unidades, "0" = agotado, "" = desconocido.
					"salesWk"	: 123,  // ventas estimadas por semana (si hay datos; consulta la ayuda del producto)
					"screenshotURL"	: "https://pricezag.com/.../screenshot.png",
					// si "withScreenshots", URL de la última captura (enlace accesible sin inicio de sesión)
					"confidence"	: 98,
					// Porcentaje de confianza en el precio detectado (consulta (?) en el producto)
					// Por debajo del 70% (configurable) lo marcamos como "no fiable" con un signo de interrogación.
					// Es independiente del nivel de error. La URL puede fallar ahora aunque el último precio fuese correcto,
					// o funcionar pero no estar seguros de haber detectado el precio correcto.
					"sick"		: 0,  // Nivel de error de URL: de 0 a 3
					// 0: la última visita tuvo éxito (página cargada y precio encontrado)
					// 1: última visita fallida, pero hubo éxito recientemente (algo habitual)
					// 2: sin precio válido desde hace varios días
					// 3: sin precio válido desde hace varias semanas
					// NOTA: "price" y "priceConv" solo aparecen para URL con nivel <=1. Niveles 2 y 3 no tienen precio.
				},
				...
			],
			"custom"	: {
				// Estos son tus campos personalizados. Si no sabes como funcionan, abre
				// un producto en la interfaz y pulsa (?) junto a CUSTOM FIELDS.
				// Si no hay campos personalizados, no aparece el objeto "custom".
				"variable_1"	: "value 1",  // Los valores siempre son cadenas, incluso si representan números.
				"variable_2"	: "value 2",  // Un valor vacío no existe: habría eliminado esa variable.
				...
			}
		},
		...
	]
}

productGetAll - Consultar todos los productos

Asegúrate de que tus ajustes de timeout sean suficientemente altos: el servidor puede tardar según la cantidad de productos y competidores.
{ "actions" : [
	...
	{
		"a"			: "productGetAll",
		"currency"		: "EUR",  // (opcional) convertir importes a esta moneda en vez de a la moneda de cada producto
		"withStats"		: 1,  // (opcional) devolver el objeto de estadísticas
		"noCompetitors"		: 1,  // (opcional) no devolver el array de competidores (respuesta más pequeña)
		"noComments"		: 1,  // (opcional) no devolver los comentarios (...)
		"withScreenshots"	: 1,  // (opcional) devolver la URL de la última captura para cada competidor
		"sickMax"		: 2,  // (opcional, predeterminado 1) 0-3; devolver solo URL con nivel de error hasta N
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "productGetAll",
			"ok"		: 10,  // Número total de productos
			"products"	: [ // Array de productos (orden alfabético por código), cada producto como objeto:
				...
				{ ... },  // Objeto de producto igual al devuelto por la acción productGet (justo arriba)
				...
			],
		},
		...
	]
}
También puede interesarte la acción categoryGet .

Categorías

categoryCreate - Crear una categoría nueva

Esta es la misma función que utiliza la interfaz en la página Categories cuando haces clic en el botón New Category, salvo que con la API también puedes asignar productos mientras creas la categoría.
A diferencia de otras acciones que admiten categorías existentes o nuevas (por ejemplo, productCreate), esta acción fallará si alguna de las categorías ya existe.
{ "actions" : [
	...
	{
		"a"		: "categoryCreate",
		"name"		: "The New Category Name",
		"name"		: ["New Category 1", "New Category 2"],  // también puede ser un array
		"products"	: ["REF-CODE-1", "REF-CODE-2"],  // (opcional) Añadir estos productos a las categorías al crearlas
		"comments"	: "Some comments\nAnd another line",  // (opcional) máximo 1000 caracteres UTF-8
	},
	...
] }

categoryEdit - Editar una categoría existente

También puedes revisar la acción productCategories para elegir cuál te conviene.
{ "actions" : [
	...
	{
		"a"			: "categoryEdit",
		"name"			: "The Category Name",		// no distingue mayúsculas
		"newName"		: "The Category Renamed",  // (opcional)
		"products"		: ["REF-CODE-1", "REF-CODE-2"],  // (opcional) Sustituir la lista de productos
		"productsAdd"		: ["REF-CODE-1", "REF-CODE-2"],  // (opcional) Añadir productos a la categoría
		"productsRemove"	: ["REF-CODE-3", "REF-CODE-4"],  // (opcional) Quitar productos de la categoría (NO los elimina)
		"comments"		: "To overwrite the comments.",  // (opcional) máximo 1000 caracteres UTF-8
	},
	...
] }
Por tanto, "products", "productsAdd" y "productsRemove" hacen lo mismo: modifican los productos de la categoría, pero de formas distintas. Para quitar todos los productos utiliza "products" : []
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "categoryEdit",
			"ok"			: 5,  // Número de modificaciones
			// (renombrar y editar comentarios cuentan como 1 cada uno; también cada producto anadido o quitado)
			"name"			: "The Category Name",  // nombre nuevo si se renombro, o nombre anterior
			"productsCount"		: 30,  // Nueva cantidad de productos en categoría (haya cambiado o no)
			"productsAdded"		: 2,  // Número de productos anadidos a categoría
			"productsRemoved"	: 2,  // Número de productos quitados de categoría
		},
		...
	]
}

categoryDelete - Eliminar una o varias categorías

Es la misma función que utiliza la interfaz cuando vas a Categories, seleccionas las categorías correspondientes y haces clic en Selected Categories > Delete.
{ "actions" : [
	...
	{
		"a"			: "categoryDelete",
		"name"			: "The Category Name",  // no distingue mayúsculas (cadena), O:
		"name"			: ["Category 1", "Category 2"],  // también puede ser un array para eliminar varias categorías (máximo 1000)
		"deleteProducts"	: 1,
		// Por defecto se elimina la categoría, pero sus productos permanecen,
		// pero con deleteProducts, todos los productos de la categoria se eliminan sin confirmacion,
		// y sus URL de competidores también se borran sin posibilidad de recuperarlas!
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "categoryDelete",
			"ok"			: 2,  // Número de categorías eliminadas
			"productsCount"		: 123,  // Número de productos afectados por esas categorías
			"productsDeleted"	: 123,  // Número de productos eliminados mediante la opción "deleteProducts"
			// NOTA: un producto que pertenezca a varias categorías indicadas solo se cuenta una vez
		},
		...
	]
}

categoryCopy - Copiar o mover productos entre categorías

Copia o mueve productos desde unas categorías a otras, nuevas o existentes. También sirve para FUSIONAR categorías (consulta los ejemplos al final).
Esta operación no elimina productos: solo los cambia de categoría.
Es la misma función que utiliza la interfaz cuando vas a Categories, seleccionas las categorías correspondientes y haces clic en Selected Categories > Copy & More. Puedes consultar esa pantalla para obtener una explicación más detallada.
{ "actions" : [
	...
	{
		"a"			: "categoryCopy",
		"categoriesFrom"	: ["Category 1", "Category 2"],  // Buscar productos en estas categorías (origen)
		"removeMode"		: "cat",  // (opcional) Quitar los productos correspondientes de las "categoriesFrom" indicadas
		"removeMode"		: "all",  // (opcional) Quitar los productos correspondientes de todas sus categorías
		// Sin removeMode los productos permanecen en "categoriesFrom" y se añaden a "categoriesTo" (copiar, no mover)
		"deleteMode"		: "cat",  // (opcional) Eliminar las categorías "categoriesFrom" después de copiar
		"deleteMode"		: "all",  // (opcional) Eliminar todas las categorías a las que pertenecen esos productos
		// Si se omite deleteMode, "categoriesFrom" sigue existiendo aunque removeMode haya quitado sus productos.
		"categoriesTo"		: ["Another Category 1", "Another Category 2"],
		// Colocar todos los productos encontrados en estas categorías de destino (si no existen se crean)
		"categoriesToClear"	: 1,  // (opcional) Primero vaciar las categorías a las que se añaden los productos
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "categoryCopy",
			"ok"			: 3,  // Número de categorías modificadas (origen y destino)
			// "ok" es la suma de categoriesModified + categoriesCreated + categoriesDeleted
			"categoriesModified"	: 2,  // Número de categorías existentes modificadas (origen y destino)
			"categoriesCreated"	: 1,  // Número de categorías nuevas creadas
			"categoriesDeleted"	: 0,  // Número de categorías eliminadas mediante "deleteMode"
			"productsCount"		: 123,  // Número de productos encontrados en las "categoriesFrom" indicadas
			// NOTA: un producto en varias "categoriesFrom" indicadas solo se cuenta una vez
		},
		...
	]
}

categoryGet - Consultar una categoría

{ "actions" : [
	...
	{
		"a"		: "categoryGet",
		"name"		: "The Category Name",  // no distingue mayúsculas
		"currency"	: "EUR",  // (OBLIGATORIO si withStats o withProducts) moneda de las estadísticas
		"withStats"	: 1,  // devolver también las estadísticas (más lento)
		"withProducts"	: 1,  // devolver también los productos de la categoría (puede generar muchos datos)
		"noCompetitors"	: 1,  // si withProducts, no devolver el array de competidores (para reducir datos)
		"noComments"	: 1,  // si withProducts, no devolver comentarios de productos (si los de categoría)
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "categoryGet",
			"ok"			: 1,
			"name"			: "The Category Name",
			"created"		: 1234567890,  // Tiempo Epoch
			"createdBy"		: "SOMEUSER",  // Nombre del usuario o "API"
			"comments"		: "Comments of this category",
			"commentsLast"		: 1234567890,  // Tiempo Epoch de la última edición de comentarios (si la hubo)
			"commentsLastBy"	: "SOMEUSER",  // Nombre del usuario o "API"
			"productsCount"		: 10,  // Número de productos de la categoría
			"stats"		: {
				// Estas estadísticas aparecen en la UI de la categoría y como columnas en la lista de categorías.
				// Para detalles, seleccionalas como columna en la lista de categorías y pulsa (?).
				// Todos los importes están en la "currency" indicada en la solicitud.
				// ADVERTENCIA: si no hay importe (p. ej. compIn* sin competidores con stock), el valor es 0.
				"priceAvg"		: 123.45,  // Tu precio promedio
				"costAvg"		: 123.45,  // Solo productos con coste entran en esta media
				"marginAvg"		: 10.5,  // Porcentaje (puede ser negativo; solo productos con coste)
				"rankAvg"		: 1.23,  // Tu rango medio por precio (1 = nadie por debajo)
				"rankInAvg"		: 1.23,  // Tu rango medio entre competidores con stock
				"productsCountComp"	: 9,  // Número de productos con competidores
				"productsCountCompIn"	: 7,  // Número de productos con competidores con stock
				"compAvg"		: 123.56,  // Media de las medias de todos los competidores
				"compAvgVsMe"		: 123.56,  // Diferencia media (en currency) entre tu precio y los competidores (negativo = eres más barato)
				"compInAvg"		: 123.56,  // Como "compAvg", pero solo con competidores con stock
				"compInAvgVsMe"		: 123.56,  // Como "compAvgVsMe", pero solo con stock
				"compLowest"		: 123.56,  // Igual que "compAvg", pero promedio del competidor más barato de cada producto
				"compLowestVsMe"	: 123.56,  // Como "compAvgVsMe", pero ...
				"compInLowest"		: 123.56,  // Igual que "compInAvg", pero ...
				"compInLowestVsMe"	: 123.56,  // Como "compInAvgVsMe", pero ...
				"compHighest"		: 123.56,  // Igual que "compAvg", pero promedio del competidor más caro de cada producto
				"compHighestVsMe"	: 123.56,  // Como "compAvgVsMe", pero ...
				"compInHighest"		: 123.56,  // Igual que "compInAvg", pero ...
				"compInHighestVsMe"	: 123.56,  // Como "compInAvgVsMe", pero ...
			},
			"products"	: [ // Array de productos (orden alfabético por código), cada producto como objeto:
				...
				{ ... },  // Objeto de producto igual al devuelto por la acción productGet
				...
			],
		},
		...
	]
}

categoryGetAll - Consultar todas las categorías

A diferencia de categoryGet, la acción categoryGetAll no devuelve los detalles completos de cada producto. Un producto puede pertenecer a varias categorías y los datos serían demasiado grandes y repetitivos. Si necesitas esos detalles, puedes utilizar categoryGet para cada categoría, o productGetAll y después organizar los resultados por categorías.
{ "actions" : [
	...
	{
		"a"		: "categoryGetAll",
		"withStats"	: 1,  // devolver también las estadísticas (más lento)
		"noComments"	: 1,  // no devolver comentarios (para reducir datos)
		"noProducts"	: 1,  // no devolver array de productos (...)
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "categoryGetAll",
			"ok"		: 10,  // Total de categorías (longitud de array "categories")
			"categories"	: [ // Array de categorías (orden alfabético), cada una es un objeto:
				...
				{
					"name"			: "The Category Name",
					"created"		: 1234567890,  // Tiempo Epoch
					"createdBy"		: "SOMEUSER",  // Nombre del usuario o "API"
					"comments"		: "Comments of this category",
					"commentsLast"		: 1234567890,  // Tiempo Epoch de la última edición de comentarios (si la hubo)
					"commentsLastBy"	: "SOMEUSER",  // Nombre del usuario o "API"
					"productsCount"		: 2,  // Número de productos de la categoría
					"products"	: ["REF-CODE-1", "REF-CODE-2"],  // Codigos de sus productos (orden alfabético), salvo noProducts=1
					"stats"		: {
						// Si se usa "withStats", es el mismo objeto de estadísticas que en la acción categoryGet (justo arriba)
						...
					},
				}
				...
			],
		},
		...
	]
}

Alertas

alertRecipientCreate - Crear un destinatario de alertas

Es la misma función que utiliza la interfaz cuando vas a Alerts y haces clic en el botón New Recipient.
Haz clic en los iconos verdes con signo de interrogación de tu cuenta para ver los detalles de cada campo.
{ "actions" : [
	...
	{
		"a"		: "alertRecipientCreate",
		"email"		: "john@example.net",  // también puede ser teléfono para alertas SMS; consulta la ayuda en UI
		"name"		: "john",  // Nombre visible sencillo (normalmente nombre de pila; no distingue mayúsculas)
		"maxFrequency"	: 1800,  // (opcional, predeterminado 7200) consulta ayuda en UI
		"simplify"	: 0,  // (opcional, predeterminado 1) Activar simplificación (consulta UI)
		"sleepEnabled"	: 1,  // (opcional) Activar período de descanso
		"sleepFrom"	: "18:30",  // (solo si sleepEnabled) formato 24 horas
		"sleepTo"	: "07:00",  // (solo si sleepEnabled) formato 24 horas
		"timezone"	: "America/Los_Angeles",  // (solo si sleepEnabled) ruta de carpetas Linux /usr/share/zoneinfo
				// Los espacios se convierten en guiones bajos.
				// Busca tu zona horaria en [New Recipient] en la UI para indicar su nombre exacto.
		"status"	: "hold",  // (opcional) "hold" o "disable". Cualquier otro valor (como "") está activo.
		"rules"		: [...],  // (opcional) Reglas de alerta iniciales (array de objetos de regla), como "rulesAdd" en alertRecipientEdit más abajo
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "alertRecipientCreate",
			"ok"	: 1,
		},
		...
	]
}

alertRecipientEdit - Editar un destinatario y/o sus reglas de alertas

Es la misma función que utiliza la interfaz cuando vas a Alerts y haces clic en el botón Settings o Rules del destinatario.
Haz clic en los iconos verdes con signo de interrogación de tu cuenta para ver los detalles de cada campo.
La página "email" determina qué destinatario se modificará. Los demás campos cambian su configuración.
{ "actions" : [
	...
	{
		"a"		: "alertRecipientEdit",
		"email"		: "john@example.net",  // Correo electrónico o número de teléfono actual (exactamente en el formato devuelto por la acción alertGetAll)
		"newEmail"	: "john2@example.net",  // (opcional) Email o teléfono nuevo; consulta ayuda de UI
		"name"		: "john2",  // (opcional) Nombre nuevo
		"maxFrequency"	: 1800,  // (opcional) consulta ayuda en UI
		"simplify"	: 1,  // (opcional) Activar simplificación (consulta UI)
		"sleepEnabled"	: 1,  // (opcional) Activar período de descanso
		"sleepFrom"	: "18:30",  // (solo si sleepEnabled) formato 24 horas
		"sleepTo"	: "07:00",  // (solo si sleepEnabled) formato 24 horas
		"timezone"	: "America/Los_Angeles",  // (solo si sleepEnabled) consulta la acción alertRecipientCreate de arriba
		"status"	: "hold",  // (opcional) "hold" o "disable". Cualquier otro valor (como "") pasa a "active".
		"rules"		: [{ruleObject}, {ruleObject}],  // (opcional) Sustituir todas las reglas actuales (array vacía para quitarlas todas)
				  // No proporciones un array "rules" si quieres conservar las reglas actuales
		"rulesAdd"	: [ // (opcional) Añadir estas reglas a las actuales
			...
			{  // ESTE ES EL FORMATO DE OBJETO DE UNA REGLA:
				"name"		: "me_cross_avg",  // ve a Alerts > [Rules] > [+ New Rule] y selecciona una regla para ver su nombre API
				"disabled"	: 1,  // (opcional) No tiene mucho sentido crear una regla desactivada, pero la acción alertRuleEdit de abajo puede necesitarlo
				"var_n"		: 123.00,  // Una variable "X" se convierte en "var_x",
				"var_c"		: "USD",  // ... así que incluye lo que necesite esa regla,
				"var_h"		: 24,  // ... algunas reglas no requieren variables.
				"direction"	: "both",  // O "drop" o "rise" si la regla tiene dirección
				"categories"	: ["The Category 1", "The Category 2"],  // (opcional) Vacio u omitido significa TODOS LOS PRODUCTOS
				"ignoreOos"	: 1,  // (opcional) Ignorar competidores sin stock (ver UI)
				"urlInclude"	: "",  // (opcional, no distingue mayúsculas)
				"urlExclude"	: "amazon",  // (opcional, no distingue mayúsculas)
				// "ruleNumber" identifica cada regla (por ejemplo para editarla o eliminarla).
				// Lo veras al leer las reglas, pero no puedes asignarlo.
			}
			...
		],
		"rulesRemove"	: [1,4,7],  // (opcional) "ruleNumber" de las reglas que se quitaran
					// Obtendrás este "ruleNumber" de la acción alertGetAll de abajo.
					// NOTA: para quitar todas las reglas usa "rules" = [].
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "alertRecipientEdit",
			"ok"	: 3,  // Número de cambios (variables y reglas añadidas/eliminadas)
		},
		...
	]
}

alertRecipientDelete - Eliminar un destinatario de alertas

La eliminación es definitiva. Todas las reglas e historial de ese destinatario se borran de inmediato y no pueden recuperarse.
{ "actions" : [
	...
	{
		"a"		: "alertRecipientDelete",
		"email"		: "john@example.net",  // Correo electrónico o número de teléfono actual (exactamente en el formato devuelto por la acción alertGetAll)
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "alertRecipientDelete",
			"ok"	: 1,
		},
		...
	]
}

alertRuleEdit - Editar una regla de alerta existente

Permite modificar una regla de alerta existente sin sustituir ni añadir otras. Por ejemplo, puedes cambiar la variable N o activar o desactivar la regla.
Para eliminar una regla, utiliza el array "rulesRemove" de la acción alertRecipientEdit ; para añadir una nueva, utiliza su array "rulesAdd".
{ "actions" : [
	...
	{
		"a"		: "alertRuleEdit",
		"email"		: "john@example.net",  // Correo electrónico o número de teléfono del destinatario (exactamente en el formato devuelto por la acción alertGetAll)
		"ruleNumber"	: 1,  // Número de referencia de la regla que se va a editar, devuelto por la acción alertGetAll de abajo.
		"rule"		: {
			// Variables de la regla que se van a sobrescribir. Consulta "rulesAdd" en alertRecipientEdit más arriba para ver el FORMATO DEL OBJETO DE REGLA.
			"disabled"	: 1,  // por ejemplo activar o desactivar una regla
			"var_n"		: 5,  // u otra variable, como N, según el tipo de regla
			...
		},
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "alertRuleEdit",
			"ok"	: 1,  // Número de variables modificadas
		},
		...
	]
}

alertGetAll - Consultar todos los destinatarios y sus reglas de alertas

{ "actions" : [
	...
	{
		"a"	: "alertGetAll",
		// Esta acción no necesita parámetros
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "alertGetAll",
			"ok"		: 3,  // Número de destinatarios (longitud del array "recipients")
			"recipients"	: [ // Array de todos los destinatarios, cada uno representado por un objeto como el de la acción alertRecipientCreate de arriba
				...
				{
					"email"		: "john@example.net",
					"name"		: "john",
					"maxFrequency"	: 1800,
					"simplify"	: 0,
					"sleepEnabled"	: 1,
					"sleepFrom"	: "18:30",
					"sleepTo"	: "07:00",
					"timezone"	: "America/Los_Angeles",
					"status"	: "active",
					"rules"		: [ // Array de reglas, cada una representada por un objeto como se describe en la acción alertRecipientEdit de arriba
						...
						{
							"ruleNumber"	: 4,  // Número de referencia que debes usar para editar esta regla mediante la acción alertRuleEdit de arriba
							"name"		: "me_cross_avg",
							"disabled"	: 0,
							"var_n"		: "123.00",  // NOTA: devolvemos todas las variables como cadenas, incluso si son números
							"var_c"		: "USD",
							"var_h"		: "24",
							"direction"	: "both",
							"categories"	: [],  // vacío significa todos los productos
							"ignoreOos"	: 0,
							"urlInclude"	: "",
							"urlExclude"	: "amazon",
						}
						...
					],
				}
				...
			],
		},
		...
	]
}

Reglas de repricing

repricingCreate - Crear una regla de repricing

Es la misma función que utiliza la interfaz cuando vas a Repricing y haces clic en el botón New Repricing Rule.
Haz clic en los iconos verdes con signo de interrogación de tu cuenta para ver los detalles de cada campo.
¿Cómo asigno productos a la regla? Editando los productos mediante la acción productEdit o productRepricing . Una regla no contiene productos: cada producto hace referencia a la regla que utiliza.
{ "actions" : [
	...
	{
		"a"	: "repricingCreate",
		"name"	: "The Rule Name",  // máximo 50 caracteres
		"init"	: { // objeto inicial (primera fila "Fijar mi precio en")
			"target"	: "cheapest_n",  // (consulta la lista inferior)
			"var_n"		: 3,  // solo si el objetivo necesita variable N
			"plusAmount"	: -2,  // positivo: por encima; negativo: por debajo
			"plusCurrency"	: "%",  // moneda (p. ej. "USD") o "%"
			// Corresponde a "Fijar mi precio un 2 % por debajo de la media de los 3 competidores más baratos"
			// ADVERTENCIA: el objeto inicial no tiene "direction", a diferencia de "never". El signo de "plusAmount" determina arriba/abajo.
		},
		"never"	: [ // (opcional) objetos "but never" ejecutados en orden (máximo 10)
			{
				"target"	: "cheapest_n_in",  // (consulta la lista inferior)
				"var_n"		: 1,  // solo si el objetivo necesita variable N
				"direction"	: "below",  // o "above"
				"plusAmount"	: -10,  // positivo: suma; negativo: resta (obligatorio incluso si 0)
				"plusCurrency"	: "USD",  // moneda o "%" (obligatorio incluso si plusAmount=0)
				// Corresponde a "Pero nunca por debajo del competidor más barato con existencias menos 10,00 USD"
			},
			{
				"target"	: "cost",
				"direction"	: "below",
				"plusAmount"	: 5,
				"plusCurrency"	: "%",
				// Corresponde a "Pero nunca por debajo de mi coste más un 5 %"
			}
		],
		"ignoreDomains"	: "amazon ebay.com MyLabel1",  // (opcional) dominios o etiquetas que se ignoraran (sin distinguir mayúsculas; ver UI)
		"charm"		: "none|zeros|charm",  // (opcional, predeterminado "none") precios psicológicos ("", "none" u omitido son iguales)
		"confidence"	: 82,  // (opcional, predeterminado 70) confianza mínima 0-99% (ver UI)
		"disabled"	: 1,  // (opcional)
	},
	...
] }
// ========== Cadenas "target" disponibles: ==========
// "average" : Media de todos los competidores
// "average_in" : Media de competidores con stock
// "cheapest_n" : Media de N competidores más baratos (o el mínimo si N=1)
// "cheapest_n_in" : Media de N competidores más baratos con stock (o ...)
// "highest_n" : Media de N competidores más caros (o ...)
// "highest_n_in" : Media de N competidores más caros con stock (o ...)
// "cost" : Mi coste
// "me_avg_n" : Mi precio promedio de las últimas N horas (limita la velocidad de cambios)
// "domain:example.com" : precio de example.com (mínimo si hay varias URL)
// "domainIn:example.com" : precio de example.com solo con stock (...)
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "repricingCreate",
			"ok"	: 3,  // Número de objetos analizados y guardados (p. ej. init + never[0] + never[1] = 3)
			"name"	: "The Rule Name",  // Nombre final en la base de datos (podemos adaptar caracteres especiales)
		},
		...
	]
}

repricingEdit - Editar una regla de repricing existente

Modifica una regla de repricing existente.
Consulta repricingCreate más arriba para entender estas variables.
Modifica la regla, no los productos que la utilizan. Para asignar productos utiliza la acción productEdit o productRepricing en su lugar.
{ "actions" : [
	...
	{
		"a"		: "repricingEdit",
		"name"		: "The Rule Name",  // no distingue mayúsculas
		"newName"	: "The Rule Renamed",  // (opcional) máximo 50 caracteres
		"init"		: { // (opcional) Si se proporciona, sustituye variables del objeto inicial (ver repricingCreate)
			"plusAmount"	: 1,  // p. ej. cambiar solo "plusAmount" y conservar las demas variables
			// ADVERTENCIA: si el nuevo "target" requiere N debes proporcionar "var_n"
		},
		"never"		: [...], // (opcional) Puedes sustituir todo el array "never", pero suele convenir never_*
		// "never":[] borra todas las condiciones. Omite la variable para conservarlas.
		"never_0"	: { // (opcional) sustituir el primer objeto "but never" (indice 0)
			"var_n"		: 2,  // p. ej. cambiar solo "var_n" y conservar las demas variables
		},
		"never_2"	: {
			"target"	: "",  // desactiva la tercera condición "but never" (indice 2)
			// No te preocupes por las otras variables del objeto si "target" es "".
			// "never_2":{} hace lo mismo
		},
		"never_6"	: {...}, // Puede ser una nueva condición "but never"; requiere todas las variables como en repricingCreate
		// "never_9" es el máximo; el array "never" admite hasta 10 elementos
		"ignoreDomains"	: "",  // (opcional) igual que repricingCreate
		"charm"		: "zeros",  // (opcional) ...
		"confidence"	: 82,  // (opcional) ...
		"disabled"	: 1,  // (opcional) 0 para activar una regla desactivada
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "repricingEdit",
			"ok"	: 3,  // Número de cambios (una variable de never_N, otra de "init" y "charm", por ejemplo)
			"name"	: "The Rule Name",  // Nombre nuevo final en la base de datos (podemos adaptar caracteres especiales)
		},
		...
	]
}

repricingDelete - Eliminar una regla de repricing

La eliminación es definitiva. La regla se elimina de inmediato y no puede recuperarse. Los productos que la utilizaban se quedarán sin regla y su repricing dejará de funcionar.
{ "actions" : [
	...
	{
		"a"		: "repricingDelete",
		"name"		: "The Rule Name",  // no distingue mayúsculas
		"onlyIfUnused"	: 1,  // (opcional) Por seguridad, genera un error si algún producto utiliza esta regla
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "repricingDelete",
			"ok"		: 1,
			"productsCount"	: 10,  // Número de productos que utilizaban esta regla (ahora sin regla)
		},
		...
	]
}

repricingGetAll - Consultar todas las reglas de repricing

Consulta primero repricingCreate más arriba, porque el formato de la respuesta es muy parecido al que se envía a repricingCreate.
{ "actions" : [
	...
	{
		"a"	: "repricingGetAll",
		// Esta acción no requiere más parámetros
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "repricingGetAll",
			"ok"	: 10,  // Número total de reglas (longitud de "rules")
			"rules"	: [ // Array de reglas de repricing (orden alfabético), cada una como objeto:
				...
				{
					"name"		: "Some Repricing Rule",
					"created"	: 1234567890,  // Tiempo Epoch de creación de la regla
					"createdBy"	: "SOMEUSER",  // Nombre del usuario o "API"
					"edited"	: 1234567890,  // Última modificacion (si la hubo; en caso contrario variable ausente)
					"editedBy"	: "SOMEUSER",  // Usuario o "API" (o ausente)
					"disabled"	: 1234567890,  // Si la regla está desactivada: tiempo Epoch de la última desactivación; si no, ausente.
					"disabledBy"	: "SOMEUSER",  // Usuario o "API" (o ausente)
					"productsCount"	: 10,  // Número de productos que utilizan actualmente la regla
					"ignoreDomains"	: "amazon ebay.com MyLabel1",  // dominios o etiquetas de competidores ignorados (ver UI)
					"charm"		: "charm",  // modo de precios psicológicos (none|zeros|charm)
					"confidence"	: 82,  // confianza mínima 0-99% (ver UI)
					"init"	: { // objeto inicial (primera fila "Fijar mi precio en")
						"target"	: "cheapest_n",  // (consulta la lista en repricingCreate)
						"var_n"		: 3,  // si el objetivo requiere N; si no, ausente
						"plusAmount"	: -2,  // positivo: por encima; negativo: por debajo
						"plusCurrency"	: "%",  // moneda (p. ej. "USD") o "%"
						// Corresponde a "Fijar mi precio un 2 % por debajo de la media de los 3 competidores más baratos"
						// ADVERTENCIA: el objeto inicial no tiene "direction", a diferencia de "never". El signo de "plusAmount" determina arriba/abajo.
					},
					"never"	: [ // objetos "but never" ejecutados en orden
						{
							"target"	: "cheapest_n_in",
							"var_n"		: 1,
							"direction"	: "below",  // o "above"
							"plusAmount"	: -10,  // positivo: sumar; negativo: restar
							"plusCurrency"	: "USD",  // moneda o "%"
							// Corresponde a "Pero nunca por debajo del competidor más barato con existencias menos 10,00 USD"
						},
						{},  // Esta segunda fila de condiciones "But never" está vacía
						{
							"target"	: "cost",
							"direction"	: "below",
							"plusAmount"	: 5,
							"plusCurrency"	: "%",
							// Corresponde a "Pero nunca por debajo de mi coste más un 5 %"
						}
					],
				}
				...
			],
		},
		...
	]
}

Hojas de cálculo

spreadsheetDownload - Descargar una hoja de cálculo

Esta acción es una EXCEPCIÓN: no puedes combinarla con otras acciones y devuelve un archivo de hoja de cálculo en lugar de una respuesta JSON. (salvo que utilices "savePreset" o "downloadURL", como se explica más abajo)
Equivale a las opciones de la página Export de tu cuenta.
Asegúrate de que tus ajustes de timeout de espera sean suficientemente altos, porque generar un archivo grande puede tardar un poco.
UNA FORMA SENCILLA: Haz clic en el botón Show API equivalent de la página Export. Se generará toda la llamada JSON y el comando curl que corresponden a las opciones elegidas en el formulario.
{ "actions" : [
	{
		"a"		: "spreadsheetDownload",
		"preset"	: "Some Preset Name",  // (opcional) En lugar de indicar los parámetros siguientes, usa uno de tus ajustes predefinidos o nuestros
			// Para tus ajustes: nombre completo sin usuario delante ni moneda detrás.
			// Para nuestros ajustes, consulta nombres en DIRECT DOWNLOAD de Export (pasa el raton sobre ellos).
			// Por ejemplo "pricezag_backup" es un ajuste especial de copia de seguridad (ver "Special BACKUP format to re-import" en DIRECT DOWNLOAD)
			// Puedes indicar más variables para sustituir opciones del ajuste (otra moneda, formato o categorías).
		"savePreset"	: "My New Preset Name",  // (opcional) Guardar los parámetros siguientes como ajuste nuevo (utilizable en UI y API)
			// EXCEPCION DE LA EXCEPCION: con savePreset no se descarga archivo; devuelve un objeto JSON.
		"savePresetOverwrite"	: 1,  // (opcional) Sustituir un ajuste existente indicado en "savePreset" (sin esto habría error)
			// ADVERTENCIA: sustituir elimina todas las opciones anteriores; no cambies solo un campo.
			// Para cambiar el nombre de un ajuste predefinido o eliminarlo, utiliza la acción spreadsheetPresetEdit de abajo.
		"downloadURL"	: 1,  // (opcional) EXCEPCION: en vez del archivo devuelve JSON con "fileURL",
			// URL pública del archivo, sin clave ni inicio de sesión. Disponible 15 minutos para descargar desde cualquier lugar.
			// "ok" es el número de filas; también "fileSize" en bytes.
		"format"	: "xlsx|xls|csv|csv-tab",  // (predeterminado CSV para API)
		"currency"	: "USD",  // (OBLIGATORIO salvo con preset) moneda de TODOS los importes
		"categories"	: ["Category 1", "Category 2"],  // Solo productos de estas categorías (si se omite, todos)
		"historyPeriod"	: "prev_6mo",  // (opcional, predeterminado "now")
			// PRIMERO: consulta los (?) sobre períodos históricos en Export; contienen explicaciones importantes.
			// "historyPeriod" indica hasta cuanto retroceder; "historyRow" divide datos en filas por producto.
			// "now": sin historial, solo datos actuales (sin "historyRow")
			// "all": todo el historial disponible desde tu registro (o el de esos productos). PUEDE SER LENTO.
			// "1234500000-1237800000": intervalo propio (tiempos Epoch inicio-fin)
			// "123h": últimas 123 horas sin alinear al reloj; fin ahora y comienzo puede ser entre horas.
			// "cur_123(d|wk|mo|yr)": ultimos 123 días/semanas/meses/años incluyendo el período actual incompleto. "cur_2mo" el día 10 = 40 días.
			// "prev_123(d|wk|mo|yr)": 123 períodos anteriores completos. "prev_2mo" el 10 feb. = diciembre+enero (62 días).
			// Inicio de cur_* y prev_* (y fin de prev_*) se alinea a medianoche anterior; cur_* termina ahora.
			// Así "cur_2d" al mediodia cubre 36 horas; "prev_2d" cubre 48 horas hasta hace 12 horas.
		"historyRow"	: "2w",  // (obligatorio si "historyPeriod" no es "now")
			// "historyRow" define la duración de cada fila (media de ese período), varias filas por producto (salvo "all").
			// Piensa en "historyRow" como división de "historyPeriod" en filas por producto.
			// "all": media del historyPeriod completo, una fila por producto.
			// "123(d|wk|mo|qt|yr)": intervalos calendario de 123 días/semanas/meses/trimestres/años desde medianoche. 123 opcional si vale 1 ("wk" = "1wk")
			// Si descargas el sábado con historyRow:"7d", cada fila promedia sábado 00:00 - viernes 23:59.
			// Pero historyRow:"1wk" promedia lunes 00:00 - domingo 23:59; fila más reciente es semana actual incompleta.
			// LIMITE 500.000 FILAS: UI y API rechazan parámetros históricos que generan más de 500K filas.
			// Puede ocurrir con historyRow:"day" y un historyPeriod largo, p. ej. 365 días x 1400 productos.
			// Si lo necesitas, descarga un archivo por categoría de unos cientos de productos.
		"timezone"	: "America/Los_Angeles",  // (opcional, predeterminado "UTC") ruta de Linux /usr/share/zoneinfo
			// Los espacios se convierten en guiones bajos.
			// Zona horaria solo sirve si history* usa períodos de calendario (para calcular medianoche).
			// UI usa zona horaria del usuario; API no tiene ajuste y debe recibirla en solicitud.
		// ========== COLUMNAS: ==========
		// Las variables column* determinan columnas del archivo (consulta el formulario Export para detalles)
		// Predeterminado 0 (no incluir), salvo Code.
		"columnCode"		: 1,  // Esta columna no se puede quitar: siempre incluye REF-CODE.
		"columnName"		: 1,  // Nombre de producto
		"columnCategories"	: 1,  // Categorías del producto ("Category 1; Category 2" en una celda)
		"columnComments"	: 1,  // Comentarios de producto
		"columnCreated"		: 1,  // Fecha de creación YYYY/MM/DD (en nuestro sistema)
		"columnCustom"		: 1,  // Campos personalizados (una columna por cada variable única entre productos)
		"columnPrice"		: 1,  // Precio del producto en moneda solicitada (NO en su moneda original)
		"columnCost"		: 1,  // Coste del producto (en ...)
		"columnMargin"		: 1,  // Porcentaje de margen basado en precio y coste
		"columnRank"		: 1,  // Mi posición
		"columnInRank"		: 1,  // Mi posición entre los que tienen existencias
		"columnMyWebsite"	: 1,  // URL de mi sitio web
		"columnReprice"		: 1,  // Importe de repricing (en ...)
		"columnRepricingRule"	: 1,  // Nombre de regla de repricing
		"columnRecommended"	: 1,  // Precio recomendado (consulta ayuda en Export)
		"columnCompUrls"	: 1,  // URL de competidores (una por columna)
		"columnCompUrlsJoin"	: 1,  // URL de competidores (separadas por espacios en una celda)
		"columnCompMinMaxAvg"	: 1,  // Añade 3 columnas: Min/Max/Media de competidores
		"columnInCompMinMaxAvg"	: 1,  // Añade 3 columnas: Min/Max/Media de competidores CON STOCK
		"columnCompPrice"	: 1,  // Una columna por competidor con su precio (en ...)
		"columnCompStock"	: 1,  // Una columna por competidor con stock (123|IN|OUT)
		"columnCompSales"	: 1,  // Una columna por competidor con ventas/semana
		"columnCompRank"	: 1,  // Una columna por competidor con su posición entre todos (incluido tu)
		"columnCompInRank"	: 1,  // Una columna por competidor con su posición entre competidores CON STOCK (incluido tu)
		// ========== PARAMETROS AVANZADOS OCULTOS: ==========
		// También tenemos opciones no oficiales, poco documentadas; algunas las usa "pricezag_backup".
		"originalCurrencies"	: 1,  // En lugar de convertir importes en números en moneda elegida, pone texto con moneda original ("123.90 USD")
		"keepUrlLabels"		: 1,  // Normalmente quitamos etiquetas de las URL; esto las conserva (para copias de seguridad).
		"csvSeparator"		: ";",  // Para usar en CSV otro separador diferente de coma o tabulador.
		"csvNoQuote"		: 1,  // Impide comillas (") en CSV. Puede producir formato invalido.
	}
] }
// Ejemplo sencillo para descargar una copia CSV:
// curl --connect-timeout 15 --max-time 600 --retry 2 -X POST 'https://pricezag.com/api/v3/MYAPIKEY' -d '{"actions":[{"a":"spreadsheetDownload","preset":"pricezag_backup"}]}' -o pricezag-backup-20241225.csv

spreadsheetPresetEdit - Cambiar el nombre o eliminar un ajuste predefinido de exportación

Equivale a lo que puedes hacer en tu cuenta desde la página Export, haciendo clic en Edit Presets.
Solo sirve para CAMBIAR EL NOMBRE o ELIMINAR un ajuste predefinido. Para crearlo o modificarlo, utiliza la acción spreadsheetDownload anterior.
{ "actions" : [
	{
		"a"		: "spreadsheetPresetEdit",
		"preset"	: "Some Preset Name",  // Nombre actual del ajuste
		"newName"	: "The Renamed Preset",  // Renombrar este ajuste
		"delete"	: 1,  // Borra ese "preset" de la cuenta
		// NOTA: no se puede borrar un ajuste usado en un auto-export (error).
		// Borra antes los auto-exports programados (ver Export).
	}
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "spreadsheetPresetEdit",
			"ok"	: 1,
		},
		...
	]
}

spreadsheetAutoCreate - Crear un envío automático de hojas de cálculo

Equivale a lo que puedes hacer en tu cuenta desde la página Export, haciendo clic en Add a new Auto-Export.
{ "actions" : [
	{
		"a"			: "spreadsheetAutoCreate",
		"preset"		: "The Preset Name",
		"email"			: "john@example.net",
		"currency"		: "USD",  // (opcional) Valor predeterminado "preset": usa moneda del preset
		"attach"		: "link",  // (opcional, predeterminado "attach") "attach" para adjunto, "link" para enlace alojado
		"everyMonday"		: 1,  // Enviar hoja todos los lunes
		"everyTuesday"		: 1,  // ... y así todos los días hasta "everySunday"
		"everyMonthDay1"	: 15,  // Enviar cada día 15 del mes
		"everyMonthDay2"	: 21,  // ... y también cada día 21
		"everyMonthDay3"	: "last",  // ... y el último día de cada mes
			// everyMonthDay* de 0 a 9, máximo 10 días del mes
		"time"			: "3:59pm",  // "15.59" también sirve y equivale a "3:59pm". "0:9", "0.09", "00:09", "0:09am" son equivalentes.
		"timezone"		: "America/Los_Angeles",  // (opcional, predeterminado "UTC") ruta de Linux /usr/share/zoneinfo
			// Los espacios de ciudad se convierten en guiones bajos.
	}
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "spreadsheetAutoCreate",
			"ok"	: 1,
			"id"	: "5gwi6fqa",  // ID de referencia de esta exportación automática por si necesitas modificarla más adelante (consulta la acción spreadsheetAutoEdit de abajo)
		},
		...
	]
}

spreadsheetAutoEdit - Editar un envío automático de hojas de cálculo

Equivale a lo que puedes hacer en tu cuenta desde la página Export, haciendo clic en uno de los botones Edit de la lista situada bajo AUTO-EXPORT TO EMAIL.
{ "actions" : [
	{
		"a"			: "spreadsheetAutoEdit",
		"id"			: "5gwi6fqa",  // ID de referencia del auto-export a modificar
			// ID devuelto por spreadsheetAutoCreate; también aparece en el titulo de la ventana Edit de auto-export en UI.
		"disabled"		: 1,  // (opcional) 0 para activar un auto-export desactivado
		"delete"		: 1,  // (opcional) Eliminar completamente este auto-export
		// ===== Los siguientes campos (todos opcionales) son iguales a los de la acción spreadsheetAutoCreate de arriba =====
		"preset"		: "The Preset Name",
		"email"			: "john@example.net",
		"currency"		: "USD",
		"attach"		: "link",
		"everyMonday"		: 1,  // ADVERTENCIA: al indicar cualquier variable every*, se borran todas las variables every* anteriores.
		"everyMonthDay1"	: 15,  // Así, si tenias "everyFriday"=1 y asignas "everyMonthDay3", se quitara "everyFriday".
		// ... y así sucesivamente (ver every* en spreadsheetAutoCreate)
		"time"			: "3:59pm",
		"timezone"		: "America/Los_Angeles",
	}
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "spreadsheetAutoEdit",
			"ok"	: 3,  // Número de cambios
		},
		...
	]
}

Competidores y más

competitorDeleteAll - Eliminar un competidor de todos los productos o categorías

Elimina de forma masiva las URL de un competidor, de todos los productos o solo de los incluidos en categorías específicas.
ADVERTENCIA: las URL del competidor se eliminan inmediatamente de tu cuenta y no se pueden recuperar.
Es la misma función que utiliza la interfaz cuando abres la página de un competidor y haces clic en Delete from all Products, o cuando abres una categoría y haces clic en el icono (X) de la lista de competidores.
{ "actions" : [
	...
	{
		"a"		: "competitorDeleteAll",
		"domain"	: "competitordomain.com",
		"categories"	: ["The Category 1", "The Category 2"],  // (opcional) Si falta debes usar "allProducts" = 1
		"allProducts"	: 1,  // (opcional) quitar de todos los productos (NO proporcionar "categories")
		// Debes usar "categories" O "allProducts", nunca ambos ni ninguno.
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "competitorDeleteAll",
			"ok"	: 10,  // Número de URL eliminadas
		},
		...
	]
}

mathEdit - Definir o editar los cálculos de precios de un dominio competidor

Es la misma función que utiliza la interfaz cuando vas a Domains, haces clic en el dominio de un competidor y después en Mathematically alter the price. Las opciones de ese formulario también están disponibles mediante la acción API mathEdit.
Haz clic en los iconos verdes con signo de interrogación de tu cuenta para ver los detalles de cada campo.
{ "actions" : [
	...
	{
		"a"		: "mathEdit",
		"domain"	: "competitordomain.com",
		"clear"		: 1,  // (opcional) Desactivar todos los cálculos de ese dominio (borra ajustes anteriores)
		// Si clear:1, no puedes indicar más campos o habrá error.
		"math"	: [  // Array de bloques matematicos a aplicar
			{  // Objeto bloque matematico; todos los campos opcionales
				"categories"		: ["Category 1", "Category 2"],  // Solo productos de estas categorías
				"theirPriceMin"		: 1234.90,  // Solo si su precio es >= N
				"theirPriceMinCurrency"	: "USD",  // Moneda ("original" = moneda original del sitio)
				"theirPriceMax"		: 1234.90,  // ... <= N
				"theirPriceMaxCurrency"	: "USD",  // Moneda (...)
				"themMeMin"		: -20.00,  // Solo si [ellos - yo] >= N (ver UI)
				"themMeMinCurrency"	: "USD",  // Moneda o "%" de tu propio precio (NO "original")
				"themMeMax"		: -1.5,  // ... <= N
				"themMeMaxCurrency"	: "%",  // Moneda (...)
				"addPre"		: -10.00,  // Importe que se suma antes de multiplicar (negativo para restar)
				"addPreCurrency"	: "USD",  // Moneda ("original" = moneda original del sitio)
				"multiply"		: 1.1,  // Multiplicar por este factor
				"divide"		: 1.1,  // O dividir (no usar ambos)
				"addPost"		: 5.00,  // Importe que se suma tras multiplicar (negativo para restar)
				"addPostCurrency"	: "USD",  // Moneda (...)
				// Parece complicado? Mira el ejemplo sencillo debajo de la respuesta.
			},
			... // Máximo 10 bloques (aplicados por orden)
		],
		// NOTA: aún no se puede modificar un solo campo/bloque. Proporcionar el array "math" sustituye todo.
		// NOTA: un bloque sin multiplicacion/división (ausente o 1) ni addPre/addPost distintos de 0 se ignora;
		// si todos se ignoran, equivale a borrar todos los cálculos con clear:1.
		// En otras palabras, los cálculos deben hacer algo para guardarse.
		// TRUCO: para desactivar temporalmente cálculos de un dominio sin borrarlos,
		// usa categories: ["Some Empty Existing Category"]
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "mathEdit",
			"ok"	: 3,  // Número de bloques matematicos cambiados (quitar o limpiar también cuenta)
		},
		...
	]
}
EJEMPLO SENCILLO — Quitar un impuesto del 10% en todo amazon.co.uk:
{ "actions" : [
	{
		"a"		: "mathEdit",
		"domain"	: "amazon.co.uk",
		"math"		: [
			{
				"divide"	: 1.1
			}
		]
	}
] }

Más ejemplos

Estas solicitudes son datos POST enviados a https://pricezag.com/api/v3/MYAPIKEY
▶ EJEMPLO 1 — Actualizar el coste de un producto
SOLICITUD:
{
	"actions" : [
		{
			"a"		: "productEdit",
			"code"		: "SKU-1234",
			"cost"		: 140.50,
			"costCurrency"	: "EUR"
		}
	]
}
RESPUESTA:
{
	"ok"		: 1,  // devolveria 0 si SKU-1234 ya tenía ese coste
	"errors"	: 0,  // devolveria 1 si SKU-1234 no existiera
	"actionsCount"	: 1,
	"actions" : [
		{
			"a"	: "productEdit",
			"ok"	: 1  // 0 si coste igual, -1 si producto no existe
		}
	]
}

▶ EJEMPLO 2 — Consultar un producto inexistente
SOLICITUD:
{
	"actions" : [
		{
			"a"		: "productGet",
			"code"		: "NON-EXISTING-SKU",
			"currency"	: "USD"
		}
}
RESPUESTA:
{
	"ok"		: 0,  // porque ninguna acción devolvió ok>0
	"errors"	: 1,  // porque una acción devolvió ok<0
	"actionsCount"	: 1,
	"actions" : [
		{
			"a"	: "productGet",
			"ok"	: -1,  // así sabes que falló
			"error"	: "Sorry, the product #NON-EXISTING-SKU does not exist. Maybe someone else just removed or renamed it?"
		}
	]
}

▶ EJEMPLO 3 — Crear una categoría, una regla de repricing y después dos productos asignados a ambas
SOLICITUD:
{
	"actions" : [
		{
			"a"		: "categoryCreate",
			"name"		: "My New Category"
		},
		{
			"a"		: "repricingCreate",
			"name"		: "My New Repricing Rule",
			"init"	: {
				"target"	: "cheapest_n",
				"var_n"		: 2,
				"plusAmount"	: 0,
				"plusCurrency"	: "%"
				// Corresponde a "Fijar mi precio en el punto medio entre los 2 competidores más baratos"
			},
			"never"	: [
				{
					"target"	: "cost",
					"direction"	: "below",
					"plusAmount"	: 5,
					"plusCurrency"	: "%"
					// Corresponde a "Pero nunca por debajo de mi coste + 5 %"
				}
			],
			"charm"		: "charm"
		},
		{
			"a"		: "productCreate",
			"code"		: "SKU-1001",
			"name"		: "My New Product 1",
			"price"		: 199.90,
			"currency"	: "USD",
			"cost"		: 112.00,
			"costCurrency"	: "USD",
			"repricingRule"	: "My New Repricing Rule",  // mismo nombre de regla que acabamos de crear
			"categories"	: ["My New Category"],	// mismo nombre de categoría que acabamos de crear
			// ... aunque productCreate crea categorías inexistentes, así que categoryCreate era innecesario
			"competitors"	: ["https://...", "https://..."]
		},
		{
			"a"		: "productCreate",
			"code"		: "SKU-1002",
			"name"		: "My New Product 2",
			"price"		: 59.95,
			"currency"	: "USD",
			"cost"		: 31.50,
			"costCurrency"	: "USD",
			"repricingRule"	: "My New Repricing Rule",
			"categories"	: ["My New Category"],
			"competitors"	: ["https://...", "https://..."]
		}
	]
}
RESPUESTA:
{
	"ok"		: 4,  // porque las 4 acciones devolvieron ok>0
	"errors"	: 0,  // porque ninguna acción devolvió ok<0
	"actionsCount"	: 4,
	"actions" : [
		{
			"a"	: "categoryCreate",
			"ok"	: 1
		},
		{
			"a"	: "repricingCreate",
			"ok"	: 1
		},
		{
			"a"	: "productCreate",
			"ok"	: 1
		},
		{
			"a"	: "productCreate",
			"ok"	: 1
		}
	]
}

▶ EJEMPLO 4 — Fusionar dos categorías en otra y eliminar las dos originales
SOLICITUD:
{
	"actions" : [
		{
			"a"			: "categoryCopy",
			"categoriesFrom"	: ["Original Category 1", "Original Category 2"],
			"deleteMode"		: "cat",
			// "removeMode":"cat" es innecesario porque deleteMode borra las dos categorías
			"categoriesTo"		: ["A New Category"]
		}
}
RESPUESTA:
{
	"ok"		: 1,  // porque una acción devolvió ok>0
	"errors"	: 0,  // porque ninguna acción devolvió ok<0
	"actionsCount"	: 1,
	"actions" : [
		{
			"a"			: "categoryCopy",
			"ok"			: 3,  // porque cambiaron 3 categorías: dos originales eliminadas y un destino creado
			"categoriesCreated"	: 1,
			"categoriesDeleted"	: 2,
			"categoriesModified"	: 0,
			"productsCount"		: 123
		}
	]
}

▶ EJEMPLO 5 — Cambiar la variable N y la dirección de una regla de alerta
SOLICITUD:
{
	"actions" : [
		{
			"a"		: "alertRuleEdit",
			"email"		: "john@example.net",
			"ruleNumber"	: 3,
			"rule"		: {
				"var_n"		: 1.5,
				"direction"	: "drop"
			}
		}
}
RESPUESTA:
{
	"ok"		: 1,  // porque una acción devolvió ok>0
	"errors"	: 0,  // porque ninguna acción devolvió ok<0
	"actionsCount"	: 1,
	"actions" : [
		{
			"a"	: "alertRuleEdit",
			"ok"	: 2  // porque 2 variables se modificaron correctamente
		}
	]
}