A backend-aware seam map for SAP Business One
SAP Business One order-to-cash automation: the HANA versus SQL Server fork most guides skip.
The B1 sales process is four documents: Sales Quotation, Sales Order, Delivery, A/R Invoice. Incoming Payment is added when the customer pays. Almost every guide for automating that cycle stops there and assumes the integration is a free choice. It is not. Service Layer, the REST API B1 added in version 9, is supported only against an SAP HANA database. SQL Server tenants do not have it. They have DI API (COM, single-threaded) or UI automation, and the practical answer differs per step. This page is the seam map.
Direct answer (verified 2026-05-11)
How do you automate O2C in SAP Business One? Map the four-document sales chain (Sales Quotation, Sales Order, Delivery, A/R Invoice) plus the Incoming Payment, then pick an integration per step based on your DB backend. Service Layer (REST) only exists on HANA. SQL Server tenants have DI API (COM, single-threaded) or UI automation against the desktop client. Verified against the SAP Help Portal Configuring SAP Business One Service Layer.
The thesis, plainly
The most common shape of a B1 O2C automation project is to draw the flow as a sequence of arrows (Quotation, Order, Delivery, Invoice, Payment) and then ask a developer to wire whichever integration the internet says to use. If your team has already done that on a friend's S/4HANA tenant, you reach for BAPIs. If you have read the official B1 Service Layer docs, you reach for REST. Both lead to a stall when the actual customer's database turns out to be Microsoft SQL Server.
The shape that ships is to score every step in the cycle as Service-Layer-only, DI-API-only, mixed, or UI-only, then build the API portion against whatever the tenant's backend supports and drive the rest with a recorder against the desktop client. The recorder is the only path that runs unchanged across HANA and SQL Server, because it talks to the same SAP Business One.exe Win32 window in either case.
The rest of this page is that score, then the parts of the cycle where the score is non-obvious (the Matrix line-item grid, the A/R Invoice posting period rules, and the Incoming Payment matching step), then a recorded workflow you can run today.
The seam map: five steps, two backends
Each row is one step in the O2C cycle. The HANA and SQL Server columns score the cleanest available API path on each backend. The UI Automation column is the same for both because it talks to the desktop client, not the database.
| O2C step | HANA backend | SQL Server backend | UI Automation (any backend) |
|---|---|---|---|
| 1. Sales Quotation | Service Layer Quotations endpoint, full coverage | DI API Quotations object, full coverage but COM-bound | Modules > Sales A/R > Sales Quotation |
| 2. Sales Order | Service Layer Orders endpoint | DI API Orders, plus Copy To from Quotation in DI | Right-click on saved Quotation, Copy To > Sales Order |
| 3. Delivery (with batch / serial) | Service Layer DeliveryNotes, batch / serial fields require exact shape | DI API DeliveryNotes, batch / serial via SerialNumbers and BatchNumbers child objects | Copy To > Delivery, drain Batch / Serial Selection modals per row |
| 4. A/R Invoice | Service Layer Invoices endpoint, posting period must be open | DI API Invoices, same posting period rule | Copy To > A/R Invoice; capture DocNum from status bar |
| 5. Incoming Payment (allocation) | Service Layer IncomingPayments accepts pre-resolved allocations only | DI API Payments accepts pre-resolved allocations only | Banking > Incoming Payments, allocate the wire across open invoices |
| Add-on screens (Beas, Boyum, Produmex) | Out of scope (Service Layer does not see add-on tables) | Out of scope (DI API does not see add-on tables) | Same UIA tree as core B1, no extra integration |
The teal column is the only one that ships unchanged across both backends. It is also the only one that handles the Incoming Payment matching step, because that step is a judgment call (which open invoices does this wire most likely cover) that no API resolves on its behalf.
Why Service Layer is HANA-only, and what changes if you have it
Service Layer is a Linux-side service that talks to the B1 HANA schema using HANA-native SQL and column-store features. The standard B1 on Microsoft SQL Server installation does not include it; the SAP Help Portal Service Layer configuration page lists HANA as the prerequisite. If a partner says they have Service Layer working against a SQL Server tenant, double-check what they actually mean, because in most cases it is a third-party REST proxy in front of DI API and not the SAP-shipped Service Layer.
On HANA, Service Layer makes the steady steps (Quotation, Order, Delivery on a clean B2B order, A/R Invoice on a clean order, posting a pre-allocated Incoming Payment) cheap. Each one is an HTTP POST with a JSON body. The endpoints are well-shaped. Throughput is better than DI API because Service Layer pools sessions across multiple workers.
What does not change: the screens where a human still decides something. The recorder still owns sales order entry from a customer-emailed PDF, the manual side of Incoming Payment allocation, credit hold release on customers near their limit, and anything in an ISV add-on. Service Layer answers fewer than half the steps for most teams; it answers the cheap half.
The shape that ships across both backends
Below is a simplified version of one recorded workflow. It walks a PDF-extracted sales order through the four-document chain using the Copy To pattern a B1 operator already uses. The same file runs on a HANA tenant, a SQL Server tenant, a Citrix-hosted client, or a dedicated Windows VM. The runtime targets the SAP Business One.exe process via Microsoft UI Automation. Nothing in the workflow file knows or cares what database is behind the screen.
Each commented step resolves to one or two MCP tool calls against the B1 UIA tree. Locators target Name plus Role on each element (name:Customer|role:Edit), not pixel coordinates. The runtime strips x, y, width, height, and the captured value attribute before diffing two trees, so a B1 patch level that nudges the layout does not produce a workflow diff. That stripping is in the open-source desktop agent at apps/desktop/src-tauri/src/dom_tree_diff.rs in github.com/mediar-ai/terminator.
“An LG-customer F&B chain on B1 cut their O2C automation cost 70 percent moving off UiPath onto Mediar.”
Mediar pilot data, F&B chain on SAP Business One, SQL Server tenant
The Matrix grid: where line-item entry actually breaks
The Matrix is the line-item editor on every B1 sales document. It looks like a spreadsheet and the temptation is to treat it like one. The accessibility tree exposes it as a UIA Table with rows and columns, which is the right substrate for automation. The hard parts are not the substrate; they are three specific behaviors a recorded workflow has to handle explicitly.
First, the Item No. cell triggers a price-list lookup that fires asynchronously. Typing the next field before the lookup completes means the unit price you see in the recording is not the unit price the document is posted with. The recorder waits on a property change on the row's UnitPrice Edit element rather than a fixed sleep, so the wait scales with how loaded the price list is.
Second, batch-managed and serial-managed items pop a modal Batch Selection or Serial Number Selection window when you set the quantity. That modal has to be drained inside the same step that sets the quantity, or the row's commit attempts to read uninitialized batch state and fails with a generic validation error. The recorder treats the quantity entry and the batch selection as one atomic step, not two.
Third, B1 keeps a trailing empty row in the Matrix until you click outside the grid. A naive recorder that reads the row count mid-entry will either over-count or attempt to address a row that does not yet exist. The fix is to commit the grid by clicking the Customer field after the last row, then capture the row count.
A/R Invoice posting and the period-status trap
The A/R Invoice is the first step in the chain that hits the general ledger, and it is the first step where B1 will refuse to post even though every field on the form is correct. The most common refusal is a posting period that is closed or locked. The posting period is set per Document Series under Administration > System Initialization > Document Numbering, and it is enforced per posting transaction.
The recorder has to capture the modal that B1 raises (Period is locked for posting, document cannot be added) and route it to the right escalation. A practical pattern is to classify it as a WorkflowLogic error in the executor: do not retry, do not call the analyzer, hold the row in the queue with a clear reason, and let the AR clerk decide whether to re-open the period or move the posting date. The retry classifier in the open-source agent is in crates/executor/src/config/retry.rs and the WorkflowLogic class is where this case lands.
The same modal can also fire for a missing chart-of-accounts mapping on a new item, a customer over its credit limit (when the credit limit rule is set to block, not warn), or a foreign-currency rate that is not in the exchange-rate table for the posting date. All four are deterministic and all four need a human, not a retry.
Incoming Payment: where the matching step is the work
The Incoming Payment screen is the densest step in O2C and the one most likely to look small to someone who has not run an AR team. The shape of the work is: a wire arrives for a customer, the customer has multiple open invoices, the wire amount does not cleanly match any single one, and the AR clerk decides which invoices to fully apply, which to short-pay, which to leave on account, and whether to charge a write-off difference.
Service Layer and DI API both accept an Incoming Payment with pre-resolved allocations. Neither does the matching itself. The shape that ships is to read the bank file (BAI2, MT940, camt.054, or a CSV from the customer's online banking export), score each open invoice for that customer against the wire amount and any reference field, propose a most-likely allocation set, and drive the Incoming Payment screen to apply that proposal. The AR clerk reviews the proposed split before clicking Add.
The structured matching pass takes a few hundred milliseconds. The screen drive takes about 45 seconds for a wire against two open invoices. The clerk review is the slow part, and it should be: AR is an audit-sensitive function and the human approval is what keeps the controls clean.
“We spent two quarters trying to get a Service Layer integration shipped against our HANA tenant before we accepted that the human-decision screens (PDF order entry, payment allocation, dunning review) were not going to fit a REST shape. The recorder gave us those screens in three weeks.”
Have a B1 tenant on SQL Server and a stuck O2C cycle?
Bring a real workflow. We will record it against your tenant on the call and price the runtime per minute, no per-seat license, no upfront integration project.
SAP Business One O2C automation: questions teams ask before they pilot
Why does the backend choice (HANA vs SQL Server) decide which integration is even available?
Service Layer, the REST API SAP added on top of B1, is supported only against an SAP HANA database. The official configuration page on the SAP Help Portal lists HANA as the prerequisite, and the SAP Business One on Microsoft SQL Server installation does not include the Service Layer service. SQL Server tenants are left with two programmable surfaces: DI API, the COM library that has shipped with B1 since the early 2000s, and SAPbouiCOM, the in-process UI SDK used by add-ons. Both are Windows-only, and DI API runs single-threaded inside one process at a time. UI automation against the desktop client is the third path, and it is the only one that runs the same way on either backend.
What is the actual document chain in SAP Business One O2C, and how does it differ from S/4HANA?
The B1 sales process is four documents: Sales Quotation, Sales Order, Delivery, and A/R Invoice. Incoming Payment is added when the customer pays. There are no T-codes (VA01, VL01N, VF01, F-28). Forms are reached through the Modules menu (Modules > Sales > Sales Order), or through dragged shortcuts. Most teams use the Copy To right-click pattern to walk a quotation forward through the chain, which is what makes UI automation efficient: the recorder is replaying a workflow a B1 operator already does by hand, not assembling a custom posting sequence.
Can DI API drive the whole O2C cycle on SQL Server tenants?
Mechanically yes, with a list of caveats most published examples do not surface. DI API is COM, so the calling process must be 32-bit or 64-bit matched to the installed library and must hold an in-process license. Sustained throughput is roughly 5 to 8 documents per second on a local box, single-threaded per process. The Marketing Document object that posts a Sales Order, Delivery, or A/R Invoice exposes most fields, but freight, discounts at line and document level, withholding tax, batch and serial assignment for inventory items, and per-row UDFs all have specific shapes that have to be set in the right order or the post fails with a generic 'Document is not valid' error. The UI client validates these as the operator types; DI API rejects them after the fact. A practical pattern is to use DI API for the steady cases (clean B2B orders against fully configured items) and the recorder for the messy ones (unfamiliar customer, mid-month pricing exceptions, items missing a default warehouse).
Where does the Matrix grid (the line-item editor in B1) make UI automation specifically harder?
The Matrix exposes itself as a UIA Table, with rows and columns addressable by index. The hard parts are: the Item No. cell triggers a price-list lookup that fires asynchronously, so the next field has to wait on the row's UnitPrice cell to populate; selecting a batch-managed item opens a modal Batch Selection window that has to be drained before the row is committed; and the row count is not stable until you click outside the grid because B1 keeps an empty trailing row. The recorder handles these by waiting on a property change (Name on the UnitPrice Edit) rather than a fixed sleep, and by dismissing the Batch Selection modal as part of the same step that sets the quantity. The same logic applies for serial-managed items in the Delivery document.
Where does Incoming Payment specifically resist a clean web-service or DI API solution?
Incoming Payment is the screen where a wire from the bank is allocated against open A/R invoices. The bank file rarely matches one invoice cleanly. A wire arrives for a customer with three open invoices, slightly under the total, and the AR clerk decides which two to fully apply, which one to short-pay, and what to leave on account. Service Layer and DI API can both create an Incoming Payment with allocations the caller already worked out, but neither does the matching itself. A practical Mediar workflow runs a structured matching pass (read the bank file, score each open invoice against the wire amount and reference, pick the most likely set), then drives the Incoming Payment screen to apply the proposed allocation, leaving the AR clerk to approve. The structured pass is cheap; the human review is the part that keeps audit happy.
How much of the cycle survives a B1 version upgrade (10.0 FP 2308 to 10.0 FP 2408, for example)?
Field role and Name on the input elements survive. Tab order across the form survives. The menu path to a screen survives. Pixel coordinates and element widths do not survive between SAP B1 patch levels because B1 reflows on DPI changes and font selection. The Mediar runtime strips x, y, width, height, and the captured value attribute before diffing two trees, so a layout shuffle that moves the Customer field down a row does not produce a workflow diff. That stripping is in the open-source desktop agent at apps/desktop/src-tauri/src/dom_tree_diff.rs in github.com/mediar-ai/terminator. A workflow recorded against B1 10.0 FP 2308 has, in our pilot data, run unmodified through three subsequent feature packs.
Do add-ons (Boyum B1, Beas, Produmex) change the picture?
Yes, in a useful way. Add-ons are loaded into the same SAP Business One.exe process via SAPbouiCOM, so any custom forms an add-on adds (Beas production work orders, Produmex warehouse pick screens, Boyum B1 Usability Package custom fields) appear in the same UIA tree as the standard B1 forms. The recorder does not care whether a window came from B1 core or an add-on. This is also where DI API gets weaker: most ISV add-ons store their data in their own tables, and DI API does not know about those tables. UI automation crosses the seam between core B1 and the add-on without a custom integration.
Pricing for an O2C workflow on B1?
Runtime is billed at $0.75 per minute regardless of outcome. A typical Sales Quotation with three lines runs in 35 to 50 seconds. Copying it forward through Sales Order, Delivery, and A/R Invoice with the right-click Copy To pattern is roughly 25 seconds per step because the carry skips most fields. An Incoming Payment allocation against a wire with two open invoices runs in about 45 seconds end to end, including the structured matching pass. The $10K turn-key program fee converts to credits with a bonus, so it is effectively prepaid usage that covers the first pilot.
Is the SDK something a B1 partner can extend?
Yes. The Terminator SDK and the desktop agent are open source under MIT at github.com/mediar-ai/terminator. The locator syntax (name:Customer|role:Edit) and the MCP tool surface (type_into_element, click_element, get_text) are stable. A B1 partner can build a workflow against a customer-specific add-on form the same way they build against a standard B1 form. Mediar staff handle the runtime, the queueing, the retry classifier, and the dashboard; a partner extends the workflow library.
Does this approach replace a B1 implementation partner?
No. The implementation partner sets up the chart of accounts, the item master, the price lists, the customer setup, the financial periods, the document numbering series, the approval procedures, and everything else that makes a B1 tenant production-ready. Mediar runs on top of that production tenant. The right phrasing for a partner conversation is that this automates the keystrokes a clerk makes against a tenant the partner already configured, not that it replaces the configuration work.
The mechanical pieces this page rests on, from a different angle each time.
Read next
SAP Business One RPA via the accessibility tree: a UIA walkthrough
The mechanical walk-through for B1 specifically: inspect.exe against SAP Business One.exe, why ControlType.Edit and stable Name attributes survive the layout changes that break ClickText and OCR-based RPA.
SAP Business ByDesign order-to-cash automation: where the OData line ends and the WorkCenter line begins
Sister piece for the cloud product. ByDesign already ships OData v2 and SOAP, so the seam map is different. Useful contrast if you are choosing between B1 and ByDesign for an O2C heavy mid-market team.
Automate SAP data entry: the failure taxonomy a working SAP queue lives or dies by
The error classifier behind a shipping SAP workflow: connection resets and 503s retry with backoff, validation failures stop immediately, novel errors stop for an operator ack. Same runtime that drives B1.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.