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 reajuste de precios, 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. El periodo inicial con todas las funciones del plan Free Forever incluye acceso completo a la API. También puedes activar el acceso completo a la API 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 una matriz 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 de la matriz. 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 la matriz de acciones que se ejecutarán.
{
	"stopOnFailure"	: 1,  // (opcional) Por defecto seguimos con la siguiente accion aunque falle. Usa 1 para detener la ejecucion.

	// Matriz con todas las acciones:
	"actions" : [
		// Accion 1:
		{
			"a"	: "someActionName",  // El nombre de la accion siempre es la variable "a" de cada objeto.
			"xx"	: "some parameter this action needs"	// Todo lo demas depende de los parametros que necesite la accion.
		},
		// Accion 2:
		{
			"a"	: "anotherActionName",
			"abc"	: "some parameter this action needs",
			"xyz"	: {"x":"some object this action needs", "y":5, "z":6}
		},
		// Accion 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,  // numero de acciones ejecutadas correctamente (ok>0)
	"errors"	: 0,  // numero de acciones que generaron un error (ok<0)
	"actionsCount"	: 20,  // total de acciones solicitadas inicialmente (longitud de la matriz "actions")
	// NOTA: deducimos que 5 acciones devolvieron ok=0 (no fallaron, pero no cambiaron nada).
	
	// Matriz con todas las acciones solicitadas (en el mismo orden):
	"actions" : [
		...
		// Objeto de respuesta de cada accion:
		{
			"a"	: "someActionName",
			"ok"	: 4,		// Resultado: >0 = exito, 0 = sin cambios, <0 = error
						// Por ejemplo, 0 si cambias un precio por el mismo que ya tenia.
						// -1 si el producto no existe.
						// >0 depende de la accion. Suele ser el numero de campos o elementos modificados.
			"error"	: "...",  // Mensaje de error, si ok < 0
						// Nuestros mensajes de error siempre son detallados. Guardalos en los registros
						// porque contienen la informacion necesaria para diagnosticar el problema.
			...	// Otros datos especificos devueltos por esta accion
		},
		...
	]
}

¿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 una matriz "rulesAdd".
alertRuleDelete ?Esa acción no existe. Usa alertRecipientEdit con una matriz "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 mayusculas (se convierte a mayusculas)
		"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 (vacia = 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) categorias del producto (si no existen se crean)
		"comments"	: "Some comments\nAnd another line",  // (opcional) maximo 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 calculo.
		// Hasta 20 campos personalizados por producto. Nombre de maximo 40 letras/cifras/guiones bajos (distingue mayusculas), sin prefijo "custom_" (47 en total).
		// Valor maximo 500 bytes (normalmente caracteres). Puedes asignar un numero (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",  // Codigo final en base de datos (podemos modificar caracteres especiales de tu codigo)
		},
		...
	]
}

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 parametros 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 categorias actuales. Como alternativa, usa productCategories o categoryEdit.
		"custom_someFieldName"	: "New value or empty to delete that custom field",
		// Maximo 20 campos personalizados por producto. Para anadir otros, quita antes algunos asignando "".
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "productEdit",
			"ok"	: 3,  // Numero de cambios (p. ej. mi precio + 2 URLs de competidores = 3)
			"code"	: "REF-CODE",  // Codigo 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) Anadir 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 raiz y hash md5 de 32 caracteres)
		// > Dominio raiz o hostname completo; se quitaran todas las URL de ese dominio del producto.
		// NOTA: "competitorsAdd" y "competitorsRemove" tambien pueden ser cadenas en vez de matrices de un elemento.
		// Primero se quita y luego se anade: puedes quitar un dominio entero y anadir una URL suya.
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "productCompetitors",
			"ok"			: 3,  // Numero de URL de competidores modificadas
			"competitorsAdded"	: 2,  // Numero de URL de competidores anadidas al producto
			"competitorsRemoved"	: 1,  // Numero de URL de competidores quitadas del producto
			// ERRORES:
			// > Anadir 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 mayusculas (cadena), O:
		"code"			: ["REF-CODE-1", "REF-CODE-2"],  // tambien puede ser una matriz con varios productos (maximo 100.000)
		"categoriesRemove"	: ["The Category 1", "The Category 2"],  // (opcional) Primero se quitan de estas categorias.
		"categoriesRemoveAll"	: 1,  // (opcional) Primero se quitan de todas las categorias (como productEdit).
		"deleteEmptyCategories"	: 1,  // Con esto cualquier categoria que quede vacia
		// como resultado de quitar productos se eliminara.
		"categoriesAdd"		: ["The Category 1", "The Category 2"],  // (opcional) Despues anadir a estas categorias (si no existen, se crean)
		"categoriesAddClear"	: 1,  // (opcional) Primero vaciar las categorias a las que se anaden los productos
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "productCategories",
			"ok"	: 3,  // Numero 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 mayusculas; "" (cadena vacia existente) significa sin regla (desactivar repricing)
		"products"		: ["REF-CODE-1", "REF-CODE-2"],  // no distingue mayusculas (maximo 100.000)
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "productRepricing",
			"ok"		: 10,  // Numero 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 mayusculas (cadena), O:
		"code"	: ["REF-CODE-1", "REF-CODE-2"],  // tambien puede ser una matriz para eliminar varios productos (maximo 100.000)
		"deleteEmptyCategories"	: 1,  // Con esto cualquier categoria que quede vacia
		// asi se borran tambien las categorias que queden vacias
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "productDelete",
			"ok"	: 2,  // Numero de productos eliminados correctamente
		},
		...
	]
}

productGet - Consultar un producto

{ "actions" : [
	...
	{
		"a"			: "productGet",
		"code"			: "REF-CODE",  // no distingue mayusculas
		"currency"		: "EUR",  // (opcional) convierte todos los importes a esta moneda en lugar de la moneda del producto
		"withStats"		: 1,  // (opcional) devolver el objeto de estadisticas
		"noCompetitors"		: 1,  // (opcional) no devolver la matriz de competidores (respuesta mas pequena)
		"noComments"		: 1,  // (opcional) no devolver los comentarios (...)
		"withScreenshots"	: 1,  // (opcional) devolver la URL de la ultima 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 "price"
			"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 segun repricingRule
			"repriceCurrency"	: "USD",  // Igual que "convCurrency", solo para mayor claridad
			"myWebsite"		: "https://...",
			"created"		: 1234567890,  // Tiempo Epoch de creacion del producto
			"createdBy"		: "SOMEUSER",  // Nombre del usuario o "API"
			"edited"		: 1234567890,  // Tiempo Epoch de la ultima edicion (si la hubo)
			"editedBy"		: "SOMEUSER",  // Nombre del usuario o "API"
			"comments"		: "Some comments\nAnd another line",
			"commentsLast"		: 1234567890,  // Tiempo Epoch de la ultima edicion 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 estadisticas, independientemente de "sickMax".
				// Todos los importes estan 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 posicion en precio (1 = nadie por debajo)
				"rankIn"		: 1.23,  // Tu posicion entre competidores con stock
				"compCount"		: 3,  // Numero de competidores con precio valido
				"compInCount"		: 3,  // Numero de competidores con stock...
				"compOutCount"		: 3,  // Numero 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 mas barato)
				"compInAvg"		: 123.56,  // Media de competidores con stock
				"compInAvgVsMe"		: 123.56,  // Como "compAvgVsMe", pero solo con stock
				"compLowest"		: 123.56,  // Competidor mas barato
				"compLowestVsMe"	: 123.56,  // Como "compAvgVsMe", pero usando el minimo en vez de la media
				"compInLowest"		: 123.56,  // Competidor mas barato con stock
				"compInLowestVsMe"	: 123.56,  // Como "compInAvgVsMe", pero ...
				"compHighest"		: 123.56,  // Competidor mas caro
				"compHighestVsMe"	: 123.56,  // Como "compAvgVsMe", pero ...
				"compInHighest"		: 123.56,  // Competidor mas caro con stock
				"compInHighestVsMe"	: 123.56,  // Como "compInAvgVsMe", pero ...
			},
			"competitors"	: [
				// Matriz de competidores (mas barato primero), cada uno es un objeto:
				...
				{
					"url"		: "https://...",  // Incluye cualquier modificador hashtag
					"ref"		: "example.com/123abc...def",
					// Referencia de URL (dominio raiz + md5 de 32 caracteres); asi identificamos URL internamente.
					"domain"	: "example.com",  // Dominio raiz de este competidor
					"price"		: 1234.90,  // Ultimo importe encontrado (tras aplicar calculos 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 ultima captura (enlace accesible sin inicio de sesion)
					"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 interrogacion.
					// Es independiente del nivel de error. La URL puede fallar ahora aunque el ultimo 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 ultima visita tuvo exito (pagina cargada y precio encontrado)
					// 1: ultima visita fallida, pero hubo exito recientemente (algo habitual)
					// 2: sin precio valido desde hace varios dias
					// 3: sin precio valido 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 numeros.
				"variable_2"	: "value 2",  // Un valor vacio no existe: habria 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 estadisticas
		"noCompetitors"		: 1,  // (opcional) no devolver la matriz de competidores (respuesta mas pequena)
		"noComments"		: 1,  // (opcional) no devolver los comentarios (...)
		"withScreenshots"	: 1,  // (opcional) devolver la URL de la ultima 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,  // Numero total de productos
			"products"	: [ // Matriz de productos (orden alfabetico por codigo), 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"],  // tambien puede ser una matriz
		"products"	: ["REF-CODE-1", "REF-CODE-2"],  // (opcional) Anadir estos productos a las categorias al crearlas
		"comments"	: "Some comments\nAnd another line",  // (opcional) maximo 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 mayusculas
		"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) Anadir productos a la categoria
		"productsRemove"	: ["REF-CODE-3", "REF-CODE-4"],  // (opcional) Quitar productos de la categoria (NO los elimina)
		"comments"		: "To overwrite the comments.",  // (opcional) maximo 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,  // Numero de modificaciones
			// (renombrar y editar comentarios cuentan como 1 cada uno; tambien cada producto anadido o quitado)
			"name"			: "The Category Name",  // nombre nuevo si se renombro, o nombre anterior
			"productsCount"		: 30,  // Nueva cantidad de productos en categoria (haya cambiado o no)
			"productsAdded"		: 2,  // Numero de productos anadidos a categoria
			"productsRemoved"	: 2,  // Numero de productos quitados de categoria
		},
		...
	]
}

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 mayusculas (cadena), O:
		"name"			: ["Category 1", "Category 2"],  // tambien puede ser una matriz para eliminar varias categorias (maximo 1000)
		"deleteProducts"	: 1,
		// Por defecto se elimina la categoria, pero sus productos permanecen,
		// pero con deleteProducts, todos los productos de la categoria se eliminan sin confirmacion,
		// y sus URL de competidores tambien se borran sin posibilidad de recuperarlas!
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "categoryDelete",
			"ok"			: 2,  // Numero de categorias eliminadas
			"productsCount"		: 123,  // Numero de productos afectados por esas categorias
			"productsDeleted"	: 123,  // Numero de productos eliminados mediante la opcion "deleteProducts"
			// NOTA: un producto que pertenezca a varias categorias 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 categorias (origen)
		"removeMode"		: "cat",  // (opcional) Quitar los productos correspondientes de las "categoriesFrom" indicadas
		"removeMode"		: "all",  // (opcional) Quitar los productos correspondientes de todas sus categorias
		// Sin removeMode los productos permanecen en "categoriesFrom" y se anaden a "categoriesTo" (copiar, no mover)
		"deleteMode"		: "cat",  // (opcional) Eliminar las categorias "categoriesFrom" despues de copiar
		"deleteMode"		: "all",  // (opcional) Eliminar todas las categorias 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 categorias de destino (si no existen se crean)
		"categoriesToClear"	: 1,  // (opcional) Primero vaciar las categorias a las que se anaden los productos
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"			: "categoryCopy",
			"ok"			: 3,  // Numero de categorias modificadas (origen y destino)
			// "ok" es la suma de categoriesModified + categoriesCreated + categoriesDeleted
			"categoriesModified"	: 2,  // Numero de categorias existentes modificadas (origen y destino)
			"categoriesCreated"	: 1,  // Numero de categorias nuevas creadas
			"categoriesDeleted"	: 0,  // Numero de categorias eliminadas mediante "deleteMode"
			"productsCount"		: 123,  // Numero 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 mayusculas
		"currency"	: "EUR",  // (OBLIGATORIO si withStats o withProducts) moneda de las estadisticas
		"withStats"	: 1,  // devolver tambien las estadisticas (mas lento)
		"withProducts"	: 1,  // devolver tambien los productos de la categoria (puede generar muchos datos)
		"noCompetitors"	: 1,  // si withProducts, no devolver la matriz de competidores (para reducir datos)
		"noComments"	: 1,  // si withProducts, no devolver comentarios de productos (si los de categoria)
	},
	...
] }
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 ultima edicion de comentarios (si la hubo)
			"commentsLastBy"	: "SOMEUSER",  // Nombre del usuario o "API"
			"productsCount"		: 10,  // Numero de productos de la categoria
			"stats"		: {
				// Estas estadisticas aparecen en la UI de la categoria y como columnas en la lista de categorias.
				// Para detalles, seleccionalas como columna en la lista de categorias y pulsa (?).
				// Todos los importes estan 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,  // Numero de productos con competidores
				"productsCountCompIn"	: 7,  // Numero 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 mas 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 mas 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 mas caro de cada producto
				"compHighestVsMe"	: 123.56,  // Como "compAvgVsMe", pero ...
				"compInHighest"		: 123.56,  // Igual que "compInAvg", pero ...
				"compInHighestVsMe"	: 123.56,  // Como "compInAvgVsMe", pero ...
			},
			"products"	: [ // Matriz de productos (orden alfabetico por codigo), 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 tambien las estadisticas (mas lento)
		"noComments"	: 1,  // no devolver comentarios (para reducir datos)
		"noProducts"	: 1,  // no devolver matriz de productos (...)
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "categoryGetAll",
			"ok"		: 10,  // Total de categorias (longitud de matriz "categories")
			"categories"	: [ // Matriz de categorias (orden alfabetico), 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 ultima edicion de comentarios (si la hubo)
					"commentsLastBy"	: "SOMEUSER",  // Nombre del usuario o "API"
					"productsCount"		: 2,  // Numero de productos de la categoria
					"products"	: ["REF-CODE-1", "REF-CODE-2"],  // Codigos de sus productos (orden alfabetico), 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",  // tambien puede ser telefono para alertas SMS; consulta la ayuda en UI
		"name"		: "john",  // Nombre visible sencillo (normalmente nombre de pila; no distingue mayusculas)
		"maxFrequency"	: 1800,  // (opcional, predeterminado 7200) consulta ayuda en UI
		"simplify"	: 0,  // (opcional, predeterminado 1) Activar simplificacion (consulta UI)
		"sleepEnabled"	: 1,  // (opcional) Activar periodo 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 "") esta activo.
		"rules"		: [...],  // (opcional) Reglas de alerta iniciales (matriz 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 telefono nuevo; consulta ayuda de UI
		"name"		: "john2",  // (opcional) Nombre nuevo
		"maxFrequency"	: 1800,  // (opcional) consulta ayuda en UI
		"simplify"	: 1,  // (opcional) Activar simplificacion (consulta UI)
		"sleepEnabled"	: 1,  // (opcional) Activar periodo 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 (matriz vacia para quitarlas todas)
				  // No proporciones una matriz "rules" si quieres conservar las reglas actuales
		"rulesAdd"	: [ // (opcional) Anadir 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",  // ... asi 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 direccion
				"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 mayusculas)
				"urlExclude"	: "amazon",  // (opcional, no distingue mayusculas)
				// "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,  // Numero de cambios (variables y reglas anadidas/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 la matriz "rulesRemove" de la acción alertRecipientEdit ; para añadir una nueva, utiliza su matriz "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, segun el tipo de regla
			...
		},
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "alertRuleEdit",
			"ok"	: 1,  // Numero de variables modificadas
		},
		...
	]
}

alertGetAll - Consultar todos los destinatarios y sus reglas de alertas

{ "actions" : [
	...
	{
		"a"	: "alertGetAll",
		// Esta accion no necesita parametros
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "alertGetAll",
			"ok"		: 3,  // Numero de destinatarios (longitud de la matriz "recipients")
			"recipients"	: [ // Matriz 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"		: [ // Matriz 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 numeros
							"var_c"		: "USD",
							"var_h"		: "24",
							"direction"	: "both",
							"categories"	: [],  // vacio 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",  // maximo 50 caracteres
		"init"	: { // objeto inicial (primera fila "Set my price to")
			"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 "Set my price 2% below average of 3 cheapest competitors"
			// 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 (maximo 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 "But never below the cheapest competitor in-stock minus 10.00 USD"
			},
			{
				"target"	: "cost",
				"direction"	: "below",
				"plusAmount"	: 5,
				"plusCurrency"	: "%",
				// Corresponde a "But never below my cost plus 5%"
			}
		],
		"ignoreDomains"	: "amazon ebay.com MyLabel1",  // (opcional) dominios o etiquetas que se ignoraran (sin distinguir mayusculas; ver UI)
		"charm"		: "none|zeros|charm",  // (opcional, predeterminado "none") precios psicologicos ("", "none" u omitido son iguales)
		"confidence"	: 82,  // (opcional, predeterminado 70) confianza minima 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 mas baratos (o el minimo si N=1)
// "cheapest_n_in" : Media de N competidores mas baratos con stock (o ...)
// "highest_n" : Media de N competidores mas caros (o ...)
// "highest_n_in" : Media de N competidores mas caros con stock (o ...)
// "cost" : Mi coste
// "me_avg_n" : Mi precio promedio de las ultimas N horas (limita la velocidad de cambios)
// "domain:example.com" : precio de example.com (minimo si hay varias URL)
// "domainIn:example.com" : precio de example.com solo con stock (...)
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "repricingCreate",
			"ok"	: 3,  // Numero 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 mayusculas
		"newName"	: "The Rule Renamed",  // (opcional) maximo 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 toda la matriz "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 condicion "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 condicion "but never"; requiere todas las variables como en repricingCreate
		// "never_9" es el maximo; la matriz 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,  // Numero 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 mayusculas
		"onlyIfUnused"	: 1,  // (opcional) Por seguridad, genera un error si algun producto utiliza esta regla
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"		: "repricingDelete",
			"ok"		: 1,
			"productsCount"	: 10,  // Numero 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 accion no requiere mas parametros
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "repricingGetAll",
			"ok"	: 10,  // Numero total de reglas (longitud de "rules")
			"rules"	: [ // Matriz de reglas de repricing (orden alfabetico), cada una como objeto:
				...
				{
					"name"		: "Some Repricing Rule",
					"created"	: 1234567890,  // Tiempo Epoch de creacion de la regla
					"createdBy"	: "SOMEUSER",  // Nombre del usuario o "API"
					"edited"	: 1234567890,  // Ultima modificacion (si la hubo; en caso contrario variable ausente)
					"editedBy"	: "SOMEUSER",  // Usuario o "API" (o ausente)
					"disabled"	: 1234567890,  // Si la regla esta desactivada: tiempo Epoch de la ultima desactivacion; si no, ausente.
					"disabledBy"	: "SOMEUSER",  // Usuario o "API" (o ausente)
					"productsCount"	: 10,  // Numero 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 psicologicos (none|zeros|charm)
					"confidence"	: 82,  // confianza minima 0-99% (ver UI)
					"init"	: { // objeto inicial (primera fila "Set my price to")
						"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 "Set my price 2% below average of 3 cheapest competitors"
						// 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 "But never below the cheapest competitor in-stock minus 10.00 USD"
						},
						{},  // Esta segunda fila de condiciones "But never" esta vacia
						{
							"target"	: "cost",
							"direction"	: "below",
							"plusAmount"	: 5,
							"plusCurrency"	: "%",
							// Corresponde a "But never below my cost plus 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 parametros siguientes, usa uno de tus ajustes predefinidos o nuestros
			// Para tus ajustes: nombre completo sin usuario delante ni moneda detras.
			// 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 mas variables para sustituir opciones del ajuste (otra moneda, formato o categorias).
		"savePreset"	: "My New Preset Name",  // (opcional) Guardar los parametros 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 habria 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 publica del archivo, sin clave ni inicio de sesion. Disponible 15 minutos para descargar desde cualquier lugar.
			// "ok" es el numero de filas; tambien "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 categorias (si se omite, todos)
		"historyPeriod"	: "prev_6mo",  // (opcional, predeterminado "now")
			// PRIMERO: consulta los (?) sobre periodos historicos 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": ultimas 123 horas sin alinear al reloj; fin ahora y comienzo puede ser entre horas.
			// "cur_123(d|wk|mo|yr)": ultimos 123 dias/semanas/meses/anos incluyendo el periodo actual incompleto. "cur_2mo" el dia 10 = 40 dias.
			// "prev_123(d|wk|mo|yr)": 123 periodos anteriores completos. "prev_2mo" el 10 feb. = diciembre+enero (62 dias).
			// Inicio de cur_* y prev_* (y fin de prev_*) se alinea a medianoche anterior; cur_* termina ahora.
			// Asi "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 duracion de cada fila (media de ese periodo), varias filas por producto (salvo "all").
			// Piensa en "historyRow" como division 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 dias/semanas/meses/trimestres/anos desde medianoche. 123 opcional si vale 1 ("wk" = "1wk")
			// Si descargas el sabado con historyRow:"7d", cada fila promedia sabado 00:00 - viernes 23:59.
			// Pero historyRow:"1wk" promedia lunes 00:00 - domingo 23:59; fila mas reciente es semana actual incompleta.
			// LIMITE 500.000 FILAS: UI y API rechazan parametros historicos que generan mas de 500K filas.
			// Puede ocurrir con historyRow:"day" y un periodo largo, p. ej. 365 dias x 1400 productos.
			// Si lo necesitas, descarga un archivo por categoria 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 periodos 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,  // Categorias del producto ("Category 1; Category 2" en una celda)
		"columnComments"	: 1,  // Comentarios de producto
		"columnCreated"		: 1,  // Fecha de creacion YYYY/MM/DD (en nuestro sistema)
		"columnCustom"		: 1,  // Campos personalizados (una columna por cada variable unica 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,  // Anade 3 columnas: Min/Max/Media de competidores
		"columnInCompMinMaxAvg"	: 1,  // Anade 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 posicion entre todos (incluido tu)
		"columnCompInRank"	: 1,  // Una columna por competidor con su posicion entre competidores CON STOCK (incluido tu)
		// ========== PARAMETROS AVANZADOS OCULTOS: ==========
		// Tambien tenemos opciones no oficiales, poco documentadas; algunas las usa "pricezag_backup".
		"originalCurrencies"	: 1,  // En lugar de convertir importes en numeros 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 asi todos los dias hasta "everySunday"
		"everyMonthDay1"	: 15,  // Enviar cada dia 15 del mes
		"everyMonthDay2"	: 21,  // ... y tambien cada dia 21
		"everyMonthDay3"	: "last",  // ... y el ultimo dia de cada mes
			// everyMonthDay* de 0 a 9, maximo 10 dias del mes
		"time"			: "3:59pm",  // "15.59" tambien 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; tambien 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,  // Asi, si tenias "everyFriday"=1 y asignas "everyMonthDay3", se quitara "everyFriday".
		// ... y asi sucesivamente (ver every* en spreadsheetAutoCreate)
		"time"			: "3:59pm",
		"timezone"		: "America/Los_Angeles",
	}
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "spreadsheetAutoEdit",
			"ok"	: 3,  // Numero 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,  // Numero 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 calculos de ese dominio (borra ajustes anteriores)
		// Si clear:1, no puedes indicar mas campos o habra error.
		"math"	: [  // Matriz de bloques matematicos a aplicar
			{  // Objeto bloque matematico; todos los campos opcionales
				"categories"		: ["Category 1", "Category 2"],  // Solo productos de estas categorias
				"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.
			},
			... // Maximo 10 bloques (aplicados por orden)
		],
		// NOTA: aun no se puede modificar un solo campo/bloque. Proporcionar la matriz "math" sustituye todo.
		// NOTA: un bloque sin multiplicacion/division (ausente o 1) ni addPre/addPost distintos de 0 se ignora;
		// si todos se ignoran, equivale a borrar todos los calculos con clear:1.
		// En otras palabras, los calculos deben hacer algo para guardarse.
		// TRUCO: para desactivar temporalmente calculos de un dominio sin borrarlos,
		// usa categories: ["Some Empty Existing Category"]
	},
	...
] }
RESPUESTA:
{
	...
	"actions" : [
		...
		{
			"a"	: "mathEdit",
			"ok"	: 3,  // Numero de bloques matematicos cambiados (quitar o limpiar tambien 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 tenia 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 accion devolvio ok>0
	"errors"	: 1,  // porque una accion devolvio ok<0
	"actionsCount"	: 1,
	"actions" : [
		{
			"a"	: "productGet",
			"ok"	: -1,  // asi sabes que fallo
			"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 "Set my price at the mid-point between the 2 cheapest competitors"
			},
			"never"	: [
				{
					"target"	: "cost",
					"direction"	: "below",
					"plusAmount"	: 5,
					"plusCurrency"	: "%"
					// Corresponde a "But never below My Cost + 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 categoria que acabamos de crear
			// ... aunque productCreate crea categorias inexistentes, asi 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 accion devolvio 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 categorias
			"categoriesTo"		: ["A New Category"]
		}
}
RESPUESTA:
{
	"ok"		: 1,  // porque una accion devolvio ok>0
	"errors"	: 0,  // porque ninguna accion devolvio ok<0
	"actionsCount"	: 1,
	"actions" : [
		{
			"a"			: "categoryCopy",
			"ok"			: 3,  // porque cambiaron 3 categorias: 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 accion devolvio ok>0
	"errors"	: 0,  // porque ninguna accion devolvio ok<0
	"actionsCount"	: 1,
	"actions" : [
		{
			"a"	: "alertRuleEdit",
			"ok"	: 2  // porque 2 variables se modificaron correctamente
		}
	]
}