Dos puertas a la misma B1.

Todo programa que lee o contabiliza algo en SAP Business One sin que una persona lo teclee usa una de dos interfaces. El Service Layer es un servicio web: se ejecuta en el servidor, habla HTTPS y OData y responde con JSON. Puedes llamarlo desde cualquier lenguaje capaz de enviar una petición web, y el servicio móvil de B1 depende de él. La DI API (Data Interface API) es la vía más antigua: una biblioteca COM (una DLL) para Windows, pensada para C/C++, Visual Basic y .NET, que el programa carga en la máquina donde se ejecuta.

Por debajo son lo mismo. La propia guía del Service Layer de SAP describe el DI Core dentro del Service Layer como "the same one that is used by SAP Business One DI API", y la lógica de negocio (impuestos, contabilización, stock) se ejecuta en el mismo componente que en el cliente de B1. Por eso un pedido que entra por cualquiera de las dos puertas pasa los mismos controles que uno tecleado en pantalla: si B1 lo rechazaría en la ventana, también lo rechaza desde tu programa. Los nombres de objetos y campos también son en gran parte iguales: CardCode se llama CardCode en ambos.

Cuál usar y cuándo.

  • Service Layer para todo lo nuevo: una app de escáner, un enlace con una tienda online, un tablero de planificación, una integración con otro sistema. Funciona en SUSE Linux y en Windows, el balanceador de carga suele escuchar en el puerto 50000 y tu programa no necesita instalar nada junto a B1. Escala con varios nodos detrás del balanceador.
  • DI API cuando mantienes un add-on existente construido sobre ella, o cuando el código se ejecuta de todos modos dentro del cliente de B1 en Windows, junto a la UI API. La ayuda del SDK de SAP indica que la DI API no admite multithreading, y debe estar instalada en cada máquina donde se ejecuta el programa.
  • Lo que solo tiene la DI API: la guía lo dice sin rodeos. El Service Layer no tiene el objeto Recordset para SQL directo, ni importación y exportación a XML, ni transacciones que abarquen varias peticiones: no hay StartTransaction ni EndTransaction como en la DI API. Cada petición, también un lote, es su propia transacción.

En la DI API, un programa crea un objeto Company, rellena Server, CompanyDB, UserName, Password y DbServerType, y llama a Connect, que devuelve 0 si todo va bien. Un pedido es entonces GetBusinessObject(BoObjectTypes.oOrders), rellenado línea a línea y guardado con Add; si una llamada falla, GetLastError da el código y el texto. El resto de esta guía trata del Service Layer, porque es ahí adonde va el trabajo nuevo.

Iniciar sesión, y cuánto dura una sesión.

El Service Layer está en https://<server>:50000/b1s/v2/. /b1s/v2 habla OData versión 4, /b1s/v1 la versión 3, más antigua; elige v2 para trabajo nuevo. Sin iniciar sesión no funciona nada:

  • POST /b1s/v2/Login con el cuerpo {"CompanyDB": "SBODEMOUS", "UserName": "manager", "Password": "1234"}. Un Language opcional fija el idioma de los mensajes.
  • La respuesta es 200 OK con un SessionId y un SessionTimeout, y dos cookies: B1SESSION y ROUTEID. Cada petición siguiente debe enviar B1SESSION; ROUTEID es opcional y te mantiene en el mismo nodo detrás del balanceador. Un navegador envía ambas por sí solo; un programa de escritorio o de servidor tiene que ponerlas él.
  • La sesión caduca tras un periodo sin peticiones: 30 minutos por defecto, configurado como SessionTimeout en b1s.conf en el servidor. Después la respuesta es 401 Unauthorized con el código 301, "Invalid session or session already timeout." Vuelve a iniciar sesión y repite la petición.
  • POST /b1s/v2/Logout con la cookie cierra la sesión; la respuesta es 204 No Content. Cierra la sesión cuando termines, y no inicies sesión para cada petición suelta: el inicio de sesión es la llamada más pesada que existe.

Leer, crear y modificar datos.

Leer es un GET sobre una entidad, con opciones de consulta OData para que la respuesta sea pequeña. GET /b1s/v2/BusinessPartners?$select=CardCode,CardName&$filter=CardType eq 'cCustomer'&$top=5 devuelve cinco clientes con solo su código y nombre. $filter conoce eq, ne, gt, ge, lt, le, and, or, not, y funciones como startswith y contains; $orderby ordena y $skip pagina. Un registro se lee por su clave: GET /b1s/v2/BusinessPartners('C20000'), con comillas porque la clave es texto, y GET /b1s/v2/Orders(22) sin ellas, porque DocEntry es un número. Las líneas de un pedido vienen con el pedido, en DocumentLines.

Una lista nunca llega de una vez. Por defecto el Service Layer devuelve 20 registros por página y añade un @odata.nextLink a la página siguiente; la cabecera Prefer: odata.maxpagesize=50 pide páginas más grandes. El código que lee solo la primera página y se para es el error más común en una primera integración.

Crear es un POST con JSON. POST /b1s/v2/Orders con {"CardCode": "C20000", "DocDueDate": "2026-11-15", "DocumentLines": [{"ItemCode": "A00001", "Quantity": 10}]} añade un pedido de cliente y responde 201 Created con el documento completo, incluidos el nuevo DocEntry y el DocNum. Modificar es un PATCH sobre la clave con solo los campos que cambian, por ejemplo PATCH /b1s/v2/BusinessPartners('C20000') con {"Phone1": "0201234567"}; la respuesta es 204 No Content. Usa PATCH, no PUT: PUT restablece todos los campos que omites. Los pasos que no son un cambio simple son acciones, como POST /b1s/v2/Orders(22)/Close. Un DELETE sobre un pedido se rechaza, igual que en el cliente de B1 no puedes borrar uno.

Las entidades no son tablas.

El Service Layer habla en objetos de negocio; la base de datos, en tablas. BusinessPartners se guarda en OCRD; Orders es el pedido de cliente, con la cabecera en ORDR y las líneas en RDR1. Muchos documentos de marketing comparten un tipo de entidad, Document, así que Orders, Invoices y PurchaseOrders tienen los mismos campos. La lista completa de entidades, campos y acciones está en GET /b1s/v2/$metadata, incluidos tus propios campos definidos por el usuario, de modo que los metadatos de una base de datos de empresa pueden diferir de los de otra. Una trampa: un campo o una tabla de usuario nuevos solo se ven después de reiniciar el Service Layer.

Leer una tabla con SQL está bien. Escribir en ella, no. Las reglas del SDK de SAP no permiten cambios en los objetos estándar, y un INSERT o un UPDATE directamente en ORDR se salta todo lo que B1 hace al añadir un documento: numeración, stock, el asiento contable, autorizaciones, aprobación, el registro de cambios. Te quedas con datos que B1 nunca comprobó. Todo lo que cambia datos pasa por el Service Layer o la DI API, sin excepción.

Errores, lotes y consultas guardadas.

  • Los errores vuelven como un estado HTTP (por ejemplo 400 para una petición rechazada, 401 sin sesión válida, 403 sin autorización) y un cuerpo JSON con un objeto error que contiene un code y un message: el mismo texto que vería un usuario en el cliente de B1, por ejemplo un código de interlocutor que ya existe. Registra ese texto; casi siempre dice qué falla.
  • Las peticiones por lotes van a POST /b1s/v2/$batch como un único mensaje multipart. Las peticiones dentro de un change set son de todo o nada: si una falla, se deshace todo el change set. Es la respuesta del Service Layer a una transacción sobre varios documentos, siempre que quepan en un lote.
  • Consultas SQL guardadas (desde 10.0 FP 2011): guardas un SELECT como entrada en SQLQueries, con SqlCode, SqlName y SqlText, y lo ejecutas con GET /b1s/v2/SQLQueries('sql01')/List. Solo se permite leer; UPDATE, INSERT y DELETE se rechazan, y solo se pueden consultar tablas y columnas permitidas. Un usuario normal necesita autorización para cada consulta en General Authorizations. Los detalles están en nuestra guía sobre consultas SQL.

Antes de empezar: una lista de comprobación.

  • El Service Layer está instalado y en marcha en tu servidor de B1, y tu programa puede llegar al puerto 50000 por HTTPS. Está pensado para llamadas internas; no hace falta exponerlo a internet.
  • Una empresa de pruebas donde ensayar las peticiones, nunca la base de datos real.
  • Un usuario de B1 propio para el programa, con solo las autorizaciones que necesita, y una licencia para ese usuario. Indirect Access es el tipo pensado para programas; consulta nuestra guía sobre licencias de B1 y confírmalo con tu partner.
  • Una sesión reutilizada entre peticiones, un nuevo inicio de sesión ante un 401 y un cierre de sesión al final.
  • Paginación resuelta: sigue @odata.nextLink hasta que desaparezca.
  • Nombres de campo tomados de los $metadata de tu propia base de datos de empresa, ni adivinados ni copiados de otro sistema.
  • El texto de error de cada petición rechazada guardado en un registro, y nada escrito directamente en las tablas de SAP.

Cómo lo enfoca KoonLearn.

KoonLearn, nuestra simulación de formación para SAP Business One, tiene un módulo de profundización llamado Service Layer y DI API: secciones sobre arquitectura e inicio de sesión, lectura, escritura, avanzado, DI API, resolución de problemas. Trabajas en una consola de peticiones en el navegador: método, URL, cabeceras y cuerpo, un botón Send y una respuesta con estado y JSON a partir de los datos de la empresa de formación. Inicias sesión y ves caducar tu sesión, filtras y paginas interlocutores y pedidos de compra, creas y modificas documentos con POST y PATCH, ejecutas Close y Cancel, envías un change set en un lote y reparas peticiones que vuelven con 400, 401 o 404. La parte de DI API consiste en leer código y encontrar el fallo: una conexión que no se comprueba, una transacción sin su gestión de errores, un bucle sobre un Recordset. La consola responde como el Service Layer; no lo es, y no se instala ni se conecta nada a un B1 real.

Los precios y las opciones están en el portal de clientes. La profundización termina con un test y un examen del módulo. Va más allá del examen: no es preparación para C_TB120 y no da ningún certificado. Si primero quieres ver cómo funciona KoonLearn, el capítulo 03 Compras es gratuito sin cuenta: empieza el capítulo gratuito en learn.koonsystems.com. KoonLearn no está afiliado a SAP SE.

Fuentes: SAP, Working with SAP Business One Service Layer (versión 1.29, 27-07-2026: inicio de sesión y sesión, CRUD, opciones de consulta, paginación, lotes, SQL Query, limitaciones frente a la DI API); la referencia de la API del Service Layer (Login, Logout, BusinessPartners, Orders); SAP Business One SDK Help 10.0 (DI API, conexión, gestión de errores, modificaciones del estándar); referencia de la DI API 10.0 (Company, Documents); Database Tables Reference 10.0 (OCRD, ORDR, RDR1); el resumen de módulos de KoonLearn. SAP y SAP Business One son marcas comerciales de SAP SE.