{
  "openapi": "3.1.0",
  "info": {
    "title": "Automeli API",
    "version": "v2",
    "description": "API pública de Automeli para publicar productos de Amazon en Mercado Libre. Las publicaciones se modelan como jobs asíncronos; el flujo recomendado es test → promote → live. Autenticación por header X-API-Key. v2 usa nombres de campo limpios y paginación por cursor en todos los listados. Esta URL sirve la versión vigente: hasta 2026-08 servía el spec de v1, que ahora vive congelado en https://www.automeli.com/api-docs/v1/openapi.json (guía de migración: https://www.automeli.com/api-docs/migration).",
    "contact": {
      "name": "Soporte Automeli",
      "url": "https://www.automeli.com/api-docs"
    },
    "x-stability": "beta"
  },
  "externalDocs": {
    "description": "Documentación",
    "url": "https://www.automeli.com/api-docs"
  },
  "servers": [
    {
      "url": "https://api.automeli.com/api/v2",
      "description": "Producción"
    }
  ],
  "security": [
    {
      "ApiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Products",
      "description": "Publicar productos y promover de prueba a real."
    },
    {
      "name": "Jobs",
      "description": "Estado, listado, reintento y cancelación de jobs."
    },
    {
      "name": "Account",
      "description": "Cuenta, créditos y categorías arancelarias."
    },
    {
      "name": "System",
      "description": "Health check / verificación de la API Key."
    }
  ],
  "paths": {
    "/products": {
      "get": {
        "operationId": "v2-products-list",
        "summary": "Listar el catálogo de la cuenta real",
        "description": "El endpoint principal de lectura de v2. Devuelve las publicaciones del catálogo del seller, paginadas por cursor, con nombres limpios (sin columnas internas de BD) y las infracciones abiertas de cada producto. Los filtros usan los mismos nombres que los campos de la respuesta y se combinan con AND. Un nombre equivocado conocido (weight_min, price_min, listing_type_id, tax_category_id, stock_quantity, y los del panel: shipping_mode, shipping_from, changed, image_changed, manufacturing_time, pause_reason_since_days…) responde 422 indicando el nombre correcto. El orden se elige con sort_by y sort_order (por defecto, listing_id ascendente); un nombre de columna interno (scraped_price, id_meli…) responde 422 con el nombre correcto. Cualquier otro parámetro desconocido se ignora. Codifique la URL: «+» como %2B y las tildes en UTF-8 (una «ó» sin codificar responde 400 antes de llegar a la API).\n\nScope requerido: `products:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Products"
        ],
        "responses": {
          "200": {
            "description": "Página del catálogo. total sólo en la primera petición (sin cursor); para seguir, repetir con ?cursor=<next_cursor> hasta que has_more sea false. Si el total no se puede calcular a tiempo, viene total: null con total_timeout: true y un warning: los productos de la página siguen siendo correctos.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "listing_id": {
                            "type": "string"
                          },
                          "sku": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "brand": {
                            "type": "string"
                          },
                          "permalink": {
                            "type": "string"
                          },
                          "image_url": {
                            "type": "string"
                          },
                          "ml_status": {
                            "type": "string"
                          },
                          "ml_sub_status": {
                            "type": "null"
                          },
                          "amazon_status": {
                            "type": "string"
                          },
                          "ml_category": {
                            "type": "string"
                          },
                          "ml_main_category": {
                            "type": "string"
                          },
                          "ml_listing_type": {
                            "type": "string"
                          },
                          "published_with_automeli": {
                            "type": "boolean"
                          },
                          "pause_reason": {
                            "type": "string"
                          },
                          "paused_since": {
                            "type": "null"
                          },
                          "amazon_total_price": {
                            "type": "number"
                          },
                          "amazon_price": {
                            "type": "number"
                          },
                          "amazon_shipping_cost": {
                            "type": "integer"
                          },
                          "amazon_taxes": {
                            "type": "integer"
                          },
                          "ml_price": {
                            "type": "integer"
                          },
                          "stock": {
                            "type": "integer"
                          },
                          "weight_lb": {
                            "type": "number"
                          },
                          "manufacturing_time": {
                            "type": "string"
                          },
                          "shipping_origin": {
                            "type": "string"
                          },
                          "ml_shipping_mode": {
                            "type": "string"
                          },
                          "is_republished": {
                            "type": "boolean"
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "amazon_reviewed_at": {
                            "type": "string"
                          },
                          "ml_updated_at": {
                            "type": "string"
                          },
                          "automeli_sync_status": {
                            "type": "string"
                          },
                          "automeli_tax_category": {
                            "type": "integer"
                          },
                          "last_change": {
                            "type": "string"
                          },
                          "discount_percentage": {
                            "type": "integer"
                          },
                          "image_differs_from_amazon": {
                            "type": "boolean"
                          },
                          "amazon_image_url": {
                            "type": "null"
                          },
                          "infractions": {
                            "type": "array",
                            "items": {}
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "next_cursor": {
                      "type": "string"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "data": [
                    {
                      "listing_id": "MCO1234567890",
                      "sku": "B003H03SDQ",
                      "title": "Ejemplo de producto",
                      "brand": "ACME",
                      "permalink": "https://articulo.mercadolibre.com.co/…",
                      "image_url": "https://http2.mlstatic.com/…jpg",
                      "ml_status": "active",
                      "ml_sub_status": null,
                      "amazon_status": "Disponible",
                      "ml_category": "Soluciones Limpiadoras",
                      "ml_main_category": "Hogar y Muebles",
                      "ml_listing_type": "gold_pro",
                      "published_with_automeli": true,
                      "pause_reason": "",
                      "paused_since": null,
                      "amazon_total_price": 24.99,
                      "amazon_price": 19.99,
                      "amazon_shipping_cost": 0,
                      "amazon_taxes": 0,
                      "ml_price": 89000,
                      "stock": 8,
                      "weight_lb": 1.2,
                      "manufacturing_time": "11 dias",
                      "shipping_origin": "amazonUSA",
                      "ml_shipping_mode": "me2",
                      "is_republished": false,
                      "created_at": "2026-05-08T12:00:00.000Z",
                      "amazon_reviewed_at": "2026-06-30T03:11:00.000Z",
                      "ml_updated_at": "2026-06-30T04:00:00.000Z",
                      "automeli_sync_status": "enabled",
                      "automeli_tax_category": 0,
                      "last_change": "Disponible",
                      "discount_percentage": -12,
                      "image_differs_from_amazon": false,
                      "amazon_image_url": null,
                      "infractions": []
                    }
                  ],
                  "next_cursor": "eyJsYXN0X2lkIjoi…",
                  "has_more": true,
                  "count": 1,
                  "total": 12840
                }
              }
            }
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_PARAM: Parámetro de query o path inválido (fecha, UUID, estado fuera de rango). Sólo v2; en v1 estos casos devuelven E_PRODUCT_INVALID_BODY",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_PARAM"
            ]
          },
          "503": {
            "description": "E_PRODUCT_LIST_TIMEOUT: Sólo v2 (GET /products): la consulta superó su tope de tiempo. Trae Retry-After: 30; reintente una sola vez y, si se repite, quite sort_by, use un término más general o busque por sku o listing_id exactos",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_LIST_TIMEOUT"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/catalog#list",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PRODUCT_INVALID_PARAM",
          "E_PRODUCT_LIST_TIMEOUT"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Tamaño de página. Default 100.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Token opaco de la página siguiente (next_cursor de la respuesta anterior). Omitir para la primera página — sólo esa incluye total.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "listing_id",
            "in": "query",
            "required": false,
            "description": "Filtra por un ID de publicación exacto.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sku",
            "in": "query",
            "required": false,
            "description": "Filtra por SKU exacto.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ml_status",
            "in": "query",
            "required": false,
            "description": "Estado de la publicación en Mercado Libre (active, paused, closed, deleted, under_review, …).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amazon_status",
            "in": "query",
            "required": false,
            "description": "Estado del producto en Amazon, texto exacto: Disponible, Agotado, Eliminado o En lista Negra.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "published_with_automeli",
            "in": "query",
            "required": false,
            "description": "Sólo publicaciones creadas (1) o no creadas (0) con el publicador de Automeli.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "automeli_sync_status",
            "in": "query",
            "required": false,
            "description": "Estado de sincronización, como palabra: enabled o disabled. Omitir = todos. Valor no habilitado para su cuenta → 422 (el mensaje lista los válidos; algunas cuentas tienen estados adicionales habilitados).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "deleted_in_automeli",
            "in": "query",
            "required": false,
            "description": "Default 0 (sólo no eliminados en Automeli). 2 = incluye ambos.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "created_from",
            "in": "query",
            "required": false,
            "description": "Rango sobre created_at: desde (inclusive).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "created_to",
            "in": "query",
            "required": false,
            "description": "Rango sobre created_at: hasta (inclusive).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "amazon_reviewed_from",
            "in": "query",
            "required": false,
            "description": "Rango sobre amazon_reviewed_at: desde (inclusive).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "amazon_reviewed_to",
            "in": "query",
            "required": false,
            "description": "Rango sobre amazon_reviewed_at: hasta (inclusive).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "ml_updated_from",
            "in": "query",
            "required": false,
            "description": "Rango sobre ml_updated_at: desde (inclusive).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "ml_updated_to",
            "in": "query",
            "required": false,
            "description": "Rango sobre ml_updated_at: hasta (inclusive).",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "ml_listing_type",
            "in": "query",
            "required": false,
            "description": "Tipo de publicación en Mercado Libre, ej. gold_pro o gold_pro|gold_special. Varios valores separados por | (máx. 100), cualquiera coincide. Comparación exacta con el campo ml_listing_type de la respuesta.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ml_category",
            "in": "query",
            "required": false,
            "description": "Nombre de la categoría de Mercado Libre, tal como viene en la respuesta. Varios valores separados por | (máx. 100), cualquiera coincide. Comparación exacta con el campo ml_category de la respuesta.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ml_main_category",
            "in": "query",
            "required": false,
            "description": "Categoría principal de Mercado Libre, tal como viene en la respuesta. Varios valores separados por | (máx. 100), cualquiera coincide. Comparación exacta con el campo ml_main_category de la respuesta.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "automeli_tax_category",
            "in": "query",
            "required": false,
            "description": "Categoría de impuesto de Automeli: entero >= 0 (ver GET /account/tax-categories), ej. 1 o 1|2. Varios valores separados por | (máx. 100), cualquiera coincide.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "brand",
            "in": "query",
            "required": false,
            "description": "Contiene el texto (campo brand de la respuesta), sin distinguir mayúsculas. % y _ se buscan literalmente (no son comodines). Se recortan los espacios; de 2 a 200 caracteres.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "title",
            "in": "query",
            "required": false,
            "description": "Contiene el texto (campo title de la respuesta), sin distinguir mayúsculas. % y _ se buscan literalmente (no son comodines). Se recortan los espacios; de 2 a 200 caracteres.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "amazon_price_min",
            "in": "query",
            "required": false,
            "description": "Precio en Amazon (USD) mínimo, inclusive (campo amazon_price de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "amazon_price_max",
            "in": "query",
            "required": false,
            "description": "Precio en Amazon (USD) máximo, inclusive (campo amazon_price de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "amazon_total_price_min",
            "in": "query",
            "required": false,
            "description": "Costo total en Amazon (USD) mínimo, inclusive (campo amazon_total_price de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "amazon_total_price_max",
            "in": "query",
            "required": false,
            "description": "Costo total en Amazon (USD) máximo, inclusive (campo amazon_total_price de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "ml_price_min",
            "in": "query",
            "required": false,
            "description": "Precio en Mercado Libre (moneda local) mínimo, inclusive (campo ml_price de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "ml_price_max",
            "in": "query",
            "required": false,
            "description": "Precio en Mercado Libre (moneda local) máximo, inclusive (campo ml_price de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "weight_lb_min",
            "in": "query",
            "required": false,
            "description": "Peso en libras mínimo, inclusive (campo weight_lb de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "weight_lb_max",
            "in": "query",
            "required": false,
            "description": "Peso en libras máximo, inclusive (campo weight_lb de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "stock_min",
            "in": "query",
            "required": false,
            "description": "Stock mínimo, inclusive (campo stock de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "stock_max",
            "in": "query",
            "required": false,
            "description": "Stock máximo, inclusive (campo stock de la respuesta). Número >= 0 (punto decimal, sin separador de miles). Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "last_change",
            "in": "query",
            "required": false,
            "description": "Último cambio detectado (campo last_change de la respuesta). Vocabulario cerrado: --, + Tiempo, - Tiempo, Subió, Bajó, + Stock, - Stock, Agotado, Disponible. Varios valores separados por |. Codifique la URL: «+» va como %2B (sin codificar llega como espacio y responde 422).",
            "schema": {
              "type": "string",
              "enum": [
                "--",
                "+ Tiempo",
                "- Tiempo",
                "Subió",
                "Bajó",
                "+ Stock",
                "- Stock",
                "Agotado",
                "Disponible"
              ]
            }
          },
          {
            "name": "shipping_origin",
            "in": "query",
            "required": false,
            "description": "Origen del envío en Amazon (campo shipping_origin de la respuesta): amazon (Amazon / Prime en amazon.com), amazonUSA, amazonMexico, amazonGlobal, amazonEuropa, amazonInternacional, otro, - (sin definir). Varios valores separados por | o coma. Cubre «Envío Amazon Prime» y «Enviado por» del panel.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ml_shipping_mode",
            "in": "query",
            "required": false,
            "description": "Modo de envío en Mercado Libre (campo ml_shipping_mode de la respuesta): me2 (Mercado Envíos), not_specified o custom (acordar con el vendedor); sin_dato = sin dato (NULL o vacío). Varios valores separados por | o coma.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "is_republished",
            "in": "query",
            "required": false,
            "description": "Sólo publicaciones republicadas desde Automeli (1) o no republicadas (0). También true/false.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "image_differs_from_amazon",
            "in": "query",
            "required": false,
            "description": "Sólo productos cuya imagen publicada difiere de la de Amazon (1) o no difiere (0, incluye los que no tienen dato). También true/false.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "pause_reason",
            "in": "query",
            "required": false,
            "description": "Motivo de pausa (campo pause_reason de la respuesta), texto exacto; varios separados por |. Además acepta grupos: otros (sin motivo), Cambió de ASIN (incluye «Cambió de ASIN: <ASIN>»), Lista Negra (todas las «Lista Negra: <marca>»), Categoría Restringida (todas las «Categoría Restringida: <categoría>») y Cambió de producto (productos que la IA marcó como cambiados).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "paused_since_from",
            "in": "query",
            "required": false,
            "description": "Rango sobre paused_since (desde, inclusive; sólo la fecha). También paused_since_to. Productos sin fecha (null) quedan fuera. Si from > to → 422.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "paused_since_to",
            "in": "query",
            "required": false,
            "description": "Rango sobre paused_since (hasta, inclusive; sólo la fecha). «Pausados hace más de N días» = paused_since_to con la fecha de hoy menos N días. Si from > to → 422.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "manufacturing_time_min",
            "in": "query",
            "required": false,
            "description": "Tiempo de preparación en días, mínimo, inclusive. (el campo manufacturing_time de la respuesta es texto, p. ej. «11 dias»: se compara su número). Entero >= 0. Sin dato u otro formato queda fuera. Si _min > _max → 422.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "manufacturing_time_max",
            "in": "query",
            "required": false,
            "description": "Tiempo de preparación en días, máximo, inclusive. (el campo manufacturing_time de la respuesta es texto, p. ej. «11 dias»: se compara su número). Entero >= 0. Sin dato u otro formato queda fuera. Si _min > _max → 422.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "margin_min",
            "in": "query",
            "required": false,
            "description": "Margen de ganancia (%) mínimo, inclusive. = (precio ML − precio Amazon × TRM de la cuenta) / (precio Amazon × TRM) × 100, como en el panel. Puede ser negativo. Sin precios no hay margen y el producto queda fuera. Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "margin_max",
            "in": "query",
            "required": false,
            "description": "Margen de ganancia (%) máximo, inclusive. = (precio ML − precio Amazon × TRM de la cuenta) / (precio Amazon × TRM) × 100, como en el panel. Puede ser negativo. Sin precios no hay margen y el producto queda fuera. Si _min > _max → 422.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "sort_by",
            "in": "query",
            "required": false,
            "description": "Campo por el que se ordena (los nombres son los de la respuesta). Por defecto listing_id. Los empates se desempatan por listing_id, así el orden es estable entre páginas. Los valores sin dato (null) van primero en asc y al final en desc. El texto se ordena sin distinguir mayúsculas ni tildes. ml_updated_at solo admite desc (lo actualizado más recientemente primero). Con deleted_in_automeli=2 solo se puede ordenar por listing_id, salvo que filtre por sku o listing_id exactos; para ver activos y eliminados ordenados, haga una consulta con cada valor. Cambiar el orden a mitad de la paginación la reinicia.",
            "schema": {
              "type": "string",
              "enum": [
                "listing_id",
                "title",
                "brand",
                "created_at",
                "ml_updated_at",
                "amazon_price",
                "ml_price",
                "amazon_total_price",
                "stock"
              ]
            }
          },
          {
            "name": "sort_order",
            "in": "query",
            "required": false,
            "description": "Sentido del orden, sin distinguir mayúsculas. Por defecto asc (desc con sort_by=ml_updated_at, que no admite asc). Los campos que cambian solos (ml_updated_at, stock, precios) se ordenan con su valor en vivo: si un producto cambia mientras pagina, puede aparecer dos veces o no aparecer.",
            "schema": {
              "type": "string",
              "enum": [
                "asc",
                "desc"
              ]
            }
          }
        ],
        "x-scope": "products:read",
        "x-credit-cost": "Sin costo (lectura)."
      },
      "post": {
        "operationId": "v2-products-create",
        "summary": "Crear un job de publicación",
        "description": "Crea un job asíncrono que la API procesa en segundo plano. Cada job admite hasta 10.000 items. El modo de prueba lo decide el environment de la API Key (automeli_test_* publica en la cuenta de prueba), no el body.\n\nScope requerido: `products:write`.\n\nSoporta `Idempotency-Key` para reintentos seguros.\n\nCosto: 1 crédito por item publicado. Las keys test consumen créditos de prueba.",
        "tags": [
          "Products"
        ],
        "responses": {
          "202": {
            "description": "Job aceptado. Devuelve el job_id para hacer seguimiento. Para conciliar: accepted / total_items incluyen los SKUs que quedaron duplicate (ya publicados y vivos, o ya en cola en otro job) y no se publican — lo que realmente se publica es queued (accepted = queued + duplicates; ambos vienen siempre, con 0 incluido). Si todo el lote era duplicado, el job nace directamente completed.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "accepted": {
                      "type": "integer"
                    },
                    "rejected": {
                      "type": "integer"
                    },
                    "total_items": {
                      "type": "integer"
                    },
                    "queued": {
                      "type": "integer"
                    },
                    "duplicates": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job_id": "8a3f2b10-4c9d-4e21-9f8a-1b2c3d4e5f60",
                  "status": "queued",
                  "name": "8 may 2026, 12:00:00",
                  "accepted": 2,
                  "rejected": 0,
                  "total_items": 2,
                  "queued": 2,
                  "duplicates": 0
                }
              }
            }
          },
          "400": {
            "description": "E_PRODUCT_CREDIT_EXHAUSTED: Sin créditos disponibles",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_CREDIT_EXHAUSTED"
            ]
          },
          "401": {
            "description": "E_AUTH_MISSING_KEY: Falta el header X-API-Key\nE_AUTH_INVALID_KEY: Key con formato inválido o no reconocida",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_MISSING_KEY",
              "E_AUTH_INVALID_KEY"
            ]
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "404": {
            "description": "E_ACCOUNT_NOT_FOUND: Cuenta Meli no encontrada",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_ACCOUNT_NOT_FOUND"
            ]
          },
          "409": {
            "description": "E_IDEMPOTENCY_CONFLICT: Misma Idempotency-Key con body distinto",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_IDEMPOTENCY_CONFLICT"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_BODY: Body malformado o con campos inválidos (POST/PATCH)\nE_PRODUCT_INVALID_SKU: SKU no cumple regex (10 alfanum)\nE_CATEGORY_INVALID: La categoría de Mercado Libre no cumple el formato (MCO…)\nE_CATEGORY_AND_AUTO_CONFLICT: Un item manda la categoría y auto_categorize a la vez",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_BODY",
              "E_PRODUCT_INVALID_SKU",
              "E_CATEGORY_INVALID",
              "E_CATEGORY_AND_AUTO_CONFLICT"
            ]
          },
          "429": {
            "description": "E_RATE_LIMITED: Excedió el rate limit. Ver Retry-After\nE_PRODUCT_MAX_CONCURRENT_JOBS: Ya tiene 6 jobs activos",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_RATE_LIMITED",
              "E_PRODUCT_MAX_CONCURRENT_JOBS"
            ]
          },
          "503": {
            "description": "E_INTERNAL: Error inesperado. Reintente con backoff",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_INTERNAL"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": true,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/products",
        "x-error-codes": [
          "E_AUTH_MISSING_KEY",
          "E_AUTH_INVALID_KEY",
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_RATE_LIMITED",
          "E_IDEMPOTENCY_CONFLICT",
          "E_PRODUCT_INVALID_BODY",
          "E_PRODUCT_INVALID_SKU",
          "E_PRODUCT_CREDIT_EXHAUSTED",
          "E_PRODUCT_MAX_CONCURRENT_JOBS",
          "E_CATEGORY_INVALID",
          "E_CATEGORY_AND_AUTO_CONFLICT",
          "E_ACCOUNT_NOT_FOUND",
          "E_INTERNAL"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Clave única por operación (ej. un UUID). Un reintento con la misma key, mismo método, ruta y body devuelve la respuesta original sin repetir el cambio (24 h; solo se guardan respuestas 2xx).",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "x-scope": "products:write",
        "x-credit-cost": "1 crédito por item publicado. Las keys test consumen créditos de prueba.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "sku": {
                          "type": "string"
                        },
                        "ml_category_id": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": true
                    },
                    "description": "Cada item: sku + (ml_category_id o auto_categorize)."
                  },
                  "ml_listing_type": {
                    "type": "string",
                    "description": "Tipo de publicación de Mercado Libre, a nivel job. Default: gold_special (Clásica). gold_pro (premium con cuotas) y gold_special (clásica); gold_premium/gold/silver/bronze se aceptan por compatibilidad.",
                    "enum": [
                      "gold_pro",
                      "gold_special",
                      "gold_premium",
                      "gold",
                      "silver",
                      "bronze"
                    ]
                  },
                  "automeli_tax_category": {
                    "type": "integer",
                    "description": "Índice (no nombre) de la categoría fiscal del seller, a nivel job. Default 0 (la primera). Los índices se obtienen con GET /account/tax-categories."
                  },
                  "scheduled_for": {
                    "type": "string",
                    "description": "Programa la publicación a una hora futura. Formato YYYY-MM-DDTHH:MM en UTC, sin segundos ni offset. Entre 5 minutos y 30 días en el futuro."
                  }
                },
                "additionalProperties": true,
                "required": [
                  "items"
                ]
              },
              "example": {
                "items": [
                  {
                    "sku": "B003H03SDQ",
                    "ml_category_id": "MCO420674"
                  },
                  {
                    "sku": "B07JHNJLYH",
                    "auto_categorize": true
                  }
                ],
                "ml_listing_type": "gold_pro",
                "automeli_tax_category": 0
              }
            }
          },
          "x-fields": [
            {
              "name": "items",
              "type": "array (1-10.000)",
              "required": "yes",
              "description": "Cada item: sku + (ml_category_id o auto_categorize)."
            },
            {
              "name": "items[].sku",
              "type": "string",
              "required": "yes",
              "description": "10 caracteres alfanuméricos (ASIN de Amazon)."
            },
            {
              "name": "items[].ml_category_id",
              "type": "string",
              "required": "conditional",
              "description": "Categoría de Mercado Libre, formato MCO420674. Excluyente con auto_categorize."
            },
            {
              "name": "items[].auto_categorize",
              "type": "boolean",
              "required": "conditional",
              "description": "Automeli infiere la categoría desde el ASIN. Excluyente con ml_category_id."
            },
            {
              "name": "ml_listing_type",
              "type": "string",
              "required": "no",
              "description": "Tipo de publicación de Mercado Libre, a nivel job. Default: gold_special (Clásica). gold_pro (premium con cuotas) y gold_special (clásica); gold_premium/gold/silver/bronze se aceptan por compatibilidad.",
              "enum": [
                "gold_pro",
                "gold_special",
                "gold_premium",
                "gold",
                "silver",
                "bronze"
              ]
            },
            {
              "name": "automeli_tax_category",
              "type": "int",
              "required": "no",
              "description": "Índice (no nombre) de la categoría fiscal del seller, a nivel job. Default 0 (la primera). Los índices se obtienen con GET /account/tax-categories."
            },
            {
              "name": "scheduled_for",
              "type": "string",
              "required": "no",
              "description": "Programa la publicación a una hora futura. Formato YYYY-MM-DDTHH:MM en UTC, sin segundos ni offset. Entre 5 minutos y 30 días en el futuro."
            }
          ]
        }
      }
    },
    "/products/sync-status": {
      "patch": {
        "operationId": "v2-products-sync-status",
        "summary": "Cambiar el estado de sincronización de un lote",
        "description": "Cambia, para una lista de publicaciones del seller, qué hace Automeli con cada una a partir de ahora. El estado va como palabra (enabled / disabled); el número crudo se rechaza con 422. Sólo afecta publicaciones del seller de la API Key: los listing_id ajenos se ignoran y no cuentan en updated.\n\nScope requerido: `products:write`.\n\nSoporta `Idempotency-Key` para reintentos seguros.\n\nCosto: Sin costo (no publica).",
        "tags": [
          "Products"
        ],
        "responses": {
          "200": {
            "description": "Cambio aplicado. updated = publicaciones del seller encontradas en la lista.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": {
                      "type": "string"
                    },
                    "requested": {
                      "type": "integer"
                    },
                    "updated": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "status": "disabled",
                  "requested": 2,
                  "updated": 2
                }
              }
            }
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "409": {
            "description": "E_IDEMPOTENCY_CONFLICT: Misma Idempotency-Key con body distinto",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_IDEMPOTENCY_CONFLICT"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_BODY: Body malformado o con campos inválidos (POST/PATCH)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_BODY"
            ]
          },
          "429": {
            "description": "E_RATE_LIMITED: Excedió el rate limit. Ver Retry-After",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_RATE_LIMITED"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": true,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/catalog#sync-status",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_RATE_LIMITED",
          "E_IDEMPOTENCY_CONFLICT",
          "E_PRODUCT_INVALID_BODY"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Clave única por operación (ej. un UUID). Un reintento con la misma key, mismo método, ruta y body devuelve la respuesta original sin repetir el cambio (24 h; solo se guardan respuestas 2xx).",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "x-scope": "products:write",
        "x-credit-cost": "Sin costo (no publica).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "status": {
                    "type": "string",
                    "description": "El estado destino, como palabra: enabled o disabled. Se rechaza el número crudo (422); el mensaje de error lista los estados válidos para su cuenta (algunas tienen adicionales habilitados)."
                  },
                  "listing_ids": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "listing_id a actualizar. Se normalizan (trim) y deduplican. Máximo 1000 por llamada; para más, dividir en lotes."
                  },
                  "include_not_found": {
                    "type": "boolean",
                    "description": "Si es true, la respuesta agrega matched (cuántos existían) y not_found (los listing_id que no pertenecen al seller). Opt-in porque cuesta una lectura extra."
                  }
                },
                "additionalProperties": true,
                "required": [
                  "status",
                  "listing_ids"
                ]
              },
              "example": {
                "status": "disabled",
                "listing_ids": [
                  "MCO1234567890",
                  "MCO9876543210"
                ]
              }
            }
          },
          "x-fields": [
            {
              "name": "status",
              "type": "string",
              "required": "yes",
              "description": "El estado destino, como palabra: enabled o disabled. Se rechaza el número crudo (422); el mensaje de error lista los estados válidos para su cuenta (algunas tienen adicionales habilitados)."
            },
            {
              "name": "listing_ids",
              "type": "array (1-1000)",
              "required": "yes",
              "description": "listing_id a actualizar. Se normalizan (trim) y deduplican. Máximo 1000 por llamada; para más, dividir en lotes."
            },
            {
              "name": "include_not_found",
              "type": "boolean",
              "required": "no",
              "description": "Si es true, la respuesta agrega matched (cuántos existían) y not_found (los listing_id que no pertenecen al seller). Opt-in porque cuesta una lectura extra."
            }
          ]
        }
      }
    },
    "/products/test": {
      "get": {
        "operationId": "v2-products-test-list",
        "summary": "Listar productos en cuenta de prueba",
        "description": "Devuelve los productos creados al publicar con una key automeli_test_*, paginados por cursor. El campo published_to_live indica si ese producto ya se promovió a la cuenta real; listing_id_test es el ID que se usa para promover.\n\nScope requerido: `products:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Products"
        ],
        "responses": {
          "200": {
            "description": "Página de productos en la cuenta de prueba.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "sku": {
                            "type": "string"
                          },
                          "listing_id_test": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "image_url": {
                            "type": "string"
                          },
                          "permalink_test": {
                            "type": "string"
                          },
                          "ml_listing_type": {
                            "type": "string"
                          },
                          "price": {
                            "type": "integer"
                          },
                          "ml_currency": {
                            "type": "string"
                          },
                          "ml_category_id": {
                            "type": "string"
                          },
                          "ml_category_name": {
                            "type": "string"
                          },
                          "automeli_tax_category": {
                            "type": "integer"
                          },
                          "ml_status": {
                            "type": "string"
                          },
                          "automeli_sync_status": {
                            "type": "string"
                          },
                          "published_to_live": {
                            "type": "boolean"
                          },
                          "test_published_at": {
                            "type": "string"
                          },
                          "ml_main_category": {
                            "type": "string"
                          },
                          "weight_lb": {
                            "type": "number"
                          },
                          "manufacturing_time": {
                            "type": "string"
                          },
                          "amazon_price": {
                            "type": "number"
                          },
                          "amazon_total_price": {
                            "type": "number"
                          },
                          "amazon_shipping_cost": {
                            "type": "integer"
                          },
                          "amazon_taxes": {
                            "type": "number"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "next_cursor": {
                      "type": "null"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "data": [
                    {
                      "sku": "B003H03SDQ",
                      "listing_id_test": "MCO1943839161",
                      "title": "Producto de prueba",
                      "image_url": "https://http2.mlstatic.com/…jpg",
                      "permalink_test": "https://articulo.mercadolibre.com.co/…",
                      "ml_listing_type": "gold_pro",
                      "price": 89000,
                      "ml_currency": "COP",
                      "ml_category_id": "MCO420674",
                      "ml_category_name": "Soluciones Limpiadoras",
                      "automeli_tax_category": 0,
                      "ml_status": "active",
                      "automeli_sync_status": "enabled",
                      "published_to_live": false,
                      "test_published_at": "2026-05-08T12:00:00.000Z",
                      "ml_main_category": "Hogar",
                      "weight_lb": 4.5,
                      "manufacturing_time": "5",
                      "amazon_price": 24.99,
                      "amazon_total_price": 31.5,
                      "amazon_shipping_cost": 0,
                      "amazon_taxes": 6.51
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false,
                  "count": 1,
                  "total": 1
                }
              }
            }
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_PARAM: Parámetro de query o path inválido (fecha, UUID, estado fuera de rango). Sólo v2; en v1 estos casos devuelven E_PRODUCT_INVALID_BODY\nE_PRODUCT_INVALID_SKU: SKU no cumple regex (10 alfanum)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_PARAM",
              "E_PRODUCT_INVALID_SKU"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/test-products#list",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PRODUCT_INVALID_PARAM",
          "E_PRODUCT_INVALID_SKU"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Tamaño de página. Default 50.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Token opaco de la página siguiente (next_cursor de la respuesta anterior). Omitir para la primera página — sólo esa incluye total.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ml_status",
            "in": "query",
            "required": false,
            "description": "Estado del listing de prueba en Mercado Libre.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused",
                "closed",
                "under_review",
                "inactive",
                "not_yet_active",
                "payment_required"
              ]
            }
          },
          {
            "name": "published_to_live",
            "in": "query",
            "required": false,
            "description": "0 → sólo los pendientes de promover; 1 → los que ya pasaron a real.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "automeli_sync_status",
            "in": "query",
            "required": false,
            "description": "Estado de sincronización, como palabra: enabled o disabled (algunas cuentas tienen estados adicionales habilitados).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sku",
            "in": "query",
            "required": false,
            "description": "Filtra por SKU exacto.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_from",
            "in": "query",
            "required": false,
            "description": "Publicados en prueba desde esta fecha (inclusive). Acepta 2026-09-11 o 2026-09-11T12:00:00Z; una fecha sin hora se toma desde las 00:00:00 UTC. Útil para aislar el lote que acabás de crear.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_to",
            "in": "query",
            "required": false,
            "description": "Publicados en prueba hasta esta fecha (inclusive). Una fecha sin hora se toma hasta las 23:59:59 UTC.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "weight_min",
            "in": "query",
            "required": false,
            "description": "Peso mínimo en libras. Los productos sin peso registrado quedan fuera de cualquier rango: publicar sin peso cotiza mal el envío.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "weight_max",
            "in": "query",
            "required": false,
            "description": "Peso máximo en libras.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "price_min",
            "in": "query",
            "required": false,
            "description": "Precio de venta mínimo en Mercado Libre (mismo valor que el campo price).",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "price_max",
            "in": "query",
            "required": false,
            "description": "Precio de venta máximo en Mercado Libre.",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "ml_category_id",
            "in": "query",
            "required": false,
            "description": "Filtra por la categoría de Mercado Libre con la que se publicó en prueba (ej. MCO420674).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "automeli_tax_category",
            "in": "query",
            "required": false,
            "description": "Índice de la categoría fiscal (entero ≥ 0). Ver GET /account/tax-categories.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "x-scope": "products:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/products/test/promote": {
      "post": {
        "operationId": "v2-products-test-promote",
        "summary": "Promover productos de prueba a la cuenta real",
        "description": "Publica en la cuenta real productos que ya existen en la cuenta de prueba, reutilizando la categoría de Mercado Libre, la categoría fiscal y el tipo de publicación que ya tenían. La selección es por listing_id_test (no por SKU). Sólo se promueven publicaciones active o paused; el resto se reporta en skipped_not_publishable. Como la categoría fiscal y el tipo son a nivel job, una llamada puede crear varios jobs (uno por combinación). Requiere una key automeli_live_*.\n\nScope requerido: `products:write`.\n\nRequiere una API Key live (`automeli_live_*`).\n\nSoporta `Idempotency-Key` para reintentos seguros.\n\nCosto: 1 crédito real por producto promovido con éxito.",
        "tags": [
          "Products"
        ],
        "responses": {
          "202": {
            "description": "Promoción aceptada. jobs[] lista un job por combinación de categoría fiscal + tipo de publicación; cada uno se sigue con GET /products/jobs/{jobId}. Para conciliar: promoted incluye los SKUs que quedaron duplicate (ya en cola en otro job) y nunca se publican — lo que realmente se encola es queued (promoted = queued + duplicates; ídem promoted_total = queued_total + duplicates_total). skipped_duplicate_sku lista los repetidos dentro de la misma llamada. Todos esos campos vienen siempre, con 0 o vacío incluido.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "jobs": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "job_id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "automeli_tax_category": {
                            "type": "integer"
                          },
                          "ml_listing_type": {
                            "type": "string"
                          },
                          "promoted": {
                            "type": "integer"
                          },
                          "queued": {
                            "type": "integer"
                          },
                          "duplicates": {
                            "type": "integer"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "requested": {
                      "type": "integer"
                    },
                    "promoted_total": {
                      "type": "integer"
                    },
                    "queued_total": {
                      "type": "integer"
                    },
                    "duplicates_total": {
                      "type": "integer"
                    },
                    "skipped_not_publishable": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "listing_id_test": {
                            "type": "string"
                          },
                          "ml_status": {
                            "type": "string"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "not_found": {
                      "type": "array",
                      "items": {}
                    },
                    "skipped_duplicate_sku": {
                      "type": "array",
                      "items": {}
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "jobs": [
                    {
                      "job_id": "a1b2c3d4-…",
                      "status": "queued",
                      "name": "8 may 2026, 12:00:00",
                      "automeli_tax_category": 0,
                      "ml_listing_type": "gold_pro",
                      "promoted": 2,
                      "queued": 2,
                      "duplicates": 0
                    }
                  ],
                  "requested": 3,
                  "promoted_total": 2,
                  "queued_total": 2,
                  "duplicates_total": 0,
                  "skipped_not_publishable": [
                    {
                      "listing_id_test": "MCO7777777777",
                      "ml_status": "under_review"
                    }
                  ],
                  "not_found": [],
                  "skipped_duplicate_sku": []
                }
              }
            }
          },
          "400": {
            "description": "E_PROMOTE_NO_CANDIDATES: Ningún producto de prueba publicable coincide con lo pedido\nE_PRODUCT_CREDIT_EXHAUSTED: Sin créditos disponibles",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PROMOTE_NO_CANDIDATES",
              "E_PRODUCT_CREDIT_EXHAUSTED"
            ]
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)\nE_PROMOTE_REQUIRES_LIVE_KEY: Endpoint /products/test/promote sólo acepta key live",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE",
              "E_PROMOTE_REQUIRES_LIVE_KEY"
            ]
          },
          "404": {
            "description": "E_ACCOUNT_NOT_FOUND: Cuenta Meli no encontrada",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_ACCOUNT_NOT_FOUND"
            ]
          },
          "409": {
            "description": "E_IDEMPOTENCY_CONFLICT: Misma Idempotency-Key con body distinto",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_IDEMPOTENCY_CONFLICT"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_BODY: Body malformado o con campos inválidos (POST/PATCH)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_BODY"
            ]
          },
          "429": {
            "description": "E_PRODUCT_MAX_CONCURRENT_JOBS: Ya tiene 6 jobs activos",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_MAX_CONCURRENT_JOBS"
            ]
          }
        },
        "x-key-env": "live",
        "x-idempotent": true,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/test-products#promote",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PROMOTE_REQUIRES_LIVE_KEY",
          "E_PROMOTE_NO_CANDIDATES",
          "E_IDEMPOTENCY_CONFLICT",
          "E_PRODUCT_INVALID_BODY",
          "E_PRODUCT_CREDIT_EXHAUSTED",
          "E_PRODUCT_MAX_CONCURRENT_JOBS",
          "E_ACCOUNT_NOT_FOUND"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Clave única por operación (ej. un UUID). Un reintento con la misma key, mismo método, ruta y body devuelve la respuesta original sin repetir el cambio (24 h; solo se guardan respuestas 2xx).",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "x-scope": "products:write",
        "x-credit-cost": "1 crédito real por producto promovido con éxito.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "listing_ids_test": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "IDs de las publicaciones en la cuenta de prueba (el listing_id_test de GET /products/test). Se normalizan (trim) y deduplican."
                  }
                },
                "additionalProperties": true,
                "required": [
                  "listing_ids_test"
                ]
              },
              "example": {
                "listing_ids_test": [
                  "MCO1943839161",
                  "MCO1943839175"
                ]
              }
            }
          },
          "x-fields": [
            {
              "name": "listing_ids_test",
              "type": "array (1-10.000)",
              "required": "yes",
              "description": "IDs de las publicaciones en la cuenta de prueba (el listing_id_test de GET /products/test). Se normalizan (trim) y deduplican."
            }
          ]
        }
      }
    },
    "/products/jobs/{jobId}": {
      "get": {
        "operationId": "v2-jobs-get",
        "summary": "Consultar el estado de un job",
        "description": "Devuelve el detalle del job y sus items, con los items paginados por cursor. Haga poll cada 5-10 segundos hasta que el status sea final (completed, failed o cancelled). Si el job publica el mismo SKU en más de un tipo de publicación, job.by_listing_type trae el desglose por tipo.\n\nScope requerido: `products:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Jobs"
        ],
        "responses": {
          "200": {
            "description": "Estado del job + sus items, paginados por cursor.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job": {
                      "type": "object",
                      "properties": {
                        "job_id": {
                          "type": "string"
                        },
                        "status": {
                          "type": "string"
                        },
                        "total_items": {
                          "type": "integer"
                        },
                        "successful": {
                          "type": "integer"
                        },
                        "failed": {
                          "type": "integer"
                        },
                        "completed_at": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": true
                    },
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "sku": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "listing_id": {
                            "type": "string"
                          },
                          "ml_listing_type": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "permalink": {
                            "type": "string"
                          },
                          "price": {
                            "type": "integer"
                          },
                          "message": {
                            "type": "null"
                          },
                          "error_category": {
                            "type": "null"
                          },
                          "retryable": {
                            "type": "boolean"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "next_cursor": {
                      "type": "null"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job": {
                    "job_id": "8a3f2b10-4c9d-4e21-9f8a-1b2c3d4e5f60",
                    "status": "completed",
                    "total_items": 2,
                    "successful": 2,
                    "failed": 0,
                    "completed_at": "2026-05-08T12:00:09.000Z"
                  },
                  "data": [
                    {
                      "sku": "B003H03SDQ",
                      "status": "success",
                      "listing_id": "MCO1234567890",
                      "ml_listing_type": "gold_pro",
                      "title": "Ejemplo de producto",
                      "permalink": "https://articulo.mercadolibre.com.co/…",
                      "price": 89000,
                      "message": null,
                      "error_category": null,
                      "retryable": false
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false,
                  "count": 1
                }
              }
            }
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "404": {
            "description": "E_JOB_NOT_FOUND: jobId no existe o no es de su seller",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_JOB_NOT_FOUND"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_PARAM: Parámetro de query o path inválido (fecha, UUID, estado fuera de rango). Sólo v2; en v1 estos casos devuelven E_PRODUCT_INVALID_BODY",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_PARAM"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/jobs#status",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_JOB_NOT_FOUND",
          "E_PRODUCT_INVALID_PARAM"
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "description": "El job_id devuelto al crear el job.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Tamaño de página. Default 100.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Token opaco de la página siguiente (next_cursor de la respuesta anterior). Omitir para la primera página — sólo esa incluye total.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filtra los items por estado, ej. failed. duplicate = el SKU ya estaba publicado y vivo, o ya en cola en otro job: se saltó sin consumir crédito.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "dispatched",
                "success",
                "failed",
                "skipped",
                "duplicate"
              ]
            }
          }
        ],
        "x-scope": "products:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/products/jobs": {
      "get": {
        "operationId": "v2-jobs-list",
        "summary": "Listar jobs",
        "description": "Listado paginado por cursor. Para auditoría o reconciliación con su sistema interno.\n\nScope requerido: `products:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Jobs"
        ],
        "responses": {
          "200": {
            "description": "Página de jobs del seller que matchean el filtro.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "job_id": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "name": {
                            "type": "string"
                          },
                          "ml_listing_type": {
                            "type": "string"
                          },
                          "test_mode": {
                            "type": "boolean"
                          },
                          "ml_site_id": {
                            "type": "string"
                          },
                          "total_items": {
                            "type": "integer"
                          },
                          "processed": {
                            "type": "integer"
                          },
                          "successful": {
                            "type": "integer"
                          },
                          "failed": {
                            "type": "integer"
                          },
                          "skipped": {
                            "type": "integer"
                          },
                          "scheduled_for": {
                            "type": "null"
                          },
                          "created_at": {
                            "type": "string"
                          },
                          "started_at": {
                            "type": "string"
                          },
                          "completed_at": {
                            "type": "string"
                          },
                          "updated_at": {
                            "type": "string"
                          },
                          "error_message": {
                            "type": "null"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "next_cursor": {
                      "type": "null"
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "count": {
                      "type": "integer"
                    },
                    "total": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "data": [
                    {
                      "job_id": "8a3f2b10-4c9d-4e21-9f8a-1b2c3d4e5f60",
                      "status": "completed",
                      "name": "8 may 2026, 12:00:00",
                      "ml_listing_type": "gold_pro",
                      "test_mode": false,
                      "ml_site_id": "MCO",
                      "total_items": 2,
                      "processed": 2,
                      "successful": 2,
                      "failed": 0,
                      "skipped": 0,
                      "scheduled_for": null,
                      "created_at": "2026-05-08T12:00:00.000Z",
                      "started_at": "2026-05-08T12:00:01.000Z",
                      "completed_at": "2026-05-08T12:00:09.000Z",
                      "updated_at": "2026-05-08T12:00:09.000Z",
                      "error_message": null
                    }
                  ],
                  "next_cursor": null,
                  "has_more": false,
                  "count": 1,
                  "total": 1
                }
              }
            }
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_PARAM: Parámetro de query o path inválido (fecha, UUID, estado fuera de rango). Sólo v2; en v1 estos casos devuelven E_PRODUCT_INVALID_BODY",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_PARAM"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/jobs#list",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PRODUCT_INVALID_PARAM"
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Tamaño de página. Default 50.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "required": false,
            "description": "Token opaco de la página siguiente (next_cursor de la respuesta anterior). Omitir para la primera página — sólo esa incluye total.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filtra por estado del job.",
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "processing",
                "scheduled",
                "completed",
                "failed",
                "cancelled"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Fecha desde (inclusive), formato YYYY-MM-DD.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Fecha hasta (inclusive), formato YYYY-MM-DD.",
            "schema": {
              "type": "string",
              "format": "date"
            }
          }
        ],
        "x-scope": "products:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/products/jobs/{jobId}/retry": {
      "post": {
        "operationId": "v2-jobs-retry",
        "summary": "Reintentar items fallidos de un job",
        "description": "Reintenta items en failed con retryable: true (los que fallaron por causas transitorias). Sólo aplica sobre jobs terminales; el job vuelve a queued. Consume créditos por cada item reintentado.\n\nScope requerido: `products:write`.\n\nSoporta `Idempotency-Key` para reintentos seguros.\n\nCosto: 1 crédito por item reintentado.",
        "tags": [
          "Jobs"
        ],
        "responses": {
          "202": {
            "description": "Reintento aceptado para los items retryables del job.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "retried": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job_id": "8a3f2b10-4c9d-4e21-9f8a-1b2c3d4e5f60",
                  "status": "queued",
                  "retried": 3
                }
              }
            }
          },
          "400": {
            "description": "E_JOB_NOT_RETRYABLE: Job no terminal o sin items retryables\nE_PRODUCT_CREDIT_EXHAUSTED: Sin créditos disponibles",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_JOB_NOT_RETRYABLE",
              "E_PRODUCT_CREDIT_EXHAUSTED"
            ]
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "404": {
            "description": "E_JOB_NOT_FOUND: jobId no existe o no es de su seller",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_JOB_NOT_FOUND"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_PARAM: Parámetro de query o path inválido (fecha, UUID, estado fuera de rango). Sólo v2; en v1 estos casos devuelven E_PRODUCT_INVALID_BODY",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_PARAM"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": true,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/jobs#retry",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PRODUCT_INVALID_PARAM",
          "E_JOB_NOT_FOUND",
          "E_JOB_NOT_RETRYABLE",
          "E_PRODUCT_CREDIT_EXHAUSTED"
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "description": "El job_id terminal cuyos items fallidos se reintentan.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Clave única por operación (ej. un UUID). Un reintento con la misma key, mismo método, ruta y body devuelve la respuesta original sin repetir el cambio (24 h; solo se guardan respuestas 2xx).",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "x-scope": "products:write",
        "x-credit-cost": "1 crédito por item reintentado."
      }
    },
    "/products/jobs/{jobId}/cancel": {
      "post": {
        "operationId": "v2-jobs-cancel",
        "summary": "Cancelar un job",
        "description": "Cancela jobs en queued, processing o scheduled. Los items pendientes pasan a skipped. Lo ya publicado no se revierte.\n\nScope requerido: `products:write`.\n\nSoporta `Idempotency-Key` para reintentos seguros.\n\nCosto: Sin costo (no genera publicaciones nuevas).",
        "tags": [
          "Jobs"
        ],
        "responses": {
          "200": {
            "description": "Job cancelado. Los items pendientes quedan en skipped.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "cancelled": {
                      "type": "boolean"
                    },
                    "skipped_items": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job_id": "8a3f2b10-4c9d-4e21-9f8a-1b2c3d4e5f60",
                  "cancelled": true,
                  "skipped_items": 12
                }
              }
            }
          },
          "400": {
            "description": "E_JOB_ALREADY_TERMINAL: Cancel sobre job ya cerrado",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_JOB_ALREADY_TERMINAL"
            ]
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "404": {
            "description": "E_JOB_NOT_FOUND: jobId no existe o no es de su seller",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_JOB_NOT_FOUND"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_PARAM: Parámetro de query o path inválido (fecha, UUID, estado fuera de rango). Sólo v2; en v1 estos casos devuelven E_PRODUCT_INVALID_BODY",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_PARAM"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": true,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/jobs#cancel",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PRODUCT_INVALID_PARAM",
          "E_JOB_NOT_FOUND",
          "E_JOB_ALREADY_TERMINAL"
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "description": "El job_id a cancelar (debe estar en un estado no terminal).",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Clave única por operación (ej. un UUID). Un reintento con la misma key, mismo método, ruta y body devuelve la respuesta original sin repetir el cambio (24 h; solo se guardan respuestas 2xx).",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "x-scope": "products:write",
        "x-credit-cost": "Sin costo (no genera publicaciones nuevas)."
      }
    },
    "/products/ml-actions": {
      "post": {
        "operationId": "v2-ml-actions-create",
        "summary": "Pausar, activar, cerrar, republicar o cambiar el tipo de publicación",
        "description": "Crea un job asíncrono que ejecuta la acción en Mercado Libre sobre las publicaciones indicadas, por lista de listing_ids o por filtros (exactamente uno de los dos). Hasta 10.000 publicaciones por llamada; si el filtro abarca más, devuelve next_cursor para seguir. Con dry_run: true no ejecuta nada y devuelve cuántas publicaciones tocaría. close y republish reales exigen el header Idempotency-Key (sin él, 428): reintentar un republish sin esa key crearía publicaciones duplicadas.\n\nScope requerido: `listings:write`.\n\nRequiere una API Key live (`automeli_live_*`).\n\nCosto: Sin costo en créditos.",
        "tags": [
          "Actions"
        ],
        "responses": {
          "200": {
            "description": "dry_run: true. No se ejecutó nada; matched es cuántas publicaciones tocaría.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "dry_run": {
                      "type": "boolean"
                    },
                    "action": {
                      "type": "string"
                    },
                    "matched": {
                      "type": "integer"
                    },
                    "sample": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "dry_run": true,
                  "action": "pause",
                  "matched": 37,
                  "sample": [
                    "MCO1234567890",
                    "MCO1234567891"
                  ],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "202": {
            "description": "Acción encolada. Consulte el avance con GET /products/ml-actions/{jobId}. Si has_more es true, vuelva a llamar con cursor para las siguientes publicaciones. Si status es \"unconfirmed\" (con un campo warning), el servicio no confirmó el encolado: consulte el job_id con GET; puede tardar hasta un minuto en aparecer, y solo si sigue en 404 pasado ese minuto, no se creó. Reintentar con la misma Idempotency-Key devuelve esta misma respuesta, sin repetir la acción.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "action": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "listings": {
                      "type": "integer"
                    },
                    "not_found": {
                      "type": "array",
                      "items": {}
                    },
                    "has_more": {
                      "type": "boolean"
                    },
                    "next_cursor": {
                      "type": "null"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job_id": "1759672800123",
                  "action": "pause",
                  "status": "queued",
                  "listings": 37,
                  "not_found": [],
                  "has_more": false,
                  "next_cursor": null
                }
              }
            }
          },
          "400": {
            "description": "E_NO_ML_TOKEN: La cuenta no tiene un token de MercadoLibre vinculado",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_NO_ML_TOKEN"
            ]
          },
          "401": {
            "description": "E_AUTH_MISSING_KEY: Falta el header X-API-Key\nE_AUTH_INVALID_KEY: Key con formato inválido o no reconocida",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_MISSING_KEY",
              "E_AUTH_INVALID_KEY"
            ]
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)\nE_ACTION_REQUIRES_LIVE_KEY: Acción real sobre Mercado Libre con key test (con test solo se permite dry_run)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE",
              "E_ACTION_REQUIRES_LIVE_KEY"
            ]
          },
          "409": {
            "description": "E_IDEMPOTENCY_CONFLICT: Misma Idempotency-Key con body distinto\nE_ACTION_COUNT_MISMATCH: Acción real con expected_count (obligatorio en close/republish por filtros): el conteo real supera expected_count más la tolerancia",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_IDEMPOTENCY_CONFLICT",
              "E_ACTION_COUNT_MISMATCH"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_BODY: Body malformado o con campos inválidos (POST/PATCH)\nE_PRODUCT_INVALID_PARAM: Parámetro de query o path inválido (fecha, UUID, estado fuera de rango). Sólo v2; en v1 estos casos devuelven E_PRODUCT_INVALID_BODY\nE_ACTION_REJECTED: El servicio de acciones rechazó la solicitud (p. ej. supera el máximo de publicaciones a cerrar); el detalle trae el motivo",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_BODY",
              "E_PRODUCT_INVALID_PARAM",
              "E_ACTION_REJECTED"
            ]
          },
          "428": {
            "description": "E_ACTION_IDEMPOTENCY_KEY_REQUIRED: close o republish real sin el header Idempotency-Key",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_ACTION_IDEMPOTENCY_KEY_REQUIRED"
            ]
          },
          "429": {
            "description": "E_RATE_LIMITED: Excedió el rate limit. Ver Retry-After\nE_ACTION_MAX_CONCURRENT_JOBS: Ya tiene 3 jobs de acciones en cola o en proceso",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_RATE_LIMITED",
              "E_ACTION_MAX_CONCURRENT_JOBS"
            ]
          },
          "503": {
            "description": "E_INTERNAL: Error inesperado. Reintente con backoff",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_INTERNAL"
            ]
          }
        },
        "x-key-env": "live",
        "x-idempotent": true,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/ml-actions",
        "x-error-codes": [
          "E_AUTH_MISSING_KEY",
          "E_AUTH_INVALID_KEY",
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_RATE_LIMITED",
          "E_IDEMPOTENCY_CONFLICT",
          "E_PRODUCT_INVALID_BODY",
          "E_PRODUCT_INVALID_PARAM",
          "E_ACTION_REQUIRES_LIVE_KEY",
          "E_ACTION_COUNT_MISMATCH",
          "E_ACTION_MAX_CONCURRENT_JOBS",
          "E_ACTION_IDEMPOTENCY_KEY_REQUIRED",
          "E_ACTION_REJECTED",
          "E_NO_ML_TOKEN",
          "E_INTERNAL"
        ],
        "parameters": [
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Clave única por operación (ej. un UUID). Un reintento con la misma key, mismo método, ruta y body devuelve la respuesta original sin repetir el cambio (24 h; solo se guardan respuestas 2xx). Obligatorio en `close` y `republish` reales (sin `dry_run`): sin él, 428 E_ACTION_IDEMPOTENCY_KEY_REQUIRED.",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "x-scope": "listings:write",
        "x-credit-cost": "Sin costo en créditos.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "action": {
                    "type": "string",
                    "description": "pause (pausar), activate (activar), close (cerrar, irreversible), republish (republicar una cerrada) o change_listing_type (cambiar el tipo de publicación).",
                    "enum": [
                      "pause",
                      "activate",
                      "close",
                      "republish",
                      "change_listing_type"
                    ]
                  },
                  "filters": {
                    "type": "object",
                    "properties": {
                      "ml_status": {
                        "type": "string"
                      },
                      "amazon_status": {
                        "type": "string"
                      }
                    },
                    "additionalProperties": true,
                    "description": "Un subconjunto de los filtros de GET /products, un valor por clave: listing_id, sku, ml_status, amazon_status, published_with_automeli, automeli_sync_status, deleted_in_automeli, created_from, created_to, amazon_reviewed_from, amazon_reviewed_to, ml_updated_from, ml_updated_to. Cualquier otra clave se rechaza con 422. Debe acotar el alcance: deleted_in_automeli por sí solo no basta. Excluyente con listing_ids."
                  },
                  "dry_run": {
                    "type": "boolean",
                    "description": "Simula: devuelve matched y una muestra de 20 listing_ids sin tocar Mercado Libre. Es lo único que permite una key test."
                  },
                  "listing_ids": {
                    "type": "string",
                    "description": "Publicaciones de Mercado Libre (MCO…). Las que no son de su cuenta vuelven en not_found. Excluyente con filters."
                  },
                  "exclude_listing_ids": {
                    "type": "string",
                    "description": "Solo con filters: publicaciones a dejar por fuera."
                  },
                  "listing_type": {
                    "type": "string",
                    "enum": [
                      "gold_special",
                      "gold_pro"
                    ],
                    "description": "Obligatorio con change_listing_type y prohibido con las demás acciones."
                  },
                  "expected_count": {
                    "type": "integer",
                    "description": "Obligatorio en close y republish por filtros; opcional en las demás acciones. Si viene, debe ser un entero > 0. En una acción real (por filtros o por listing_ids), si el conteo real supera expected_count + máx(5, 5 %), responde 409 y no ejecuta nada. En dry_run y en las continuaciones con cursor solo se valida (el conteo se compara en la 1ª tanda). Tómelo de un dry_run."
                  },
                  "cursor": {
                    "type": "string",
                    "description": "next_cursor de la respuesta anterior, para seguir con las siguientes 10.000. Solo sirve para la misma acción, filtros, exclusiones y modo (dry_run o real)."
                  }
                },
                "additionalProperties": true,
                "required": [
                  "action"
                ]
              },
              "example": {
                "action": "pause",
                "filters": {
                  "ml_status": "active",
                  "amazon_status": "Agotado"
                },
                "dry_run": true
              }
            }
          },
          "x-fields": [
            {
              "name": "action",
              "type": "string",
              "required": "yes",
              "description": "pause (pausar), activate (activar), close (cerrar, irreversible), republish (republicar una cerrada) o change_listing_type (cambiar el tipo de publicación).",
              "enum": [
                "pause",
                "activate",
                "close",
                "republish",
                "change_listing_type"
              ]
            },
            {
              "name": "listing_ids",
              "type": "string[] (1-1.000)",
              "required": "conditional",
              "description": "Publicaciones de Mercado Libre (MCO…). Las que no son de su cuenta vuelven en not_found. Excluyente con filters."
            },
            {
              "name": "filters",
              "type": "object",
              "required": "conditional",
              "description": "Un subconjunto de los filtros de GET /products, un valor por clave: listing_id, sku, ml_status, amazon_status, published_with_automeli, automeli_sync_status, deleted_in_automeli, created_from, created_to, amazon_reviewed_from, amazon_reviewed_to, ml_updated_from, ml_updated_to. Cualquier otra clave se rechaza con 422. Debe acotar el alcance: deleted_in_automeli por sí solo no basta. Excluyente con listing_ids."
            },
            {
              "name": "exclude_listing_ids",
              "type": "string[] (máx 1.000)",
              "required": "no",
              "description": "Solo con filters: publicaciones a dejar por fuera."
            },
            {
              "name": "listing_type",
              "type": "string",
              "required": "conditional",
              "description": "Obligatorio con change_listing_type y prohibido con las demás acciones.",
              "enum": [
                "gold_special",
                "gold_pro"
              ]
            },
            {
              "name": "expected_count",
              "type": "int",
              "required": "conditional",
              "description": "Obligatorio en close y republish por filtros; opcional en las demás acciones. Si viene, debe ser un entero > 0. En una acción real (por filtros o por listing_ids), si el conteo real supera expected_count + máx(5, 5 %), responde 409 y no ejecuta nada. En dry_run y en las continuaciones con cursor solo se valida (el conteo se compara en la 1ª tanda). Tómelo de un dry_run."
            },
            {
              "name": "dry_run",
              "type": "boolean",
              "required": "no",
              "description": "Simula: devuelve matched y una muestra de 20 listing_ids sin tocar Mercado Libre. Es lo único que permite una key test."
            },
            {
              "name": "cursor",
              "type": "string",
              "required": "no",
              "description": "next_cursor de la respuesta anterior, para seguir con las siguientes 10.000. Solo sirve para la misma acción, filtros, exclusiones y modo (dry_run o real)."
            }
          ]
        }
      }
    },
    "/products/ml-actions/{jobId}": {
      "get": {
        "operationId": "v2-ml-actions-get",
        "summary": "Consultar el avance de una acción",
        "description": "Estado del job de acción (queued, processing, completed, failed o cancelled), con el conteo de procesadas, exitosas y fallidas, y el motivo de cada fallo.\n\nScope requerido: `products:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Actions"
        ],
        "responses": {
          "200": {
            "description": "Estado del job. failed_items_truncated indica que hay más fallos que los listados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "action": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "total": {
                      "type": "integer"
                    },
                    "processed": {
                      "type": "integer"
                    },
                    "successful": {
                      "type": "integer"
                    },
                    "failed": {
                      "type": "integer"
                    },
                    "failed_items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "listing_id": {
                            "type": "string"
                          },
                          "error": {
                            "type": "string"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "failed_items_truncated": {
                      "type": "boolean"
                    },
                    "cancellation_requested": {
                      "type": "boolean"
                    },
                    "message": {
                      "type": "null"
                    },
                    "created_at": {
                      "type": "string"
                    },
                    "updated_at": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job_id": "1759672800123",
                  "action": "pause",
                  "status": "completed",
                  "total": 37,
                  "processed": 37,
                  "successful": 36,
                  "failed": 1,
                  "failed_items": [
                    {
                      "listing_id": "MCO1234567899",
                      "error": "item_under_review"
                    }
                  ],
                  "failed_items_truncated": false,
                  "cancellation_requested": false,
                  "message": null,
                  "created_at": "2026-10-05T14:00:00.000Z",
                  "updated_at": "2026-10-05T14:01:12.000Z"
                }
              }
            }
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "404": {
            "description": "E_JOB_NOT_FOUND: jobId no existe o no es de su seller",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_JOB_NOT_FOUND"
            ]
          },
          "503": {
            "description": "E_INTERNAL: Error inesperado. Reintente con backoff",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_INTERNAL"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/ml-actions#status",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_JOB_NOT_FOUND",
          "E_INTERNAL"
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "description": "El job_id que devolvió POST /products/ml-actions.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "x-scope": "products:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/products/ml-actions/{jobId}/cancel": {
      "post": {
        "operationId": "v2-ml-actions-cancel",
        "summary": "Cancelar una acción en curso",
        "description": "Pide detener un job en queued o processing. Se detiene antes del siguiente lote: lo que ya se hizo en Mercado Libre no se revierte.\n\nScope requerido: `listings:write`.\n\nSoporta `Idempotency-Key` para reintentos seguros.\n\nCosto: Sin costo.",
        "tags": [
          "Actions"
        ],
        "responses": {
          "200": {
            "description": "Cancelación solicitada.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "message": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job_id": "1759672800123",
                  "status": "cancellation_requested",
                  "message": "Cancelación solicitada: el job se detiene antes del siguiente lote; lo ya hecho en Mercado Libre queda hecho."
                }
              }
            }
          },
          "400": {
            "description": "E_JOB_ALREADY_TERMINAL: Cancel sobre job ya cerrado",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_JOB_ALREADY_TERMINAL"
            ]
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "404": {
            "description": "E_JOB_NOT_FOUND: jobId no existe o no es de su seller",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_JOB_NOT_FOUND"
            ]
          },
          "503": {
            "description": "E_INTERNAL: Error inesperado. Reintente con backoff",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_INTERNAL"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": true,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/ml-actions#cancel",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_JOB_NOT_FOUND",
          "E_JOB_ALREADY_TERMINAL",
          "E_INTERNAL"
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "description": "El job_id a cancelar (en queued o processing).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "Idempotency-Key",
            "in": "header",
            "required": false,
            "description": "Clave única por operación (ej. un UUID). Un reintento con la misma key, mismo método, ruta y body devuelve la respuesta original sin repetir el cambio (24 h; solo se guardan respuestas 2xx).",
            "schema": {
              "type": "string",
              "maxLength": 255
            }
          }
        ],
        "x-scope": "listings:write",
        "x-credit-cost": "Sin costo."
      }
    },
    "/account": {
      "get": {
        "operationId": "v2-account-get",
        "summary": "Info de la cuenta y créditos",
        "description": "Datos de la cuenta asociada a la API Key: conexión con Mercado Libre, créditos y la configuración con la que se publica. Créditos: hay un solo credits.total y dos consumos que se descuentan de él por separado, used_live (publicaciones reales) y used_test (en prueba); no se suman entre sí. Los dos saldos vienen calculados: available_live (total − used_live, para publicar en real) y available_test (total − used_test, para publicar en prueba). credits.available es el del entorno de la key usada.\n\nScope requerido: `account:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Cuenta, créditos y configuración de publicación efectiva del seller.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "seller_id": {
                      "type": "integer"
                    },
                    "email": {
                      "type": "string"
                    },
                    "ml_nickname": {
                      "type": "string"
                    },
                    "ml_site_id": {
                      "type": "string"
                    },
                    "amazon_site": {
                      "type": "string"
                    },
                    "ml_currency": {
                      "type": "string"
                    },
                    "ml_account_status": {
                      "type": "string"
                    },
                    "ml_connected": {
                      "type": "boolean"
                    },
                    "api_key": {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "integer"
                        },
                        "name": {
                          "type": "string"
                        },
                        "environment": {
                          "type": "string"
                        },
                        "tier": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": true
                    },
                    "credits": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "available": {
                          "type": "integer"
                        },
                        "available_live": {
                          "type": "integer"
                        },
                        "available_test": {
                          "type": "integer"
                        },
                        "used_live": {
                          "type": "integer"
                        },
                        "used_test": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true
                    },
                    "publishing_config": {
                      "type": "object",
                      "properties": {
                        "trm": {
                          "type": "integer"
                        },
                        "warranty_time": {
                          "type": "string"
                        },
                        "manufacturing_time_days": {
                          "type": "integer"
                        },
                        "stock_quantity": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "seller_id": 108386,
                  "email": "cuenta@ejemplo.com",
                  "ml_nickname": "MITIENDA",
                  "ml_site_id": "MCO",
                  "amazon_site": "amazon.com",
                  "ml_currency": "COP",
                  "ml_account_status": "active",
                  "ml_connected": true,
                  "api_key": {
                    "id": 12,
                    "name": "ERP Producción",
                    "environment": "live",
                    "tier": "default"
                  },
                  "credits": {
                    "total": 5000,
                    "available": 1240,
                    "available_live": 1240,
                    "available_test": 4915,
                    "used_live": 3760,
                    "used_test": 85
                  },
                  "publishing_config": {
                    "trm": 4100,
                    "warranty_time": "30 días",
                    "manufacturing_time_days": 12,
                    "stock_quantity": 5
                  }
                }
              }
            }
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "404": {
            "description": "E_ACCOUNT_NOT_FOUND: Cuenta Meli no encontrada",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_ACCOUNT_NOT_FOUND"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/account#info",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_ACCOUNT_NOT_FOUND"
        ],
        "x-scope": "account:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/account/tax-categories": {
      "get": {
        "operationId": "v2-account-tax-categories",
        "summary": "Categorías fiscales del seller",
        "description": "Devuelve las categorías fiscales configuradas por el seller. El `id` es exactamente el valor numérico que se pasa como automeli_tax_category en POST /products. Conviene cachear esta lista en lugar de hardcodear ids.\n\nScope requerido: `account:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Array de categorías fiscales tal cual están en la config del seller.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "seller_id": {
                      "type": "integer"
                    },
                    "tax_categories": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer"
                          },
                          "name": {
                            "type": "string"
                          },
                          "taxes": {
                            "type": "object",
                            "properties": {
                              "iva": {
                                "type": "integer"
                              },
                              "impuesto2": {
                                "type": "integer"
                              },
                              "impuesto3": {
                                "type": "integer"
                              },
                              "iva_v2": {
                                "type": "integer"
                              },
                              "impuesto2_v2": {
                                "type": "integer"
                              },
                              "impuesto3_v2": {
                                "type": "integer"
                              }
                            },
                            "additionalProperties": true
                          }
                        },
                        "additionalProperties": true
                      }
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "seller_id": 108386,
                  "tax_categories": [
                    {
                      "id": 0,
                      "name": "IVA 19%",
                      "taxes": {
                        "iva": 19,
                        "impuesto2": 0,
                        "impuesto3": 0,
                        "iva_v2": 19,
                        "impuesto2_v2": 0,
                        "impuesto3_v2": 0
                      }
                    }
                  ]
                }
              }
            }
          },
          "403": {
            "description": "E_AUTH_FORBIDDEN_SCOPE: Su key no tiene el permiso requerido (ver scopes)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_FORBIDDEN_SCOPE"
            ]
          },
          "404": {
            "description": "E_ACCOUNT_NOT_FOUND: Cuenta Meli no encontrada",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_ACCOUNT_NOT_FOUND"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/account#tax-categories",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_ACCOUNT_NOT_FOUND"
        ],
        "x-scope": "account:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/ping": {
      "get": {
        "operationId": "v2-ping",
        "summary": "Verificar la API Key (health check autenticado)",
        "description": "La forma más rápida de validar el setup completo (DNS, credenciales, conectividad) antes de integrar. No requiere scope: cualquier key válida responde, con api_version: \"v2\".\n\nNo requiere scope: cualquier API Key válida funciona.\n\nCosto: Sin costo.",
        "tags": [
          "System"
        ],
        "responses": {
          "200": {
            "description": "La key es válida. Devuelve el seller asociado, el environment y la versión.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "api_version": {
                      "type": "string"
                    },
                    "seller_id": {
                      "type": "integer"
                    },
                    "environment": {
                      "type": "string"
                    },
                    "key_name": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "ok": true,
                  "api_version": "v2",
                  "seller_id": 108386,
                  "environment": "live",
                  "key_name": "ERP Producción",
                  "request_id": "cd66c602-…",
                  "timestamp": "2026-05-08T12:00:00.000Z"
                }
              }
            }
          },
          "401": {
            "description": "E_AUTH_MISSING_KEY: Falta el header X-API-Key\nE_AUTH_INVALID_KEY: Key con formato inválido o no reconocida\nE_AUTH_KEY_REVOKED: Key revocada por el dueño\nE_AUTH_KEY_EXPIRED: Key con expires_at vencido",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_AUTH_MISSING_KEY",
              "E_AUTH_INVALID_KEY",
              "E_AUTH_KEY_REVOKED",
              "E_AUTH_KEY_EXPIRED"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/auth/verify",
        "x-error-codes": [
          "E_AUTH_MISSING_KEY",
          "E_AUTH_INVALID_KEY",
          "E_AUTH_KEY_REVOKED",
          "E_AUTH_KEY_EXPIRED"
        ],
        "x-credit-cost": "Sin costo."
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "X-API-Key",
        "description": "API Key del seller, con prefijo automeli_live_* o automeli_test_*."
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "description": "Problem Details (RFC 7807). `code` es el contrato público estable — haga switch sobre `code`, no sobre `title`.",
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "URI del tipo, https://api.automeli.com/errors/{code}."
          },
          "title": {
            "type": "string",
            "description": "Resumen legible. Puede cambiar."
          },
          "status": {
            "type": "integer",
            "description": "HTTP status code."
          },
          "code": {
            "type": "string",
            "enum": [
              "E_AUTH_MISSING_KEY",
              "E_AUTH_INVALID_KEY",
              "E_AUTH_KEY_REVOKED",
              "E_AUTH_KEY_EXPIRED",
              "E_AUTH_FORBIDDEN_SCOPE",
              "E_RATE_LIMITED",
              "E_IDEMPOTENCY_CONFLICT",
              "E_PRODUCT_INVALID_BODY",
              "E_PRODUCT_INVALID_PARAM",
              "E_PRODUCT_LIST_TIMEOUT",
              "E_PRODUCT_INVALID_SKU",
              "E_PRODUCT_CREDIT_EXHAUSTED",
              "E_PRODUCT_MAX_CONCURRENT_JOBS",
              "E_PROMOTE_NO_CANDIDATES",
              "E_PROMOTE_REQUIRES_LIVE_KEY",
              "E_ACTION_REQUIRES_LIVE_KEY",
              "E_ACTION_COUNT_MISMATCH",
              "E_ACTION_MAX_CONCURRENT_JOBS",
              "E_ACTION_IDEMPOTENCY_KEY_REQUIRED",
              "E_ACTION_REJECTED",
              "E_CATEGORY_INVALID",
              "E_CATEGORY_AND_AUTO_CONFLICT",
              "E_JOB_NOT_FOUND",
              "E_JOB_NOT_RETRYABLE",
              "E_JOB_ALREADY_TERMINAL",
              "E_ACCOUNT_NOT_FOUND",
              "E_NO_ML_TOKEN",
              "E_INVALID_JSON",
              "E_UNSUPPORTED_MEDIA_TYPE",
              "E_PAYLOAD_TOO_LARGE",
              "E_NOT_FOUND",
              "E_INTERNAL"
            ],
            "description": "Código machine-readable estable."
          },
          "instance": {
            "type": "string",
            "description": "Path de la request que falló."
          },
          "detail": {
            "type": "string",
            "description": "Detalle específico de esta ocurrencia."
          }
        },
        "required": [
          "type",
          "title",
          "status",
          "code"
        ],
        "additionalProperties": true
      }
    }
  }
}