{
  "openapi": "3.1.0",
  "info": {
    "title": "Automeli API",
    "version": "v1",
    "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. ATENCIÓN: v1 es la versión anterior, congelada, y se apaga el 2027-01-31 — las respuestas v1 lo anuncian con los headers Deprecation y Sunset. Migrar a v2 (la versión recomendada, spec en https://www.automeli.com/api-docs/openapi.json).",
    "contact": {
      "name": "Soporte Automeli",
      "url": "https://www.automeli.com/api-docs/v1"
    },
    "x-stability": "beta"
  },
  "externalDocs": {
    "description": "Documentación",
    "url": "https://www.automeli.com/api-docs/v1"
  },
  "servers": [
    {
      "url": "https://api.automeli.com/api/v1",
      "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": {
      "post": {
        "operationId": "products-create",
        "summary": "Crear un job de publicación",
        "description": "Endpoint principal. 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_* no consume créditos), 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 no consumen créditos.",
        "tags": [
          "Products"
        ],
        "responses": {
          "202": {
            "description": "Job aceptado y encolado. Devuelve el job_id para hacer seguimiento.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "accepted": {
                      "type": "integer"
                    },
                    "rejected": {
                      "type": "integer"
                    },
                    "total_items": {
                      "type": "integer"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job_id": "8a3f2b10-4c9d-4e21-9f8a-1b2c3d4e5f60",
                  "status": "queued",
                  "accepted": 2,
                  "rejected": 0,
                  "total_items": 2
                }
              }
            }
          },
          "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 o query malformado (campo, fecha o estado inválido)\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/v1/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"
        ],
        "x-scope": "products:write",
        "x-credit-cost": "1 crédito por item publicado. Las keys test no consumen créditos.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "items": {
                    "type": "array",
                    "items": {
                      "type": "object",
                      "properties": {
                        "sku": {
                          "type": "string"
                        },
                        "category_id": {
                          "type": "string"
                        }
                      },
                      "additionalProperties": true
                    },
                    "description": "Cada item: sku + (category_id o auto_categorize)."
                  },
                  "listing_type_id": {
                    "type": "string",
                    "description": "Tipo de publicación de Mercado Libre. Default: el configurado por el seller. 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"
                    ]
                  },
                  "tax_category_id": {
                    "type": "integer",
                    "description": "Índice (no nombre) de la categoría arancelaria del seller. 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",
                    "category_id": "MCO420674"
                  },
                  {
                    "sku": "B07JHNJLYH",
                    "auto_categorize": true
                  }
                ],
                "listing_type_id": "gold_pro",
                "tax_category_id": 0
              }
            }
          },
          "x-fields": [
            {
              "name": "items",
              "type": "array (1-10.000)",
              "required": "yes",
              "description": "Cada item: sku + (category_id o auto_categorize)."
            },
            {
              "name": "items[].sku",
              "type": "string",
              "required": "yes",
              "description": "10 caracteres alfanuméricos (ASIN de Amazon)."
            },
            {
              "name": "items[].category_id",
              "type": "string",
              "required": "conditional",
              "description": "ID Meli, 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 category_id."
            },
            {
              "name": "listing_type_id",
              "type": "string",
              "required": "no",
              "description": "Tipo de publicación de Mercado Libre. Default: el configurado por el seller. 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": "tax_category_id",
              "type": "int",
              "required": "no",
              "description": "Índice (no nombre) de la categoría arancelaria del seller. 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/test": {
      "get": {
        "operationId": "products-test-list",
        "summary": "Listar productos en cuenta de prueba",
        "description": "Devuelve los productos creados al publicar con una key automeli_test_*. El campo published_to_live indica si ese SKU ya se promovió a la cuenta real.\n\nScope requerido: `products:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Products"
        ],
        "responses": {
          "200": {
            "description": "Lista paginada de productos en la cuenta de prueba.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "products": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "sku": {
                            "type": "string"
                          },
                          "listing_id_test": {
                            "type": "string"
                          },
                          "title": {
                            "type": "string"
                          },
                          "image": {
                            "type": "string"
                          },
                          "permalink_test": {
                            "type": "string"
                          },
                          "listing_type_id": {
                            "type": "string"
                          },
                          "price": {
                            "type": "integer"
                          },
                          "currency": {
                            "type": "string"
                          },
                          "category_id": {
                            "type": "string"
                          },
                          "category_name": {
                            "type": "string"
                          },
                          "tax_category_id": {
                            "type": "integer"
                          },
                          "status_meli": {
                            "type": "string"
                          },
                          "app_status": {
                            "type": "integer"
                          },
                          "published_to_live": {
                            "type": "boolean"
                          },
                          "test_published_at": {
                            "type": "string"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        },
                        "returned": {
                          "type": "integer"
                        },
                        "total": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "products": [
                    {
                      "sku": "B003H03SDQ",
                      "listing_id_test": "MCO1943839161",
                      "title": "Producto de prueba",
                      "image": "https://http2.mlstatic.com/...jpg",
                      "permalink_test": "https://articulo.mercadolibre.com.co/...",
                      "listing_type_id": "gold_pro",
                      "price": 89000,
                      "currency": "COP",
                      "category_id": "MCO420674",
                      "category_name": "Soluciones Limpiadoras",
                      "tax_category_id": 0,
                      "status_meli": "active",
                      "app_status": 1,
                      "published_to_live": false,
                      "test_published_at": "2026-05-08T12:00:00.000Z"
                    }
                  ],
                  "pagination": {
                    "limit": 50,
                    "offset": 0,
                    "returned": 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_BODY: Body o query malformado (campo, fecha o estado inválido)\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_BODY",
              "E_PRODUCT_INVALID_SKU"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/v1/test-products#list",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PRODUCT_INVALID_BODY",
          "E_PRODUCT_INVALID_SKU"
        ],
        "parameters": [
          {
            "name": "already_published",
            "in": "query",
            "required": false,
            "description": "Filtra por la columna en BD (en el response sale como published_to_live). false → solo los pendientes de promover; true → los que ya pasaron a real.",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "status_meli",
            "in": "query",
            "required": false,
            "description": "Estado del listing en Mercado Libre.",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "paused",
                "closed",
                "under_review",
                "inactive",
                "not_yet_active",
                "payment_required"
              ]
            }
          },
          {
            "name": "app_status",
            "in": "query",
            "required": false,
            "description": "Estado interno de Automeli (0=pausado/eliminado, 1=activo).",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "sku",
            "in": "query",
            "required": false,
            "description": "Filtra por SKU exacto.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Default 50.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Default 0. Para paginar.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "x-scope": "products:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/products/test/promote": {
      "post": {
        "operationId": "products-test-promote",
        "summary": "Promover productos de prueba a la cuenta real",
        "description": "Atajo que lista internamente los SKUs activos pendientes en prueba y los publica en la cuenta real, en una sola llamada. Sin el campo skus promueve todos los candidatos (hasta 1000 por llamada). 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 por SKU promovido.",
        "tags": [
          "Products"
        ],
        "responses": {
          "202": {
            "description": "Job de promoción aceptado. Devuelve job_id y la lista de SKUs aceptados.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "job_id": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "promoted": {
                      "type": "integer"
                    },
                    "rejected": {
                      "type": "integer"
                    },
                    "total_candidates": {
                      "type": "integer"
                    },
                    "skus": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "job_id": "8a3f2b10-4c9d-4e21-9f8a-1b2c3d4e5f60",
                  "status": "queued",
                  "promoted": 12,
                  "rejected": 0,
                  "total_candidates": 12,
                  "skus": [
                    "B003H03SDQ",
                    "B07JHNJLYH",
                    "..."
                  ]
                }
              }
            }
          },
          "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"
            ]
          },
          "422": {
            "description": "E_PRODUCT_INVALID_BODY: Body o query malformado (campo, fecha o estado inválido)\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_BODY",
              "E_PRODUCT_INVALID_SKU"
            ]
          },
          "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/v1/test-products#promote",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PROMOTE_REQUIRES_LIVE_KEY",
          "E_PROMOTE_NO_CANDIDATES",
          "E_PRODUCT_INVALID_BODY",
          "E_PRODUCT_INVALID_SKU",
          "E_PRODUCT_CREDIT_EXHAUSTED",
          "E_PRODUCT_MAX_CONCURRENT_JOBS",
          "E_ACCOUNT_NOT_FOUND"
        ],
        "x-scope": "products:write",
        "x-credit-cost": "1 crédito por SKU promovido.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "skus": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    },
                    "description": "SKUs a promover. Si se omite, promueve todos los candidatos activos (hasta 1000)."
                  },
                  "listing_type_id": {
                    "type": "string",
                    "description": "Tipo de publicación. Default: el configurado por el seller.",
                    "enum": [
                      "gold_pro",
                      "gold_special",
                      "gold_premium",
                      "gold",
                      "silver",
                      "bronze"
                    ]
                  },
                  "tax_category_id": {
                    "type": "integer",
                    "description": "Índice de la categoría arancelaria. Default 0."
                  }
                },
                "additionalProperties": true
              },
              "example": {
                "skus": [
                  "B003H03SDQ",
                  "B07JHNJLYH"
                ],
                "listing_type_id": "gold_pro",
                "tax_category_id": 0
              }
            }
          },
          "x-fields": [
            {
              "name": "skus",
              "type": "array",
              "required": "no",
              "description": "SKUs a promover. Si se omite, promueve todos los candidatos activos (hasta 1000)."
            },
            {
              "name": "listing_type_id",
              "type": "string",
              "required": "no",
              "description": "Tipo de publicación. Default: el configurado por el seller.",
              "enum": [
                "gold_pro",
                "gold_special",
                "gold_premium",
                "gold",
                "silver",
                "bronze"
              ]
            },
            {
              "name": "tax_category_id",
              "type": "int",
              "required": "no",
              "description": "Índice de la categoría arancelaria. Default 0."
            }
          ]
        }
      }
    },
    "/products/jobs/{jobId}": {
      "get": {
        "operationId": "jobs-get",
        "summary": "Consultar el estado de un job",
        "description": "Haga poll cada 5-10 segundos hasta que el status sea final (completed, failed o cancelled).\n\nScope requerido: `products:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Jobs"
        ],
        "responses": {
          "200": {
            "description": "Estado del job + sus items, paginados.",
            "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
                    },
                    "items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "sku": {
                            "type": "string"
                          },
                          "status": {
                            "type": "string"
                          },
                          "listing_id": {
                            "type": "string"
                          },
                          "permalink": {
                            "type": "string"
                          },
                          "price": {
                            "type": "integer"
                          }
                        },
                        "additionalProperties": true
                      }
                    },
                    "pagination": {
                      "type": "object",
                      "properties": {
                        "limit": {
                          "type": "integer"
                        },
                        "offset": {
                          "type": "integer"
                        },
                        "returned": {
                          "type": "integer"
                        }
                      },
                      "additionalProperties": true
                    }
                  },
                  "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:09Z"
                  },
                  "items": [
                    {
                      "sku": "B003H03SDQ",
                      "status": "success",
                      "listing_id": "MCO1234567890",
                      "permalink": "https://articulo.mercadolibre.com.co/…",
                      "price": 89000
                    }
                  ],
                  "pagination": {
                    "limit": 100,
                    "offset": 0,
                    "returned": 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"
            ]
          },
          "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"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/v1/jobs#status",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_JOB_NOT_FOUND"
        ],
        "parameters": [
          {
            "name": "jobId",
            "in": "path",
            "required": true,
            "description": "El job_id devuelto al crear el job.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Filtra los items por estado, ej. failed.",
            "schema": {
              "type": "string",
              "enum": [
                "success",
                "failed",
                "skipped",
                "pending"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items por página. Default 100.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Default 0. Para paginar los items.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "x-scope": "products:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/products/jobs": {
      "get": {
        "operationId": "jobs-list",
        "summary": "Listar jobs",
        "description": "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": "Lista paginada de jobs del seller que matchean el filtro."
          },
          "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_BODY: Body o query malformado (campo, fecha o estado inválido)",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            },
            "x-error-codes": [
              "E_PRODUCT_INVALID_BODY"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/v1/jobs#list",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "E_PRODUCT_INVALID_BODY"
        ],
        "parameters": [
          {
            "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"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Jobs por página.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "offset",
            "in": "query",
            "required": false,
            "description": "Para paginar.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "x-scope": "products:read",
        "x-credit-cost": "Sin costo (lectura)."
      }
    },
    "/products/jobs/{jobId}/retry": {
      "post": {
        "operationId": "jobs-retry",
        "summary": "Reintentar items fallidos de un job",
        "description": "Reintenta items en failed con retryable: true. Solo aplica sobre jobs terminales. Consume créditos por cada item reintentado.\n\nScope requerido: `products:write`.\n\nCosto: 1 crédito por item reintentado.",
        "tags": [
          "Jobs"
        ],
        "responses": {
          "202": {
            "description": "Reintento aceptado para los items retryables del job."
          },
          "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"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/v1/jobs#retry",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "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"
            }
          }
        ],
        "x-scope": "products:write",
        "x-credit-cost": "1 crédito por item reintentado."
      }
    },
    "/products/jobs/{jobId}/cancel": {
      "post": {
        "operationId": "jobs-cancel",
        "summary": "Cancelar un job",
        "description": "Cancela jobs en queued, processing o scheduled. Los items pendientes pasan a skipped. Los ya publicados no se afectan.\n\nScope requerido: `products:write`.\n\nCosto: Sin costo (no genera publicaciones nuevas).",
        "tags": [
          "Jobs"
        ],
        "responses": {
          "200": {
            "description": "Job cancelado. Los items pendientes quedan en skipped."
          },
          "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"
            ]
          }
        },
        "x-key-env": "any",
        "x-idempotent": false,
        "x-stability": "beta",
        "x-doc-url": "https://www.automeli.com/api-docs/v1/jobs#cancel",
        "x-error-codes": [
          "E_AUTH_FORBIDDEN_SCOPE",
          "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"
            }
          }
        ],
        "x-scope": "products:write",
        "x-credit-cost": "Sin costo (no genera publicaciones nuevas)."
      }
    },
    "/account": {
      "get": {
        "operationId": "account-get",
        "summary": "Info de la cuenta y créditos",
        "description": "Antes de un batch grande conviene chequear créditos disponibles y la config efectiva del seller. credits.available se calcula según el environment de la key.\n\nScope requerido: `account:read`.\n\nCosto: Sin costo (lectura).",
        "tags": [
          "Account"
        ],
        "responses": {
          "200": {
            "description": "Créditos + configuración de publicación efectiva del seller.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "seller_id": {
                      "type": "integer"
                    },
                    "site_id": {
                      "type": "string"
                    },
                    "currency": {
                      "type": "string"
                    },
                    "credits": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "integer"
                        },
                        "available": {
                          "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,
                  "site_id": "MCO",
                  "currency": "COP",
                  "credits": {
                    "total": 5000,
                    "available": 4500,
                    "used_live": 500,
                    "used_test": 0
                  },
                  "publishing_config": {
                    "trm": 4200,
                    "warranty_time": "1 mes",
                    "manufacturing_time_days": 5,
                    "stock_quantity": 8
                  }
                }
              }
            }
          },
          "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/v1/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": "account-tax-categories",
        "summary": "Categorías arancelarias del seller",
        "description": "Devuelve las categorías arancelarias configuradas por el seller. El `id` es exactamente el valor numérico que se pasa como tax_category_id 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 arancelarias 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": "Nuevo",
                      "taxes": {
                        "iva": 21,
                        "impuesto2": 38,
                        "impuesto3": 8,
                        "iva_v2": 21,
                        "impuesto2_v2": 38,
                        "impuesto3_v2": 8
                      }
                    },
                    {
                      "id": 1,
                      "name": "49",
                      "taxes": {
                        "iva": 21,
                        "impuesto2": 23,
                        "impuesto3": 5,
                        "iva_v2": 21,
                        "impuesto2_v2": 23,
                        "impuesto3_v2": 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/v1/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": "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.\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 el nombre.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "ok": {
                      "type": "boolean"
                    },
                    "seller_id": {
                      "type": "integer"
                    },
                    "environment": {
                      "type": "string"
                    },
                    "key_name": {
                      "type": "string"
                    },
                    "request_id": {
                      "type": "string"
                    },
                    "timestamp": {
                      "type": "string"
                    }
                  },
                  "additionalProperties": true
                },
                "example": {
                  "ok": true,
                  "seller_id": 108386,
                  "environment": "test",
                  "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/v1/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_SKU",
              "E_PRODUCT_CREDIT_EXHAUSTED",
              "E_PRODUCT_MAX_CONCURRENT_JOBS",
              "E_PROMOTE_NO_CANDIDATES",
              "E_PROMOTE_REQUIRES_LIVE_KEY",
              "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_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
      }
    }
  }
}