Integrations / ERP / Odoo
Odoo Integration Guide for SkyPlanner APS Production Scheduling
This guide shows Odoo partners, developers and IT leads how to connect Odoo Manufacturing to SkyPlanner APS. For the business case and what Odoo’s Plan button already does, read the Odoo production scheduling page and Does Odoo have finite capacity scheduling?.
Odoo stays the system of record for products, bills of materials, operations, manufacturing orders, stock and costing. SkyPlanner builds the schedule from that data with its Arcturus engine. It integrates with Odoo in both directions:
- Manufacturing orders, work orders, BoM operations, work centers and purchase orders come in.
- Planned start and end and work centers are written back to
mrp.workorder. - Progress and logged time go back as Odoo Time Logs.
- SkyPlanner webhooks push schedule changes as they happen.
The SkyPlanner team configures the integration on Odoo’s standard external API during onboarding, fitted to your version, hosting and customizations, and supports it after go-live. This guide is for partners and developers who want to take part, or to build on SkyPlanner’s documented REST API (API reference) themselves. Products, materials and purchase order handling are described in the public SkyPlanner documentation.
Step zero: check the Odoo plan and hosting
First find out which Odoo the customer runs. It decides the route.
| Setup | External API | Custom modules | Practical route |
|---|---|---|---|
| Odoo Online, One App Free or Standard | No | No | CSV/XLSX, or move to the Custom plan |
| Odoo Online, Custom plan | Yes | No | External API |
| Odoo.sh (Custom plan) | Yes | Yes | External API, optional module |
| On-premise, Community or Enterprise | Yes | Yes | External API, optional module |
Odoo’s API documentation states that external API access is “only available on Custom Odoo pricing plans”, not on One App Free or Standard. Its pricing page describes Standard as hosted on Odoo Online “without custom modules”. Ask this in discovery, not halfway through the build.
Odoo’s integration options
| Option | Versions | Auth | Role in a scheduling integration |
|---|---|---|---|
External JSON-2 API: POST /json/2/<model>/<method> | New in 19.0 | API key in Authorization: bearer <key>, optional X-Odoo-Database header | Default for new builds: search_read for reads, write for date write-back |
External XML-RPC / JSON-RPC: /xmlrpc/2, /jsonrpc, services common, object | Up to 19.0; scheduled for removal | common.authenticate with login and password or API key, then execute_kw | Required for customers on 16.0 to 18.0 |
| Custom controllers in a module | All | Per route, e.g. auth='bearer' | Combined payloads: an MO with its work orders in one call |
| Automation rules: “Send Webhook Notification” | In the docs from 17.0 | Outbound POST to a URL | Push on create or edit of MOs and work orders |
| Import records (CSV, XLSX) and export | All | User session | Trial data and one-off master data loads |
Plan for the removal now. Odoo has scheduled XML-RPC and JSON-RPC for removal in Odoo 22 (fall 2028) and Odoo Online 21.1 (winter 2027). Build on JSON-2 for 19.0 and isolate the RPC path behind one adapter for older databases, so an upgrade is a single change. Custom controllers with @route(type='jsonrpc') are not affected by the removal.
Authentication
Create a dedicated integration user with read access to Manufacturing and Inventory and write access to work orders. Generate its key under Preferences > Account Security > New API Key. On 19.0, keys last at most three months, so the middleware needs key rotation and an alert on authentication failures. Without them, an expired key stops the sync unnoticed. On the SkyPlanner side the REST API uses JWT, so the middleware holds both credentials.
Every JSON-2 call runs in its own SQL transaction, so a write spread over several calls is not atomic. Write per work order and log each result.
Events
Odoo pushes changes through automation rules. A rule on mrp.production or mrp.workorder with the trigger On create and edit and the action “Send Webhook Notification” sends a POST with the selected fields to a URL. Build the rule in Studio, or in developer mode from the Automation Rules form. Pair it with a scheduled search_read poll on write_date to catch imports and anything the rule missed. In the other direction, SkyPlanner webhooks push schedule and state changes as they happen.
Field names differ between versions. On 19.0 each database lists its models, fields and methods at /doc; on older versions, call fields_get. Map from there, not from memory.
Data mapping: Odoo to SkyPlanner
| Odoo model | SkyPlanner object | Direction | Frequency |
|---|---|---|---|
product.product / product.template (default_code, uom_id, qty_available) | Product or material | Odoo → SkyPlanner | Initial load, then daily or on change |
mrp.bom (product_tmpl_id, product_qty, produce_delay), mrp.bom.line (product_id, product_qty, operation_id), mrp.bom.byproduct | Multi-level product, material requirements per step | Odoo → SkyPlanner | On change |
mrp.routing.workcenter (Operations tab: workcenter_id, sequence, time_mode, time_cycle_manual, blocked_by_operation_ids) | Process steps with order and run time | Odoo → SkyPlanner | On change |
mrp.workcenter (resource_calendar_id, time_efficiency, time_start, time_stop, alternative_workcenter_ids) | Workstation, efficiency, setup and teardown, alternative workstations | Odoo → SkyPlanner, then maintained in SkyPlanner | Initial load |
mrp.workcenter.capacity (capacity) | Pieces per cycle, product-specific setup and teardown times | Odoo → SkyPlanner | Initial load |
resource.calendar, resource.calendar.attendance, resource.calendar.leaves | Shifts and leave | Odoo → SkyPlanner | Initial load, leave on change |
mrp.production (product_id, product_qty, date_deadline, priority, state, workorder_ids) | Order with due date and priority | Odoo → SkyPlanner | Webhook on confirm, plus poll |
mrp.workorder (operation_id, workcenter_id, duration_expected, state) | Job on a workstation | Odoo → SkyPlanner | Webhook, plus poll |
stock.quant, stock.move (component moves) | Stock on hand and material requirements for material-driven scheduling | Odoo → SkyPlanner | Scheduled, e.g. every 15 to 60 minutes |
purchase.order (partner_id, state), purchase.order.line (product_id, product_qty, date_planned, qty_received) | Purchase orders and incoming material, available on the expected delivery date | Odoo → SkyPlanner | Webhook on PO confirm or edit, plus the same scheduled poll |
| Planned start, end and workstation | mrp.workorder.date_start, date_finished, workcenter_id | SkyPlanner → Odoo | On schedule change, via SkyPlanner webhook |
| Mobile Confirmations, timelogs | mrp.workcenter.productivity (Time Logs: workcenter_id, workorder_id, date_start, date_end, loss_id) | SkyPlanner → Odoo | Per confirmation |
| Quantity done, operation finished | qty_producing on the work order, then button_finish; button_mark_done on the MO | SkyPlanner → Odoo, or done in Odoo Shop Floor | Per confirmation |
Integration patterns
Master data first.
Load work centers and calendars, then products, BoMs and operations, which reference work centers. In the 30-day trial, the same lists go in as CSV exports. Odoo’s Import and Export tool works on any list view.
Order sync.
Bring in MOs in state confirmed and progress with their work orders. Leave draft MOs out or treat them as tentative demand. Sub-assemblies with their own BoM can arrive as separate child MOs, and Odoo plans each MO on its own. Map them to SkyPlanner subproducts so sub-assemblies finish before the parent starts.
Schedule write-back.
When the schedule changes, a SkyPlanner webhook triggers the integration, which calls the ORM write method on each affected mrp.workorder. On Odoo 19.0 that is one JSON-2 request per work order:
“ POST /json/2/mrp.workorder/write Authorization: bearer <api-key> {"ids": [4711], "vals": {"date_start": "2026-11-03 06:00:00", "date_finished": "2026-11-03 09:30:00", "workcenter_id": 7}} “
JSON-2 takes every method argument by name plus ids and context, so write(vals) becomes the vals key. On 16.0 to 18.0 the same call runs as execute_kw(db, uid, key, 'mrp.workorder', 'write', [[4711], vals]) over XML-RPC or JSON-RPC, and on 16.0 the keys are date_planned_start and date_planned_finished. Datetimes go in UTC. A few rules keep the write clean:
- Send both dates in the same call.
- Add
workcenter_idonly when the engine chose an alternative machine. - Write only scheduling fields, never quantities or BoMs.
Writing the dates moves Odoo’s own work center booking, so Odoo’s planning views show SkyPlanner’s plan.
Shop floor back to Odoo. Operators log work in SkyPlanner Mobile Confirmations. For each confirmation the integration calls create on mrp.workcenter.productivity (JSON-2: POST /json/2/mrp.workcenter.productivity/create with vals_list). It fills workorder_id, workcenter_id, date_start, date_end and a loss_id of type Productive, and labor time and costing post in Odoo.
When an operation is complete, the integration sets the produced quantity and calls button_finish on the work order. The last work order leaves the MO ready for button_mark_done. Each confirmation is posted once, and its Odoo record id is kept with the SkyPlanner timelog, so a retried webhook never creates a second Time Log.
Plants on the Enterprise Shop Floor app reverse this: SkyPlanner reads work order state and qty_produced, and Autopilot reschedules automatically when production changes.
Ownership. Write the rules down before go-live:
| Data | Owner |
|---|---|
| Products, BoMs, operations, quantities, MO state | Odoo |
| Work order sequence, start and end times, work center choice | SkyPlanner |
| Setting time matrix, tool and operator requirements, alternative resources | SkyPlanner |
| Work center calendars and Time Off | One system, chosen in scoping |
| Time Logs, stock and costing | Odoo, fed from SkyPlanner confirmations |
Planners stop pressing Plan and Unplan in Odoo on MOs that SkyPlanner schedules. Otherwise Odoo books its own slots over SkyPlanner’s dates.
Typical project steps
Implementation is normally completed within weeks after onboarding starts. Before that, the 30-day free trial runs on CSV exports of your own Odoo data. The project itself contains:
- Master data mapping: Odoo models and fields per version (check
/docorfields_get), units of measure, and which system maintains calendars and Time Off. - Clean-up: work center calendars, Setup Time and Cleanup Time, and Fixed instead of Computed durations on BoM operations.
- Initial load: products, work centers with calendars, BoMs and their operations.
- Order and purchase order sync: confirmed and in-progress MOs with their work orders, plus
purchase.orderlines with their expected arrival dates. - Schedule write-back: dates and work centers on
mrp.workorder, with API key rotation on the Odoo side. - Shop-floor confirmations: Time Logs and work order completions back to Odoo.
- Testing in parallel with the current plan, then go-live.
Odoo pitfalls
- Renamed date fields. Up to 16.0,
date_planned_startanddate_planned_finishedheld the plan anddate_start/date_finishedheld actuals. From 17.0,date_startanddate_finishedare the planned dates. A mapping copied from a 16.0 project silently reads actuals as plan on 17+. - Work order dates are bookings. On 19.0,
date_startanddate_finishedonmrp.workorderare computed from aresource.calendar.leavesrecord (leave_id) on the work center calendar. Writing the dates on the work order updates that booking. Never write into the leave table directly. - Started work orders block Unplan. Odoo refuses to unplan an MO when “Some work orders have already started”. Skip work orders in
progressordoneon write-back and only move what has not started. - Durations drift. Operations set to Computed take their duration from the last work orders (10 by default), scaled by Time Efficiency. Set them to Fixed for the trial, or accept moving inputs. Operations live on each BoM, with no shared routing master, so every BoM needs its own clean-up.
- Broken calendars. Every work center needs a working-hours calendar. Odoo’s own planner searches up to 700 days ahead and then stops with “Impossible to plan the workorder”. Fix calendars before the first load.
- Units of measure.
mrp.bom.linecarries its ownproduct_uom_id, which can differ from the product’s stock unit. Convert before checking material availability.
Who configures the Odoo integration
Every plant runs Odoo differently: its own BoM operations, work center calendars, alternative work centers and custom modules. Getting the mapping right for that setup is the expertise the SkyPlanner team brings.
- The SkyPlanner team configures it to your Odoo setup during onboarding and supports it after go-live. It runs on the SkyPlanner REST API and webhooks and Odoo’s JSON-2 or RPC API. This is the default path.
- Your Odoo partner can take part. The partner knows your setup and custom modules and can build on the same documented REST API. It reads and writes orders, products, materials, process steps and timelogs, with JWT authentication and Swagger/OpenAPI documentation.
- Your own developers can do the same, usually as small middleware next to Odoo, or as a module on Odoo.sh or on-premise. An API key is enough to start (integration tutorial), and the SkyPlanner team assists when needed.
The same model runs in production with other ERPs. At Laboratory & Allied, the in-house IT team built the SAP Business One integration largely on its own, with SkyPlanner’s help. On NetSuite, UTU runs SkyPlanner beside its ERP.
Why the integration pays off
The write-back is what turns the integration into daily value. Once it runs:
- Odoo work orders carry real dates. The Arcturus AI engine sequences every open MO in seconds, and its dates and workstation choices land on
mrp.workorder, where Odoo’s planning views show them. - Nobody replans by hand. Autopilot reschedules automatically when production changes, and the webhook pushes the new dates to Odoo.
- The shop floor closes the loop. Operators log work on phone or tablet with Mobile Confirmations, Production Timer and Quick Log Mode, and Time Logs post to Odoo for stock and costing. Scheduling and execution run in one tool, on Community as well as Enterprise.
- The schedule holds constraints Odoo does not. A setting time matrix sets sequence-dependent changeovers per product pair. Tools are finite resources shared between machines, and a job can take several operators at once. The engine turns to alternative machines or personnel when the primary is unavailable. The dates written back to
mrp.workorderrespect all of them. - Material arrival drives the plan. Stock on hand and open Odoo purchase orders feed material-driven scheduling. Ordered components count as available on the PO delivery date, and stock updates when the PO is marked Delivered. Each job is checked against what is in the warehouse and what is on its way.
You can judge the schedule before any integration work. Start the 30-day free trial on CSV exports and see your own Odoo work orders on the Gantt, with up to 20 workstations and no credit card. Pricing is from 199 € per month with 5 workstations included, billed monthly, cancel any time. The integration is quoted up front for your process and needs, together with your plan, so you see the full cost before you start. See features and customers, or book a demo.
SkyPlanner reviews from manufacturers
2 hsaved every week
“SkyPlanner has taken our production planning from Excel spreadsheets to real-time production optimization.”
Kalle Kalliomäki, Supply Chain Specialist
UTU · Electrical switchboards and switchgear
Production planning saves 2 hours of working time every week, and a new work queue reaches the line in seconds.
+90%production efficiency
“Efficiency has gone up 90% in production.”
Abdul Rucyinga, Head of IT
Laboratory & Allied · Pharmaceutical manufacturing
Production efficiency is up 90%, and a three-month optimized plan across all workstations takes under 30 minutes.
1,000swork orders scheduled automatically
“Production is under control in a different way, and our understanding of capacity is on a completely different level.”
Hannu Ryynänen, CEO
Mamec · Industrial mixers, pumps and high-tech contract manufacturing
Thousands of work orders are scheduled automatically, with a real-time view of production for the whole organization.
99.2%delivery reliability
“SkyPlanner has brought visibility to identifying bottlenecks and clarified production management.”
Toni Tuori, Production Manager
Piristeel · Roof safety and rainwater systems
Delivery reliability reached 99.2% this year, and scheduling saves up to four hours of working time per day.
FAQ
Does the integration work on Odoo Online?
On the Custom plan, yes, through the external API. One App Free and Standard have no external API access and Standard runs without custom modules, so those plans are limited to CSV/XLSX import and export.
Should we use JSON-2 or XML-RPC?
JSON-2 on Odoo 19.0 and later. XML-RPC and JSON-RPC are still needed for 16.0 to 18.0, but they are scheduled for removal in Odoo 22.
How does the schedule get back into Odoo?
Through the ORM write method on each mrp.workorder: POST /json/2/mrp.workorder/write with ids and vals on 19.0, or execute_kw with write over XML-RPC or JSON-RPC on 16.0 to 18.0. The values are date_start, date_finished (date_planned_start and date_planned_finished on 16.0) and, if changed, workcenter_id. Odoo moves the work center booking with it, so Odoo’s planning views show SkyPlanner’s dates.
How do operator confirmations reach Odoo?
As Time Logs: the integration creates mrp.workcenter.productivity records against the work order with start, end and a Productive loss reason, then calls button_finish when the operation is complete. Each confirmation is posted once, so retries do not duplicate time.
Who maintains the integration after go-live?
The SkyPlanner team configures the integration during onboarding and supports it after go-live, including changes when your Odoo setup changes. If your partner or your developers build it, they work from the documented REST API and the SkyPlanner docs, and the team assists when needed.
What happens to work orders that have already started?
Leave them alone on write-back. Odoo blocks unplanning an MO once a work order is in progress or done. SkyPlanner reads their state and progress and schedules the remaining work around them.
How long does the Odoo integration take?
Implementation is normally completed within weeks after onboarding starts. Run the 30-day trial on CSV exports first, and the schedule is proven on your own Odoo data before the API work begins.