Webhooks: List Products
Overview
The List Products webhook allows Talk2sync to retrieve your complete product catalog. Talk2sync will periodically request your product endpoint to synchronize product data including details, prices, availability, images, and custom attributes.
Endpoint Requirements
You must create a GET endpoint that accepts pagination and sorting parameters from Talk2sync.
Request Format
Talk2sync will send GET requests to your configured products endpoint with the following parameters:
Numeric Offset Pagination (Recommended)
GET https://www.example.com/your/endpoint/url?offset=0&sortorder=desc&jobid=123
T2SKey: {{API_KEY}}
Cursor-Based Pagination (Alternative)
If numeric offset pagination is not feasible for your system, you can implement cursor-based pagination:
GET https://www.example.com/your/endpoint/url?next=YXNkaWhhc3BvZGhpYXM&sortorder=desc&jobid=123
T2SKey: {{API_KEY}}
Request Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
offset | integer | Starting position for numeric pagination (0-based) | If using numeric pagination |
next | string | Base64-encoded cursor for cursor-based pagination | If using cursor pagination |
sortorder | string | Sort direction: asc (ascending) or desc (descending) | ✓ Yes |
jobid | integer | Unique identifier for this sync job (for tracking) | ✓ Yes |
T2SKey | header | Your security key provided by Talk2sync | ✓ Yes |
Authentication
The security key must be included in the T2SKey header (not the Authorization header for this endpoint):
T2SKey: your_generated_key_here
Response Format
Your endpoint must return a JSON response with the following structure:
{
"paging": {
"pageSize": 20,
"itemsTotal": 2,
"offset": 0
},
"products": [
{
"_id": "100004777",
"sku": "100004777",
"last_updated": 1517360038797,
"title": "EON618S JBL SUBWOOFER 18\" AMPLIFICADO",
"url": "",
"brand": "",
"mpn": "",
"model": "",
"description": "JBL Premium Transducers",
"variations": [
{
"availabilities": [
{
"tag": "default",
"quantity": 50
}
],
"prices": [
{
"tag": "default",
"currency": "USD",
"number": 1060.51
}
],
"images": [
{
"url": "https://www.example.com/13080-thickbox_default/eon618s-jbl-subwoofer-18-amplificado-.jpg"
}
],
"videos": [
{
"url": ""
}
],
"barcode": "",
"size": "",
"color": "",
"variationid": ""
}
],
"properties": [
{
"extraattributes": {
"promociones": "",
"status": "",
"condicion_venta": "",
"peso": "",
"relacionados": "",
"custom_01": "",
"custom_02": "1",
"custom_03": ""
}
}
]
}
]
}
Response Structure
Paging Object
| Field | Type | Description |
|---|---|---|
pageSize | integer | Number of items returned in this page |
itemsTotal | integer | Total number of products in your system |
offset | integer | Current offset position (only for numeric pagination) |
next | string | Base64-encoded cursor for the next page (only for cursor pagination) |
Product Object
| Field | Type | Description |
|---|---|---|
_id | string | Unique product identifier (required) |
sku | string | Product SKU/code |
last_updated | integer | Unix timestamp (milliseconds) of last modification |
title | string | Product name/title |
url | string | Product URL in your store |
brand | string | Product brand |
mpn | string | Manufacturer Part Number |
model | string | Product model |
description | string | Detailed product description |
variations | array | Array of product variations (see below) |
properties | array | Array of custom properties/attributes |
Variation Object
| Field | Type | Description |
|---|---|---|
variationid | string | Unique variation identifier |
size | string | Size attribute |
color | string | Color attribute |
barcode | string | Barcode/EAN code |
availabilities | array | Stock information by location/warehouse |
prices | array | Pricing information by currency/region |
images | array | Product images |
videos | array | Product videos |
Availability Object
| Field | Type | Description |
|---|---|---|
tag | string | Location identifier (e.g., "default", "warehouse_1") |
quantity | integer | Available quantity at this location |
Price Object
| Field | Type | Description |
|---|---|---|
tag | string | Price tier identifier (e.g., "default", "wholesale") |
currency | string | ISO 4217 currency code (e.g., "USD", "MXN") |
number | number | Price value |
Image Object
| Field | Type | Description |
|---|---|---|
url | string | Full URL to the product image |
Extra Attributes Object
Custom fields can be included in the extraattributes object. Common examples:
| Field | Type | Description |
|---|---|---|
promociones | string | Promotion information |
status | string | Product status (active, inactive, etc.) |
condicion_venta | string | Sales condition |
peso | string | Product weight |
relacionados | string | Related products |
custom_01 to custom_03 | string | Custom fields |
Implementation Example (Node.js/Express)
app.get('/api/products', (req, res) => {
const { offset = 0, next, sortorder = 'desc', jobid } = req.query;
const apiKey = req.headers['t2skey'];
// Validate API key
if (apiKey !== process.env.TALK2SYNC_KEY) {
return res.status(401).json({ error: 'Unauthorized' });
}
try {
// Fetch products from your database
const allProducts = fetchProductsFromDatabase(sortorder);
// Implement pagination (numeric offset example)
const pageSize = 20;
const startIndex = parseInt(offset) || 0;
const paginatedProducts = allProducts.slice(startIndex, startIndex + pageSize);
// Build response
const response = {
paging: {
pageSize: paginatedProducts.length,
itemsTotal: allProducts.length,
offset: startIndex
},
products: paginatedProducts.map(product => ({
_id: product.id,
sku: product.sku,
last_updated: new Date(product.updatedAt).getTime(),
title: product.name,
url: product.url,
brand: product.brand,
mpn: product.mpn,
model: product.model,
description: product.description,
variations: product.variations.map(v => ({
variationid: v.id,
size: v.size || "",
color: v.color || "",
barcode: v.barcode || "",
availabilities: v.stocks.map(s => ({
tag: s.location || "default",
quantity: s.quantity
})),
prices: v.prices.map(p => ({
tag: p.tier || "default",
currency: p.currency || "USD",
number: p.value
})),
images: v.images.map(img => ({ url: img })),
videos: v.videos.map(vid => ({ url: vid }))
})),
properties: [{
extraattributes: product.customFields || {}
}]
}))
};
res.json(response);
} catch (error) {
console.error('Error fetching products:', error);
res.status(500).json({ error: 'Internal Server Error' });
}
});
Response Status Codes
| Status | Meaning | Action |
|---|---|---|
200 OK | Products retrieved successfully | Talk2sync processes the data |
400 Bad Request | Invalid parameters | Check your request parameters |
401 Unauthorized | Invalid or missing API key | Verify your security key |
500 Internal Server Error | Server error | Check your server logs |
Pagination Guidelines
Numeric Offset Strategy
Best for: Small to medium datasets (< 100,000 items)
- Return items from
offsettooffset + pageSize - Increment
offsetbypageSizefor each request - Include
offsetin the paging response
Cursor-Based Strategy
Best for: Large datasets or frequently changing data
- Encode the next page's starting point as a base64 cursor
- Return the cursor in the response as
next - Use the
nextparameter for subsequent requests - More efficient for large datasets
Timing and Frequency
- Talk2sync will request products according to the synchronization schedule configured in your connection settings
- The
jobidparameter helps you track which sync job initiated each request - Each request should be processed and return within 1 minute
Best Practices
✓ Do:
- Return data sorted consistently (use
sortorderparameter) - Include accurate
last_updatedtimestamps - Validate the API key on every request
- Implement pagination to handle large catalogs
- Test with various page sizes
- Monitor API response times
✗ Don't:
- Include sensitive information in responses
- Return the same product multiple times
- Ignore the sorting parameter
- Return responses larger than 10MB per page