DingTalk Wiki CDC (Beta)
This topic describes how to use the DingTalk CDC (dingtalk-cdc) connector.
Background Information
Overview
The DingTalk CDC connector periodically polls the DingTalk Open Platform API to continuously capture new and updated online documents in DingTalk Wiki workspaces based on document modification time. The connector outputs metadata such as the title, URL, workspace, parent node, and update time of each document, along with the document body in Markdown format. You can also obtain the raw block structure of documents. This connector applies to scenarios such as RAG knowledge base building, document search indexing, and lakehouse content synchronization.
How It Works (Polling)
DingTalk Wiki does not provide a change event stream that can be consumed directly. DingTalk CDC implements full and incremental reads by polling the OpenAPI:
-
Each workspace is an independent read shard. If
workspace-idis not configured, the connector calls the workspace list API at the interval specified byscan.discovery.intervalto discover all workspaces visible to the operator. After it is configured, only the specified workspaces are synchronized. -
On each pull, the connector traverses the workspace node tree according to
scan.discovery.max-depthandscan.discovery.max-nodes, filters DingTalk online document nodes (type=FILEandcategory=ALIDOC), and generates the cursor position for this pull based on document modification time. -
Documents after the cursor are sorted by modification time. A single shard outputs at most
scan.prefix-sizedocuments per pull. For each changed document, the connector reads its block structure through a consistency check mechanism and renders it into a Markdown body. -
When there are no incremental changes, the connector repeats the preceding checks at the interval specified by
scan.poll-interval.
Changelog Semantics
The connector outputs a changelog with upsert semantics keyed by the primary key doc_id. The changelog contains INSERT and UPDATE_AFTER records, but does not contain UPDATE_BEFORE:
|
Scenario |
Output |
|
A document read for the first time in the full phase |
INSERT |
|
A document whose content or metadata changes in the incremental phase |
UPDATE_AFTER |
The current implementation does not detect document deletions. After a document is deleted, it no longer appears in the node list, and the connector does not output DELETE events. The corresponding row in the downstream system retains the state of the last synchronization. To clean up residual data, submit a batch job that performs an anti-join between the sink table and the source table on the primary key, and deletes the rows whose primary key no longer exists in the source table.
Supported Capabilities
|
Category |
Details |
|
Supported types |
Source table and data ingestion source |
|
Execution mode |
Streaming mode |
|
Data format |
Fixed schema. Field pruning is not supported. |
|
API types |
SQL and data ingestion YAML |
|
Synchronization objects |
DingTalk online document nodes in workspaces that the operator has permission to read (node type |
|
Startup mode |
|
|
Watermark |
Not supported |
|
Dimension tables and result tables |
Not supported |
Prerequisites
Network Requirements
A Flink job needs to access the DingTalk Open Platform API (the default domain is api.dingtalk.com). If the job is deployed in a VPC, make sure that it has Internet access. For more information, see Network connection options in the Realtime Compute for Apache Flink documentation.
Application Creation and API Authorization
Regardless of the startup mode, you must first create an application and complete API authorization on the DingTalk Open Platform.
-
Log on to the DingTalk Developer Console and create an enterprise internal application. On the Credentials and Basic Information page of the application, obtain the Client ID (AppKey) and Client Secret (AppSecret). The connector uses the AppKey and AppSecret to call
POST /v1.0/oauth2/accessTokento obtain the access token of the enterprise internal application and automatically renews the token. -
Grant the API permissions required by this connector to the application. In the developer console, go to the Permissions page of the target application, and search for and apply for the permissions listed in the following table. Some permissions require approval by an organization administrator. The connector calls the following DingTalk OpenAPI operations:
|
API |
Purpose |
Permission |
|
|
Obtains the access token of an enterprise internal application. |
Basic capability. No additional permission is required. |
|
|
Lists the workspaces visible to the operator. |
Workspace read permission |
|
|
Traverses the workspace node tree and lists child nodes. |
Workspace node read permission |
|
|
Queries node metadata. |
Workspace node read permission |
|
|
Queries document block elements. |
Enterprise storage file read permission |
Permission names are subject to the official documentation of the DingTalk Open Platform. The following table summarizes the required permissions:
|
Capability |
API |
Required permission |
Required |
|
Obtain an access token |
|
No additional permission is required. |
Yes |
|
Read the workspace list |
|
Workspace read permission |
Yes |
|
Read node lists and node metadata |
|
Workspace node read permission |
Yes |
|
Read document block content |
|
Enterprise storage file read permission |
Yes |
Operator and Workspace Data Authorization
Set operator-id to the Union ID of an enterprise member. You can obtain the Union ID by calling the Query User Details API of the DingTalk Open Platform. All API calls of the connector are made as this operator, and the visible scope is determined by the permissions of the operator:
-
The operator must have at least the View Only permission on the target workspace or document. The View/Download permission or a higher permission is also acceptable.
-
If
workspace-idis not configured for the job, the connector can discover only the workspaces visible to the operator.
DingTalk Wiki supports three permission levels: workspace level, folder level, and document level. Documents inherit the permissions of their parent directory by default. The following table describes the permission types and the minimum requirements of this connector:
|
Permission type |
Readable by this connector |
Description |
|
View Only |
Yes |
Meets the minimum read requirement. |
|
View/Download |
Yes |
Recommended. This avoids additional requirements of some APIs on download capabilities. |
|
Edit |
Yes |
Exceeds the read requirement. Granting this permission only for synchronization is not recommended. |
|
Manage |
Yes |
Exceeds the read requirement. Granting this permission only for synchronization is not recommended. |
|
No permission |
No |
The workspace or document does not appear in the synchronization results. |
Authorization methods: The workspace administrator adds the operator in Settings > Members and Permissions of the workspace. Authorization by member, department, or group is supported. You can also grant permissions to the operator in the sharing settings of a single document. New documents inherit workspace permissions by default. After you grant permissions on the whole workspace, newly added documents do not require separate configuration. The connector is a read-only pipeline and does not require any write permission.
Authorization Troubleshooting
The connector does not retry on authorization errors. It fails directly or skips the corresponding document. Troubleshoot based on the following table:
|
Error code / Symptom |
Description |
Solution |
|
|
Cross-organization access is denied. |
Make sure that the application, the operator, and the target workspace belong to the same organization. Cross-organization workspaces cannot be synchronized. |
|
|
The organization authentication level does not meet the API requirements. |
Complete enterprise verification or upgrade the authentication level in the DingTalk admin console, and then retry. |
|
Insufficient permissions (permission denied errors) |
The required permissions are not granted to the application. |
Go back to the Permissions page and check whether the workspace read permission, workspace node read permission, and enterprise storage file read permission are all granted. |
|
A workspace or document does not appear in the synchronization results |
The operator has no permission to read it. |
In Members and Permissions of the workspace, grant the operator the View Only permission or a higher permission. |
|
|
The node has been deleted or the ID is invalid. |
The connector automatically skips it. No action is required. |
|
|
The document identifier is invalid. |
This is a permanent failure and is not retried. Check the node status or contact DingTalk support. |
Limits
-
Only source tables are supported. Dimension tables, result tables, and watermarks are not supported.
-
Only DingTalk online document nodes in workspaces are synchronized (
type=FILEandcategory=ALIDOC). Other objects such as folders, sheets, and uploaded files are skipped. -
The current implementation does not detect document deletions and does not output DELETE events.
-
The
timestampstartup mode is not supported because the DingTalk OpenAPI cannot read historical document content. -
In a Flink SQL source table,
workspace-idsupports multiple comma-separated values, but all the workspaces are read into the same source table. To store each workspace in a separate table with an independent schema, use the data ingestion YAML, or create one SQL source table for each workspace. -
The YAML schema differs from the SQL schema. In the YAML schema,
blocks_jsonis a physical column controlled byscan.block.include-raw-json, andworkspace_idis NOT NULL. Choose the corresponding schema definition based on your access method. -
The incremental pipeline is based on OpenAPI polling and generates continuous API calls. The DingTalk Open Platform imposes quotas on organization-level API calls. The standard edition has a lower quota, and the dedicated edition has a higher quota. If a workspace contains many documents, configure
scan.poll-interval,scan.prefix-size, and the rate limiting parameters to control the call cost and the synchronization latency of new content. -
The process-level rate limiting parameters (
scan.discovery/metadata/content.rate-limit.requests-per-second) are shared by all clients that use the same app-key. If multiple jobs share the same application, evaluate the quota as a whole. -
contentis Markdown text rendered from the document block structure. It does not guarantee complete preservation of all rich media and structured elements. Blocks that cannot be rendered are marked with placeholder comments. If you need the raw block structure, declare theblocks_jsonMETADATA column in Flink SQL, or enablescan.block.include-raw-jsonin the data ingestion YAML to output theblocks_jsonphysical column. -
Failover recovery may output duplicate INSERT and UPDATE_AFTER records. We recommend that the downstream system perform idempotent writes based on the primary key
doc_id. -
The synchronization scope cannot be narrowed at runtime. If you reduce
workspace-idor addscan.document.exclude-node-idswhile the job is running, the change affects only the resources that are discovered later. The workspaces or documents that are already discovered are not removed from the current job. To remove them completely, stop the job and restart it without state. -
Authorization errors (
forbidden.acrossOrg,orgAuthLevelNotEnough, invalid docKey, and so on) are permanent failures. The connector does not automatically retry on them. Handle them as described in Authorization Troubleshooting.
SQL
Key Features
-
Fixed-schema source table: outputs the document title, URL, body (Markdown), and metadata, and outputs a changelog with upsert semantics keyed by the primary key
doc_id. -
Startup modes: select the read method by using
scan.startup.mode.
|
Mode |
Full read |
Incremental read |
Behavior on first startup |
|
|
Yes |
Yes |
First performs a full read of documents in scope, and then continuously polls for incremental changes. |
|
|
Yes |
No |
Performs only a full read of documents in scope and ends after completion. |
|
|
No |
Yes |
Processes only document changes that occur after the job starts. |
-
Raw block structure output: outputs the JSON text of the raw document block structure through the
blocks_jsonMETADATA column. You must also enablescan.block.include-raw-json.
Syntax
The Flink SQL DDL must declare all seven physical fields listed in the following table. The field order, names, and case must match exactly. Field names are case-sensitive. You must also declare PRIMARY KEY (doc_id) NOT ENFORCED.
|
DDL field |
Type |
Description |
|
|
STRING NOT NULL |
The document node identifier. The primary key of the source table. |
|
|
STRING |
The ID of the workspace to which the document belongs. |
|
|
STRING |
The parent node ID of the document in the workspace node tree. |
|
|
STRING |
The document title. |
|
|
STRING |
The URL of the document. |
|
|
STRING |
The document body. Markdown text rendered from the document block structure. |
|
|
TIMESTAMP_LTZ(3) |
The last modification time of the document. |
In addition, the DDL can declare the following read-only metadata by using METADATA. Metadata columns do not change the physical schema described above.
|
Metadata key |
Type |
Description |
|
|
STRING |
The JSON text of the raw document block structure. You can use it to preserve block-level structure or perform custom parsing. If you declare this column, you must also set |
CREATE TEMPORARY TABLE dingtalk_wiki_source (
doc_id STRING NOT NULL,
workspace_id STRING,
parent_node_id STRING,
title STRING,
url STRING,
content STRING,
modified_time TIMESTAMP_LTZ(3),
blocks_json STRING METADATA VIRTUAL,
PRIMARY KEY (doc_id) NOT ENFORCED
) WITH (
'connector' = 'dingtalk-cdc',
'object-type' = 'document',
'app-key' = '<yourAppKey>',
'app-secret' = '<yourAppSecret>',
'operator-id' = '<yourOperatorUnionId>',
'workspace-id' = '<yourWorkspaceId>',
'scan.startup.mode' = 'initial',
'scan.block.include-raw-json' = 'true'
);
WITH Parameters
|
Parameter |
Description |
Data type |
Required |
Default value |
Remarks |
|
connector |
The table type. |
String |
Yes |
None |
Fixed value: |
|
object-type |
The type of object to synchronize. |
String |
Yes |
None |
Only |
|
app-key |
The Client ID (AppKey) of the DingTalk enterprise internal application. It is used to obtain the access token. |
String |
Yes |
None |
None. |
|
app-secret |
The Client Secret (AppSecret) of the DingTalk enterprise internal application. |
String |
Yes |
None |
None. |
|
operator-id |
The Union ID of the operator. This user must have permission to read the documents to be synchronized. |
String |
Yes |
None |
You can obtain it by calling the Query User Details API of the DingTalk Open Platform. |
|
endpoint |
The domain of the DingTalk Open Platform OpenAPI. |
String |
No |
|
None. |
|
workspace-id |
Limits the discovery scope to the specified workspaces. |
String |
No |
None |
Multiple comma-separated values are supported. Note
If not configured, all workspaces visible to the operator are automatically discovered. We recommend that you explicitly configure |
|
scan.document.exclude-node-ids |
A list of node IDs to exclude. |
String |
No |
None |
Comma-separated. These nodes are skipped during both the discovery and pull phases. |
|
scan.discovery.max-depth |
The maximum node tree depth allowed for a single workspace polling scan. |
Integer |
No |
100 |
None. |
|
scan.discovery.max-nodes |
The maximum number of nodes allowed to be accessed in a single workspace polling scan. |
Integer |
No |
100000 |
None. |
|
scan.startup.mode |
The startup mode. |
String |
No |
initial |
Supports |
|
scan.discovery.interval |
The discovery interval of new workspaces. |
Duration |
No |
1min |
None. |
|
scan.poll-interval |
The polling interval when there are no incremental changes. |
Duration |
No |
10s |
Each poll traverses workspace node metadata and reads the body only for the prefix of changed documents sorted by modification time. |
|
scan.prefix-size |
The maximum number of documents whose body is output in a single scan of one workspace. |
Integer |
No |
100 |
None. |
|
scan.document.consistency.max-retries |
The maximum number of retries to obtain a document read with stable metadata. |
Integer |
No |
3 |
Set the value to 0 to disable retries. |
|
scan.document.fetch.max-duration |
The maximum duration allowed for one consistency content pull of a single document. |
Duration |
No |
10min |
None. |
|
scan.document.max-bytes |
The maximum number of bytes allowed for a single document, including the rendered Markdown body. |
Long |
No |
52428800 (50 MiB) |
None. |
|
scan.block.fetch-size |
The number of top-level blocks requested in a single Block API call. |
Integer |
No |
10 |
None. |
|
scan.block.max-pages |
The maximum number of Block API pages read for a single document. |
Integer |
No |
1000 |
None. |
|
scan.block.include-raw-json |
Specifies whether to output the raw block JSON through the |
Boolean |
No |
false |
You must set this parameter to true if you declare the |
|
request.timeout |
The timeout period of a single OpenAPI request. |
Duration |
No |
30s |
None. |
|
request.max-retries |
The maximum number of retries for a failed OpenAPI request. |
Integer |
No |
3 |
None. |
|
request.retry-after.max-delay |
The maximum acceptable Retry-After backoff duration. |
Duration |
No |
60s |
Requests are treated as failures when the value is exceeded. |
|
scan.discovery.rate-limit.requests-per-second |
The process-level rate limit for discovery requests (listing workspaces and nodes). |
Double |
No |
5 |
Shared by all clients that use the same app-key. |
|
scan.metadata.rate-limit.requests-per-second |
The process-level rate limit for node metadata requests. |
Double |
No |
20 |
Shared by all clients that use the same app-key. |
|
scan.content.rate-limit.requests-per-second |
The process-level rate limit for Block API requests. |
Double |
No |
10 |
Shared by all clients that use the same app-key. |
|
scan.fetch.rate-limit.requests-per-second |
The global pull rate limit. |
Double |
No |
10 |
Distributed among all subtasks of the source. |
Examples
Synchronize workspace documents in full + incremental mode and write them to a Paimon table:
CREATE TEMPORARY TABLE dingtalk_wiki_source (
doc_id STRING NOT NULL,
workspace_id STRING,
parent_node_id STRING,
title STRING,
url STRING,
content STRING,
modified_time TIMESTAMP_LTZ(3),
blocks_json STRING METADATA VIRTUAL,
PRIMARY KEY (doc_id) NOT ENFORCED
) WITH (
'connector' = 'dingtalk-cdc',
'object-type' = 'document',
'app-key' = '<yourAppKey>',
'app-secret' = '<yourAppSecret>',
'operator-id' = '<yourOperatorUnionId>',
'workspace-id' = '<yourWorkspaceId>',
'scan.startup.mode' = 'initial',
'scan.block.include-raw-json' = 'true'
);
CREATE TEMPORARY TABLE paimon_sink (
doc_id STRING,
workspace_id STRING,
parent_node_id STRING,
title STRING,
url STRING,
content STRING,
modified_time TIMESTAMP_LTZ(3)
) WITH (
'connector' = 'paimon',
...
);
INSERT INTO paimon_sink
SELECT doc_id, workspace_id, parent_node_id, title, url, content, modified_time
FROM dingtalk_wiki_source;
snapshot performs only one full read. It is suitable for content migration or one-time export:
CREATE TEMPORARY TABLE dingtalk_wiki_snapshot (
doc_id STRING NOT NULL,
workspace_id STRING,
parent_node_id STRING,
title STRING,
url STRING,
content STRING,
modified_time TIMESTAMP_LTZ(3),
PRIMARY KEY (doc_id) NOT ENFORCED
) WITH (
'connector' = 'dingtalk-cdc',
'object-type' = 'document',
'app-key' = '<yourAppKey>',
'app-secret' = '<yourAppSecret>',
'operator-id' = '<yourOperatorUnionId>',
'workspace-id' = '<yourWorkspaceId>',
'scan.startup.mode' = 'snapshot'
);
To exclude specific documents, add 'scan.document.exclude-node-ids' = '<nodeId1>,<nodeId2>' to the WITH parameters.
CDC YAML Data Ingestion
With the DingTalk CDC YAML connector, you can continuously synchronize the full and incremental changes of online documents in DingTalk Wiki workspaces to a downstream data lake or data warehouse. The type of the data ingestion connector is fixed to dingtalk-cdc.
Key Features
-
Automatic table creation: Each workspace corresponds to a table named
<workspaceId>.documents. When the connector discovers a workspace for the first time, it automatically creates the table and synchronizes the schema. -
Multi-workspace synchronization:
workspace-idsupports multiple comma-separated values. If not configured, all workspaces visible to the operator are automatically discovered, and each workspace is automatically routed to its own table. -
Raw block structure output: After you enable
scan.block.include-raw-json: true, the output schema contains theblocks_jsonphysical column.
Usage Notes
-
Data ingestion does not support the BATCH execution mode. To export all data, use the
snapshotstartup mode: the read is bounded, and the job ends automatically after the read completes in a streaming deployment. -
The full phase (snapshot shards) outputs INSERT events. The incremental phase outputs REPLACE (upsert) events. The downstream system only needs to perform idempotent writes based on the primary key
doc_id. -
Workspaces newly discovered during execution are always read in the
initialmanner: the current full content is read first, and then subsequent changes are followed. -
You cannot change
scan.block.include-raw-jsonwhen a job is restored from a checkpoint or savepoint. Otherwise, the job reports an error and refuses to start. -
Only DingTalk online document nodes are supported (
type=FILEandcategory=ALIDOC). Other objects are skipped. Document deletions are not detected. -
The connector continuously calls the DingTalk Open Platform API. Use the rate limiting parameters to control the API call costs. For more information, see the Control Synchronization Speed and API Call Costs example below.
-
app-secretis sensitive information. Reference it by using a project variable, such as${secret_values.dingtalk_app_secret}, instead of writing plaintext credentials in the job configuration. For more information, see Manage variables.
Syntax
The fixed YAML schema is as follows. The primary key is doc_id. Compared with Flink SQL, the YAML schema outputs blocks_json directly as a physical column instead of a METADATA column, and workspace_id is NOT NULL.
|
Field |
Type |
Description |
|
|
STRING NOT NULL |
The document node identifier. The primary key. |
|
|
STRING NOT NULL |
The ID of the workspace to which the document belongs. |
|
|
STRING |
The parent node ID of the document in the workspace node tree. |
|
|
STRING |
The document title. |
|
|
STRING |
The URL of the document. |
|
|
STRING |
The document body. Markdown text rendered from the document block structure. |
|
|
STRING |
The JSON text of the raw document block structure. It is output only when |
|
|
TIMESTAMP_LTZ(3) |
The last modification time of the document. |
Minimal syntax example:
source:
type: dingtalk-cdc
name: DingTalk Wiki Source
object-type: document
app-key: <yourAppKey>
app-secret: <yourAppSecret>
operator-id: <yourOperatorUnionId>
workspace-id: <yourWorkspaceId>
scan.startup.mode: initial
route:
- source-table: <yourWorkspaceId>.documents
sink-table: dingtalk_wiki.documents
sink:
type: paimon
catalog.properties.metastore: rest
catalog.properties.token.provider: dlf
catalog.properties.uri: <yourDlfCatalogEndpoint>
catalog.properties.warehouse: <yourWarehouse>
The preceding example performs a full read of documents in the specified workspace, continuously synchronizes incremental changes, and writes them to Paimon. To synchronize multiple workspaces, set workspace-id to multiple comma-separated IDs. To preserve the raw block structure, add scan.block.include-raw-json: true.
Examples
Each of the following examples is a complete configuration of a data ingestion YAML job. Copy an example and modify it based on your job scenario. For more information about the meaning and the method of obtaining app-key, app-secret, and operator-id, see Prerequisites. The source connector is compatible with all data ingestion sink connectors, such as Paimon, Hologres, and MaxCompute. For the sink configuration, see the documentation of the corresponding connector. All the following examples use Paimon.
Synchronize a Single Workspace (Full + Incremental)
The most basic usage: perform a full read of all documents in the specified workspace, and then continuously synchronize the subsequent changes. The data is written to Paimon (DLF Catalog). This mode is suitable for building a RAG index or a lakehouse content base that must stay consistent with DingTalk Wiki.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator. All API operations are called as this identity, which must have permission to read the workspaces to synchronize
workspace-id: <yourWorkspaceId> # Optional. The ID of the workspace to synchronize. If you leave this parameter empty, all workspaces visible to the operator are automatically discovered
scan.startup.mode: initial # Optional. The startup mode. Valid values: initial (default, full + incremental), snapshot (full only), and latest-offset (incremental only)
route:
# The connector automatically creates a source table named <workspaceId>.documents for each workspace,
# and you can use route to map it to a specific sink table. If you do not configure route, the data is written to the downstream as <workspaceId>.documents.
- source-table: <yourWorkspaceId>.documents # The source table. The format is fixed as <workspaceId>.documents
sink-table: dingtalk_wiki.documents # The name of the sink table, which can be changed
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server, in the format of http://<region-id>-vpc.dlf.aliyuncs.com
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
# (Optional) Enable deletion vectors to improve the read performance of downstream systems
table.properties.deletion-vectors.enabled: true
pipeline:
name: DingTalk Wiki to Paimon Pipeline # The job name
Synchronize Multiple Workspaces, One Sink Table per Workspace
A single job synchronizes multiple workspaces. The connector automatically creates a <workspaceId>.documents sink table for each workspace, which keeps the data of the workspaces separate. This mode is suitable if you want to manage and query the synchronized results by workspace.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator, which must have read permissions on all workspaces to synchronize
workspace-id: <workspaceId1>,<workspaceId2> # Optional. The IDs of multiple workspaces, separated by commas (,)
# (Optional) The discovery interval for new workspaces. Default value: 1min. If workspace-id is configured, this parameter affects only the node scan cycle of the specified workspaces
scan.discovery.interval: 1min
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
table.properties.deletion-vectors.enabled: true # (Optional) Enable deletion vectors to improve the read performance of downstream systems
# route is not configured: the two workspaces are written to the <workspaceId1>.documents and <workspaceId2>.documents sink tables
pipeline:
name: DingTalk Wikis to Paimon Pipeline # The job name
# (Optional) The parallelism of the job. Each workspace is an independent read shard. When you synchronize multiple workspaces, a higher parallelism speeds up the full read
parallelism: 2
Merge Multiple Workspaces into One Sink Table
The documents in multiple workspaces share the same schema. You can merge them into a single sink table and query the table as a whole, which is suitable for cross-workspace RAG retrieval. After the merge, use the primary key doc_id of the sink table to ensure idempotence.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator, which must have read permissions on all workspaces to synchronize
workspace-id: <workspaceId1>,<workspaceId2> # Optional. The IDs of multiple workspaces, separated by commas (,)
route:
# Point multiple route rules to the same sink table to merge multiple workspaces.
# To distinguish the source of each document, keep the workspace_id field in the sink table.
- source-table: <workspaceId1>.documents # The source table of the first workspace
sink-table: dingtalk_wiki.documents # The sink table that receives the merged data
- source-table: <workspaceId2>.documents # The source table of the second workspace
sink-table: dingtalk_wiki.documents # Written to the same table as the preceding rule
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
table.properties.deletion-vectors.enabled: true # (Optional) Enable deletion vectors to improve the read performance of downstream systems
pipeline:
name: Merge DingTalk Wikis to One Paimon Table # The job name
Automatically Discover All Workspaces
If you leave workspace-id empty, the connector periodically discovers all workspaces that are visible to the operator and automatically synchronizes them. The workspaces that are created later are also added to the synchronization scope in the next discovery cycle. This mode is suitable if the synchronization scope expands along with the workspaces of your organization.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator. The synchronization scope covers the workspaces visible to this operator
# workspace-id is not configured: all workspaces visible to the operator are automatically discovered
# (Optional) The discovery interval for new workspaces. Default value: 1min
scan.discovery.interval: 1min
# (Optional) The IDs of the document or folder nodes to exclude, separated by commas (,). The excluded nodes are skipped in both the discovery and pull phases
scan.document.exclude-node-ids: <excludeNodeId1>,<excludeNodeId2>
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
table.properties.deletion-vectors.enabled: true # (Optional) Enable deletion vectors to improve the read performance of downstream systems
pipeline:
name: Sync All DingTalk Wikis to Paimon # The job name
# (Optional) The parallelism of the job. If there are many workspaces, a higher parallelism speeds up the full read
parallelism: 4
Export All Data at Once (snapshot)
The snapshot startup mode performs a bounded read: it exports the current content of the workspaces to the downstream system in one run, and the job ends automatically when the read completes. This mode is suitable for content migration, one-time backups, and data preparation for offline analysis.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator, which must have permission to read the workspaces to synchronize
workspace-id: <yourWorkspaceId> # Optional. The ID of the workspace to export. If you leave this parameter empty, all workspaces visible to the operator are exported
scan.startup.mode: snapshot # Full read only. The job ends automatically after the read completes (bounded)
route:
- source-table: <yourWorkspaceId>.documents # The source table. The format is fixed as <workspaceId>.documents
sink-table: dingtalk_wiki.documents # The name of the sink table, which can be changed
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
pipeline:
name: DingTalk Wiki One-Time Export # The job name
Synchronize Only the Changes After the Job Starts
All existing documents are skipped, and only the documents that are added or modified after the job starts are processed. This mode is suitable if the downstream system already holds complete data and you only need to catch up on the subsequent changes.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator, which must have permission to read the workspaces to synchronize
workspace-id: <yourWorkspaceId> # Optional. The ID of the workspace to synchronize. If you leave this parameter empty, all workspaces visible to the operator are automatically discovered
scan.startup.mode: latest-offset # Skip the full phase and synchronize only the documents that change after the job starts
route:
- source-table: <yourWorkspaceId>.documents # The source table. The format is fixed as <workspaceId>.documents
sink-table: dingtalk_wiki.documents # The name of the sink table, which can be changed
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
table.properties.deletion-vectors.enabled: true # (Optional) Enable deletion vectors to improve the read performance of downstream systems
pipeline:
name: DingTalk Wiki Incremental Sync # The job name
Preserve the Raw Document Block Structure (RAG Scenarios)
The content field is Markdown text rendered from the document block structure, and it cannot preserve all rich media and structured elements. If your RAG pipeline splits documents by block or parses them in a custom way, such as tables, code blocks, and quotes, enable scan.block.include-raw-json: true. The output schema then appends the blocks_json physical column, which stores the raw block structure of the document as JSON text.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator, which must have permission to read the workspaces to synchronize
workspace-id: <yourWorkspaceId> # Optional. The ID of the workspace to synchronize
scan.startup.mode: initial # Optional. The startup mode. Default value: initial (full + incremental)
scan.block.include-raw-json: true # Optional. Appends the blocks_json physical column to the output schema, which stores the raw block structure of the document as JSON text
route:
- source-table: <yourWorkspaceId>.documents # The source table. The format is fixed as <workspaceId>.documents
sink-table: dingtalk_wiki.documents # The name of the sink table, which can be changed
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
table.properties.deletion-vectors.enabled: true # (Optional) Enable deletion vectors to improve the read performance of downstream systems
pipeline:
name: DingTalk Wiki with Raw Blocks # The job name
You cannot change scan.block.include-raw-json when a job is restored from a checkpoint or savepoint, because this parameter changes the output schema. If you change it, the job reports an error and refuses to start. Decide whether you need this column before you start the job for the first time.
Trim Synchronized Columns (Transform)
The output schema of the connector is fixed. However, you can use Transform rules to trim columns in the synchronization pipeline, so that only the columns that the downstream system requires are written to the result table, which reduces storage costs. The primary key doc_id must be kept in the projection.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator, which must have permission to read the workspaces to synchronize
workspace-id: <yourWorkspaceId> # Optional. The ID of the workspace to synchronize
transform:
- source-table: <yourWorkspaceId>.documents # The source table of the workspace to which the transform rule applies
# Projection: keeps only the fields required by the RAG index and drops the columns that are not required, such as parent_node_id. The primary key doc_id must be kept.
projection: doc_id, workspace_id, title, url, content, modified_time
description: keep only fields required by the RAG index
route:
- source-table: <yourWorkspaceId>.documents # The source table. The format is fixed as <workspaceId>.documents
sink-table: dingtalk_wiki.documents # The name of the sink table, which can be changed
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
pipeline:
name: DingTalk Wiki to Paimon with Transform # The job name
Control Synchronization Speed and API Call Costs
The DingTalk Open Platform imposes quotas on organization-level API calls. The standard edition has a lower quota. If your organization has many workspaces or the documents are updated frequently, you can use the following parameters to reduce the call frequency, or to control the API costs within an acceptable synchronization latency for new content. Increasing these parameters instead speeds up the synchronization.
source:
type: dingtalk-cdc # Fixed value. The type of the DingTalk Wiki CDC connector
name: DingTalk Wiki Source # The source name
object-type: document # Required. The type of the object to synchronize. Only document is supported
app-key: <yourAppKey> # Required. The Client ID (AppKey) of the DingTalk internal app
app-secret: <yourAppSecret> # Required. The Client Secret (AppSecret) of the DingTalk internal app
operator-id: <yourOperatorUnionId> # Required. The union ID of the operator, which must have permission to read the workspaces to synchronize
workspace-id: <yourWorkspaceId> # Optional. The ID of the workspace to synchronize
# (Optional) The polling interval when no incremental changes occur. Default value: 10s. A larger value reduces API calls during idle periods, at the cost of a higher synchronization latency for new content
scan.poll-interval: 30s
# (Optional) The maximum number of documents whose content a single workspace emits in one scan. Default value: 100. A larger value synchronizes more changed documents in each round
scan.prefix-size: 100
# (Optional) The following three rate limiting parameters are process-level and shared by all jobs that use the same app-key. Evaluate them against the API quota of your organization
# The rate limit on the discovery requests that list workspaces and nodes. Default value: 5 QPS
scan.discovery.rate-limit.requests-per-second: 5
# The rate limit on the requests that resolve node metadata. Default value: 20 QPS
scan.metadata.rate-limit.requests-per-second: 20
# The rate limit on the Block API requests that read document content. Default value: 10 QPS
scan.content.rate-limit.requests-per-second: 10
route:
- source-table: <yourWorkspaceId>.documents # The source table. The format is fixed as <workspaceId>.documents
sink-table: dingtalk_wiki.documents # The name of the sink table, which can be changed
sink:
type: paimon # The type of the sink. This example writes data to Paimon
catalog.properties.metastore: rest # The metastore type. Fixed value rest for DLF
catalog.properties.token.provider: dlf # The token provider. Fixed value dlf for DLF
catalog.properties.uri: <yourDlfCatalogEndpoint> # The endpoint of the DLF Rest Catalog Server
catalog.properties.warehouse: <yourWarehouse> # The name of the DLF catalog
pipeline:
name: DingTalk Wiki Rate-Limited Sync # The job name
Configuration Parameters
|
Parameter |
Description |
Data type |
Required |
Default value |
Remarks |
|
type |
The connector type. |
String |
Yes |
None |
Fixed value: |
|
object-type |
The type of object to synchronize. |
String |
Yes |
None |
Only |
|
app-key |
The Client ID (AppKey) of the DingTalk enterprise internal application. |
String |
Yes |
None |
None. |
|
app-secret |
The Client Secret (AppSecret) of the DingTalk enterprise internal application. |
String |
Yes |
None |
None. |
|
operator-id |
The Union ID of the operator. This user must have permission to read the documents to be synchronized. |
String |
Yes |
None |
None. |
|
endpoint |
The domain of the DingTalk Open Platform OpenAPI. |
String |
No |
|
None. |
|
workspace-id |
A comma-separated list of workspace IDs. |
String |
No |
None |
If not configured, all workspaces visible to the operator are automatically discovered. |
|
scan.document.exclude-node-ids |
A list of node IDs to exclude. |
String |
No |
None |
Comma-separated. These nodes are skipped during both the discovery and pull phases. |
|
scan.discovery.max-depth |
The maximum node tree depth allowed for a single workspace polling scan. |
Integer |
No |
100 |
None. |
|
scan.discovery.max-nodes |
The maximum number of nodes allowed to be accessed in a single workspace polling scan. |
Integer |
No |
100000 |
None. |
|
scan.startup.mode |
The startup mode. |
String |
No |
initial |
Supports |
|
scan.discovery.interval |
The discovery interval of new workspaces. |
Duration |
No |
1min |
None. |
|
scan.poll-interval |
The polling interval when there are no incremental changes. |
Duration |
No |
10s |
None. |
|
scan.prefix-size |
The maximum number of documents whose body is output in a single scan of one workspace. |
Integer |
No |
100 |
None. |
|
scan.document.consistency.max-retries |
The maximum number of retries to obtain a document read with stable metadata. |
Integer |
No |
3 |
Set the value to 0 to disable retries. |
|
scan.document.fetch.max-duration |
The maximum duration allowed for one consistency content pull of a single document. |
Duration |
No |
10min |
None. |
|
scan.document.max-bytes |
The maximum number of bytes allowed for a single document, including the rendered Markdown body. |
Long |
No |
52428800 (50 MiB) |
None. |
|
scan.block.fetch-size |
The number of top-level blocks requested in a single Block API call. |
Integer |
No |
10 |
None. |
|
scan.block.max-pages |
The maximum number of Block API pages read for a single document. |
Integer |
No |
1000 |
None. |
|
scan.block.include-raw-json |
Specifies whether to include the |
Boolean |
No |
false |
This configuration cannot be changed when the job is restored. |
|
request.timeout |
The timeout period of a single OpenAPI request. |
Duration |
No |
30s |
None. |
|
request.max-retries |
The maximum number of retries for a failed OpenAPI request. |
Integer |
No |
3 |
None. |
|
request.retry-after.max-delay |
The maximum acceptable Retry-After backoff duration. |
Duration |
No |
60s |
Requests are treated as failures when the value is exceeded. |
|
scan.discovery.rate-limit.requests-per-second |
The process-level rate limit for discovery requests. |
Double |
No |
5 |
Shared by all clients that use the same app-key. |
|
scan.metadata.rate-limit.requests-per-second |
The process-level rate limit for node metadata requests. |
Double |
No |
20 |
Shared by all clients that use the same app-key. |
|
scan.content.rate-limit.requests-per-second |
The process-level rate limit for Block API requests. |
Double |
No |
10 |
Shared by all clients that use the same app-key. |
|
scan.fetch.rate-limit.requests-per-second |
The global pull rate limit. |
Double |
No |
10 |
Distributed among all subtasks of the source. |