Intentflow
The detailed reference for how Intentflow Reconcile actually behaves - bootstrapping NetBox from your existing devices, the reconciliation report every upload produces, supported platforms, what each batch status means, and exactly how conflicts get detected and resolved.
Four steps, whether it's one switch or your whole network.
A .zip, a .tar.gz, or a single .txt of show-command output and running-configs - however your backup tooling already collects it. Drop it in from your dashboard on any plan, or send it automatically from CI with a scoped API key on Business, Enterprise and Reconcile.
Cisco IOS/IOS-XE, Cisco NX-OS, Juniper Junos, and Arista EOS, normalized into devices, interfaces, IP addresses, VLANs, and physical links.
New devices, updated fields, and anything that conflicts with data you've already curated - every field diffed against what's live in NetBox right now, viewable on the dashboard or downloadable as PDF, text or JSON, before a single write happens (view a sample report).
Confirm what you want written by hand, or, on Business, Enterprise and Reconcile, trigger the synchronize step from CI so only the safe, obvious stuff ever writes itself.
Filename or content is enough to identify what you've uploaded - there's no manifest to fill out first.
| Platform | Device inventory | Topology (LLDP) | VLANs | Interfaces / IPs | VRFs | FHRP (HSRP) | FHRP (VRRP) | Interface details |
|---|---|---|---|---|---|---|---|---|
| Cisco IOS / IOS-XE | show version | show lldp neighbors detail | show vlan | show running-config | via running-config | show standby | show vrrp brief | show interfaces |
| Cisco NX-OS | show version | show lldp neighbors detail | show vlan | show running-config | via running-config | show hsrp all | not yet | show interface |
| Arista EOS | show version | show lldp neighbors detail | show vlan | show running-config | via running-config | not yet | not yet | show interfaces (MTU/MAC only) |
| Juniper Junos | show version | show lldp neighbors | show vlans | show configuration | show route instance detail | not yet | not yet | show interfaces (MTU only) |
One upload can carry a device from bare identity to a fully wired-up NetBox record.
Name, model, serial, and platform from show version. Platform is written as a real NetBox Platform object (e.g. "Cisco IOS") - kept current automatically, the same "always trust what the device just reported" treatment a MAC address gets, never held as a reviewable conflict. Matched against existing NetBox devices by serial first, then hostname - never assumed to be new.
Name, description, admin state, and IP addresses parsed directly from the running-config - handled by a purpose-built parser per platform.
Created per Site and assigned to the interfaces that carry them - untagged (access) or tagged (trunk) - combining each platform's VLAN table with its running-config's switchport settings.
Drawn between two interfaces whenever LLDP identifies a neighbor that's also part of NetBox (either already there, or created in the same batch). A link with no resolvable neighbor is left out, never guessed.
Every interface IP already implies a subnet - 10.0.1.5/24 means the prefix 10.0.1.0/24 exists - so Prefixes are derived straight from the same running-config data already being parsed, no extra upload needed. VRF membership comes along with it: Cisco/Arista carry it as a line inside the interface's own config, Junos needs the separate show route instance detail upload (see Supported platforms above). A VRF's Prefixes and IP addresses are scoped to it automatically.
Bundle membership parsed from channel-group (Cisco/Arista) or 802.3ad (Junos) config - the bundle interface gets NetBox's native LAG type, and its member interfaces get linked to it.
Neighbor sessions from router bgp/protocols bgp config, written as real BGP session objects - AS numbers, peer addresses, and descriptions. Previewed before anything's applied, the same as a VLAN or VRF field change - a changed description shows as a reviewable conflict, and a peer with no resolvable local address shows as its own Unresolved state rather than being silently guessed at. Global/default-VRF sessions for now; VRF-scoped BGP peering is on the roadmap.
Gateway redundancy groups from show standby/show hsrp all/show vrrp brief, written as real FHRP group objects shared across the routers that belong to them - group ID, virtual IP, and each router's own priority. A changed virtual IP shows up as a reviewable conflict before anything's applied, the same as a VLAN or VRF field change - a wrong gateway address breaks failover, not just a cosmetic mismatch. VRRP is Cisco IOS only for now; VRRP on other platforms and FHRP on Juniper/Arista generally are on the roadmap.
Speed, duplex, MTU, and MAC address from a separate, optional show interfaces/show interface upload - matched onto the interfaces already discovered from your running-config, not a new object of their own. Speed/duplex/MTU changes show up as reviewable conflicts the same way a description change does; MAC addresses are kept current automatically, never flagged as a conflict, since a NIC's own hardware address essentially never changes hands the way a gateway's virtual IP does. Real per-platform gaps apply - see Supported platforms above.
Chassis, line cards, power supplies, and fans from a separate, optional show inventory upload (Cisco IOS/NX-OS for now) - each part's name, part number, serial number, and description. A swapped part shows up as a reviewable conflict, the same way any other field change does - a changed serial number on "Power Supply 1" means someone physically replaced it.
Layer 2 VNIs from a separate, optional VXLAN upload (Cisco IOS/NX-OS for now), matched onto the VLAN each one maps to and written as real network segment objects - shared across every device that belongs to the same segment, the same as a BGP session or FHRP group. A segment switching between classic multicast flooding and BGP EVPN shows up as a reviewable conflict.
NetBox core has no built-in object for BGP sessions - out of the box, it has nowhere to put one. We install the open-source netbox-bgp plugin on every hosted instance we provision, on every plan, so this works without you having to install or configure anything yourself.
Every upload becomes a batch that moves through these states, visible on its own page.
uploadedFile received, not parsed yet - usually momentary.
parsingIdentifying and parsing each file's platform and command.
reconciledReconciliation is complete - the full report is ready to view or download. Nothing has been written to NetBox yet; that's a separate, explicit step.
reconcilingAn on-demand re-check ("Reconcile now") is in progress - re-diffs the same upload against NetBox as it stands right now, without re-uploading. Only reachable from a batch that's already been reconciled, synchronized, or failed once; the page keeps showing that prior report while this runs.
synchronizingWriting the requested changes to NetBox - either a human's reviewed selections, or (CI-triggered imports) the safe, unambiguous subset from an explicit synchronize call.
synchronizedDone, cleanly - nothing left to look at. Open the batch to see exactly what was written, per device and per field, in the synchronization log.
synchronized_with_issuesThe synchronization itself ran without error on every device, but something is still held for a human - an unresolved conflict, a Removed IP address nobody confirmed, a cable whose neighbor couldn't be identified. Routine, not a bug - reopen the batch, resolve what's left, and sync again.
failedAt least one device raised an actual error while being written - the specific error is shown on the batch's page, per device, in the synchronization log. Not all-or-nothing: every OTHER confirmed device in the same batch still gets a full, independent attempt, so a batch can be "Failed" and still have most of its devices synchronized cleanly. Reopen and retry; it re-checks live NetBox first rather than replaying a stale plan, so anything already synchronized just shows as no change needed.
Every device, interface, VLAN, VRF, Prefix, IP address, and physical link Import touches moves through the same small set of states, in two phases - what reconciliation found, and what synchronization actually did about it. Same underlying data, same counts, just before and after the write.
| Reconciliation (before anything's written) | Synchronization (what actually happened) | Meaning |
|---|---|---|
| New | Created | Didn't exist in NetBox yet |
| Changed | Updated | Exists, a field differs, safe to write - nothing's touched that field since Intentflow's last sync |
| Needs Review | Unresolved | Exists, a field differs, but has never been compared before - no sync history to say the imported value is any more trustworthy than what NetBox already has, which may be a value you curated yourself before ever using Import. Held the same way a conflict is, until a human picks a side. |
| Changed — conflict | Unresolved | Exists, a field differs, but it's drifted independently since the last sync - held, never overwritten, until a human picks a side |
| In Sync | Kept | Exists and already matches - nothing to do, not a problem |
| Removed (IP addresses only) | Unassigned / Unresolved | NetBox has this address assigned to an interface the upload covers, but the upload no longer lists it there - see Conflict detection for how this is scoped and why it's never automatic |
| n/a at reconcile time | Unresolved | Only for physical links and IP addresses: the other end (neighbor device/interface, or the device/interface an address is really assigned to) couldn't be identified at all - genuinely unknown, not a drift |
| n/a - synchronization-only | Failed | A device raised an actual error while synchronizing was trying to write it - a real problem, not a routine "still needs a decision". See Batch statuses for how this affects the batch as a whole. |
Reconciliation's counts describe the current full diff across every device in the batch, refreshed by "Reconcile now" - Review & Sync's counts describe what the last sync actually did, which can be a smaller set if you only selected some devices, or resolved some conflicts and not others. The two won't match unless the last sync covered everything reconciliation found - that's expected, not a bug.
Two different views into a batch, for two different questions.
Each row is a data type (device inventory, interfaces/IPs, VLANs, LLDP topology), and the fraction is how many of the devices in this batch had that specific data uploaded - not a count of individual files or objects. "Interfaces/IPs: 1/2" means one of the two devices in the batch had a running-config uploaded; the other didn't. A device can be fully identified but still show a gap in another row if that command's output was never uploaded for it.
Missing source data never implies deletion or removal. Not uploading show vlan this round is never read as "this device has no VLANs" - it's read as "nothing to check this round," and no VLAN field is touched. The same holds for every data type: skip the LLDP upload and no cable is ever flagged, skip the running-config and no interface or IP address on that device is touched at all. When interface data is present, IP assignment is treated differently, but this isn't an exception to the rule above - it's the rule applying to a case where the data genuinely is there: an address previously assigned in NetBox but absent from that interface's observed configuration can be proposed for unassignment, scoped strictly to interfaces this same upload actually covers, and only ever as a proposal you explicitly confirm, never a default.
A clean "Synchronized" does mean exactly that - every confirmed entity's outcome is final, nothing left to look at. If something's still held - a field you didn't resolve, a Removed IP nobody confirmed, a physical link whose neighbor couldn't be identified - the batch instead shows "Synchronized with issues": the write itself completed with no errors, but there's a decision still waiting on you. If a device actually raised an error while being written, the batch shows "Failed", and any other confirmed device in the same batch still got its own full, independent attempt - a "Failed" batch can still have most of its devices synchronized cleanly. Open the batch and check the synchronization log for the precise, per-entity record of what actually happened either way.
One line per device, interface, VLAN, VRF, Prefix, IP address, Site, Role, and cable the synchronization step touched, with its outcome - Created, Updated, Unassigned, Kept, Unresolved, or Failed (see Reconciliation & synchronization states). It's built from what actually happened during the write, not from what was merely proposed at parse time - the two can differ if something changed in NetBox between review and synchronize, since synchronizing always re-checks live NetBox first rather than trusting a stale plan.
The rule this whole feature is built around: never silently overwrite something a human changed.
Every field Intentflow could write is compared three ways: the new value from this import, the live value in NetBox, and the value Intentflow last synced there. In order:
| Imported value vs. NetBox value | Ever synced before? | NetBox value vs. last synced value | Result |
|---|---|---|---|
| match | — | — | No-op - already correct, nothing to write |
| differ | no | — | Needs Review - no history to say the import is any more trustworthy than what's already there |
| differ | yes | matches | Safe update - nothing's touched this field since Intentflow last wrote it |
| differ | yes | differs | Conflict - something changed it independently, so it's held rather than overwritten |
That "last synced" value isn't kept in some separate database - it's stored directly on the object itself, in a hidden intentflow_sync custom field created during setup, and it only ever holds what Intentflow itself last wrote. It also moves forward every time a field applies cleanly, so a manual edit only shows up as a conflict if it happened after Intentflow's most recent import touched that field - an edit from three imports ago that's already been synced over won't reappear as a conflict now.
A field that's never been synced and differs is held, not silently written - a NetBox that already had devices, interfaces, or VRFs before you ever ran an import is the normal case here, not an edge case, and there's no way to tell "this predates Import" from "this import's value is stale" without a sync history. Needs Review and Conflict resolve exactly the same way - keep NetBox's current value, or use the imported one - the difference is only in why the field is held, shown next to each one on the review screen. A field that already matches, with no sync history yet, needs no decision at all: it silently gets a baseline the next time anything else on that same object is written, so it's protected against actually going stale later without ever showing up as a false alarm now.
Devices: name. Interfaces: description, admin state, and (once VLAN data is present for that device) trunk/access mode and VLAN assignment - checked in both directions, so an interface that lost its VLAN assignment since the last import is caught the same way as one that gained or changed one. That check only ever runs when this round's upload actually included VLAN data for that device - see the missing-data principle above; a batch with no VLAN command uploaded leaves every interface's VLAN fields untouched, never reads the absence as "clear everything." A single interface can have one field land as a safe update and another as a conflict at the same time - resolving the conflict never blocks the unrelated safe field from applying.
Each conflicting field on the review screen gets a choice: keep NetBox's current value, or use the imported value. It defaults to keeping NetBox's value - nothing changes unless you explicitly pick otherwise. Choosing "use imported value" is itself the confirmation to apply it; there's no separate checkbox to remember on top of that choice.
VLANs are created if they don't already exist, matched by Site and VLAN ID if they do - and if one does already exist, its name is re-checked for drift the same way a device or interface field is: a safe rename (nothing's touched it since our last import) applies automatically, a genuine conflict (renamed in NetBox independently) gets its own "VLAN conflicts" section on the review screen. Physical links work the same way: a link is created if neither end already has a cable, left alone as already-correct if one end is already cabled to exactly the expected neighbor, and surfaced under "Physical link conflicts" if an end is cabled to someone else - pick "use imported value" and the old cable is disconnected and the new one created, or leave it on NetBox's current connection to skip it this round. Resolving a physical-link conflict is the one place Import can delete anything at all - a narrow, Cable-only exception to the "never deletes" rule, needed because NetBox won't let an already-cabled port take a second cable.
Prefixes are New-or-In-Sync only, matched by identity alone (VRF + the CIDR itself, independent of Site) - a derived Prefix carries no imported description or status to compare against an existing one, so there's genuinely nothing to conflict on. VRFs get the fuller treatment: matched by name, and if a route-distinguisher and/or description were parsed for it (Cisco/Arista pull both from the VRF's own config block; Junos gets a route-distinguisher only, from the same show route instance detail upload used for membership - that platform's source command has no description field at all, so Junos never proposes touching one either way), those are re-checked for drift the same way a VLAN's name is - a safe change applies automatically, a genuine conflict gets its own "VRF conflicts" section on the review screen.
An address that doesn't exist in NetBox yet is New. One that already exists and is assigned to exactly the device and interface this import expects is In Sync. One that already exists but is assigned to a different device or interface - or isn't assigned to anything at all - is a conflict: reassigning an address is a meaningful write (it could disrupt whatever's actually using it right now), so it's held under its own "IP address conflicts" section on the review screen with the same keep-NetBox's-value-or-use-imported choice as everything else, never silently moved.
An address NetBox has assigned to an interface this upload covers, that the upload no longer lists there, shows up separately as Removed, under its own "IP addresses no longer in this config" section. Scoped strictly to interfaces this same upload actually has data for - an interface the upload doesn't mention at all tells us nothing about its addresses, so nothing is claimed about it (see the missing-data principle above). The default is to leave it assigned; opting in unassigns it - detaches the address from the interface, the record itself, its VRF, and its history all stay in NetBox, nothing is deleted. This is never automatic, including through POST /api/reconcile/import/{batch_id}/synchronize's safe-subset path - it always requires the same explicit, per-address confirmation a reassignment conflict does.
Standalone Reconcile connects to a NetBox you run yourself. Everything above works the same way - what follows is only what differs when the instance isn't ours.
From your dashboard, enter your NetBox's base URL and an API token you generate in NetBox itself. That's the whole setup - there's nothing to install, no agent, and no inbound access to your network. Intentflow calls your NetBox's REST API the same way any other API client would. If your NetBox isn't reachable from the internet, it won't be reachable from Intentflow either; that's the one hard requirement.
Reconciliation - reading your NetBox and showing you every difference - works across the compatible range. Synchronization is deliberately narrower, because writing into an object model we haven't tested against is how you get confidently wrong results rather than an obvious error. Your connected version is checked automatically and your dashboard always shows which row you're in.
| Your NetBox | What works | Why |
|---|---|---|
| NetBox 4.2 - 4.6 | Reconciliation and synchronization | Certified - covered by Intentflow's own test suite |
| NetBox below 4.2 | Not supported | The object model differs enough that results would be unreliable |
| netbox_bgp 0.19 | Compared and synchronized | Certified - the plugin version Intentflow tests against |
| netbox_bgp, any other version | Discovered and reported only | Its objects are still found and listed; they are not compared or written |
| netbox_bgp not installed | Discovered and reported only | Nothing in your NetBox to compare them against |
API keys. NetBox 4.5 and above issue an API token as a composite value beginning nbt_, shown once when you create it and not retrievable afterwards - copy the whole string, including the part after the dot, not the shortened key the token list shows later. NetBox below 4.5 uses a single 40-character key you can view at any time. Intentflow accepts either - paste exactly what your NetBox shows you.
A newer NetBox. When a NetBox newer than 4.6 is released, Intentflow reconciles against it and shows you every difference, but will not write to it until that version has been through the same test suite - the certified range only ever widens after CI has proven it.
At minimum, read access to devices, interfaces and IP addresses - without all three, a reconciliation report would silently look like an empty NetBox rather than a permissions problem, so Intentflow refuses the connection instead of showing you that. Read access alone is a perfectly good place to start: you get the full discovery and reconciliation report, and synchronization is simply unavailable until you widen the token. To synchronize, it additionally needs write access to the object types you want written. It also needs permission to manage custom fields, unless the one field Intentflow uses is already present in your NetBox - in which case a token that can't manage custom fields is fine, and Reconcile detects that rather than assuming the worst.
No. The connection check is strictly read-only - it reads your version, what the token can see, and which optional models exist. It creates nothing, and we hold ourselves to that in the test suite rather than as a promise.
Synchronizing does make exactly one schema addition, the first time you run it: a custom field named intentflow_sync, which records which fields Intentflow itself last wrote and when. That field is what makes the three-way comparison possible - it's how Reconcile can tell "you changed this by hand" apart from "this drifted since our last sync" and refuse to overwrite the former. Nothing else in your schema is touched, and no object is ever written until you confirm it.
BGP sessions are still parsed from your configs, still counted in Discovery, and still appear in your reports - they just aren't compared against NetBox or synchronized, because there's nowhere in your NetBox to compare them against. Reconcile says so explicitly on the batch rather than quietly leaving them out: the objects are real and we found them, it's their representation in the target NetBox that's unavailable. Everything else reconciles normally. Installing the plugin later needs no action here - the next import picks it up.
Reconcile re-checks what your NetBox can do before every import, so a token you widen (or a plugin you install, or a NetBox you upgrade) takes effect on the next run with nothing to re-enter. If a token is revoked partway through a synchronization, Reconcile stops rather than retrying every remaining object against a credential that will refuse all of them, and the report records exactly what was written before it stopped. Re-running after fixing the token is always safe.
Yes, but not repeatedly: a subscription covers one network, so it may be repointed at a genuinely different NetBox deployment once per month. That is what a migration needs; it is not enough to service several customers' NetBoxes in turn from one subscription. If a migration goes wrong and you need to switch back sooner, contact us and we will lift it.
Routine changes to the same NetBox do not count and are unlimited: rotating or replacing the API token, changing authentication or TLS settings, or correcting the URL you entered. Switching from http to https, adding or removing a trailing slash or an /api suffix, changing the case, or naming the default port explicitly are all recognised as the same deployment.
When you do switch, existing reconciliation history stays attached to the NetBox that produced it - the drift baseline a past report was measured against lives inside that instance, so trend comparisons do not cross the boundary.
Same parsing and the same safety rules either way - what differs is who's around to review.
Manual upload from the dashboard is free on every plan, Free through Enterprise. Triggering imports from CI - the POST /api/reconcile/import path below - is available on Business, Enterprise and Reconcile, since it's meant for recurring, unattended use rather than a one-off upload. Standalone Reconcile is included because keeping your own NetBox current between manual uploads is the point of it. Free-tier accounts don't see the "Generate API key" option.
A standalone Reconcile subscription includes 30 reconciliation runs a month. One run covers the whole cycle for a single upload - discovery, reconciliation, your review, and synchronizing the changes you approve - so reviewing a report, re-running the reconciliation on it, or syncing it later never costs a second run. An upload we could not read anything from is not counted at all.
The allowance resets monthly from the date Reconcile was activated on your account, which is not necessarily your billing date, so an annual subscription gets the same 30 runs each month. Worth planning for if you import from CI: a nightly job is about 30 runs a month on its own, so if you also import on every merge, tell us and we will sort out the capacity.
Imports on a Hosted NetBox plan are not metered - Reconcile is a bundled feature of those plans rather than the product being bought.
No - uploading, whether from the dashboard or from POST /api/reconcile/import, only ever parses and reconciles. Nothing is written to NetBox until something explicitly synchronizes it. For a manual upload that's a person clicking "Sync selected changes" after reading the report; for a CI-triggered one, it's a second, deliberate call to POST /api/reconcile/import/{batch_id}/synchronize, which writes the safe subset - no-ops, safe updates, and new devices whose Site match came from your own IPAM data specifically (the one signal backed by curated data, not a guess). Anything uncertain - any conflict, any weaker-signal new device - is left for a human to resolve on the normal review screen whenever they check in.
Generated from the Import page, shown once in plaintext, never again - only its hash is stored, the same disclosure model as a GitHub personal access token. It authenticates every /api/reconcile/import... endpoint below (see API reference) - nothing else in the app. Generating a new key immediately invalidates the old one; there's no window where both work.
Point a scheduled job - a nightly GitHub Actions run, a cron on your backup box, whatever already collects your config dumps - at POST /api/reconcile/import with the API key as a bearer token and the archive as the request body. You get a batch_id back immediately; poll GET /api/reconcile/import/{batch_id} until status leaves parsing. Once it's reconciled, that same response already tells you reconciliation.new/changed/in_sync - call GET /api/reconcile/import/{batch_id}/report if you want the actual per-entity Imported-vs-NetBox detail behind those counts, not just the totals. Then decide what to do: call POST /api/reconcile/import/{batch_id}/synchronize to write the safe subset, fail the build if devices_needing_review is non-zero, post the diff to Slack, or just let it sit until someone opens the dashboard. Intentflow doesn't impose an opinion there. Full request/response shapes for every step are in the API reference below.
Five calls, four endpoints, called in this order. Every one takes Authorization: Bearer <your API key> and returns JSON.
Uploads and starts parsing/reconciling a batch - same parser, same conflict rules as a dashboard upload. Never writes to NetBox; always lands on reconciled (or failed) for you to inspect before deciding anything.
Request
multipart/form-data
file: your .zip / .tar.gz / .txt (max 50 MB)Response — 202
{ "batch_id": "f4de4f62-0d96-40a0-9592-109e929c86fd" }Poll this until status leaves parsing/reconciling/synchronizing. reconciliation appears once a diff exists; synchronization appears once a synchronize has actually run - same New/Changed/Needs Review/In Sync and Created/Updated/Unassigned/Kept/Unresolved/Failed counts shown on the dashboard for this exact batch, never a separately-computed set (see Reconciliation & synchronization states). A non-zero needs_review never gets touched by POST /api/reconcile/import/{batch_id}/synchronize either - it's held for a human exactly like a conflict is. status itself can be synchronized (clean), synchronized_with_issues (ran cleanly, something's still held), or failed (at least one device raised an actual error - other devices in the same batch may still have synchronized).
Response — after reconciling, before synchronizing
{
"batch_id": "f4de4f62-...",
"status": "reconciled",
"error": null,
"devices_applied_automatically": 0,
"devices_needing_review": 0,
"reconciliation": { "new": 25, "changed": 6, "in_sync": 7, "needs_review": 0 }
}Response — after a CI-triggered synchronize, some devices still need review
{
"batch_id": "f4de4f62-...",
"status": "reconciled",
"error": null,
"devices_applied_automatically": 4,
"devices_needing_review": 1,
"reconciliation": { "new": 25, "changed": 6, "in_sync": 7, "removed": 1, "needs_review": 4 },
"synchronization": { "created": 25, "updated": 4, "unassigned": 0, "kept": 7, "unresolved": 7, "failed": 0 }
}status stays reconciled here rather than turning terminal, specifically for the CI/API auto-synchronize path (POST /api/reconcile/import/{batch_id}/synchronize) - so the batch stays fully actionable on the normal dashboard for whatever's still held. A manual synchronize from the dashboard instead resolves to a terminal synchronized (clean), synchronized_with_issues (ran cleanly, something's still held), or failed (at least one device raised an actual error) - this same endpoint reflects whichever status the batch is actually in, regardless of which path last touched it.
The detail behind the counts above - every entity's Imported-vs-NetBox diff, and, once synchronized, what was actually done about each one. Same complete-record rule as the dashboard's downloads: every entity is included, In Sync/Kept ones too, not just what changed.
Response
{
"batch_id": "f4de4f62-...",
"status": "synchronized",
"reconciliation": [
{ "entity": "sw-lab-01", "status": "In Sync", "changes": [] },
{ "entity": "sw-lab-01 VLAN 10 (Management)", "status": "Changed",
"changes": [ { "field": "name", "imported": "Management", "netbox": "DATA" } ] }
],
"synchronization_log": [
{ "device": "sw-lab-01", "entity_type": "vlan", "entity_name": "VLAN 10 (Management)",
"status": "Updated",
"changes": [ { "field": "name", "imported": "Management", "netbox": "DATA" } ] }
]
}synchronization_log is only present once a synchronize has run - it's the same record as the dashboard's synchronization log (see Data coverage & the synchronization log), just under the API's own field name. reconciliation is null if the batch's diff data has since expired (kept 30 days) - synchronization_log survives that, since it's a permanent record of the batch, not a snapshot of live NetBox state at reconcile time.
Writes whatever's unambiguous - no-ops, safe updates, and new devices whose Site match came from your own IPAM data specifically (see Manual vs. automated). Everything else is held for a human on the normal review screen. Only valid while status is reconciled. Returns immediately; poll step 2 again for the outcome.
Response — 202
{ "batch_id": "f4de4f62-...", "status": "synchronizing" }Same endpoint as step 2 - call it again after synchronizing to see the final synchronization counts and, if anything's still devices_needing_review > 0, open the dashboard to resolve what's left.
Every endpoint 404s (not 403) on a batch_id your key doesn't own, and 401s on a missing or invalid key. POST /api/reconcile/import and POST /api/reconcile/import/{batch_id}/synchronize both 403 on tiers without automation - automated imports are Business, Enterprise and Reconcile (manual upload from the dashboard is free on every plan).
Said plainly, not buried in a footnote.
update-source/local-address configured - common; many networks rely on the directly-connected interface instead - can't have its local address resolved without guessing, so it previews and applies as Unresolved rather than being attributed to a guessed interface. Everything else gets the full review-screen treatment: a safe change applies automatically, a genuine conflict shows under its own "BGP peering conflicts" section with a resolve control, same as any other entity type.switchport trunk allowed vlan add ... on a second line is a real but rare config pattern this doesn't yet handle - the first "allowed vlan" statement is what's used.Reach out at support@intentflow.co