Product ID vs. Retailer ID: The productId field used here is the Facebook-assigned catalog item ID returned by commerce/createProduct or listed in commerce/getProducts. This is distinct from your internal retailerId (SKU). Store the Facebook product ID alongside your SKU when creating products.
When to Use
- Pre-send product verification: Before sending a product message to a customer, a workflow calls this node to confirm the product is still "in stock" and its price has not changed since the product ID was last cached, preventing customers from seeing outdated information.
- Order fulfilment cross-check: When an order arrives, a fulfilment workflow retrieves the product details for each ordered item to enrich the order record with the current product name, price, and image URL for display in the merchant's order management system.
- Inventory status check for cart abandonment: A cart abandonment workflow checks whether the product the customer left in their cart is still available before sending a re-engagement message, avoiding messages about out-of-stock items.
- Product detail enrichment: A reporting workflow fetches full product details for each item sold to populate a sales report with product descriptions and images, enriching the report beyond what the order record alone provides.
- Post-create validation: After calling
commerce/createProduct, an idempotency-check workflow reads back the product using the returned ID to confirm that all fields were saved correctly by Meta before proceeding with downstream product messaging workflows.
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 (e.g. 9876543210123). This is the id returned when the product was created, not the internal retailer SKU. |
Sample Configuration
{
"resource": "commerce",
"operation": "getProduct",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"productId": "{{ $input.catalogProductId }}"
}
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 does not have access to the catalog containing this product. |
200 (Meta) | Permissions error — the token lacks catalog_management permission. |
190 (Meta) | Access token expired or revoked. Rotate the token in Meta Business Manager. |
Output
Success Port
Fires when Meta returns product details. All fields returned by the Graph API are populated. The availability field reflects the current stock status of the product in the catalog.
| Field | Type | Description |
success | boolean | true on the success port. |
productId | string | The Facebook catalog product item ID. |
name | string | Product display name. |
description | string | Product description. |
price | string | Price in minor currency units (e.g. "2999" for $29.99). |
currency | string | ISO 4217 currency code (e.g. USD). |
imageUrl | string | Product image URL as stored in the catalog. |
availability | string | Current availability: in stock, out of stock, preorder, or available for order. |
status | string | "success" 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 the product cannot be found or the API 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": "Classic Polo Shirt",
"description": "100% cotton polo shirt. Available in sizes S, M, L, XL.",
"price": "2999",
"currency": "USD",
"imageUrl": "https://cdn.example.com/products/polo-shirt.jpg",
"availability": "in stock",
"status": "success",
"errorCode": "",
"errorMessage": "",
"payload": "{\"id\":\"9876543210123\",\"name\":\"Classic Polo Shirt\",\"description\":\"...\",\"price\":\"2999\",\"currency\":\"USD\",\"image_url\":\"https://...\",\"availability\":\"in stock\"}"
}
Expression Reference
| Value | Expression | Notes |
| Product name | {{ $output.getProduct.name }} | Use in order fulfilment records and customer notification messages. |
| Price | {{ $output.getProduct.price }} | Minor currency units. Divide by 100 in a Function node for display purposes in reports. |
| Availability | {{ $output.getProduct.availability }} | Check === "in stock" in an IfCondition node before sending a product message to a customer. |
| Image URL | {{ $output.getProduct.imageUrl }} | Use to display the product image in external dashboards or reporting systems. |
| Error code | {{ $output.getProduct.errorCode }} | Non-empty on error port. A 100 error indicates the product ID is invalid or has been deleted. |
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. |
| Inventory accuracy | The availability field reflects the value stored in Meta's catalog, not your live warehouse system. Always sync availability via commerce/updateProduct before relying on this node's output for customer-facing stock checks. |
| Product ID caching | Cache the Facebook product ID (productId) in your internal database when a product is created. Do not repeatedly call commerce/getProducts just to resolve a product ID — use the cached value and call this node directly for detail lookups. |
| Image CDN requirements | Verify that the returned imageUrl is still accessible before using it in customer-facing messages. CDN URLs can expire or be moved. Implement a URL health check step if images are served from short-lived signed URLs. |
| Error port handling | Always connect the error port. A product-not-found error (Meta error 100) typically means the product was deleted. Update your internal database to mark the product as removed from the WhatsApp catalog. |
| Rate limits | Do not call this node in tight loops over a large product list. Use commerce/getProducts with pagination to read multiple products in a single call. Reserve this node for single-product lookups triggered by specific events. |
Examples
Pre-Send Inventory Check
{
"resource": "commerce",
"operation": "getProduct",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"productId": "{{ $input.catalogProductId }}"
}
Before sending a single-product WhatsApp message, this node is called first. An IfCondition node checks {{ $output.getProduct.availability }} === "in stock". If in stock, the workflow proceeds to message/sendInteractive with the product. If out of stock, the workflow sends a "notify me when back" template instead.
Order Fulfilment Record Enrichment
{
"resource": "commerce",
"operation": "getProduct",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"productId": "{{ $item.catalogProductId }}"
}
When processing an inbound order, a ForEach node iterates over ordered items and calls this node per item. The returned name, price, currency, and imageUrl are merged into the order record in the database. The enriched record is used to render the order confirmation PDF and the delivery notification message.
Post-Creation Validation
{
"resource": "commerce",
"operation": "getProduct",
"accessToken": "{{ $credentials.whatsAppToken }}",
"phoneNumberId": "123456789012345",
"productId": "{{ $output.createProduct.productId }}"
}
Immediately after commerce/createProduct succeeds, this node reads back the product to confirm all fields were saved correctly by Meta. A Function node compares the submitted price with {{ $output.getProduct.price }} and raises an alert if there is a mismatch, catching potential data corruption issues before any product messages are sent.