Velo Orders API: Order.fulfillmentStatus Auto-Sets to FULFILLED After Payment, Despite Creating "Pending" Fulfillment Record

Okay, here’s an expanded version of the post for the Velo community or Wix Support, structured to fit the common “ask a question” template you provided. This version incorporates all the details we’ve uncovered.


Question:

How can we ensure that an Order.fulfillmentStatus for physical goods remains NOT_FULFILLED after payment confirmation when using the Velo eCommerce Orders API, instead of it automatically changing to FULFILLED?

Product:

Wix Velo (Backend code using wix-ecom-backend and wix-auth modules, specifically the orders, orderTransactions, and orderFulfillments APIs). This backend is being called from a Flutter mobile application.

What are you trying to achieve:

We are implementing a custom checkout flow for physical products (sculptures). Our desired order lifecycle is:

  1. Initial Order Creation: When a user finalizes their cart in our Flutter app, we call a Velo HTTP function (post_createWixOrder which delegates to createOrderFunction in backend/orderCreator.js) to create an order using orders.createOrder().
  • Expected Initial State: status: INITIALIZED, paymentStatus: NOT_PAID, fulfillmentStatus: NOT_FULFILLED.
  • Actual Initial State (SUCCESS): We have successfully achieved this. Our logs (from orderCreator.js) confirm this state after orders.createOrder() completes.
  1. Payment Processing: The user pays via Stripe. After successful payment, our Flutter app calls another Velo HTTP function (post_confirmOrderPayment which delegates to handleConfirmOrderPayment in backend/orderHttpHandlers.js).
  • This function records the payment using orderTransactions.addPayments() and orderTransactions.updatePaymentStatus() with TransactionStatus.APPROVED.
  • This correctly updates the order’s paymentStatus to PAID and the overall order status to APPROVED.
  1. Desired Fulfillment State After Payment: We want the Order.fulfillmentStatus to remain NOT_FULFILLED at this point, as the physical items have not yet been prepared or shipped.
  2. Actual Fulfillment State After Payment (The Problem): Immediately after the payment is confirmed and the order status becomes APPROVED and paymentStatus becomes PAID, the summary Order.fulfillmentStatus automatically changes to FULFILLED. This happens even before any explicit fulfillment actions are taken by us for shipping.

What have you already tried:

  1. Verifying Wix Dashboard Settings: We have confirmed that in our Wix Store settings, there are no options enabled to “automatically mark orders as fulfilled when paid.”
  2. Checking Wix Automations: We have confirmed there are no active Wix Automations that would change the fulfillmentStatus upon order payment or approval.
  3. Attempting to Set Initial Order.status:
  • We tried explicitly setting status: orders.OrderStatus.INITIALIZED or status: "INITIALIZED" in the payload for orders.createOrder().
  • Result: This caused a “Bad Request” error from the API. It seems orders.createOrder() enforces a default status (likely APPROVED, though our initial logs show INITIALIZED when no status is provided, which is fine).
  1. Attempting to Directly Update Order.fulfillmentStatus After Payment:
  • In handleConfirmOrderPayment, after the order became PAID and FULFILLED, we tried calling elevate(orders.updateOrder)(orderId, { fulfillmentStatus: orders.FulfillmentStatus.NOT_FULFILLED }, { fieldMask: ["fulfillmentStatus"] }).
  • Result: This failed with an INVALID_ARGUMENT: "options.fieldMask" Field mask points to read-only field error, indicating Order.fulfillmentStatus cannot be directly written to this way.
  1. Attempting to Delete Auto-Created Fulfillments (Strategy 1):
  • Our hypothesis was that Wix might be auto-creating a fulfillment record.
  • In handleConfirmOrderPayment, after the order became PAID and FULFILLED, we called elevate(orderFulfillments.listFulfillmentsForSingleOrder)(orderId).
  • Result: This returned an empty fulfillments: [] array. Thus, there were no explicit fulfillment records to delete to try and revert the summary status.
  1. Attempting to Proactively Create a “Pending” Fulfillment During Initial Order Creation (orderCreator.js):
  • After orders.createOrder() (which resulted in an INITIALIZED, NOT_PAID, NOT_FULFILLED order), we immediately tried to call elevate(orderFulfillments.createFulfillment)(orderId, placeholderFulfillmentPayload).
  • Result: This failed with INVALID_ARGUMENT: Order [...] - is not approved so cannot be fulfilled. This confirms fulfillments can only be created for APPROVED orders.
  1. Attempting to Proactively Create a “Pending” Fulfillment After Payment Confirmation (orderHttpHandlers.js):
  • After addPayments and updatePaymentStatus (order becomes PAID, APPROVED, and automatically FULFILLED by Wix).
  • We then successfully call elevate(orderFulfillments.createFulfillment)(orderId, { lineItems: [...], status: "Pending" }). A new fulfillment record with status: "Pending" is successfully created and associated with the order.
  • Problem Persists: Despite this “Pending” fulfillment record existing, when we immediately re-fetch the main Order object using elevate(orders.getOrder)(orderId), its summary Order.fulfillmentStatus still shows FULFILLED.

Additional Information:

  • We are using the V3 eCommerce APIs (wix-ecom-backend).
  • The products are configured as physical items.
  • Our orderCreator.js now successfully creates orders that initially log as status: INITIALIZED, paymentStatus: NOT_PAID, fulfillmentStatus: NOT_FULFILLED. The issue arises after payment confirmation.
  • We need the fulfillmentStatus to accurately reflect NOT_FULFILLED in the Wix dashboard and for our app’s order history page until we manually initiate and complete the shipping process (at which point we would use the orderFulfillments API to create/update a fulfillment with tracking details and a “Fulfilled” status).

Our Core Question for the Velo Community/Wix Support:

Given that: a. The order starts as NOT_FULFILLED. b. Wix automatically changes the summary Order.fulfillmentStatus to FULFILLED once the order is PAID and APPROVED. c. We cannot directly update this summary Order.fulfillmentStatus back to NOT_FULFILLED using orders.updateOrder(). d. Creating an explicit “Pending” Fulfillment record after payment (which succeeds) does not revert the summary Order.fulfillmentStatus from FULFILLED.

What is the correct Velo API procedure to ensure an order for physical goods remains NOT_FULFILLED (or reflects PARTIALLY_FULFILLED due to a “Pending” fulfillment record) in its summary Order.fulfillmentStatus after payment, until we explicitly mark it as shipped by creating/completing a fulfillment with tracking information?

Is there a specific property on the Order object during creation (via orders.createOrder), or an option during payment confirmation (via orderTransactions API), or a specific way to structure the initial “Pending” Fulfillment object that will prevent the main Order.fulfillmentStatus from defaulting to FULFILLED prematurely?

Thank you for any guidance!


Code Snippets (You can attach or link to your Velo files if the forum supports it, or paste key functions):

  • Your current backend/orderCreator.js (the version that successfully creates an order with initial NOT_FULFILLED status).
  • Your current backend/orderHttpHandlers.js (specifically the handleConfirmOrderPayment function showing the payment confirmation and the attempt to create a “Pending” fulfillment).
  • Example Velo logs showing the sequence:
    1. Log from orderCreator.js after orders.createOrder() (showing initial NOT_FULFILLED).
    2. Logs from orderHttpHandlers.js after payment showing Order.fulfillmentStatus becoming FULFILLED.
    3. Logs showing the successful creation of the “Pending” Fulfillment record.
    4. Logs showing the re-fetched Order.fulfillmentStatus still being FULFILLED.

Thank you in advance for your help!