BE Merchants. Deals Products (1.0.0)
Download OpenAPI specification:Download
Billease Deals. Product Sync API
Documentation: https://docs.billease.ph/
Keeps your product catalog in sync with the Billease Deals catalog. This API is implemented on the Billease side and called by you.
It is a standalone API, separate from the Transactions API: it belongs to a different
service (be-store-admin, not be-transactions), has its own base URL, and is used only by
Deals partners. Your static JWT is scoped to both.
Sync is push-only and partner-initiated. There is no scheduled pull; catalog data moves
only when you call POST /products/sync.
1.0.0 - Initial release
Sync products
The single entry point for keeping your catalog in sync with ours. Call it whenever your
catalog changes. Each affected product is one entry in products, and each entry is
resolved independently.
How the operation is determined
There is no operation field; we infer it from the fields present:
| Operation | What you send | Applied |
|---|---|---|
| New product | The complete product object, with an id we have not seen before |
Pending Billease approval |
| Update | id + only the fields to change, and no status |
Instantly if the only change is in_stock; otherwise pending approval |
| Archive | id + status: 2, nothing else |
Instantly |
| Unarchive | id + status: 1, nothing else |
Instantly |
Only status values 1 and 2 may be sent; anything else is rejected with 400.
Approval model
New products, and any edit other than a pure stock-count change, create a pending version. The currently-active version stays live until Billease approves the pending one. Stock changes, archives and unarchives bypass approval and take effect immediately.
Poll GET /products to see what we currently hold, including anything still pending.
Update semantics
On an update an absent field means "leave unchanged"; an explicit null means
"clear this field". Configure your JSON serializer to omit unset fields; one that emits
null for unset fields will erase catalog data. To replace the image set, send the complete
image_url array.
Batch size
At most 1000 entries per call. Larger batches are rejected with 413.
Authorizations:
Request Body schema: application/json
Shop and merchant identifiers plus one or more product operations
| shop_code required | string <uuid> Shop UUID code. Issued by Billease at onboarding; different per environment. |
| mer_code required | string <uuid> Merchant UUID code. Issued by Billease at onboarding; different per environment. |
required | Array of objects (Root Type for prdProduct) [ 1 .. 1000 ] items One or more product operations, max 1000. Each entry is resolved independently; the fields present determine the operation. |
Responses
Request samples
- Payload
{- "shop_code": "3c9b1f2a-7d5e-4c11-8a6f-2b9d0e7c1a42",
- "mer_code": "8f1c2b7a-3e5d-4c11-9a6f-2b9d0e7c1b13",
- "products": [
- {
- "id": "1000001",
- "in_stock": 12
}, - {
- "id": "1000002",
- "name": "Acme Tab 11 Wi-Fi 128GB"
}, - {
- "id": "1000003",
- "status": 2
}, - {
- "id": "1000004",
- "status": 1
}
]
}Response samples
- 202
- 400
- 401
- 403
- 404
- 409
- 413
- 422
- 429
- 500
{- "results": [
- {
- "id": "1000001",
- "sku": 50231,
- "operation": "update",
- "applied": "instant"
}, - {
- "id": "1000002",
- "sku": 50232,
- "operation": "update",
- "applied": "pending_approval"
}, - {
- "id": "1000003",
- "sku": 50233,
- "operation": "archive",
- "applied": "instant"
}, - {
- "id": "1000004",
- "sku": 50234,
- "operation": "unarchive",
- "applied": "instant"
}
]
}Get products
Returns what we currently hold for your shop, so you can detect drift and see the outcome of anything awaiting approval.
This is the only way to observe status 3 (Pending) and 4 (Rejected); the sync response
tells you a pending version was created, not what happened to it afterwards.
Authorizations:
query Parameters
| shop_code required | string <uuid> Your shop UUID |
| status | integer Enum: 1 2 3 4 Filter by status. Omit for all. |
| page | integer Default: 1 Page number, 1-based |
| per_page | integer Default: 50 Items per page, max 200 |
Responses
Response samples
- 200
- 401
- 500
{- "pages": {
- "page": 1,
- "per_page": 50,
- "total": 2
}, - "products": [
- {
- "id": "1000001",
- "sku": 50231,
- "name": "Acme Phone X 128GB Midnight",
- "category": "Mobile phone",
- "deals_price": 27999,
- "retail_price": 33999,
- "in_stock": 12,
- "status": 1,
- "updated": "2026-08-08T10:14:02+08:00"
}, - {
- "id": "1000002",
- "sku": 50232,
- "name": "Acme Tab 11 Wi-Fi 128GB",
- "category": "Tablet",
- "deals_price": 18999,
- "retail_price": 21999,
- "in_stock": 40,
- "status": 3,
- "updated": "2026-08-09T09:02:44+08:00"
}
]
}Get categories
The categories we recognize and, for each, the device-spec keys allowed inside device.
Both are case-sensitive. Read this at build time rather than hardcoding the list; it
changes without a version bump.
Device keys outside a category's list are not recognized and are dropped; the rest of the
product is stored and the batch is not rejected. An unrecognized category, however, rejects
the whole POST /products/sync call with 400.
Authorizations:
Responses
Response samples
- 200
- 401
{- "categories": [
- {
- "category": "Mobile phone",
- "device_keys": [
- "device_brand",
- "device_color",
- "device_camera",
- "device_display",
- "device_processor",
- "device_memory",
- "device_storage",
- "device_os"
]
}, - {
- "category": "Vouchers",
- "device_keys": [
- "device_brand",
- "device_merchant"
]
}
]
}