Automating Finance Operations Without Manual Supervision: Desktop Flows for Unattended Batch Processing in Power Automate

The accounts payable team receives vendor invoices across email, portals, and EDI feeds. Someone needs to log into three separate legacy systems, extract data, cross-check line items, and route approvals. This work consumes 12 hours daily, happens at predictable times, and does not require human judgment except for exceptions. Your finance director has asked: can we stop paying for four additional AP staff and let the system handle the routine work?

This is the real-world problem desktop flows address. While cloud flows orchestrate modern cloud-native APIs and services, they cannot click buttons in legacy Windows applications, extract text from PDF scans, or navigate desktop tax compliance software. Desktop flows bridge this gap by providing unattended, schedule-driven automation of legacy application interactions, freeing your team to concentrate on exceptions and decision-making while batch operations run overnight.

Why Desktop Flows Matter for Finance Operations

Finance teams in mid-market and enterprise organizations operate mixed technology landscapes. Core enterprise applications like Dynamics 365 Finance coexist alongside legacy on-premises tax software, obsolete bank reconciliation tools, and third-party applications with no modern APIs. Replacing all of these is neither feasible nor economically justified when the application only requires data entry at predictable intervals.

Desktop flows, also called Robotic Process Automation (RPA), automate routine system interactions without rewriting the applications. A bot logs into the legacy system, executes the exact sequence of steps a human operator would perform, and exits cleanly. If the expected screen does not appear or a business rule blocks the action, the bot detects the failure and alerts an operator. An invoice entry workflow requiring 5 minutes per vendor invoice, repeated 200 times per month, consumes 1,000 hours annually. Automating that workflow with desktop flows reduces workload to oversight and exception handling while eliminating transcription errors and enabling overnight batch completion.

Desktop Flows Versus Cloud Flows

Cloud flows in Power Automate work with APIs and cloud services. They call Dynamics 365, send emails through Exchange Online, read SharePoint files, or trigger webhooks. Cloud flows excel at integration and orchestration but assume the target application exposes an API.

Desktop flows operate at the UI layer, interacting with Windows applications like a human user does: clicking buttons, typing text, reading screen content, interpreting dialog boxes. This makes desktop flows universally applicable to any Windows application, regardless of age. The tradeoff is brittleness; desktop flows rely on locating UI elements by coordinate, accessibility label, or image recognition, so UI layout changes break selectors. For finance operations, this distinction is critical. A desktop flow automates a legacy tax system without APIs because it mimics manual steps your tax accountant performs daily. A cloud flow cannot do this without significant custom development.

Architecture for Unattended Finance Automation

Unattended automation means the bot runs on a scheduled timer without human intervention, executing overnight during non-business hours to avoid contention with human users.

A robust finance automation workflow follows this pattern:

Pre-execution validation. Before the bot starts, verify preconditions. Check that required input files are present, confirm the target system is online and accessible, and validate that previous runs completed successfully. A cloud flow orchestrates these checks and decides whether to launch the desktop flow.

Bot execution with retry logic. The desktop flow logs into the target application, performs required operations, and captures results. If an operation fails, it logs the exception and continues with the next item if possible, or halts if the failure is blocking. Desktop flows include error handling for UI recognition failures, network timeouts, and permission errors.

Output logging and escalation. After each automated action, the desktop flow logs results to a structured output table: success, failure reason, timestamp, and extracted data. If exceptions occur, the flow writes them to a queue for human review. This is critical. The bot must not silently fail; it must make failures visible so operators can triage and fix issues before they compound.

Completion notification. Once the batch completes, a cloud flow sends a summary to finance stakeholders: how many items processed, exceptions logged, and link to the exception queue.

Practical Implementation Considerations

UI Recognition and Fragility. Desktop flows locate UI elements by image recognition, coordinate position, or accessibility properties. If the application layout changes, image-based selectors break. Use accessibility labels and text properties where possible, as these survive minor layout changes. Reserve image selectors for elements without stable labels.

Performance and Scalability. A single desktop flow bot runs on one machine and processes one item at a time. For high-volume automation (processing 1,000 invoices nightly), register multiple desktop flow machines in a machine group to distribute load.

Logging and Observability. Desktop flows execute headless; you cannot see what the bot is doing in real time. Detailed logging is mandatory. Log application state before each action, results after each action, and any exception. Store logs in a Dataverse table so they are queryable and auditable, supporting both troubleshooting and compliance reporting.

Maintenance and Regression Testing. When the underlying application receives updates, test your desktop flows immediately. UI changes, new validation rules, or altered field names break selectors or logic. Establish a regression test suite of known input scenarios your bot should handle correctly, and re-run after each application patch.

A Real Finance Workflow Example

Consider invoice entry automation: vendors email invoices. An AP team member downloads each invoice, logs into a legacy accounting system, enters vendor name, invoice amount, invoice date, and account coding, then routes for approval. The system allows bulk CSV import but only accepts one file per session and takes 10 minutes to process.

An unattended desktop flow workflow:

Step 1: A cloud flow monitors a SharePoint folder for new invoice PDFs. When a file arrives, it extracts to a temporary folder.

Step 2: A cloud flow calls Azure Form Recognizer to extract vendor name, invoice amount, and date from the PDF. Results write to a staging table in Dataverse.

Step 3: A desktop flow runs for each PDF. It logs into the legacy accounting system, fills in extracted vendor name, amount, and date, selects the appropriate GL account, and saves. If the vendor is not found, the bot adds it first.

Step 4: The desktop flow writes success or exception status back to Dataverse. A cloud flow checks the status table; if an exception occurred (vendor already exists with different details, invalid GL account), it sends an alert to the AP supervisor.

Step 5: Each night at 11 PM, a cloud flow sends a summary: invoices processed, exceptions logged, link to the exception queue.

The result is invoices moving from inbox to approval routing without manual data entry. The AP team focuses on resolving exceptions and approving borderline items, not transcribing PDFs.

Security and Compliance

Desktop flows handle confidential financial data and interact with sensitive systems. Security requirements include:

Credential Management. Never hardcode credentials in the desktop flow. Store them in Azure Key Vault or Power Automate connection references, retrieving them at runtime. Rotate credentials regularly.

Audit Trail. Document every action the bot takes. Log entries should include who authorized the automation, when it ran, what it did, and who reviewed results. Finance auditors often require this for SOX compliance.

Exception Handling. If the bot encounters an error, it should halt, log the error, and alert a human. This prevents the bot from automatically creating duplicate invoices or misrouting approvals.

Testing in Isolation. Test desktop flows in a sandboxed environment before production deployment. Test happy path (normal invoices) and edge cases (missing vendor data, invalid GL accounts, locked records).

Conclusion

Desktop flows bring practical capability to finance operations: automating routine legacy system interaction without expensive system replacement or ongoing manual labor. The tradeoff is operational complexity. Desktop flows require robust logging, exception handling, UI selector maintenance, and audit oversight. For organizations willing to invest in these practices, the result is a finance team that operates more efficiently, catches exceptions faster, and focuses on value-added work.

Routeget Technologies has built and maintained desktop flow automation for finance processes across dozens of implementations. We understand UI-based automation fragility, observability importance, and the specific requirements auditors impose on unattended bots operating on financial data. If your organization is evaluating desktop flow automation for AP, AR, GL reconciliation, or tax compliance workflows, we can help you design robust patterns that scale without creating compliance or operational risk.


#PowerAutomateRPA #DesktopFlows #FinanceAutomation #UnattendedBots #ERPIntegration #FinanceOperations #ProcessAutomation #LegacySystemModernization

Business Central Virtual Tables Eliminate the ETL Job Between BC and Dataverse. They Also Eliminate Half Your Filter Options.

Solution architect reviewing a real-time data integration visualization between enterprise systems

A solution architect scoping a Dynamics 365 Sales rollout for a distribution client recently asked a straightforward question: does the sales team need to see live Business Central order and inventory data inside their CRM records, or is a nightly sync job good enough? The honest answer took longer than it should have, because Business Central virtual tables, the feature Microsoft built specifically to answer this question, solve it only for a narrower set of scenarios than the AppSource listing and most walkthroughs suggest. The core mechanism works exactly as advertised. Where it falls short is rarely covered in the getting-started guides, and that gap is exactly where a scoping conversation needs to happen before anyone commits to an architecture.

Virtual tables have been positioned, correctly in most cases, as the end of a certain kind of integration project: the one where someone builds a scheduled job to copy Business Central records into Dataverse so Power Apps and Dynamics 365 Sales can read them. That job needs error handling, a schema that drifts every time BC gets a service update, and someone on call when the sync silently stops. Virtual tables remove that job entirely for read-heavy scenarios, just not for every scenario, and the difference is worth planning around before it’s discovered mid-build.

How Business Central Virtual Tables Actually Work

The Business Central Virtual Table plugin, published on AppSource, gives Dataverse a way to read and write Business Central records without copying that data into Dataverse storage. Under the hood, it consumes the Business Central API (v2.0), turns each endpoint’s response properties into virtual table columns, and maps the API’s own relationships into table relations that Power Apps and Power Automate can traverse like any native table. None of that translation happens on a schedule. Every query against a Business Central virtual table becomes a live OData call back to the Business Central tenant the moment a user opens a form, loads a subgrid, or a flow condition evaluates.

That real-time behavior is the actual selling point, and it’s a legitimate one. A Dynamics 365 Sales rep looking at an account record sees the customer’s current balance and open orders as they exist in Business Central right now, not as of last night’s sync window. There’s no data duplication to reconcile, no field mapping table to maintain as BC’s schema evolves, and no separate storage cost in Dataverse for records that already live somewhere else.

What Setup Actually Involves

Getting virtual tables running is a Power Platform admin task more than a developer task, which is worth knowing before anyone estimates the work. The solution installs from AppSource into a target Power Platform environment. Inside Business Central, an administrator enables the corresponding Microsoft Entra application, listed on BC’s own Entra applications page as the option for virtual tables. In Dataverse, the Business Central Virtual Data Source Configuration table needs the target BC environment name and a default company, since every request has to resolve to a specific company context.

Microsoft ships this as a set of managed solutions rather than one package: a company reference table every request depends on, the core plugin support, a catalog of tables available from the connected BC environment, and the generated virtual table definitions themselves. Because that catalog reflects the full breadth of Business Central’s OData surface, tables aren’t visible in Power Apps by default. An admin has to open the Business Central Configuration app and mark each table an app will use, a sensible governance control once you know it’s coming, and a confusing missing-table problem the first time you don’t.

Developer workstation displaying live data flow dashboards representing database integration

The Tenant Requirement That Ends Some Projects Before They Start

The detail worth checking on the first scoping call, not discovering three weeks into a build, is that the Business Central environment and the Dataverse environment must sit in the same Microsoft Entra tenant. For an organization that has run its Dynamics footprint under one tenant from the start, this is a non-issue. It becomes a real blocker for companies that grew through acquisition and still operate a separate Business Central tenant for a subsidiary, and it comes up constantly on engagements where a client’s CRM and ERP environments were provisioned years apart, sometimes by different vendors, under different tenants.

When that’s the situation, virtual tables aren’t an option regardless of how well everything else fits, and the project falls back to a conventional integration built on Power Automate flows against the Business Central API, or a dedicated integration platform between the two systems. Confirming tenant alignment costs a few minutes of checking admin center settings. Discovering the mismatch after a Power Apps screen is already designed around virtual tables costs a redesign.

Where the Filtering Restrictions Actually Bite

Because every virtual table query is a live OData call, the filtering grammar available to a Dataverse view or an advanced find is exactly as expressive as OData’s filter syntax, and no more. Predicates like does not equal, does not contain, does not begin with, and does not end with aren’t available. A view can’t combine AND and OR groups across different columns the way a native Dataverse table allows, and filtering on related tables or calculated fields isn’t supported either, nor are charts, attachments, images, or any BLOB-backed multiline text field built on a virtual table.

None of that shows up in a basic demo, which is the actual problem. A subgrid or gallery built against a virtual table for a first pass usually works, because the first pass rarely tests anything more demanding than “show me the open orders.” The gap surfaces once a real user asks for something like “show open sales orders where the requested ship date isn’t blank and the customer isn’t on credit hold,” a query needing a does-not-equal check on one column joined with an AND against a second. A native Dataverse table handles that without anyone thinking twice. A virtual table view can’t express it, and the fix ends up being either a purpose-built custom API on the Business Central side shaped for that exact query, or pushing the filtering logic into a Power Automate flow or a canvas app formula instead of the view. Either workaround is manageable, but only if someone anticipated it, and the tutorials rarely mention it exists.

Synthetic Relationships Connect the Models, But Only One Way

Virtual tables can also link to native Dataverse tables through what Microsoft calls synthetic relationships, letting a record like a Dataverse Account display related Business Central sales orders in a subgrid without custom plugin code. Building one means creating a foreign key on the native table first, then defining the relationship in the Business Central Configuration app’s Table Relations screen, mapping the native table’s key columns to the matching virtual table columns.

The relationship, once created, isn’t editable. Changing which columns participate means deleting it and rebuilding from scratch, and refreshing the underlying virtual table’s metadata while a relationship depends on it tends to throw errors rather than update quietly. The practical implication is to stabilize the Business Central side of the schema first: it’s far cheaper to adjust a Dataverse foreign key than to reconstruct several relationship mappings after a field gets renamed on the BC side. It’s also worth knowing upfront that relationships between two virtual tables aren’t supported at all, only between a native table and a virtual table, so an architecture chaining two Business Central entities purely through Dataverse relationships needs a custom API instead.

When Virtual Tables Are the Right Call

Virtual tables fit read-heavy scenarios well: a Power App or Dynamics 365 Sales form that needs current item availability, order status, or account balance without anyone owning a sync pipeline, where the filtering the business needs stays inside basic equality and straightforward AND logic. They’re a poor fit for anything involving attachments or images tied to BC records, analytics that need to chart or aggregate BC data directly, filter logic needing negation or mixed AND/OR groups, and any architecture spanning two Entra tenants.

The habit worth building into every Business Central to Dataverse integration scope is prototyping the specific filter and subgrid scenarios the business will actually use, not a generic list view, before the architecture is locked in. Almost every gap covered here only shows up once a real filter requirement meets OData’s grammar, and that’s cheap to test in the first week and expensive to discover after Power Apps screens are already built around the wrong assumption. Teams we’ve helped scope this kind of integration get the most value out of virtual tables when the tenant check and a short filter-requirements workshop are treated as the first two deliverables, not something left until a screen doesn’t do what the demo implied it would.

Virtual tables genuinely remove a maintenance burden that used to be permanent: the sync job nobody wanted to own, the schema drift nobody wanted to chase down. What they don’t remove is the need to know, before the architecture is set, exactly which filters, which tenant, and which record types the integration actually has to support.


#BusinessCentral #DataverseIntegration #VirtualTables #PowerPlatform #ERPIntegration #DynamicsConsulting

The Business Central SOAP Retirement Deadline Is Closer Than It Looks

IT director reviewing a systems integration architecture diagram on a monitor in a modern office

The Business Central SOAP Retirement Deadline Is Closer Than It Looks

An IT director doing an annual vendor risk review recently found an integration nobody on her team remembered building. A bank feed connector, installed years earlier by a consultant who has long since moved on, was quietly pulling transaction data into Business Central through a SOAP endpoint pointed at a standard Microsoft page. It had run without incident since before her tenure started. The discovery only mattered because of one line buried in a Microsoft release note: that endpoint, and every other SOAP connection built the same way, stops working the moment Business Central version 29 reaches general availability in the first week of October 2026.

That is the practical shape of the Business Central SOAP retirement. It is not a single dramatic cutoff so much as the final step in a multi-year phase-out that a lot of IT teams filed away as a developer’s problem and never revisited. Microsoft introduced a feature key called “Disable SOAP web services on Microsoft UI pages” in the 2025 release wave 1 update, version 26, and it has been switched on by default ever since, blocking any new attempt to publish a standard Microsoft page as a SOAP endpoint. What made that default setting survivable for older integrations was the fact that an administrator could still go into Feature Management and turn the key back off, keeping the legacy behavior alive. Version 29 removes that feature key entirely. Once it is gone, there is no setting left to flip back on, and any integration still pointed at a Microsoft UI page over SOAP simply stops receiving responses.

The Business Central SOAP Retirement Only Touches Microsoft’s Own Pages

The scope here matters more than the deadline itself, because it is easy to overreact or underreact depending on how the news reaches you. What is actually being removed in version 29 is narrower than “SOAP support in Business Central.” Microsoft’s own justification, stated plainly in its developer documentation, is that a UI page was never designed to function as a stable API contract: a field can move, a control can be renamed, and none of that counts as a breaking change from Microsoft’s perspective, even though it can silently break an integration built directly against that page’s SOAP surface. So the retirement targets exactly that pattern: standard, out-of-the-box Microsoft pages exposed as SOAP web services.

Two other patterns are not affected by this particular change. SOAP endpoints built on codeunits keep working, since a codeunit is intentionally structured as a stable interface rather than a UI surface. SOAP endpoints built on custom, per-tenant extension pages also continue to function, because your organization controls that page’s schema and accepts responsibility for changes to it. If your integration inventory turns out to be built entirely on one of those two patterns, version 29 will not touch it. Many organizations, though, will find that at least one long-running integration, often the oldest one, was built the simple way: pointing directly at a Microsoft page because that was the path of least resistance when someone set it up years ago.

Abstract illustration of a legacy data connector being replaced by a modern API connector

The Stopgap That Isn’t a Real Exemption

Microsoft’s own migration guidance includes an option that looks like an easy out: copy the source of the affected Microsoft page into a per-tenant extension, republish that copy as your own page, and expose the copy as a SOAP endpoint instead. Technically, this works, and it buys time without touching whatever consumes the integration on the other end. It is worth treating as exactly what it is, a stopgap, and not as a long-term architectural decision.

Two things argue against leaning on it permanently. First, you now own and maintain that copied page yourself, including any future logic changes Microsoft makes to the original that you will need to track and replicate by hand, which is precisely the maintenance burden the API-first approach was designed to avoid. Second, this is not the only deprecation moving through the same pipeline. Microsoft has already issued the equivalent warning for exposing Microsoft UI pages as OData endpoints, with removal currently targeted for the 2027 release wave 1 update, version 30. The pattern is consistent: UI-page-based web services of any protocol are being phased out in favor of purpose-built API pages and queries. A team that spends its 2026 budget re-platforming a SOAP integration onto a per-tenant extension, rather than onto a proper API page, is likely to be back doing similar work again in 2027 for the same underlying reason.

What This Means for Your Integration Portfolio

For a CIO or IT director, the practical risk is less about any single connector breaking and more about not knowing how many connectors exist in this pattern in the first place. SOAP-based integrations against Microsoft pages tend to cluster in a few high-value, low-visibility categories: bank statement and payment feeds set up early in an ERP implementation, EDI order intake with a long-standing trading partner, warehouse scanning or shop-floor tools built from an older sample or tutorial, and ISV add-ons purchased years ago from a vendor who may or may not have modernized their own connector since. None of these show up on a typical application inventory unless someone specifically goes looking for the transport protocol underneath them, which is exactly why this kind of deprecation tends to surface as an incident rather than as a planned project.

The financial exposure is concentrated, not diffuse. A broken bank feed means a manual reconciliation process returns overnight, right when finance least wants to discover it. A broken EDI intake means orders stop flowing from a partner who is unlikely to be sympathetic to an internal software upgrade as an excuse. Compare that to, say, a reporting dashboard built the same way, where a short outage is an inconvenience rather than a revenue event. Triage should follow that same logic: not every SOAP endpoint deserves equal urgency, but the ones tied to cash and order flow deserve attention well before the October deadline, not the week of it.

A Practical Sequence Before October

The starting point is visibility, not migration. Business Central logs incoming web service requests, and that telemetry can be pulled to show exactly which endpoints are being called, how often, and by page or codeunit type, before anyone commits engineering time to fixing something that may not even be at risk. From there, the sequence is straightforward in outline even if the execution takes real effort: separate the SOAP calls hitting Microsoft UI pages from those hitting codeunits or per-tenant extensions, since only the first category is on the clock; rank the affected integrations by business impact rather than by ease of fixing them, so a low-effort reporting connector does not quietly jump the queue ahead of a bank feed; and for anything ranked high, start the conversation with whoever owns the other end of the integration; internal developer, systems integrator, or third-party vendor, well before the release actually lands, since REST API pages or OData V4 endpoints for the same data may already exist and simply were never adopted when the integration was first built.

For integrations tied to a purchased ISV app, it is worth a direct question to the vendor rather than an assumption either way: ask specifically whether their connector talks to Business Central over SOAP against a standard page, and if so, what their own migration timeline looks like. A vendor who has not addressed this yet is effectively asking your organization to inherit their technical debt on their schedule, not yours.

Treat This as a Cleanup Project, Not a Fire Drill

The organizations that come out of this in good shape are the ones that treat the Business Central SOAP retirement as the forcing function for an integration inventory they should have had anyway, rather than as an isolated ticket to close before a deadline. We have seen the alternative version of this play out with prior Business Central deprecations: a scramble in the final weeks, a rushed fix that solves the immediate protocol problem without addressing the underlying design, and the same conversation repeating itself at the next deprecation cycle. Version 29 is a good moment to ask the larger question once, properly, rather than answering the narrow one twice.


#BusinessCentral #SOAPRetirement #ERPIntegration #APIModernization #IntegrationGovernance #DigitalTransformation

Why Business Central Webhook Notifications Go Missing, and How to Architect Around It

Solutions architect reviewing a network integration dashboard representing Business Central webhook notifications

A Business Central integration that sailed through testing starts dropping records three weeks into production, and nobody can explain why until someone finally opens the subscription logs and finds a long trail of silent deletions. This is one of the more common failure patterns solution architects run into once Business Central webhook notifications move from a sandbox demo into a live integration carrying order confirmations, inventory adjustments, or approval status changes. The webhook model itself is well documented, but a handful of its operational rules are easy to miss during initial build-out, and missing them is exactly what causes integrations to degrade quietly instead of failing loudly where someone would notice.

The Handshake Most Implementations Get Half Right

Every Business Central webhook subscription begins with a validation handshake, and it is stricter than most developers expect on first pass. When a subscription is created against the v2.0 API, Business Central sends a request to the registered notification URL with a validationToken appended as a query parameter. The receiving endpoint has to echo that exact token back in the response body with an HTTP 200 status, and this is not a one-time formality. The same handshake fires again every time the subscription is renewed, which matters because Business Central webhook subscriptions expire after three days by design. There is no way to extend that window through configuration; the only supported pattern is issuing a PATCH request to the subscription resource before expiration, which triggers a fresh validation round trip.

Teams that build their receiver as a lightweight Azure Function often hit trouble here because of cold starts. If the function has scaled to zero and the handshake response takes more than a few seconds to come back, Business Central treats it as a failed validation and the subscription is never established or renewed. Keeping the receiver warm, or at minimum handling the validation response as the very first branch in the function before any other logic runs, removes most of the flakiness teams report during initial rollout.

Why Business Central Webhook Notifications Stop Coming, With No Error in Sight

The part of the design that catches experienced integration teams off guard is what happens after a notification actually fails to deliver. Business Central will retry a failed notification for up to 36 hours, but only if the subscriber’s endpoint responds with HTTP 408, 429, or something in the 5xx range. Any other response code, including a 400 or a 404 that might result from a temporary bug in the receiver’s routing logic, causes the subscription to be deleted immediately with no further retry and no separate alert. From the Business Central side, everything looks fine because the delivery attempt technically completed. From the integration’s side, notifications simply stop arriving for that entity, and unless someone is actively polling the subscriptions endpoint to check for unexpected deletions, the gap can persist for days before anyone notices missing sales order lines or unsynced customer records downstream.

This is the mechanism behind the scenario at the top of this article. A receiver that returns a 500 during a genuine outage is actually in a safer position than one that returns a 400 because of a malformed payload edge case, since the 500 at least buys 36 hours of retry attempts while the underlying issue gets fixed. Teams that want resilience here should treat any unhandled exception in the receiver as a 5xx rather than letting it bubble up as a generic error page, and should build a scheduled check that compares active subscriptions against the expected list so a silent deletion gets flagged rather than discovered by a downstream data gap weeks later.

Developer workstation showing an abstract data synchronization diagram representing a Business Central API integration

The Records Webhooks Quietly Refuse to Support

Before troubleshooting delivery issues, it is worth confirming the subscribed entity was ever eligible for webhooks in the first place, since Business Central will let a subscription be created against certain API pages that then never fire a single notification. Webhooks are not supported for API pages built on temporary tables, for pages where the OData key consists of more than one field or is otherwise composite, for system tables above table number 2000000000, for anything exposed as an API type query rather than an API type page, or for the Job Queue Entry table specifically. An API page built for a custom extension needs ODataKeyFields set to a single field, typically SystemId, or the subscription will appear to register successfully while silently never delivering anything.

Document-style entities carry their own nuance worth designing around. A change to a sales invoice line does not generate its own notification; instead, Business Central notifies against the parent sales invoice header when any of its lines change. Integrations that subscribe only at the header level and assume line-level granularity will miss the specific detail of what changed and need to follow up with a GET request against the full document to reconstruct it, which is standard practice anyway since webhook payloads never carry the actual record data, only a pointer to it and the type of change that occurred.

Batching, Delay, and the Events That Let You Tune Both

Business Central does not fire a notification the instant a record changes. There is a default 30 second delay built in after the first change to a watched entity, which exists to let a burst of related changes settle before anything is sent. If more than 1,000 records change within that delay window, Business Central collapses the individual notifications into a single collection notification rather than sending a thousand separate payloads, which is a sensible default for bulk imports but can surprise a downstream system expecting one notification per record during something like a large data migration or batch order release.

Both behaviors are adjustable for AL developers who need finer control. The delay interval can be modified through the OnGetDelayTime integration event in the API Webhook Notification Mgt. codeunit, and the threshold that triggers collection-style batching can be adjusted through OnGetMaxNumberOfNotifications in API Webhook Notification Send. Extensions that need near-real-time delivery for smaller entities, such as a status flag that a warehouse floor system needs to react to within a couple of seconds, are reasonable candidates for tightening the delay through these events; extensions dealing with high-volume header tables like sales lines are usually better served leaving the defaults alone and designing the receiver to handle collection notifications gracefully.

Designing for the Gaps: A Hybrid Pattern That Actually Holds Up

Given all of the above, the honest engineering position is that Business Central webhooks were never meant to be the sole source of truth for keeping two systems in sync, and Microsoft’s own documentation is candid that delivery is not guaranteed. Subscriptions can lapse from a missed renewal, a receiver bug can trigger an unannounced deletion, and network conditions on either side can drop a notification outright. The pattern that holds up in production combines the two mechanisms rather than choosing one: webhooks handle the fast path, giving near-real-time propagation for the vast majority of changes, while a scheduled reconciliation job, often running hourly or nightly depending on data volume, polls the same API endpoints using a last-modified timestamp filter to catch anything the webhook layer missed.

This is a small amount of extra engineering for a meaningful reliability gain, and it also solves the operational blind spot described earlier: the reconciliation job can double as the subscription health check, verifying that expected subscriptions still exist and re-registering anything that was unexpectedly deleted. Teams that skip this step tend to discover the gap only when a customer or finance team member notices a record that should have synced and did not, which is a far more expensive way to find the same bug.

What This Means for Your Next Integration Build

None of these behaviors are hidden or undocumented, but they are scattered across API reference pages that most teams read once during initial scoping and rarely revisit once the integration is live. The practical takeaway is to treat the three-day renewal window, the narrow retry code list, the unsupported table types, and the batching thresholds as design inputs from day one rather than issues to debug after the fact. At Routeget Technologies, the integrations that hold up longest in production are the ones where the reconciliation safety net was scoped alongside the webhook subscriptions from the start, not bolted on after the first silent data gap got noticed. Getting that sequencing right the first time is usually the difference between an integration the business trusts and one that quietly needs babysitting.


#BusinessCentralAPI #WebhookReliability #ERPIntegration #DynamicsBusinessCentral #ALDevelopment #EnterpriseIntegration