Import Selected Pages
Imports pages from a crawl preview into documents and returns the same run, now queued to import. Poll Get Source Run with the same id until state is completed, failed, or canceled.
The pages are imported from what the preview staged, without crawling again.
When the run completes, these pages become the source’s page list. Each import sets the whole list, so include every page you want the source to keep.
For the preview-and-import flow, see Import Website Pages.
curl --request POST \
--url https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"pageIds": [
"0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f",
"5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f"
]
}
'import requests
url = "https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection"
payload = { "pageIds": ["0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f", "5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f"] }
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
pageIds: [
'0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f',
'5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f'
]
})
};
fetch('https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'pageIds' => [
'0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f',
'5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection"
payload := strings.NewReader("{\n \"pageIds\": [\n \"0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f\",\n \"5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"pageIds\": [\n \"0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f\",\n \"5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"pageIds\": [\n \"0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f\",\n \"5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"canceled_at": null,
"checkpoint": "selection-frozen",
"completed_at": null,
"created_at": "2026-10-20T10:00:00Z",
"cursor": null,
"execution_attempts": 1,
"failure": null,
"id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
"kind": "crawl-preview",
"knowledge_space_id": "0a9d3c2e-5b6f-4e1a-8c7d-2f3e4a5b6c7d",
"last_error_code": null,
"max_execution_attempts": 5,
"progress_completed": 0,
"progress_failed": 0,
"progress_skipped": 0,
"progress_total": 2,
"source_id": "6f1c2b0e-3d0b-4a5e-9f4c-1c0e6a7b8d90",
"state": "queued",
"updated_at": "2026-10-20T10:06:30Z"
}Authorizations
Every request authenticates with an API key: Authorization: Bearer {API_KEY}. App endpoints take an app API key; knowledge endpoints take a knowledge base API key (Get Started).
Keep keys server-side; never embed them in client code. Requests with a missing or invalid key fail with HTTP 401 (unauthorized).
Headers
Repeating the same key and page set returns the run instead of importing again. Once the run has a selection, any other key or page set answers 409. Use printable ASCII characters without leading or trailing whitespace.
8 - 255Path Parameters
Knowledge base ID: the last segment of the Service API endpoint shown in the knowledge base's API Access dialog (…/knowledge-fs/spaces/<knowledge base ID>), and the segment after /datasets/new/ in the address bar.
Run ID of a crawl preview whose state is preview_ready: id from Preview Website Crawl.
Body
page_id values from List Crawl Preview Pages. Duplicates are collapsed.
1 - 200 elements1 - 128Response
The same run, queued, with progress_total set to the number of distinct pages.
When the run was canceled. null unless state is canceled.
Last step the run reached: queued, provider-read, preview-staged, selection-frozen, materialized, cleanup-staging, or source-committed. Retry Source Run starts the run over whatever its checkpoint.
When the run ended (completed, zero_results, failed, or canceled), ISO 8601. null while it runs.
Creation time, ISO 8601.
Provider cursor the run resumes from. null when the run has not paged.
Times a worker has picked up the run, including after Retry Source Run, which does not reset it.
Error details when state is failed. stage is the run's checkpoint at the failure, and traceId is the run ID. null otherwise.
Show child attributes
Show child attributes
Run ID. Pass it to Get Source Run, Cancel Source Run, or Retry Source Run.
What the run does:
sync: started by Sync Source, Update Source, a schedule, or Dify.crawl-preview: started by Preview Website Crawl. It keeps this kind while Import Selected Pages imports from it.crawl-import: started by Import Website Pages.online-document-import,online-drive-import: started by Import Source Items.
Dify also starts previews and imports when a source is added or edited there.
Internal ID of the knowledge base. Not the knowledge base ID in the path.
failure.code when state is failed. null otherwise.
Limit on execution_attempts. Once it is reached, Retry Source Run answers 409.
Items finished, including unchanged items a sync checked.
Always 0 for source runs: a failing item fails the whole run.
Always 0 for source runs.
Items the run expects to process: the pages or items an import requested, the pages a crawl preview has staged so far, or the source's items once a sync has listed them. null until known.
While an Import Website Pages run crawls its URLs, progress_completed and progress_total both count the pages crawled so far. Once every URL is crawled, they restart at 0 of the number of URLs.
Source the run belongs to.
Progress of the run.
Live states:
queued: waiting for a workercrawling: a crawl preview is fetching pagespreview_ready: a crawl preview is waiting for Import Selected Pages or Cancel Source Runimporting: importing and indexing itemssyncing: refreshing the source's documents
Terminal states:
completed: every item was imported or refreshed, indexed, and made activezero_results: a crawl preview found no pagesfailed: seefailurecanceled
After failed or canceled, Retry Source Run runs it again, and Sync Source starts a new sync.
Last change, ISO 8601.
Was this page helpful?
curl --request POST \
--url https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"pageIds": [
"0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f",
"5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f"
]
}
'import requests
url = "https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection"
payload = { "pageIds": ["0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f", "5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f"] }
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
pageIds: [
'0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f',
'5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f'
]
})
};
fetch('https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'pageIds' => [
'0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f',
'5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection"
payload := strings.NewReader("{\n \"pageIds\": [\n \"0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f\",\n \"5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"pageIds\": [\n \"0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f\",\n \"5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://{api_base_url}/knowledge-fs/spaces/{knowledge_base_id}/source-workflows/{run_id}/selection")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"pageIds\": [\n \"0b6e9a1f3c5d7e9f1a3b5c7d9e1f3a5b7c9d1e3f5a7b9c1d3e5f7a9b1c3d5e7f\",\n \"5e0f9a6c2b8d4e1f7a3c9b5d1e7f3a9c5b1d7e3f9a5c1b7d3e9f5a1c7b3d9e5f\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"canceled_at": null,
"checkpoint": "selection-frozen",
"completed_at": null,
"created_at": "2026-10-20T10:00:00Z",
"cursor": null,
"execution_attempts": 1,
"failure": null,
"id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
"kind": "crawl-preview",
"knowledge_space_id": "0a9d3c2e-5b6f-4e1a-8c7d-2f3e4a5b6c7d",
"last_error_code": null,
"max_execution_attempts": 5,
"progress_completed": 0,
"progress_failed": 0,
"progress_skipped": 0,
"progress_total": 2,
"source_id": "6f1c2b0e-3d0b-4a5e-9f4c-1c0e6a7b8d90",
"state": "queued",
"updated_at": "2026-10-20T10:06:30Z"
}