Twee deuren naar dezelfde B1.

Elk programma dat iets in SAP Business One leest of boekt zonder dat iemand het intikt, gebruikt een van twee koppelingen. De Service Layer is een webservice: hij draait op de server, spreekt HTTPS en OData, en antwoordt met JSON. Je roept hem aan vanuit elke taal die een webverzoek kan sturen, en de mobiele service van B1 hangt ervan af. De DI API (Data Interface API) is de oudere route: een COM-bibliotheek (een DLL) voor Windows, gemaakt voor C/C++, Visual Basic en .NET, die een programma laadt op de machine waar het draait.

Onder de motorkap zijn ze hetzelfde. SAP's eigen Service Layer-gids beschrijft de DI Core in de Service Layer als "the same one that is used by SAP Business One DI API", en de bedrijfslogica (btw, boeken, voorraad) draait in hetzelfde onderdeel als in de B1-client. Daarom gaat een order die via een van beide deuren binnenkomt door dezelfde controles als een order die op het scherm is ingetikt: weigert B1 hem in het venster, dan weigert hij hem ook vanuit je programma. Ook de namen van objecten en velden zijn grotendeels gelijk: CardCode heet in allebei CardCode.

Welke je wanneer gebruikt.

  • Service Layer voor alles wat nieuw is: een scanner-app, een koppeling met een webshop, een planbord, een integratie met een ander systeem. Hij draait op SUSE Linux en op Windows, de load balancer luistert meestal op poort 50000, en je programma hoeft niets naast B1 te installeren. Hij schaalt met meerdere nodes achter de load balancer.
  • DI API als je een bestaande add-on onderhoudt die erop gebouwd is, of als de code toch al in de B1-client op Windows draait, naast de UI API. De SDK-help van SAP vermeldt dat de DI API geen multithreading ondersteunt, en hij moet geïnstalleerd zijn op elke machine waar het programma draait.
  • Wat alleen de DI API heeft: de gids zegt het zonder omwegen. De Service Layer heeft geen Recordset-object voor directe SQL, geen import en export naar XML, en geen transactie over meerdere verzoeken: er is geen StartTransaction en EndTransaction zoals in de DI API. Elk verzoek, ook een batch, is een eigen transactie.

In de DI API maakt een programma een Company-object, vult Server, CompanyDB, UserName, Password en DbServerType, en roept Connect aan, dat 0 teruggeeft als het lukt. Een order is dan GetBusinessObject(BoObjectTypes.oOrders), regel voor regel gevuld en opgeslagen met Add; mislukt een aanroep, dan geeft GetLastError de code en de tekst. De rest van deze gids gaat over de Service Layer, want daar gaat nieuw werk heen.

Inloggen, en hoe lang een sessie leeft.

De Service Layer staat op https://<server>:50000/b1s/v2/. /b1s/v2 spreekt OData versie 4, /b1s/v1 de oudere versie 3; kies v2 voor nieuw werk. Zonder inloggen werkt er niets:

  • POST /b1s/v2/Login met als body {"CompanyDB": "SBODEMOUS", "UserName": "manager", "Password": "1234"}. Een optionele Language bepaalt de taal van de meldingen.
  • Het antwoord is 200 OK met een SessionId en een SessionTimeout, en twee cookies: B1SESSION en ROUTEID. Elk volgend verzoek moet B1SESSION meesturen; ROUTEID is optioneel en houdt je op dezelfde node achter de load balancer. Een browser stuurt ze vanzelf mee; een desktop- of serverprogramma moet ze zelf zetten.
  • De sessie verloopt na een periode zonder verzoeken: standaard 30 minuten, ingesteld als SessionTimeout in b1s.conf op de server. Daarna is het antwoord 401 Unauthorized met code 301, "Invalid session or session already timeout." Log opnieuw in en herhaal het verzoek.
  • POST /b1s/v2/Logout met de cookie beëindigt de sessie; het antwoord is 204 No Content. Log uit als je klaar bent, en log niet voor elk los verzoek opnieuw in: inloggen is de zwaarste aanroep die er is.

Gegevens lezen, aanmaken en wijzigen.

Lezen is een GET op een entiteit, met OData-queryopties om het antwoord klein te houden. GET /b1s/v2/BusinessPartners?$select=CardCode,CardName&$filter=CardType eq 'cCustomer'&$top=5 geeft vijf klanten met alleen hun code en naam. $filter kent eq, ne, gt, ge, lt, le, and, or, not, en functies als startswith en contains; $orderby sorteert en $skip bladert. Eén record lees je op zijn sleutel: GET /b1s/v2/BusinessPartners('C20000'), met aanhalingstekens omdat de sleutel tekst is, en GET /b1s/v2/Orders(22) zonder, omdat DocEntry een getal is. De regels van een order komen mee met de order, in DocumentLines.

Een lijst komt nooit in één keer. Standaard geeft de Service Layer 20 records per pagina en zet er een @odata.nextLink naar de volgende pagina bij; de header Prefer: odata.maxpagesize=50 vraagt om grotere pagina's. Code die alleen de eerste pagina leest en dan stopt, is de meest gemaakte fout in een eerste koppeling.

Aanmaken is een POST met JSON. POST /b1s/v2/Orders met {"CardCode": "C20000", "DocDueDate": "2026-11-15", "DocumentLines": [{"ItemCode": "A00001", "Quantity": 10}]} voegt een verkooporder toe en antwoordt 201 Created met het hele document, inclusief de nieuwe DocEntry en DocNum. Wijzigen is een PATCH op de sleutel met alleen de velden die veranderen, bijvoorbeeld PATCH /b1s/v2/BusinessPartners('C20000') met {"Phone1": "0201234567"}; het antwoord is 204 No Content. Gebruik PATCH, geen PUT: PUT zet elk veld dat je weglaat terug. Stappen die geen gewone wijziging zijn, zijn acties, zoals POST /b1s/v2/Orders(22)/Close. Een DELETE op een order wordt geweigerd, net zoals je er in de B1-client geen kunt verwijderen.

Entiteiten zijn geen tabellen.

De Service Layer praat in bedrijfsobjecten, de database in tabellen. BusinessPartners staat in OCRD; Orders is de verkooporder, met de kop in ORDR en de regels in RDR1. Veel marketingdocumenten delen één entiteitstype, Document, dus Orders, Invoices en PurchaseOrders hebben dezelfde velden. De volledige lijst van entiteiten, velden en acties staat in GET /b1s/v2/$metadata, inclusief je eigen gebruikersvelden, dus de metadata van de ene bedrijfsdatabase kan verschillen van die van de andere. Eén addertje: een nieuw gebruikersveld of een nieuwe gebruikerstabel is pas zichtbaar nadat de Service Layer opnieuw is gestart.

Een tabel lezen met SQL is prima. Erin schrijven niet. De SDK-regels van SAP staan geen wijzigingen aan standaardobjecten toe, en een INSERT of UPDATE rechtstreeks in ORDR slaat alles over wat B1 doet als een document wordt toegevoegd: nummering, voorraad, de journaalpost, autorisaties, goedkeuring, het wijzigingslog. Je houdt gegevens over die B1 nooit heeft gecontroleerd. Alles wat gegevens verandert, gaat via de Service Layer of de DI API, zonder uitzondering.

Fouten, batches en opgeslagen query's.

  • Fouten komen terug als HTTP-status (bijvoorbeeld 400 voor een geweigerd verzoek, 401 zonder geldige sessie, 403 zonder autorisatie) en een JSON-body met een error-object met een code en een message: dezelfde tekst die een gebruiker in de B1-client zou zien, bijvoorbeeld een relatiecode die al bestaat. Log die tekst; hij zegt bijna altijd wat er mis is.
  • Batchverzoeken gaan naar POST /b1s/v2/$batch als één multipart-bericht. Verzoeken binnen een change set slagen samen of mislukken samen: faalt er één, dan wordt de hele change set teruggedraaid. Dat is het antwoord van de Service Layer op een transactie over meerdere documenten, zolang ze in één batch passen.
  • Opgeslagen SQL-query's (sinds 10.0 FP 2011): je slaat een SELECT op als item in SQLQueries, met SqlCode, SqlName en SqlText, en voert hem uit met GET /b1s/v2/SQLQueries('sql01')/List. Alleen lezen mag; UPDATE, INSERT en DELETE worden geweigerd, en alleen toegestane tabellen en kolommen zijn op te vragen. Een gewone gebruiker heeft per query autorisatie nodig in General Authorizations. De details staan in onze gids over SQL-query's.

Voordat je begint: een checklist.

  • De Service Layer is geïnstalleerd en draait op je B1-server, en je programma kan poort 50000 bereiken via HTTPS. Hij is bedoeld voor interne aanroepen; hij hoeft niet aan internet te hangen.
  • Een testbedrijf om verzoeken op uit te proberen, nooit de live database.
  • Een eigen B1-gebruiker voor het programma, met alleen de autorisaties die het nodig heeft, en een licentie voor die gebruiker. Indirect Access is het type dat voor programma's bedoeld is; zie onze gids over B1-licenties en stem het af met je partner.
  • Eén sessie die je hergebruikt over verzoeken, opnieuw inloggen bij een 401, en uitloggen aan het eind.
  • Paginering geregeld: volg @odata.nextLink tot hij er niet meer is.
  • Veldnamen uit de $metadata van je eigen bedrijfsdatabase, niet gegokt en niet overgenomen uit een ander systeem.
  • De fouttekst van elk geweigerd verzoek in een log, en niets rechtstreeks in SAP-tabellen geschreven.

Hoe KoonLearn het aanpakt.

KoonLearn, onze trainingssimulatie voor SAP Business One, heeft een verdieping Service Layer en DI API: secties over architectuur en inloggen, lezen, schrijven, gevorderd, DI API, foutzoeken. Je werkt in een request-console in de browser: methode, URL, headers en body, een knop Send, en een antwoord met status en JSON uit de gegevens van het trainingsbedrijf. Je logt in en ziet je sessie verlopen, filtert en bladert door relaties en inkooporders, post en patcht documenten, voert Close en Cancel uit, stuurt een change set in een batch, en repareert verzoeken die terugkomen met 400, 401 of 404. Het DI API-deel is code lezen en de fout vinden: een verbinding die niet wordt gecontroleerd, een transactie zonder foutafhandeling, een lus over een Recordset. De console antwoordt zoals de Service Layer; hij is er geen, en er wordt niets geïnstalleerd of met een echte B1 verbonden.

Prijzen en opties staan in het klantportaal. De verdieping eindigt met een toets en een module-examen. Ze gaat verder dan het examen: ze is geen voorbereiding op C_TB120 en geeft geen certificaat. Wil je eerst zien hoe KoonLearn werkt, dan is hoofdstuk 03 Inkoop gratis zonder account: begin het gratis hoofdstuk op learn.koonsystems.com. KoonLearn is niet verbonden aan SAP SE.

Bronnen: SAP, Working with SAP Business One Service Layer (versie 1.29, 27-07-2026: inloggen en sessie, CRUD, queryopties, paginering, batch, SQL Query, beperkingen ten opzichte van de DI API); de Service Layer API-referentie (Login, Logout, BusinessPartners, Orders); SAP Business One SDK Help 10.0 (DI API, verbinden, foutafhandeling, wijzigingen aan de standaard); DI API-referentie 10.0 (Company, Documents); Database Tables Reference 10.0 (OCRD, ORDR, RDR1); het moduleoverzicht van KoonLearn. SAP en SAP Business One zijn handelsmerken van SAP SE.