REST API v1 · Resource
Product catalog
Read, add, change, delete and sync the products in your Meta catalog.
API reference · Product catalog
Last updated
Endpoints
Paths are relative to https://fliok.com/api/v1. Each endpoint names the scope and the lowest key role it needs; a key without them gets 403 (see Authentication).
The catalog is in early access. It opens for your workspace once Meta approves the catalog permissions; until then every /catalog endpoint answers 404 not_available, the same as the dashboard. Your workspace needs a Meta catalog connected and chosen in Integrations. Once it is, these endpoints run the same code as the dashboard’s Catalog page and inbox, with the same roles, rules and limits. Reads need any key with catalog:read. Changing products, pictures, settings and the link needs an admin key with catalog:write. Sending needs an agent key with messages:send.
- Syncing means Meta has it. A product you add or change is pushed to your Meta catalog at once.
syncStatussays how that went (synced, pending or error, withlastError), andinMetasays whether Meta has the product. Only products in Meta’s catalog can be sent.POST /catalog/products/syncretries the rest, 100 a call. The SKU (retailerId) can’t change once Meta has the product. - Pictures go in by URL.
POST /catalog/imagesdownloads a JPG or PNG (up to 8 MB) from a public https:// address and returns animageKeyfor the product. Private and internal addresses are refused. Every product needs a picture. - Sending follows the inbox’s rules.
POST /catalog/sendworks only inside the 24-hour window after the customer’s last message (422 outside_24h_window). It never reaches an opted-out customer and counts against your plan’s messages. It needs a Cloud API number (a number shared with the WhatsApp Business app can’t send product messages) and a catalog linked to WhatsApp. - Connecting is done in the browser. Connecting a catalog and choosing which one to use is a Facebook sign-in, so it isn’t in the API.
GET /integrations/meta-cataloggives theconnectUrl, andDELETE /integrations/meta-catalogdisconnects it.
Product catalog
12- GET
/catalogThe Meta catalog: connected or not, its name, linked to WhatsApp, profile and cart settings, last sync and product counts. ?conversationId= says if that chat can get product messagesScopecatalog:read· viewer role or higherNeeds an API key - GET
/catalog/productsYour products, newest first and paged (?limit=, ?cursor=). ?q= searches name and SKU; ?synced=true keeps only those in the Meta catalogScopecatalog:read· viewer role or higherNeeds an API key - GET
/catalog/products/{id}One product: SKU, name, price, picture URL, link, stock, and whether it is in the Meta catalog (syncStatus, inMeta, lastError)Scopecatalog:read· viewer role or higherNeeds an API key - POST
/catalog/productsAdd a product (name, price, currency, picture) and push it to the Meta catalog at once. Optional Idempotency-KeyScopecatalog:write· admin role or higherNeeds an API key - PATCH
/catalog/products/{id}Change a product; send only the fields to change. Pushed to Meta at once. The SKU is fixed once Meta has the productScopecatalog:write· admin role or higherNeeds an API key - DELETE
/catalog/products/{id}Remove a product from the Meta catalog, then from Fliok. If Meta refuses, the product stays, with the reasonScopecatalog:write· admin role or higherNeeds an API key - POST
/catalog/imagesFliok downloads a product picture (JPG or PNG, up to 8 MB) from a public https:// URL and returns an imageKey for a productScopecatalog:write· admin role or higherNeeds an API key - POST
/catalog/products/syncPush every product that is not in the Meta catalog yet, 100 a call; call again while `remaining` is above zeroScopecatalog:write· admin role or higherNeeds an API key - POST
/catalog/importCopy the products already in your Meta catalog (made in Commerce Manager) into Fliok by SKU, so you can send themScopecatalog:write· admin role or higherNeeds an API key - PATCH
/catalog/settingsShow the catalog on your WhatsApp profile and let customers send a cart. Saved only once Meta accepts it on every numberScopecatalog:write· admin role or higherNeeds an API key - POST
/catalog/linkLink the chosen catalog to your WhatsApp Business Account again and re-apply the profile and cart settingsScopecatalog:write· admin role or higherNeeds an API key - POST
/catalog/sendSend one product, a list or the whole catalog into a chat, with the inbox rules: 24-hour window, opt-out, plan allowanceScopemessages:send· agent role or higherNeeds an API key
Request bodies
What these endpoints take, field by field. A body that doesn’t match answers 400 naming the field.
POST /catalog/products · PATCH /catalog/products/{id}
JSON body, admin keys. POST needs name, price, currency and imageKey. PATCH takes only the fields to change; the rest stay. POST takes an `Idempotency-Key` header.
| Field | Type | What it is |
|---|---|---|
namerequired | string | The product’s name, as customers see it. |
pricerequired | string | number | The price in the currency’s main unit, like 499 or "1,299.50". Above zero. |
currencyrequired | string | INR, USD, EUR, GBP, AED, SAR, SGD, AUD or CAD. |
imageKeyrequired | string | The picture: the imageKey from POST /catalog/images. Required to add a product; on PATCH, leave it out to keep the picture. |
description | string | What it is. Empty by default. |
retailerId | string | Your SKU. Made from the name if you leave it out. Unique in your workspace, and fixed once Meta has the product. |
url | string | null | The product’s page on your website, starting with https://. Without one, Fliok’s product page is used. |
availability | string | "in stock" (the default) or "out of stock". |
brand | string | null | The brand, up to 100 characters. |
Returns POST → 201 { "product" }, PATCH → 200 { "product" }, as Meta took it. 409 sku_taken: another product has that SKU. 409 sku_locked: the SKU can’t change now.
POST /catalog/images
JSON body, admin keys. Fliok downloads the picture once and keeps it in your workspace. Takes an `Idempotency-Key` header.
| Field | Type | What it is |
|---|---|---|
urlrequired | string | A public https:// address of a JPG or PNG, up to 8 MB. Redirects are followed, at most three. |
Returns 201 { "imageKey", "contentType", "size" }. 400 url_not_allowed for a private or internal address, 413 for a file over 8 MB, 415 when it isn’t a JPG or PNG.
PATCH /catalog/settings
JSON body, admin keys. Send one or both.
| Field | Type | What it is |
|---|---|---|
catalogVisible | boolean | Show the catalog on your WhatsApp profile. |
cartEnabled | boolean | Let customers put products in a cart and send it to you. |
Returns 200 { "ok": true, "catalogVisible", "cartEnabled" }. 502 { "ok": false, "problems" } when Meta refused it for a number; then nothing is saved.
POST /catalog/products/sync · POST /catalog/import · POST /catalog/link
No body, admin keys. Import takes an `Idempotency-Key` header.
| Field | Type | What it is |
|---|
Returns Sync → { "synced", "failed", "remaining" }. Import → { "imported", "updated", "skipped", "truncated" }. Link → { "ok", "linked", "problems" }. 409 no_catalog when no catalog is chosen yet; 502 meta_error when Meta refused.
POST /catalog/send
JSON body, agent keys with messages:send. Takes an `Idempotency-Key` header.
| Field | Type | What it is |
|---|---|---|
conversationIdrequired | uuid | The WhatsApp chat (GET /conversations). |
kindrequired | string | product (exactly one product), product_list (several products) or catalog (the whole catalog). |
productIds | uuid[] | The products, in the order the customer sees them, up to 30. Each must be in Meta’s catalog. For catalog, the first one is the thumbnail. |
header | string | product_list only, and required for it: the title, up to 60 characters. |
body | string | The message text. Required for product_list and catalog. |
footer | string | A short line under the message. |
replyTo | string | The WhatsApp message id (wamid) this answers. |
Returns 200 { "ok": true, "messageId" }. The message is queued; delivery comes as message.status webhooks. 422 outside_24h_window, 409 contact_opted_out, product_not_synced, catalog_not_linked or product_messages_need_cloud_api, 402 when the plan’s messages are used up.
Examples
Add a product with its picture
curl -X POST https://fliok.com/api/v1/catalog/images \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "url": "https://cdn.mithaighar.in/kaju-katli-500g.jpg" }'
curl -X POST https://fliok.com/api/v1/catalog/products \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: kaju-katli-500g" \
-d '{
"name": "Kaju katli (500 g)",
"price": "649",
"currency": "INR",
"imageKey": "catalog/7c1e…/4b2d9f0e-….jpg",
"retailerId": "KK-500",
"description": "Made fresh every morning with pure ghee.",
"url": "https://mithaighar.in/kaju-katli"
}'// 201 Created — POST /catalog/images
{ "imageKey": "catalog/7c1e…/4b2d9f0e-….jpg", "contentType": "image/jpeg", "size": 184213 }
// 201 Created — POST /catalog/products: pushed to Meta at once
{
"product": {
"id": "5e0b7a8c-2f4d-4b1e-9c3a-7d6e5f4a3b21",
"retailerId": "KK-500",
"name": "Kaju katli (500 g)",
"description": "Made fresh every morning with pure ghee.",
"priceMinor": 64900,
"currency": "INR",
"imageUrl": "https://fliok.com/api/public/product-image/5e0b7a8c-2f4d-4b1e-9c3a-7d6e5f4a3b21?v=4b2d9f0e",
"url": "https://mithaighar.in/kaju-katli",
"availability": "in stock",
"brand": null,
"syncStatus": "synced",
"inMeta": true,
"lastError": null,
"syncedAt": "2026-10-29T06:30:04.000Z",
"createdAt": "2026-10-29T06:30:02.000Z",
"updatedAt": "2026-10-29T06:30:04.000Z"
}
}Read the catalog and change a price
curl "https://fliok.com/api/v1/catalog" -H "Authorization: Bearer wa_YOUR_API_KEY"
curl "https://fliok.com/api/v1/catalog/products?q=katli&synced=true&limit=20" \
-H "Authorization: Bearer wa_YOUR_API_KEY"
curl -X PATCH https://fliok.com/api/v1/catalog/products/5e0b7a8c-2f4d-4b1e-9c3a-7d6e5f4a3b21 \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "price": 699, "availability": "out of stock" }'// 200 OK — GET /catalog (never the token)
{
"connected": true,
"catalog": {
"id": "1187654321098765",
"name": "Mithai Ghar",
"linkedToWhatsApp": true,
"catalogVisible": true,
"cartEnabled": true,
"lastError": null,
"lastSyncAt": "2026-10-29T06:30:04.000Z"
},
"products": { "total": 42, "synced": 40, "pending": 1, "error": 1 }
}
// 200 OK — GET /catalog/products
{ "products": [ { "id": "5e0b…", "retailerId": "KK-500", "name": "Kaju katli (500 g)", "priceMinor": 64900, … } ], "nextCursor": null }
// 200 OK — PATCH: only price and stock changed, pushed to Meta again
{ "product": { "id": "5e0b…", "priceMinor": 69900, "availability": "out of stock", "syncStatus": "synced", "inMeta": true, … } }Send products into a chat
curl -X POST https://fliok.com/api/v1/catalog/send \
-H "Authorization: Bearer wa_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: diwali-box-9f1c" \
-d '{
"conversationId": "9f1c2b7e-5d1a-4c3e-9b0a-2f6d8e7c1a44",
"kind": "product_list",
"header": "Diwali sweets",
"body": "Here are this week’s boxes. Tap one to order.",
"productIds": ["5e0b7a8c-2f4d-4b1e-9c3a-7d6e5f4a3b21", "a3c9e1f2-7b6d-4e5a-8c9b-0d1e2f3a4b5c"]
}'// 200 OK — queued on the ordinary send path; delivery comes as message.status webhooks
{ "ok": true, "messageId": "0c8d6e4f-1a2b-4c3d-9e8f-7a6b5c4d3e2f" }
// 422 — the customer last wrote more than 24 hours ago
{ "error": "outside_24h_window" }Rate limits
The buckets these endpoints use. Burst is how many requests you can make back-to-back from a full bucket; sustained is how fast it refills.
| Bucket | Endpoints | Burst | Sustained |
|---|---|---|---|
| Reads | /messages · /conversations · /contacts · /templates · /phone-numbers · GET /webhooks · Instagram, LinkedIn, ads and catalog reads · GET /payment-requests/{id} | 600 | 60 / sec |
| Catalog products | POST /catalog/products · PATCH and DELETE /catalog/products/{id} | 60 | 1 / sec |
| Catalog pictures | POST /catalog/images | 30 | 1 / 2 sec |
| Catalog sync | POST /catalog/products/sync | 6 | 6 / 10 min |
| Catalog import | POST /catalog/import | 3 | 3 / 10 min |
| Product messages | POST /catalog/send (the inbox's send bucket, shared with replies sent from the dashboard) | 120 | 30 / sec |
Every limit, the RateLimit-* headers and what to do on a 429: Rate limits.