Naar de inhoud
SyncMyShop

Systemen

Odoo koppeling met je webshop: orders in Odoo, voorraad per magazijn terug

Een Odoo koppeling zet webshoporders en klanten als verkooporder in Odoo en haalt artikelen, voorraad, prijzen en trackingnummers terug naar je webshop. Sinds Odoo 19 loopt dat over de JSON-2 API met een API-sleutel; XML-RPC verdwijnt in Odoo 22. Het werk zit in varianten, voorraadvelden, adressen en de veldnamen die per versie veranderen.

Wat is Odoo en wie gebruikt het?

Odoo is een ERP-pakket uit België dat uit losse apps bestaat: verkoop, inkoop, voorraad, boekhouding, productie, CRM en een eigen webshop. Er is een open source-editie, Odoo Community, en een betaalde editie met een abonnement.

Voor een koppeling tellen twee dingen: waar Odoo draait en welke versie het is. Er zijn drie manieren van hosten:

Hosting Eigen modules Versies
Odoo Online nee, ook geen modules uit de Apps Store major versies plus SaaS-versies elke 2 tot 3 maanden
Odoo.sh ja major versies
Eigen server ja major versies, ook met verlengde support

Odoo brengt elk najaar een major versie uit en geeft daar 3 jaar standaardsupport op. Odoo 20.0 kwam in september 2026, Odoo 19.0 in september 2025, Odoo 18.0 in oktober 2024. De support van Odoo 17.0 liep in september 2026 af. Een koppeling die vandaag gebouwd wordt, draait dus vaak op 18 of 19 en gaat binnen een jaar of twee door een upgrade.

Wat je met Odoo koppelt

Odoo is in de meeste koppelingen leidend voor artikelen, voorraad, prijzen en facturen. De webshop levert de order en de nieuwe klant.

Stroom Richting Model in Odoo
Orders webshop naar Odoo sale.order met order_line
Klanten en adressen webshop naar Odoo res.partner
Artikelen en varianten Odoo naar webshop product.template, product.product
Voorraad Odoo naar webshop qty_available, free_qty op product.product; stock.quant
Prijslijsten Odoo naar webshop product.pricelist, product.pricelist.item
Verzending en tracking Odoo naar webshop stock.picking, veld carrier_tracking_ref
Facturen Odoo naar webshop account.move

Een order gaat met de regels erin in één aanroep naar binnen. Klant en artikel gaan mee als id, dus die zoekt de koppeling eerst op. Dit is order 10482 van Bakker Installatie B.V. op Odoo 19:

POST /json/2/sale.order/create HTTP/1.1
Host: bakker.odoo.com
Authorization: bearer 3f9c...e1a7
Content-Type: application/json; charset=utf-8

{
  "vals_list": [{
    "partner_id": 4711,
    "partner_shipping_id": 4712,
    "client_order_ref": "WEB-10482",
    "order_line": [[0, 0, {
      "product_id": 881, "product_uom_qty": 12,
      "price_unit": 17.08, "tax_ids": [[6, 0, [17]]]
    }]]
  }]
}

De lijsten met drie elementen zijn de schrijfopdrachten van Odoo voor gekoppelde records: 0 maakt een regel aan, 6 zet de btw-codes. Via de API moeten ze letterlijk zo, als getallen. Het webshopordernummer gaat in client_order_ref, het veld Customer Reference. Daarop zoekt de koppeling bij elke nieuwe poging eerst of de order er al staat. Welke velden per stroom meegaan staat op orders, klanten en verzending.

Een webshoporder als verkooporder in Odoo Vijf velden van webshoporder WEB-10482 en waar ze in Odoo landen. Klant en artikel worden eerst opgezocht en gaan als id mee. Het adres komt in street. Staat de module base_address_extended aan, dan splitst Odoo die regel, maar bij een toevoeging met spatie blijft alles in street_name en blijft het huisnummer leeg. Het btw-veld heet sinds Odoo 19 tax_ids in plaats van tax_id. Webshoporder Odoo: sale.order, res.partner order_number WEB-10482 billing.email inkoop@bakker-installatie.nl shipping.address1 Dorpsstraat 12 A line_items[0].sku KB-2210 line_items[0].tax_rate 21 client_order_ref WEB-10482 partner_id 4711 res.partner, gezocht op e-mail street Dorpsstraat 12 A street_name Dorpsstraat 12 A base_address_extended splitst niet street_number (leeg) order_line.product_id 881 product.product, op default_code order_line.tax_ids [[6, 0, [17]]] tot en met Odoo 18: tax_id zoeken, dan id split door Odoo zoeken, dan id tarief naar account.tax
Vijf velden van één webshoporder en waar ze in Odoo landen. In rood de twee plekken waar een koppeling zonder controle stil verkeerde data schrijft.

Hoe Odoo data vrijgeeft

JSON-2 vanaf Odoo 19, XML-RPC daarvoor

Versie Externe API Inloggen
Odoo 17 en 18 XML-RPC en JSON-RPC op /xmlrpc/2 en /jsonrpc database, login en wachtwoord of API-sleutel
Odoo 19 JSON-2 op /json/2/<model>/<methode>; RPC verouderd API-sleutel als bearer-token
Odoo 20 JSON-2; database-service van RPC verwijderd API-sleutel als bearer-token
Odoo 22 (najaar 2028) alleen JSON-2; RPC verwijderd API-sleutel als bearer-token

In beide gevallen praat de koppeling met dezelfde modellen en methodes die Odoo intern gebruikt: search_read, create, write en de knoppen van het scherm, zoals action_confirm op een verkooporder. Welke modellen en velden jouw database heeft, hangt af van de geïnstalleerde apps. Methodes waarvan de naam met een underscore begint, zijn via de API niet aan te roepen.

Op een server met meerdere databases gaat de databasenaam mee in de header X-Odoo-Database. Bij XML-RPC is het de eerste parameter van elke aanroep; dat is de "databasenaam" die je bij oudere koppelingen moest invullen.

API-sleutels van maximaal 90 dagen

Een API-sleutel maak je per gebruiker aan onder Voorkeuren, Accountbeveiliging. Odoo toont de sleutel één keer. In Odoo 19 krijgt elke sleutel een verloopdatum. Voor een gewone interne gebruiker is de maximale looptijd 90 dagen; alleen een beheerder kan een sleutel zonder einddatum maken. Odoo raadt voor een koppeling een aparte botgebruiker aan met alleen de rechten die de koppeling nodig heeft en zonder wachtwoord. Die botgebruiker komt dan ook in de wijzigingslog te staan in plaats van een medewerker.

Een sleutel van 90 dagen betekent dat de koppeling na drie maanden stopt als niemand hem vervangt. Odoo heeft daarvoor res.users.apikeys/generate: met de lopende sleutel maakt de koppeling een nieuwe aan en trekt de oude in. Standaard mag alleen een gebruiker met beheerrechten dat; een systeemparameter zet het voor andere gebruikers aan. Per gebruiker zijn standaard 10 zo gemaakte sleutels toegestaan, daarboven volgt HTTP 422.

Alleen op het Custom-plan

Odoo schrijft dat de externe API alleen beschikbaar is op het Custom-plan, niet op One App Free of Standard. Een koppeling met een webshop is externe API. Verzoeken die Odoo zelf naar buiten doet, zoals naar een betaalprovider of vervoerder, vallen er niet onder. De documentatie van de JSON-2 API noemt het plan, de authenticatie en de foutcodes.

Elke aanroep is een eigen transactie

De documentatie van Odoo noemt geen limiet in verzoeken per minuut. Wat er wel staat: elke JSON-2-aanroep is een eigen databasetransactie, en meerdere aanroepen samen in één transactie kan niet. Voor een order betekent dat twee transacties: create maakt een offerte, action_confirm maakt er een bevestigde verkooporder van. Faalt de tweede, dan staat er een onbevestigde offerte met het webshopnummer erop. Zonder de controle op client_order_ref maakt de volgende poging een tweede offerte.

De rekensom voor 600 orders op een drukke dag: per order één zoekvraag naar de klant, één naar de artikelen van alle regels samen, één create en één action_confirm. Dat zijn 4 aanroepen per order, 2.400 per dag. Lezen gaat in pagina's: 15.000 varianten met search_read en een limit van 1.000 zijn 15 aanroepen. Hoe snel Odoo antwoordt, hangt af van je hosting en de geïnstalleerde apps, dus die meten we op jouw database voor de livegang.

Waar het bij Odoo op vastloopt

Wat de webshop nodig heeft In Odoo Gevolg zonder regel
Eén unieke SKU per variant default_code op product.product, niet uniek afgedwongen twee varianten met dezelfde code, order op de verkeerde
Voorraad die verkoopbaar is qty_available, free_qty en virtual_available te hoge voorraad in de shop
Voorraad die gewijzigd is berekende velden, geen write_date op het artikel wijzigingen worden niet gezien
Huisnummer en toevoeging street en street2, splitsing alleen met een extra module lege huisnummers
Klantprijs regels in product.pricelist.item, geen publieke rekenmethode verkeerde prijs in een B2B-shop

Template, variant en een code die niet uniek is

Een artikel in Odoo is een product.template; elke variant daarvan is een product.product. De webshop-SKU hoort op de variant, in default_code (Internal Reference). Odoo dwingt die code niet uniek af: het scherm waarschuwt bij een dubbele code, de API niet. De streepjescode in barcode is wel uniek binnen een bedrijf. De koppeling controleert daarom voor elke run of een SKU precies één variant oplevert en zet een dubbele code op de controlelijst. Zie varianten.

Drie voorraadgetallen en geen wijzigingsdatum

Op een variant staan drie getallen. qty_available is wat er fysiek ligt. free_qty is dat min wat al gereserveerd is voor bevestigde orders. virtual_available telt ook geplande in- en uitgaande leveringen mee. Voor de webshop is free_qty meestal het juiste getal. Met warehouse_id of location in de context van de aanroep geeft Odoo het getal voor één magazijn of locatie; zonder context telt het alle interne locaties op. Zie meerdere magazijnen.

Alle drie zijn berekende velden. Een voorraadmutatie verandert de write_date van het artikel dus niet, en een koppeling die artikelen filtert op write_date mist elke voorraadwijziging. De koppeling leest wijzigingen daarom uit stock.quant. Odoo slaat datums op in UTC zonder tijdzone; een filter op 00:30 Nederlandse tijd op 1 oktober is 2026-09-30 22:30:00. Zie welke voorraad toon je in je webshop.

Adressen: één regel of een splitsing die niet klopt

Een adres in Odoo heeft street en street2. De module base_address_extended voegt street_name, street_number en street_number2 toe en splitst street automatisch. Die splitsing herkent een Nederlandse toevoeging met spatie niet: Dorpsstraat 12 A komt in zijn geheel in street_name en het huisnummer blijft leeg, terwijl Dorpsstraat 12A wel als straat plus huisnummer 12A uitkomt. De Nederlandse boekhoudmodule l10n_nl installeert base_address_extended niet mee. Schrijft de koppeling zelf naar de losse velden, dan bouwt Odoo street daaruit op als Dorpsstraat 12 - A, met een streepje voor de toevoeging. Zie adresvelden mappen.

Klantprijzen en veldnamen die per versie wijzigen

De prijs van een artikel voor een klant komt uit de prijslijst van die klant: regels met een vaste prijs, een korting of een formule, een min_quantity en een date_start. De methodes die daar een prijs van maken beginnen met een underscore en zijn via de API niet aan te roepen. De koppeling leest de regels en rekent de prijs zelf uit, of op Odoo.sh en een eigen server doet een kleine module dat. Zie klantspecifieke prijzen.

Veldnamen veranderen bij een upgrade. Het btw-veld op een orderregel heette tot en met Odoo 18 tax_id en heet in Odoo 19 tax_ids. Een koppeling die het oude veld blijft sturen, krijgt na de upgrade een fout op elke order. Bij een upgrade draait de koppeling daarom eerst als dry run tegen een kopie van je database. Op Odoo Online kan dat met een duplicaat: maximaal 5 per database, 15 dagen geldig, en met de optie For testing purposes staan e-mails, betalingen en leveringen erin uit.

Platformen die we aan Odoo koppelen

De koppeling wordt gebouwd op jouw Odoo, met jouw apps, prijslijsten en magazijnen. Voor WooCommerce staat de combinatie op WooCommerce Odoo koppeling. De platformen zelf staan op WooCommerce koppeling, Shopify koppeling en Magento koppeling. Andere ERP-systemen: Business Central koppeling en Exact Online koppeling. De ERP-kant in het algemeen staat op ERP koppeling met je webshop, alle stromen op koppelingen.

Wij bouwen de koppeling voor een vaste prijs, en hosten, draaien en bewaken hem daarna voor een vast bedrag per maand. Voor de livegang draait hij als dry run: je ziet per order welke klant, varianten en btw-codes in Odoo zouden ontstaan, zonder dat er iets wordt aangemaakt. Vertel welke Odoo-versie en welk plan je hebt, dan hoor je welke stromen via de API kunnen en waar een module nodig is.

Veelgestelde vragen

Werkt een koppeling met Odoo Online, Odoo.sh en een eigen server?

Ja, alle drie hebben dezelfde externe API. Het verschil zit in wat er naast de API kan. Odoo Online draait geen eigen modules en geen modules uit de Odoo Apps Store, dus alles moet via de standaardmodellen en publieke methodes. Op Odoo.sh en op een eigen server kan een kleine module erbij, bijvoorbeeld voor een klantprijs of een order die in één transactie wordt aangemaakt en bevestigd.

Heb ik het Custom-plan van Odoo nodig?

Volgens de documentatie van Odoo is de externe API alleen beschikbaar op het Custom-plan, niet op One App Free en niet op Standard. Een koppeling die van buitenaf gegevens in Odoo leest of schrijft valt daaronder. Gaat het verzoek vanuit Odoo naar een andere dienst, zoals een betaalprovider of vervoerder, dan telt Odoo dat niet als externe API. Controleer dus eerst welk plan je hebt.

Welke Odoo-versie heb ik nodig?

Een koppeling werkt op elke versie met standaardsupport. Odoo 19 en 20 hebben de JSON-2 API, Odoo 17 en 18 alleen XML-RPC en JSON-RPC. Standaardsupport voor Odoo 17 liep in september 2026 af, voor Odoo 18 loopt hij tot september 2027. Wie nu nog op 17 of 18 zit, upgradet binnen afzienbare tijd, en dan verandert de API en een deel van de veldnamen.

Wat gebeurt er met mijn koppeling als XML-RPC verdwijnt?

De database-service van XML-RPC en JSON-RPC is in Odoo 20 al verwijderd. De services common en object, waar koppelingen over lopen, volgen in Odoo 22, gepland voor najaar 2028, en op Odoo Online in versie 21.1, winter 2027. Een koppeling die nog op /xmlrpc/2/object draait moet voor die tijd naar /json/2. Inloggen verandert mee: geen gebruikers-id en wachtwoord meer, maar een API-sleutel in de header.

Kan Odoo een webhook sturen als er iets wijzigt?

Ja, via een automatiseringsregel met de actie Send Webhook Notification. Die stuurt een POST met de velden die je kiest naar een adres. De documentatie beschrijft geen herhaalpogingen als de ontvanger even onbereikbaar is. Wij gebruiken zo'n webhook als signaal en draaien daarnaast een controleronde op write_date, zodat een gemiste melding geen gemiste order of voorraadwijziging wordt. Zie wat is een webhook.

Odoo heeft zelf een webshop. Waarom een koppeling?

Met de eCommerce-app van Odoo heb je geen koppeling nodig: shop en ERP zijn dan dezelfde database. Deze pagina gaat over een webshop op een ander platform, zoals WooCommerce, Shopify of Magento, met Odoo als ERP erachter. Dan zijn het twee systemen met elk een eigen artikelnummer, klant en order, en daar zit de mapping.

Vertel wat je nodig hebt

Vertel welke systemen je gebruikt en wat je wilt verbeteren. Je krijgt binnen één werkdag een persoonlijk antwoord. We helpen je de werkzaamheden helder te krijgen en spreken de prijs en planning af voordat je iets toezegt.

  • Je weet de prijs en de doorlooptijd voordat je iets toezegt
  • Wij zoeken uit welke koppeling het werk uit handen neemt
  • Wij verzorgen de bouw, hosting, bewaking en het onderhoud
  • Je team krijgt minder overtypwerk en minder uitzoekwerk

Leveranciers, producten, orders per dag, een ruwe schatting is prima.

Of mail direct: carsten@syncmyshop.com