VTEX OMS: order flows, API integration & ERP connections

order management warehouse

VTEX OMS sits between the customer's browser and your fulfilment stack: its four flow types, indexing independence, and dual event-consumption patterns (Feed v.3 and Hook) mean a misconfigured integration will either miss status transitions or hammer the API with redundant polling.

This guide walks through the OMS mechanics that matter to engineers: how orderForm becomes an order, what each lifecycle status triggers downstream, and which API patterns hold up at scale.

TL;DR: What VTEX integrators need to know

VTEX OMS manages the full order flow lifecycle across four distinct flow types: Marketplace, Seller, Complete, and Chain, and every integration decision flows from understanding which flow your store participates in.

We've shipped VTEX OMS integrations for scale-up retailers across Europe, observing Feed v.3 queue saturation under flash-sale load and making live Feed-vs-Hook architecture calls for clients with sub-5-minute SLA requirements. The mechanics matter: when the Checkout API's Place Order endpoint returns a 201, an orderId is born and the order enters the OMS as a new entity, the orderForm fields persist in OMS API responses, but the object is now the OMS's to own, not Checkout's.

From there, status progresses through payment, a cancellation window, handling, and invoicing. How you track those status changes, Feed v.3 pull queue or Hook webhook, is the architecture call this guide works through. If you're evaluating whether VTEX OMS fits within a broader platform overhaul, the integration complexity discussed here is directly relevant to modernizing your OMS infrastructure without disrupting live operations.

Where VTEX OMS sits inside the commerce platform

VTEX OMS sits downstream of the VTEX Checkout API, it receives control the moment a confirmed orderId exists, and manages every subsequent status stage from there.

During checkout, the orderForm is the live object: a mutable cart structure built, validated, and mutated entirely within the Checkout API. When a shopper completes purchase, the Checkout API's Place Order endpoint returns a 201 response containing an orderId. That response marks the boundary. From this point, the order exists as a VTEX OMS entity entering the order flow lifecycle, though orderForm fields persist and appear in most VTEX Orders API response payloads, which regularly surprises developers who expect a clean separation.

One architectural detail that catches teams early: the OMS index operates independently from the order record itself. An order can be fully committed and progressing through handling stages while the search index reflects an earlier state. Querying orders by f_creationDate or status against the indexed list endpoint can return stale results; the order record via direct orderId lookup will always be authoritative.

For external systems managing logistics or catalog data, this matters: inventory reservation occurs at the OMS layer, not at checkout, and a Seller Flow order may show ready-for-handling in the record before the indexed list reflects it. Our team has encountered this lag in high-throughput environments where flash-sale volumes push indexing delays past what polling intervals can tolerate, the reason Feed v.3 was built to run independently of indexing entirely.

For a broader view of how VTEX's platform layers connect, see our VTEX platform guide.

From orderForm to OMS: How an order is created

An orderForm becomes an OMS order record at the exact moment the VTEX Checkout API Place Order endpoint returns a 201 response (VTEX Developers, Creating a regular order with the Checkout API). That response carries a generated orderId. VTEX's default format is a 12-digit numeric ID with a 6-digit sequence starting from 500001; stores can instead opt into an alphanumeric format combining a prefix with an account-name abbreviation and a sequence number, for example `v1233363wlmr-02` (VTEX Help Center - Precautions when setting the order numbering). Either way, the increment between sequential order numbers is randomized so outsiders can't estimate order volume from the ID alone, and the numbering format is locked in permanently once chosen. Before that 201, the orderForm is mutable state inside Checkout. After it, the order exists as a VTEX OMS entity with its own status stage progression.

Inventory reservation happens at the same boundary. VTEX reserves stock the moment it receives the 201 confirmation, not at cart creation. Consider two shoppers racing through checkout for the last unit: the first request to complete the Place Order call succeeds and triggers a reservedItems update in the logistics layer, locking that unit against the confirmed orderId. The second shopper's request is blocked before payment can proceed because the available quantity in the warehouse settings is now zero. To learn how this reservation state is exposed, query the order detail endpoints and inspect the logisticsInfo array inside shippingData, where each item carries a quantity and a warehouseId reflecting the reservation.

The orderForm fields do not disappear once the order is created. They persist and appear across most VTEX Orders API responses, which is why integrations querying order detail endpoints still see familiar checkout-era fields such as clientProfileData, shippingData, and itemMetadata in the OMS payload.

From the 201 onward, the OMS system owns the order lifecycle across all fulfillment channels. Status progresses from payment-pending through payment-approved, into the cancellation window, then ready-for-handling, and eventually invoiced. The orderId is the stable key for all downstream operations: ERP middleware, fulfillment connectors, and the Feed v.3 queue all reference it.

The four VTEX order flow types explained

VTEX OMS assigns every order to exactly one of four flow types at the moment the 201 response returns the orderId (VTEX Help Center - Order flow and status). The flow type is not a setting you configure manually, it derives from the store's role in the transaction.

Chain Flow is the one that consistently surprises teams new to VTEX. Unlike Marketplace Flow, where the platform collects payment on the store's behalf, a Chain Flow store receives only a notification that payment was processed upstream. The practical consequence: invoicing logic and ERP triggers must check the flow type before assuming your store holds the payment record. Per the VTEX orders overview documentation, each flow type surfaces a distinct subset of order status stages, so a status like waiting-for-seller-decision appears only in Marketplace and Chain contexts.

Complete Flow is the default for single-seller storefronts. If your architecture involves a multi-vendor marketplace, where the platform and fulfillment are split across separate accounts, order data will be split across Marketplace and Seller flows, each with its own orderId visible only to the relevant account. The VTEX marketplace architecture guide covers how those flows map to seller order routing; we won't repeat that detail here.

The orderForm fields persist into OMS API responses across all four flow types, which means line-item data, custom fields, and customer address data remain accessible regardless of which role the store plays. What changes between flows is which status stages are present and whether payment data is owned or merely referenced.

Chain Flow in depth: Intermediary stores and payment notifications

Chain Flow applies when a store sits between a marketplace and a seller: it receives a payment notification rather than direct payment, and that distinction is where most integrations break.

In a multilevel inventory scenario, the intermediary store's VTEX OMS order record reflects the payment notification event, not a settled payment. This means the order's status progression through the lifecycle looks superficially identical to Complete Flow, but the payment stage carries different semantics: the intermediary confirms receipt of notification, not funds.

Any downstream system, whether ERP middleware or a finance reconciliation webhook, that treats this status as "payment approved" will produce false positives on cash-in-hand reporting. The reconciliation workflow requires explicit handling at each stage. When the payment notification event lands on the intermediary store, your consumer should write a provisional record flagged as "notification received, not settled." Only after the upstream marketplace confirms cleared funds, typically via a separate status update, should that record be promoted to a settled state in your ERP or finance system.

Teams that skip this two-step write pattern and resolve both states in a single transaction are the ones that encounter reconciliation gaps across channels.

The cancellation window edge case creates frustrating experiences for users trying to manage their subscriptions. After payment notification, Chain Flow orders still pass through the customer grace period before reaching ready-for-handling. If the upstream marketplace cancels during that window, the VTEX OMS record on the intermediary store updates independently of whatever the seller-side flow shows. Integrations that subscribe to Hook notifications on the intermediary store can fire a fulfillment trigger before the cancellation window closes. Inventory reservation then needs unwinding manually because the cancel event arrives seconds later on a separate webhook call.

For reliable tracking across Chain Flow orders, Feed v.3 is the safer choice precisely because it runs independently of indexing. A Hook fires once per status change; Feed v.3 queues the event and holds it until your consumer acknowledges it, so a downstream system that processes the payment notification and the subsequent cancellation gets both events in order, not in a race. Review the VTEX Orders documentation and learn the full Chain Flow status map to configure your settings correctly before going live.

Order status stages: What each means and what to monitor

VTEX OMS order statuses are not all equal weight for downstream systems. Most statuses are informational; five are actionable triggers for ERP integration, WMS reservation, or carrier handoff.

The order flow lifecycle runs through these stages, per VTEX help documentation:

Status Description ERP/WMS action
order-created orderId issued; orderForm fields committed to OMS Log; do not allocate stock yet
payment-pending Awaiting payment gateway confirmation Monitor only
payment-approved Payment confirmed Trigger ERP order creation
cancellation-window Customer grace period before fulfillment begins Hold all WMS actions; cancellations here cost nothing
ready-for-handling Cancellation window closed; fulfillment authorized Trigger inventory reservation and WMS pick
handling Items being picked and packed Progress only
verifying-invoice Invoice submitted via Orders API; VTEX validating Monitor for rejection
invoiced Delivered to carrier; order flow complete Close ERP sales order
canceled Voided at any prior stage Reverse ERP and inventory reservation

The cancellation window is the status most teams under-monitor. VTEX defaults to a 30-minute grace period before progressing to ready-for-handling, configurable in VTEX Admin under Store Settings > Orders > Settings (VTEX Help Center - Setting the grace period for order cancellation). Any WMS action before ready-for-handling risks wasted pick labor on orders that cancel cleanly within that window.

For ERP integration specifically, the three statuses that must fire API calls are payment-approved (create the order record), ready-for-handling (commit inventory), and invoiced (close fulfillment). The canceled status needs an unconditional rollback path across both systems; in our experience on VTEX delivery work, missed cancellation handlers are the most common source of inventory drift in production environments.

Feed v.3 vs Hook: Choosing the right event-consumption pattern

Feed v.3 is a pull-based queue you poll on a schedule; Hook is a push-based webhook VTEX fires to a URL you configure (VTEX Developers - Feed v3). The right choice depends on your delivery guarantees, infrastructure, and order volume, but for most production integrations, Feed v.3 is the safer default.

Feed v.3: Reliable queue polling under load

Feed v.3 runs independently of VTEX OMS indexing, which matters more than it first appears. Indexing delays, common during flash sales or high-volume periods, do not block Feed events from appearing in the queue. Each event contains the orderId and the new status; you acknowledge receipt explicitly, so unprocessed events stay in the queue until your system confirms them. That acknowledgment loop makes Feed v.3 resilient to transient downstream failures: if your ERP middleware drops a connection, the event waits rather than disappears.

Polling frequency is configurable. In our experience integrating VTEX Orders API for a flash-sale client, queue depth spiked to several hundred unacknowledged events within minutes of a campaign going live. Feed v.3 held cleanly: events queued, consumed in order, and acknowledged without loss. A Hook-only architecture in the same scenario would have required a durable inbound buffer on our side to avoid dropped webhooks under burst load.

Hook: Push notifications as a complement

Hook suits lower-volume environments or cases where you want near-real-time push to an external system, a customer notification service, a BI pipeline, or a lightweight status dashboard, without managing poll intervals. Configure the target URL via the VTEX Orders API, and VTEX sends a POST payload on each status change across the order flow lifecycle.

The VTEX platform documentation explicitly positions Hook as a complement to Feed, not a replacement. Where this breaks down: Hook gives you no built-in retry guarantee beyond VTEX's own delivery attempt. If your endpoint returns a non-2xx, the event is not re-queued the way Feed events are.

Decision matrix

Factor Feed v.3 Hook
Delivery guarantee Acknowledgment-based queue Single attempt, no re-queue
Indexing dependency Independent Depends on indexing
Infrastructure requirement Polling scheduler Public HTTPS endpoint
Best for ERP, WMS, inventory reservation triggers Notifications, BI, low-volume pipelines
Burst resilience High, events queue Low without your own buffer

For any integration touching inventory reservation or ERP order status, Feed v.3 is the correct choice. Use Hook for read-side consumers that can tolerate occasional missed events.

VTEX Orders API: Key endpoints, pagination, and date filtering

The VTEX Orders API exposes two distinct endpoint patterns: a list endpoint for querying across orders, and a detail endpoint for retrieving a single order by orderId. Getting pagination and date filtering right from the start saves significant debugging time.

List endpoint: Pagination and date filtering

The list endpoint (`GET /api/oms/pvt/orders`) accepts per_page up to a maximum of 30, requests above that are silently capped, which surprises teams migrating from systems with higher page-size defaults. Combine it with page for offset pagination across large order sets.

Date filtering uses the f_creationDate parameter in ISO 8601 format with a range syntax:

f_creationDate=creationDate:[2025-01-01T00:00:00.000Z TO 2025-03-31T23:59:59.999Z]

The brackets and TO keyword are required, passing a single timestamp or a Unix epoch returns an empty result set without an error, which makes the failure silent. Per the VTEX Orders API reference, both bounds must be present. Use UTC throughout; VTEX OMS stores creation timestamps in UTC regardless of the store's configured timezone.

Detail endpoint and orderId structure

The detail endpoint (`GET /api/oms/pvt/orders/{orderId}`) returns the full order object, including the orderForm fields that persist from checkout into the OMS representation. An orderId is generated at the moment the Checkout API's Place Order call returns a 201: from that point, the order exists as a VTEX OMS entity and is queryable via this endpoint.

One practical note from our VTEX delivery work: the detail endpoint response includes the complete orderForm payload, which means SKU-level data, custom fields, and payment metadata are all present. Teams building ERP middleware often pull the full detail object rather than stitching together multiple calls. Cross-filtering on orderId ranges is not supported on the list endpoint, use f_creationDate for bulk extraction, then fetch detail records individually.

For real-time tracking, the VTEX developer documentation recommends Feed v.3 over repeated list polling, precisely because Feed v.3 runs independently of OMS indexing, a newly created order appears in the Feed queue before it surfaces in list endpoint results.

Connecting VTEX OMS to an ERP or back-office system

ERP integration with VTEX OMS works best when you treat the VTEX Orders API as an event stream rather than a polling target. Querying the list endpoint on a timer introduces race conditions at status boundaries and adds unnecessary load. Feed v.3 is the right pattern for most middleware designs.

Feed v.3 as the middleware foundation

Feed v.3 gives your middleware a persistent queue of order-update events. Each call to the Feed endpoint returns pending events; you process them, then commit the queue offset to acknowledge receipt. Because Feed v.3 runs independently of VTEX's internal indexing pipeline, status transitions appear in the queue faster than they would through a filtered list query, a meaningful difference when your ERP's pick-wave generation is time-sensitive.

The integration loop your ERP middleware should follow:

  1. Pull pending events from the Feed endpoint.
  2. Fetch the full order detail via `GET /api/oms/pvt/orders/{orderId}`. Feed events carry status and orderId, not the full order payload.
  3. Upsert the ERP record, using orderId as the idempotency key.
  4. Commit the Feed offset only after the ERP write succeeds.

Step 4 is where most first implementations break, a challenge that leading organizations address through careful planning. Committing before confirming the ERP write means a failed upsert silently drops the event, the queue advances but the ERP never updates. Commit last, always.

Idempotency and error handling: Because network failures and ERP timeouts are inevitable, design every upsert to be safe to replay. Store the orderId and its last-processed status in a local state table before writing to the ERP. If the upsert fails, the uncommitted Feed offset means the event is redelivered on the next pull cycle, and your state table prevents double-processing. For reconciliation, run a nightly job that queries `GET /api/oms/pvt/orders` filtered by a short update-time window and compares results against your ERP records. Any gap surfaces orders that slipped through during an extended outage, giving you a clean recovery path without manual intervention across sales channels.

Hook as a complement, not a replacement

Hook (VTEX's push-based webhook) sends a notification to your configured URL on every order status change. In practice, Hook works well as a low-latency alert layer, triggering a downstream notification or a lightweight cache invalidation, but it carries no delivery guarantee and provides no replay mechanism if your endpoint is unavailable. For the authoritative ERP sync, Feed v.3's pull-and-commit model is more reliable.

A common pattern in production integrations we've built: run Hook and Feed v.3 in parallel with different jobs. Hook handles customer-facing status emails while Feed v.3 drives inventory reservation updates. The separation keeps latency low for customer communications while ensuring the ERP's stock ledger is never updated from a partial or unconfirmed push.

Handling the orderForm boundary

OrderForm fields persist into OMS API responses, which means your middleware will encounter Checkout-era fields, including shipping estimates, payment method tokens, and custom fields set during cart assembly, inside what looks like a pure order record. Map these deliberately in your schema rather than ignoring them.

Key fields to map explicitly:

  • `paymentData.transactions[].payments[].paymentSystemName`: required by finance modules that reconcile online payment method totals.
  • `paymentData.transactions[].payments[].installments`: needed for installment-count reporting and fiscal documents in markets where that content is legally required.
  • openTextField and any custom customData app fields: these carry merchant-specific settings set during cart assembly and are easy to discard accidentally.
  • invoiceData fields: fiscal document references that your ERP's accounts-receivable flow depends on.

Ignoring these fields entirely risks dropping data your ERP finance module needs. Learn which fields your ERP consumes early in the mapping phase, not after go-live.

For the full VTEX platform architecture context that underpins these integration points, see our VTEX platform guide. If your setup involves Marketplace or Seller order flows routing across multiple accounts, the VTEX marketplace architecture guide covers how order routing affects which account's Feed receives which events.

FAQ: VTEX OMS technical questions developers ask most

What is the difference between Feed v.3 and Hook in VTEX OMS?

Feed v.3 is a pull-based queue you poll to retrieve pending order status events; Hook is a push-based webhook that VTEX fires to a URL you configure on each order update. Feed v.3 runs independently of indexing, so status changes appear in the queue faster and more reliably than in list-endpoint responses, a meaningful difference under load. Use Feed v.3 as your middleware foundation and Hook as a complement when you need parallel notification delivery.

What format does the f_creationDate filter use in the VTEX Orders API?

The f_creationDate filter accepts ISO 8601 UTC ranges in the format `creationDate:[2024-01-01T00:00:00.000Z TO 2024-01-31T23:59:59.999Z]`. Both the opening and closing bounds are inclusive, and the field name in the query string must match exactly, a common integration bug is omitting the creationDate: prefix inside the brackets. This matters most when backfilling order history across a date range after a cutover.

What is the per_page limit for VTEX Orders API pagination?

The VTEX Orders API caps per_page at 30 results per request, per the VTEX Orders API documentation. For order list endpoints, you combine per_page and page parameters to walk through result sets, there is no cursor-based pagination. If your ERP middleware expects a single bulk export, plan for multiple sequential requests with a delay between calls to avoid rate-limiting.

How does an orderForm become an OMS order and when is the orderId assigned?

The orderForm is a Checkout API object, the cart and pre-order payload built during the checkout session, and it becomes a VTEX OMS order the moment your system calls the Place Order endpoint and receives a 201 response containing the orderId. From that point the order exists as a distinct OMS entity and enters the order flow lifecycle; orderForm fields persist and appear in subsequent OMS API responses, but the two objects are architecturally separate. The orderId assignment boundary is where ERP systems should begin tracking.

What are the four VTEX order flow types?

VTEX OMS defines four order flow types based on a store's role in the transaction: Marketplace Flow (store manages the sale), Seller Flow (store handles fulfillment), Complete Flow (store is both marketplace and seller), and Chain Flow (store sits between a marketplace and a seller as an intermediary). Each flow type exposes a different lifecycle view and status set in the Orders API. Choosing the wrong flow to monitor is the most common reason ERP integrations miss status transitions on multi-vendor orders.

Which order status stages should an ERP integration monitor?

At minimum, an ERP integration should track: payment-approved, ready-for-handling, handling, invoiced, and canceled. The ready-for-handling stage is where inventory reservation is confirmed and warehouse operations should begin; invoiced signals the order is complete and delivered to carrier. Monitoring only invoiced and canceled is common but insufficient, orders can stall at verifying-invoice without triggering a final status change.

How does Chain Flow differ from the Complete Flow payment model?

In Chain Flow, the intermediary store receives a payment notification rather than direct payment, the marketplace retains the financial transaction and passes fulfillment responsibility down the chain. In Complete Flow, the store handles both the sale and payment directly, with no upstream marketplace involved. This distinction affects how you reconcile order revenue in your ERP: a Chain Flow orderId will not carry a direct payment record on the seller side.

Where to go next: VTEX platform resources

VTEX OMS sits at the center of a broader platform decision. If you're evaluating the full architecture, our VTEX platform guide covers the commerce environment, catalog structure, and API surface that surrounds order data. For teams building multi-vendor systems where Marketplace Flow and Seller Flow order routing matter, the VTEX marketplace architecture guide maps how seller orders and inventory reservation interact across storefronts.

If your integration spans ERP integration or catalog data that underlies order line items, the PIM - VTEX integration guide is worth reading alongside the OMS documentation. Teams migrating order history from Magento will find the mechanics covered in the Magento - VTEX migration guide rather than here.

Netguru has delivered VTEX OMS integrations across complex commerce environments. For teams considering how order events propagate across decoupled services, our overview of headless commerce architecture patterns covers the underlying design principles.

If your team is scoping a VTEX OMS build, an ERP integration, or a Marketplace Flow setup and wants a second opinion on the architecture, talk to our team.

We're Netguru

At Netguru we specialize in designing, building, shipping and scaling beautiful, usable products with blazing-fast efficiency.

Let's talk business