API Reference
Catalog & Knowledge
Keep the account's catalog and knowledge base in step with your own system. The WhatsApp assistant answers prices, availability and questions from this data.
catalog:read / catalog:write or knowledge:read / knowledge:write. A legacy null credential is denied. The account's plan must include the catalog API, otherwise the answer is 403 feature_disabled.
How to sync
Send your records with your own external_id to the bulk upsert (up to 500 per call). A record that exists is updated; one that did not change answers unchanged and is not written again. Fields of the account's item types (for example nationality and age on a CV) go in field_values; read their keys from GET /catalog/schema. category_path finds or creates up to three category levels by name.
Webhooks: catalog.item.*, catalog.category.* and knowledge.entry.* fire for single changes made in the panels or through these routes. A bulk upsert sends one catalog.items.bulk_upserted (or knowledge.entries.bulk_upserted) event, and a data source run sends one data_source.sync.finished or data_source.sync.failed. The account's plan must include catalog webhooks.
Schema and categories
/catalog/schema
catalog:read
https://staging-mobile.washeej.com/v1/catalog/schema
Item types and their custom fields (keys, labels, field type, options). Use the keys in field_values.
curl -H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
https://staging-mobile.washeej.com/v1/catalog/schema
/catalog/categories
catalog:read
https://staging-mobile.washeej.com/v1/catalog/categories
All categories (flat list with parent_id).
curl -H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
https://staging-mobile.washeej.com/v1/catalog/categories
/catalog/categories
catalog:write
https://staging-mobile.washeej.com/v1/catalog/categories
Create a category. name or name_ar is required; parent_id makes it a subcategory.
| Parameter | Type | Required | Description |
|---|---|---|---|
name
|
string | optional | English name (or name_ar). |
name_ar
|
string | optional | Arabic name. |
parent_id
|
integer | optional | Parent category id. |
external_id
|
string | optional | Your id for the category. |
curl -X POST https://staging-mobile.washeej.com/v1/catalog/categories \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"name":"Oils","name_ar":"زيوت"}'
Common errors:
validation_error, feature_disabled
/catalog/categories/{id}
catalog:write
https://staging-mobile.washeej.com/v1/catalog/categories/{id}
Update a category (only the fields sent).
curl -X PATCH https://staging-mobile.washeej.com/v1/catalog/categories/12 \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"status":false}'
/catalog/categories/{id}
catalog:write
https://staging-mobile.washeej.com/v1/catalog/categories/{id}
Delete a category. Its items stay without a category; its subcategories move up one level.
curl -X DELETE https://staging-mobile.washeej.com/v1/catalog/categories/12 \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET"
Items
/catalog/items/bulk-upsert
catalog:write
https://staging-mobile.washeej.com/v1/catalog/items/bulk-upsert
Create or update up to 500 items by external_id in one call. Each item is checked on its own; the answer has one result per item (created, updated, unchanged, failed with errors). Sends one catalog.items.bulk_upserted webhook, not one per item.
| Parameter | Type | Required | Description |
|---|---|---|---|
items
|
array | required | 1-500 item objects (same fields as POST /catalog/items), each with external_id. |
curl -X POST https://staging-mobile.washeej.com/v1/catalog/items/bulk-upsert \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"items":[{"external_id":"SKU-1","name":"Olive oil 1L","price":45},{"external_id":"SKU-2","name":"Ghee 500g","price":30}]}'
Common errors:
validation_error, feature_disabled
/catalog/items
catalog:read
https://staging-mobile.washeej.com/v1/catalog/items
List items. Filters: category_id, external_id, item_type (key), status (true/false), search, updated_since (ISO date), per_page (1-100).
curl -H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
"https://staging-mobile.washeej.com/v1/catalog/items?updated_since=2026-10-29T00:00:00Z&per_page=50"
/catalog/items/{id}
catalog:read
https://staging-mobile.washeej.com/v1/catalog/items/{id}
Show one item with its type, field values, media and tags.
curl -H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
https://staging-mobile.washeej.com/v1/catalog/items/345
/catalog/items
catalog:write
https://staging-mobile.washeej.com/v1/catalog/items
Create an item. name or name_ar is required. category_path (up to 3 names) finds or creates the category tree. field_values are checked against the item type (see /catalog/schema).
| Parameter | Type | Required | Description |
|---|---|---|---|
name
|
string | optional | English name (or name_ar). |
price
|
number | optional | Price; currency defaults to SAR. |
type
|
string | optional | product (default) or service. |
availability
|
string | optional | in_stock (default), out_of_stock, on_request. |
category_path
|
array | optional | Category names from top to bottom, e.g. ["Oils","Olive"]. Or category_id. |
item_type
|
string | optional | Item type key from /catalog/schema (or item_type_id). |
field_values
|
object | optional | Custom field values by field key. |
external_id
|
string | optional | Your id; unique among the items you send. |
media
|
array | optional | Up to 20 {url, kind: image|video|file, caption}. |
tags
|
array | optional | Up to 30 tags. |
curl -X POST https://staging-mobile.washeej.com/v1/catalog/items \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"external_id":"SKU-1","name":"Olive oil 1L","price":45,"category_path":["Oils","Olive"],"stock":12}'
Common errors:
validation_error, duplicate_external_id, feature_disabled
/catalog/items/{id}
catalog:write
https://staging-mobile.washeej.com/v1/catalog/items/{id}
Update an item (only the fields sent).
curl -X PATCH https://staging-mobile.washeej.com/v1/catalog/items/345 \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"price":49,"availability":"out_of_stock"}'
/catalog/items/{id}
catalog:write
https://staging-mobile.washeej.com/v1/catalog/items/{id}
Delete an item.
curl -X DELETE https://staging-mobile.washeej.com/v1/catalog/items/345 \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET"
Knowledge base
/knowledge/entries/bulk-upsert
knowledge:write
https://staging-mobile.washeej.com/v1/knowledge/entries/bulk-upsert
Create or replace up to 500 entries by external_id (title and content required for each). One result per entry; one knowledge.entries.bulk_upserted webhook.
curl -X POST https://staging-mobile.washeej.com/v1/knowledge/entries/bulk-upsert \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"entries":[{"external_id":"faq-1","title":"Hours","content":"9am to 9pm"}]}'
/knowledge/entries
knowledge:read
https://staging-mobile.washeej.com/v1/knowledge/entries
List knowledge base entries (what the assistant answers from). Filters: type, tag, search, per_page.
curl -H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
https://staging-mobile.washeej.com/v1/knowledge/entries
/knowledge/entries
knowledge:write
https://staging-mobile.washeej.com/v1/knowledge/entries
Create an entry: title, content, type (faq, policy, price, offer, note…), tags, priority, valid_from, valid_until, external_id.
curl -X POST https://staging-mobile.washeej.com/v1/knowledge/entries \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"title":"Delivery","content":"Free delivery inside Riyadh.","type":"policy"}'
Common errors:
validation_error, duplicate_external_id, feature_disabled
/knowledge/entries/{id}
knowledge:write
https://staging-mobile.washeej.com/v1/knowledge/entries/{id}
Update an entry (only the fields sent).
curl -X PATCH https://staging-mobile.washeej.com/v1/knowledge/entries/9 \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
-H "Content-Type: application/json" \
-d '{"is_active":false}'
/knowledge/entries/{id}
knowledge:write
https://staging-mobile.washeej.com/v1/knowledge/entries/{id}
Delete an entry.
curl -X DELETE https://staging-mobile.washeej.com/v1/knowledge/entries/9 \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET"
Data sources
Files, Google Sheets, APIs and WooCommerce stores connected in the panel. Ask for a run right after your data changed instead of waiting for the schedule.
/data-sources
catalog:read
https://staging-mobile.washeej.com/v1/data-sources
The account's data sources (files, Google Sheets, APIs, WooCommerce) with their last run. Connection details are never returned.
curl -H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET" \
https://staging-mobile.washeej.com/v1/data-sources
/data-sources/{id}/sync
catalog:write
https://staging-mobile.washeej.com/v1/data-sources/{id}/sync
Run a data source now (for example right after your system changed). Answers 202 with the queued run; 409 when a run is already in progress or the mapping is not saved yet.
curl -X POST https://staging-mobile.washeej.com/v1/data-sources/3/sync \
-H "client-id: YOUR_CLIENT_ID" \
-H "client-secret: YOUR_CLIENT_SECRET"
Common errors:
not_runnable, not_found, feature_disabled