API externa JSON-2

Con la llegada de Odoo 19, los desarrolladores ahora cuentan con una nueva forma más moderna y eficiente de integrar sistemas externos: la API JSON-2. Esta interfaz simplifica la comunicación con los modelos de Odoo usando peticiones HTTP y datos en formato JSON, dejando atrás la complejidad del tradicional JSON-RPC. En este blog, mostraremos las características de esta nueva API, así como un ejemplo de su implementación.

Daniel Sánchez

10/24/20258 min read

¿Qué es la API externa JSON-2?

La API JSON-2 es una nueva alternativa para exponer el API externa de Odoo 19, pensada para simplificar el consumo desde sistemas externos (aplicaciones web, scripts, integraciones) utilizando una ruta tipo REST basada en JSON.

Características principales de la API externa JSON-2

  • Permite invocar métodos de los modelos de Odoo (ORM) mediante peticiones HTTP POST con cuerpo JSON.

  • Reemplaza (o convive con) las APIs tradicionales de JSON-RPC, XML-RPC, u otras capas de servicio, pero con una sintaxis más “RESTful” en cuanto a la estructura de la URL y el uso de JSON como formato único.

  • Tiene una documentación dinámica integrada en la instancia de Odoo, lo que permite explorar los modelos, métodos y esquemas de datos desde el propio servidor.

¿Cómo se estructura una request a la API externa JSON-2?

Consiste en una request a la URL /json/2/<model>/<method> con un objeto JSON. La request debe contener las siguientes características:

HTTP Headers

  • Host: Requerido, el nombre del host del servidor.

  • Authorization: Requerido, consiste en la oración “bearer” seguido de la clave de la API.

  • Content-Type: Requerido, siempre será “application/json”; se recomienda agregar un charset (por ejemplo, utf-8).

  • X-Odoo-Database: Opcional, el nombre de la base de datos a la que se conectará.

  • User-Agent: Recomendado, el nombre del software que se está conectando a Odoo.

Ruta URL

  • model: Requerido, nombre técnico del modelo.

  • method: Requerido, el método a ejecutar.

Cuerpo del objeto JSON

  • ids: Arreglo con los ids de los registros en los cuales ejecutar el método. Vacío u omitido cuando se llama a un método que contiene el decorador @api.model.

  • Context: Opcional, un diccionario con valores adicionales. Por ejemplo, {“lang”: “en_US”}.

  • param: Parámetros del método. Requeridos según la definición del método.

Ejemplo de request a API externa JSON-2

Tanto en planes community como enterprise se debe crear una clave de la API externa, la misma que será agregada dentro de un encabezado de la solicitud, funcionando como un token de autorización. Para crearla, se debe ingresar a la sección Preferencias / Seguridad / Claves API.

Al presionar el botón “Agregar clave API” se solicita la descripción y el propósito de la clave, así como su duración. La intención de la descripción es identificar la clave para determinar si aún se seguirá utilizando o se debe eliminar después de utilizarla. Mientras que si se supera el tiempo del campo ‘Duración’ desde que se creó la clave, se vuelve inválida.

El botón ‘Generar clave’ crea una clave aleatoria de 160 bits. Esta se muestra solo una vez y no se puede recuperar después de la creación, por lo que se debe copiar inmediatamente y guardar en un lugar seguro. La intención de esta funcionalidad es que si la clave se compromete o pierde, se puede eliminar y volver a generar una nueva.

Ahora que tenemos la clave, la podemos agregar dentro de nuestras requests. Supongamos que tenemos una base de datos llamada odoo19 con datos demo en nuestro entorno local, aunque podría estar alojada en un sitio web. Dentro de nuestro script agregamos esa información:

Es importante mencionar que la clave de la API externa se debe cargar dentro del script de alguna forma más segura, por ejemplo, desde una variable de entorno o desde un archivo de configuración. Solo se agregó de esta forma por motivos de ejemplificación.

Supongamos que queremos buscar si existe algún cliente (modelo res.partner) cuyo nombre contenga la palabra ‘deco’ y sea una compañía. El código para verificar esta información sería el siguiente.

Al correr el anterior script, obtenemos el siguiente resultado.

Donde 9 es el id del cliente que cumple con las condiciones anteriores. Ahora que sabemos que existe ese cliente, podemos obtener más información de él, como su nombre, RFC, email o teléfono. El código para obtener esta información es el siguiente:

Al correr el anterior script, obtenemos el siguiente resultado.

Hagamos algo más complejo. Supongamos que desde el script queremos crear una venta con un producto y confirmarla. Estructuramos el código en las siguientes partes:

Primero buscamos clientes cuyo nombre contenga la palabra ‘azure’ y que sea una compañía, y después buscamos productos cuyo nombre contenga la palabra ‘pantalla’. Al ejecutar esta parte del script obtenemos los siguientes resultados:

En este caso obtenemos un cliente con las condiciones mencionadas y 3 productos cuyo nombre contiene la palabra ‘pantalla’. Crearemos la venta con una línea por cada uno de los 3 productos obtenidos.

En la siguiente parte del código realizamos lo siguiente:

Ahora llamamos a la función ‘create’ del modelo de ventas (sale.order), la misma función que crea el registro dentro de la base de datos. El parámetro que debe ingresar es “vals_list”, el mismo que es una lista de diccionarios, donde cada diccionario son los campos y valores de la orden. Para el ejemplo anterior, los campos que agregamos son los siguientes:

  • name (Nombre de la venta): Agregamos el texto “Orden creada desde API JSON-2” para identificarla dentro del sistema, además de que cuando la creemos desde el script obtendremos su id.

  • partner_id (Cliente de la venta): Agregamos el cliente que encontramos en la parte 1, es decir, el cliente que contiene la palabra “azure” dentro de su nombre.

  • order_line (Líneas de productos): Agregamos cada uno de los productos que encontramos en la parte 1, es decir, los productos que contienen la palabra “pantalla” dentro de su nombre (que ya vimos que obtenemos 3 productos).

Al ejecutar el anterior código obtenemos el siguiente resultado:

Notamos que se ha creado la venta con id 25. La verificamos dentro del sistema:

Se ha creado la venta con id 25, con el nombre personalizado que le dimos y con los 3 productos cuyo nombre contiene la palabra “pantalla”.

En la siguiente parte tenemos el siguiente código.

Después de crear la venta, la confirmamos llamando al método “action_confirm”, que pertenece al módulo de ventas (sale). Recibe como parámetros el id de la venta (que se crea en la parte 2) y el contexto. Si eliminamos la venta que creamos anteriormente (ya que si volvemos a ejecutar el script completo, se volverá a crear una venta con el mismo nombre, que choca con una condición que tiene el modelo de no permitir más de un registro con el mismo nombre) y volvemos a ejecutar el script, obtenemos lo siguiente: 

Se ha creado una nueva orden con id 26 y se ha confirmado. Al verificar en el sistema, obtenemos:

Ahora, ¿cómo podemos saber los métodos que podemos llamar desde la API externa, así como sus parámetros? El sistema contiene el endpoint /doc, donde podemos ver por cada modelo sus métodos disponibles, así como sus parámetros, todos estructurados por módulos. Por ejemplo, si quisiéramos ver los parámetros y el tipo de respuesta del método create del modelo de ventas (sale.order), lo vemos de la siguiente manera:

Seleccionamos el modelo “Orden de venta” (sale.order) y los métodos disponibles dentro del módulo core (que es la base de Odoo); aquí encontramos el método create, que se utiliza para crear y guardar registros, y la documentación nos muestra un ejemplo de la request, con campos y valores de ejemplo, así como sus parámetros, lo que responde y el tipo de la respuesta, así como su descripción.

Supongamos que queremos ver el método “action_confirm” para poder confirmar la venta dentro de la documentación. Seleccionamos el módulo sale y buscamos el método, el cual nos muestra la siguiente información:

Nos muestra un ejemplo de la request, su descripción, parámetros y lo que nos devuelve el método (que en este caso es un booleano).

Notemos que el método nos muestra la siguiente descripción:

Esto es ya que la información se construye a partir de la descripción que se agrega en la definición del método en Python. Es decir, la información anterior se construye a partir de la siguiente información dentro del archivo Python que define el método.

Modificamos la descripción y cambiamos la información del retorno, así como su tipo a lo siguiente.

Por lo que ahora estos cambios se ven en la documentación al momento de actualizar el módulo api_doc.

Consejos rápidos:

  • Evita enviar usuario y contraseña. Genera una API key desde el perfil del usuario y úsala en el header Authorization: bearer <API_KEY>.

  • En entornos con varias bases, agrega el header X-Odoo-Database: nombre_base para evitar errores de conexión.

  • Envía siempre Content-Type: application/json. Toda la comunicación se basa en JSON; no uses formularios ni multipart.

  • La API respeta las reglas de acceso y permisos de Odoo. Asegúrate de que el usuario tenga los permisos adecuados sobre los modelos a los que accede.

  • La API devuelve errores con códigos HTTP estándar (400, 403, 404, 500). Úsalos para manejar fallos de forma elegante en tu integración.

  • Odoo 19 incluye documentación interactiva para explorar los métodos disponibles en /doc (si está activado). Aprovéchala para obtener información de los métodos.

  • Evita exponer la clave API en el frontend. Si tu integración involucra un sitio web, haz las llamadas desde el backend para proteger las credenciales.

En Exdoo podemos desarrollar cualquier módulo para Odoo en México, implementamos tu ERP con consultores experimentados no solo en Odoo, sino en procesos de negocios; tenemos 10 años trabajando solamente con Odoo en México y otros países.