Portal Community
WhatsApp Commerce Cart orders: Orders returned by this node are customer cart orders submitted via the WhatsApp native shopping cart, not orders received as inbound webhook messages (which are handled by the commerce/receiveOrder trigger). Use this node for batch polling and reporting workflows.

When to Use

Configuration

Connection

FieldRequiredDescription
accessTokenRequiredPermanent System User access token from Meta Business Manager. Store in BizFirst Credentials Manager and reference via {{ $credentials.whatsAppToken }}.
phoneNumberIdRequiredNumeric string ID of the WhatsApp Business phone number (e.g. 123456789012345). Orders are scoped to the WABA associated with this phone number.
apiVersionOptionalMeta Graph API version, e.g. v18.0. Defaults to v18.0.

Operation

FieldRequiredDescription
limitOptionalNumber of orders per page. Default is 20. Use smaller values when each order requires heavy downstream processing.
afterOptionalPagination cursor from the previous call's cursor output. Omit on the first call.
statusOptionalFilter by order status. Accepted values: pending, shipped, delivered, cancelled. Omit to return orders of all statuses.
sinceOptionalISO 8601 datetime string (e.g. 2025-05-01T00:00:00Z). Returns only orders created on or after this timestamp.
untilOptionalISO 8601 datetime string (e.g. 2025-05-31T23:59:59Z). Returns only orders created before or at this timestamp.

Sample Configuration

{
  "resource": "commerce",
  "operation": "getOrders",
  "accessToken": "{{ $credentials.whatsAppToken }}",
  "phoneNumberId": "123456789012345",
  "status": "pending",
  "since": "{{ $vars.lastPollTime }}",
  "limit": "50"
}

Validation Errors

ErrorCause
accessToken is requiredThe accessToken field is empty or missing.
phoneNumberId is requiredThe phoneNumberId field is empty or missing.
100 (Meta)Invalid phone number ID or the System User does not have access to this WABA's orders.
200 (Meta)Permissions error — the token lacks order management permissions.
190 (Meta)Access token expired or revoked.
invalid status filter (Meta)The status value is not one of: pending, shipped, delivered, cancelled.
invalid date format (Meta)The since or until value is not a valid ISO 8601 datetime string.

Output

Success Port

Fires when Meta returns order data. The orders array contains one summary entry per order. Use the cursor field for pagination. When cursor is empty, you have retrieved the last page.

FieldTypeDescription
successbooleantrue on the success port.
ordersarrayArray of order summary objects. Each contains id, status, created_time, and estimated_total.
countintegerNumber of orders in this page.
cursorstringPagination cursor for the next page. Empty string when on the last page.
statusstring"success" on the success port.
errorCodestringEmpty on success.
errorMessagestringEmpty on success.
payloadstringFull raw JSON response from the Meta Graph API.

Error Port

Fires when the API call fails.

FieldTypeDescription
successbooleanfalse on the error port.
statusstring"failed" or "error".
errorCodestringMeta error code or BizFirst internal validation code.
errorMessagestringHuman-readable error description.
payloadstringRaw API error response for diagnostics.

Sample Output

{
  "success": true,
  "orders": [
    {
      "id": "order_112233",
      "status": "pending",
      "created_time": "2025-05-26T08:12:44Z",
      "estimated_total": "7998"
    },
    {
      "id": "order_112234",
      "status": "pending",
      "created_time": "2025-05-26T08:45:10Z",
      "estimated_total": "2999"
    }
  ],
  "count": 2,
  "cursor": "QVFIUmNSbXJkT2xNQ1...",
  "status": "success",
  "errorCode": "",
  "errorMessage": "",
  "payload": "{\"data\":[...],\"paging\":{\"cursors\":{\"after\":\"QVFIUmNSbXJkT2xNQ1...\"}}}"
}

Expression Reference

ValueExpressionNotes
Orders array{{ $output.getOrders.orders }}Pass to a ForEach node to process each order individually, e.g. routing each to commerce/getOrder for full details.
Order count{{ $output.getOrders.count }}Use to decide whether to continue polling. A count of 0 with no cursor means no new orders since last poll.
Next page cursor{{ $output.getOrders.cursor }}Pass as the after input on the next call. Empty string signals the last page.
First order ID{{ $output.getOrders.orders[0].id }}Use to initiate a single-order detail lookup via commerce/getOrder.
Error code{{ $output.getOrders.errorCode }}Non-empty on error port. Log for order polling diagnostics.

Node Policies & GuardRails

Policy AreaRecommendation
Credential storageAlways store the access token in BizFirst Credentials Manager. Never embed raw tokens in node configuration fields.
Order idempotencyTrack processed order IDs in a database. When polling for new orders, only process order IDs that have not been seen before. Polling the same time window twice may return the same orders — always check against your processed orders table before sending fulfilment requests to the OMS.
Poll frequencyDo not poll more than once per minute. For real-time order ingestion, prefer webhook-based order receipt via commerce/receiveOrder. Use this node for batch polling and catch-up scenarios only.
Date range accuracyUse since set to the timestamp of the last successful poll, not the current time minus an interval. Store the last successful poll timestamp in a persistent variable to avoid gaps caused by workflow failures or delays.
Error port handlingAlways connect the error port. A polling failure should not advance the lastPollTime variable — leave it at the previous value so the next poll re-fetches the missed window.
Order fulfilmentThis node returns order summaries only. For fulfilment, call commerce/getOrder per order ID to retrieve the full item list and customer details before submitting to the OMS.

Examples

Pending Order Fulfilment Polling

{
  "resource": "commerce",
  "operation": "getOrders",
  "accessToken": "{{ $credentials.whatsAppToken }}",
  "phoneNumberId": "123456789012345",
  "status": "pending",
  "since": "{{ $vars.lastOrderPollTime }}",
  "limit": "50"
}

A ScheduledTrigger fires every 15 minutes. This node fetches all pending orders since the last successful poll. On success, the workflow stores the current UTC timestamp as lastOrderPollTime. A ForEach node passes each order ID to commerce/getOrder to retrieve item details. A deduplication check against the processed_orders table ensures each order is sent to the OMS exactly once.

Cart Abandonment Recovery

{
  "resource": "commerce",
  "operation": "getOrders",
  "accessToken": "{{ $credentials.whatsAppToken }}",
  "phoneNumberId": "123456789012345",
  "status": "pending",
  "since": "{{ $vars.twoHoursAgo }}",
  "until": "{{ $vars.oneHourAgo }}",
  "limit": "100"
}

A workflow scheduled every hour retrieves pending orders that are between 1 and 2 hours old — these represent carts that were started but not completed. A ForEach node calls commerce/getOrder for each to retrieve the customer phone and items. A template message is sent to each customer via message/sendTemplate with a personalised cart recovery message. Orders already contacted are tracked in a cart_recovery_attempts table to prevent multiple messages to the same customer.

Daily Order Revenue Report

{
  "resource": "commerce",
  "operation": "getOrders",
  "accessToken": "{{ $credentials.whatsAppToken }}",
  "phoneNumberId": "123456789012345",
  "since": "{{ $vars.yesterdayStart }}",
  "until": "{{ $vars.yesterdayEnd }}",
  "limit": "100",
  "after": "{{ $vars.nextPageCursor }}"
}

A nightly report workflow paginates through all orders from the previous day. Each page's cursor is stored in nextPageCursor to drive the next loop iteration. After collecting all order IDs, a second loop calls commerce/getOrder per order to aggregate item quantities and revenue by product. The aggregated report is written to a reporting database and emailed to the commerce team at 07:00.