Kingdee Cloud Sales Order (executeBillQuery) API Field Handbook Tutorial
What This API Solves
In Kingdee Cloud to CRM integration scenarios, we frequently need to pull sales order master data from Kingdee into a middle platform for linking orders with opportunities/contracts, status callbacks, reconciliation, and sales funnel calculation. Kingdee's executeBillQuery WebAPI is the standard entry for querying the business object form SAL_SaleOrder. It supports incremental pulls of approved orders by approval date. After scheduled extraction, data lands in Qeasy for downstream mapping, acting as the "water source" of the order integration pipeline.
API Capability Overview
- Authentication: Kingdee Cloud WebAPI using app secret + tenant credentials with signature; private deployments typically go through an internal gateway.
- Request:
POST executeBillQuery, form ID fixed asSAL_SaleOrder. - Response: Standard JSON array; each record contains fields declared in
FieldKeys. Primary key and bill number are exposed via metadata asidandnumber. - Pagination/Incremental: Combine
Limit(page size),StartRow(start index), andTopRowCount(total count) for pagination. Incremental conditions are hardcoded into the filter expression, e.g.,FApproveDate >= last_sync_time and FDocumentStatus = 'C'. - Schedule: Typical cron is
*/5 7-23 * * *, i.e., every 5 minutes from 07:00 to 23:59, avoiding nightly archive windows.
Typical Field Mapping
| Field | Type | Meaning | Practical Notes |
|---|---|---|---|
| FID | string | Sales order primary key, exposed as id in metadata | Anchor for cross-system reconciliation; must be used for incremental deduplication |
| FBillNo | string | Bill number, exposed as number in metadata | Most common human-readable identifier; recommended for mapping with CRM order numbers |
| FDate | string | Business date | Returned as string; unify timezone and date format before persistence |
| FCustId.FNumber | string | Customer code | Must be explicitly added to FieldKeys; not returned by default |
| FSaleOrgId.FName | string | Sales organization | Used to split data by branch in multi-org scenarios |
| FDocumentStatus | string | Document status | 'C' means approved; core condition for incremental filter |
| FApproveDate | string | Approval date | Time anchor for incremental sync; use server time |
How to Configure in Qeasy
In the Qeasy integration platform, this API is typically wrapped by a Kingdee Cloud adapter that ships with an executeBillQuery template. We just select form SAL_SaleOrder in the Source configuration, set the filter expression and FieldKeys, and the platform handles signing, pagination, and checkpoint resumption automatically. If the Target is set to "Write Empty Operation," the strategy degrades to a pure query, landing data into Qeasy's intermediate storage for downstream strategies. Qeasy's field mapper automatically exposes FID as id and FBillNo as number based on metadata, ready for cross-system mapping.
Cross-Project Practical Points
- Use approval date, not creation date: Incremental field must be
FApproveDate, notFDate, otherwise re-approved orders after un-approval will be missed. FDocumentStatus = 'C'is a hard constraint: Unapproved orders have incomplete fields; syncing them pollutes downstream data.- Add fields on demand to FieldKeys: Only FID/FBillNo/FDate are returned by default; customer, material, amount must be explicitly declared in
FieldKeys, otherwise returned empty. - Combine pagination with incremental logic: Recommend Limit 2000–5000; use TopRowCount to decide if more pages are needed; checkpoint resumption relies on
StartRow+ last max FID. - Schedule away from archive windows: Every 5 minutes from 07:00–23:00 is an empirical value; running during nightly archive will trigger table locks.
- Use FBillNo as cross-system correlation key: FBillNo is more business-friendly than FID and can serve as the order number field on the CRM side.
Pitfall Retrospective
- Filter condition overwritten: In one retail project,
FApproveDate >= last_sync_timewas mistakenly placed insideFieldKeys, causing Kingdee errors. The safe approach is to put it in the filter expression, not the field list. - Timezone offset causing data loss: Server timezones differed between Kingdee and Qeasy; without timezone conversion, orders crossing midnight were missed. Always unify to UTC or explicitly mark timezone.
- Unapproved orders leaked in: After a strategy change,
FDocumentStatus='C'was forgotten, pulling in draft orders and causing reconciliation errors downstream. Add a pre-filter in Qeasy as a safety net. - Pagination infinite loop:
StartRowwas not incremented per page, so the same batch was repeatedly fetched. Always writeStartRow += Limitcorrectly in the pagination loop. - Wrong case in FieldKeys: Kingdee field names are case-sensitive; writing
fbillnosilently returns empty, easy to miss during troubleshooting.
When to Use
This API is suitable for private-deployment integration scenarios where Kingdee is the sole order source and approved sales orders need to be pushed to CRM/BI/middle platforms. It is not suitable for legacy Kingdee versions without WebAPI, lightweight queries that don't need order details, or complex reconciliation scenarios requiring bi-directional real-time writes.