Partial update semantics: You must supply productId plus at least one of name, description, or price. Omitting a field does not clear it; the existing value is preserved. To update the price, always supply the price in minor currency units as a string.
Price accuracy: Incorrect prices in the WhatsApp catalog are displayed directly to customers. Always validate price values from the source system before passing them to this node. Consider a human-approval workflow gate for price changes above a defined threshold.
When to Use
- Real-time inventory status sync: When a product goes out of stock in the warehouse management system, an event-driven workflow immediately updates the product's availability to
out of stock in the WhatsApp catalog, preventing customers from adding unavailable items to their cart.
- Dynamic price adjustments: A repricing engine publishes price changes throughout the day. A workflow subscribes to the price change event stream and calls this node for each affected product, keeping catalog prices in sync with the live pricing system.
- Product description refresh: After a product content team updates marketing copy in the PIM, a publishing workflow detects the change and propagates the new description to the WhatsApp catalog, ensuring customers see the latest product information.
- Promotional price application: A promotion management workflow applies discounted prices to targeted products at the start of a sale and reverts them to original prices when the sale ends, automating the entire promotional cycle without manual Commerce Manager access.
- Seasonal content updates: At the start of each season, a bulk update workflow changes product names and descriptions across a collection to reflect seasonal branding, keeping the catalog consistent with the rest of the marketing channel.
Configuration
Connection
| Field | Required | Description |
accessToken | Required | Permanent System User access token from Meta Business Manager. Store in BizFirst Credentials Manager and reference via {{ $credentials.whatsAppToken }}. |
phoneNumberId | Required | Numeric string ID of the WhatsApp Business phone number (e.g. 123456789012345). |
apiVersion | Optional | Meta Graph API version, e.g. v18.0. Defaults to v18.0. |
Operation
| Field | Required | Description |
productId | Required | The Facebook catalog product item ID to update (e.g. 9876543210123). |
name | Optional | New product display name. Maximum 100 characters. Omit to leave unchanged. |
description | Optional | New product description. Maximum 5000 characters. Omit to leave unchanged. |
price | Optional | New price in minor currency units as a string (e.g. "1999" for $19.99). Omit to leave unchanged. |
Sample Configuration
{
"resource": "commerce",
"operation": "updateProduct",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"productId": "{{ $input.catalogProductId }}",
"price": "{{ $input.newPriceInCents }}"
}
Validation Errors
| Error | Cause |
accessToken is required | The accessToken field is empty or missing. |
productId is required | The productId field is empty or missing. |
100 (Meta) | The product ID does not exist or the System User lacks write access. |
200 (Meta) | Permissions error — the token lacks catalog_management permission. |
190 (Meta) | Access token expired or revoked. |
100 (Meta — bad price) | The price value is not a valid positive integer string. |
Output
Success Port
Fires when Meta confirms the product update. The output echoes back the fields that were updated for confirmation logging. Fields not included in the request are returned as empty strings.
| Field | Type | Description |
success | boolean | true on the success port. |
productId | string | The product ID that was updated. |
name | string | New name if supplied in the request; otherwise empty. |
description | string | New description if supplied in the request; otherwise empty. |
price | string | New price if supplied in the request; otherwise empty. |
currency | string | Currency code if returned by Meta; otherwise empty. |
imageUrl | string | Image URL if returned by Meta; otherwise empty. |
availability | string | Availability status if returned by Meta; otherwise empty. |
status | string | "updated" on the success port. |
errorCode | string | Empty on success. |
errorMessage | string | Empty on success. |
payload | string | Full raw JSON response from the Meta Graph API. |
Error Port
Fires when Meta rejects the update or the network call fails.
| Field | Type | Description |
success | boolean | false on the error port. |
status | string | "failed" or "error". |
errorCode | string | Meta error code or BizFirst internal validation code. |
errorMessage | string | Human-readable error description. |
payload | string | Raw API error response for diagnostics. |
Sample Output
{
"success": true,
"productId": "9876543210123",
"name": "",
"description": "",
"price": "1999",
"currency": "",
"imageUrl": "",
"availability": "",
"status": "updated",
"errorCode": "",
"errorMessage": "",
"payload": "{\"success\":true}"
}
Expression Reference
| Value | Expression | Notes |
| Updated product ID | {{ $output.updateProduct.productId }} | Confirms which product was updated. Use in audit log entries. |
| New price | {{ $output.updateProduct.price }} | The new price in minor units. Log alongside the previous price for pricing audit trails. |
| Status | {{ $output.updateProduct.status }} | Use in an IfCondition node to confirm the update before sending a price-change notification to customers. |
| Error code | {{ $output.updateProduct.errorCode }} | Non-empty on error port. Route to a retry queue for transient failures. |
| Full API response | {{ $output.updateProduct.payload }} | Raw JSON string for extended diagnostics. |
Node Policies & GuardRails
| Policy Area | Recommendation |
| Credential storage | Always store the access token in BizFirst Credentials Manager. Never embed raw tokens in node configuration fields. |
| Price accuracy | Price updates take effect immediately and are visible to customers. Always validate the source price and consider requiring an approval step for price changes exceeding a defined percentage threshold. Log old and new prices in an audit table on every price update. |
| Inventory accuracy | Availability status changes (in stock / out of stock) should be triggered by authoritative inventory events from your warehouse system, not by heuristics. A product incorrectly marked "in stock" can result in overselling. |
| Partial update verification | After updating a product, call commerce/getProduct to verify the change was applied correctly, especially for price updates. This catches any silent failures where Meta returns success but the value was not persisted. |
| Image CDN requirements | If updating imageUrl (via direct API extension), ensure the new URL is publicly accessible on HTTPS and will not expire. Broken image URLs cause product cards to render without an image in WhatsApp. |
| Error port handling | Always connect the error port. Failed price updates in a bulk repricing workflow should be logged with the original product ID and the failed price, and queued for retry rather than silently dropped. |
Examples
Real-Time Inventory Status Update
{
"resource": "commerce",
"operation": "updateProduct",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"productId": "{{ $input.catalogProductId }}",
"description": "{{ $input.updatedDescription }}"
}
A warehouse event triggers this workflow when stock reaches zero. The description is updated to include an "out of stock" notice. A separate step in the workflow (via direct API call or future node extension) sets availability. The product remains in the catalog so returning customers can see the item and get notified when it is back.
Promotional Price Application
{
"resource": "commerce",
"operation": "updateProduct",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"productId": "{{ $item.catalogProductId }}",
"price": "{{ $item.salePriceInCents }}",
"name": "{{ $item.originalName }} — Sale Price"
}
A promotion workflow reads the sale items and their discounted prices from the promotions table and updates each product in a loop. A Delay node paces the updates to avoid rate limits. The original prices and names are saved to a revert table. A second workflow scheduled for sale-end reads the revert table and restores each product's original name and price.
Daily ERP Price Sync
{
"resource": "commerce",
"operation": "updateProduct",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"productId": "{{ $item.catalogProductId }}",
"price": "{{ $item.erpPriceInCents }}"
}
A nightly workflow queries the ERP system for products whose price changed in the last 24 hours. Each changed product is passed to this node with its new price. On success, the workflow calls commerce/getProduct to verify the price was saved. Products with verification failures are logged in an exception report sent to the pricing team at 06:00.