API リファレンス
Imports
Management API: GET /sites/{id}/imports, POST /sites/{id}/imports, GET /sites/{id}/imports/detect, …
List this website's recent import batches, newest first, all in one page (batches are kept for 7 days). Errors: FORBIDDEN.
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
Response 200
dataobject[]requireddata[].idstringrequireddata[].operationIdstringrequiredPass to operations.get to poll; equals op_import_job_<id>.
data[].domain"POSTS" | "PRODUCTS" | "CONTACTS" | "COLLECTION_ITEMS"requireddata[].inputKind"URL" | "FILE"requireddata[].platform"WORDPRESS" | "WIX" | "WEEBLY" | "SQUARESPACE" | "BLOGGER" | "SUBSTACK" | "GHOST" | "MEDIUM" | "TUMBLR" | "WEBFLOW" | "HUBSPOT" | "SHOPIFY" | "WOOCOMMERCE" | "MAILCHIMP" | "KLAVIYO" | "GOOGLE_CONTACTS" | "OUTLOOK" | "GENERIC" | "UNKNOWN"requireddata[].source"WP_REST" | "SQUARESPACE_JSON" | "BLOGGER_ATOM" | "GHOST_API" | "SITEMAP" | "RSS" | "LISTING" | "URL_LIST" | "WXR" | "BLOGGER_XML" | "FEED_FILE" | "MEDIUM_ZIP" | "SUBSTACK_ZIP" | "TUMBLR_ZIP" | "WEEBLY_ARCHIVE" | "GHOST_JSON" | "CSV_HTML" | "MARKDOWN" | "HTML" | "CONTACTS_CSV" | "VCARD" | "PRODUCTS_CSV" | "UNKNOWN"requireddata[].status"PENDING" | "DISCOVERING" | "PARSING" | "REVIEW" | "APPLYING" | "POSTPROCESSING" | "DONE" | "FAILED" | "CANCELLED"requiredREVIEW means parsing is done and the batch waits for imports.apply: a human confirms the list (rows carry warnings such as duplicate_of, title_generated, empty_content).
data[].stagestring | nullrequireddata[].siteUrlstring | nullrequireddata[].fileNamestring | nullrequireddata[].totalsobjectrequireddata[].totals.discoveredintegerrequireddata[].totals.selectedintegerrequireddata[].totals.readyintegerrequireddata[].totals.duplicatesintegerrequireddata[].totals.importedintegerrequireddata[].totals.skippedintegerrequireddata[].totals.failedintegerrequireddata[].totals.discardedintegerrequireddata[].totals.linksRewrittenintegerrequireddata[].totals.pagesintegerrequiredPages found in the source that are not imported (only posts are).
data[].totals.attachmentsintegerrequireddata[].progressobject | nullrequireddata[].progress.currentintegerrequireddata[].progress.totalinteger | nullrequireddata[].errorCodestring | nullrequireddata[].createdAtstringrequireddata[].updatedAtstringrequireddata[].completedAtstring | nullrequireddata[].expiresAtstring | nullrequiredBatch rows and the uploaded file are deleted after this time (7 days).
hasMorebooleanrequiredTrue when another page exists; pass nextCursor to fetch it.
nextCursorstring | nullrequiredCursor for the next page, or null on the last page.
Errors
FORBIDDEN403
MCP tool imports_list
curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/imports" \
-H "Authorization: Bearer $KANORIO_TOKEN"{
"data": [
{
"id": "imp_example01",
"operationId": "op_import_job_imp_example01",
"domain": "POSTS",
"inputKind": "URL",
"platform": "WORDPRESS",
"source": "WP_REST",
"status": "DONE",
"stage": null,
"siteUrl": "https://old-blog.example.com",
"fileName": null,
"totals": {
"discovered": 0,
"selected": 0,
"ready": 0,
"duplicates": 0,
"imported": 41,
"skipped": 0,
"failed": 0,
"discarded": 0,
"linksRewritten": 17,
"pages": 6,
"attachments": 120
},
"progress": {
"current": 42,
"total": 42
},
"errorCode": null,
"createdAt": "2026-10-01T02:30:00.000Z",
"updatedAt": "2026-10-06T08:00:00.000Z",
"completedAt": "2026-10-06T08:00:00.000Z",
"expiresAt": "2026-10-13T02:30:00.000Z"
}
],
"hasMore": false,
"nextCursor": null
}Start importing posts from an old site into this website as DRAFT posts. Give either siteUrl (the whole public post list is imported; large sites are discovered in the background and stop at REVIEW for confirmation) or urls (up to 20 specific post URLs). The batch runs in the background: poll with operations.get (operationId) or imports.get. After parsing it always stops at REVIEW: inspect rows with imports.get (failures, duplicates, generated titles, empty bodies) and call imports.apply to write the confirmed rows; nothing is written before that. Images are copied into the media library, categories/tags are reused or created, posts link to each other with the new paths, and the original publish date is kept. One active batch per site. Importing never consumes AI credits. Errors: FORBIDDEN, VALIDATION, IMPORT_IN_PROGRESS (details.batchId), IMPORT_DAILY_LIMIT_REACHED, SITE_UNREACHABLE, NO_LISTING.
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
Idempotency-Keystring · headerClient-chosen key (1-200 chars). Retrying with the same key and the same body returns the original result; the same key with a different body is rejected with IDEMPOTENCY_CONFLICT (409). Keys expire after 24 hours.
Request body
siteUrlstringPublic URL of the old site (homepage is enough), e.g. https://example.com.
urlsstring[]Specific post URLs instead of a whole site (max 20).
keepPublishedAtbooleanKeep the original publish dates (default true).
Response 201
batchobjectrequiredbatch.idstringrequiredbatch.operationIdstringrequiredPass to operations.get to poll; equals op_import_job_<id>.
batch.domain"POSTS" | "PRODUCTS" | "CONTACTS" | "COLLECTION_ITEMS"requiredbatch.inputKind"URL" | "FILE"requiredbatch.platform"WORDPRESS" | "WIX" | "WEEBLY" | "SQUARESPACE" | "BLOGGER" | "SUBSTACK" | "GHOST" | "MEDIUM" | "TUMBLR" | "WEBFLOW" | "HUBSPOT" | "SHOPIFY" | "WOOCOMMERCE" | "MAILCHIMP" | "KLAVIYO" | "GOOGLE_CONTACTS" | "OUTLOOK" | "GENERIC" | "UNKNOWN"requiredbatch.source"WP_REST" | "SQUARESPACE_JSON" | "BLOGGER_ATOM" | "GHOST_API" | "SITEMAP" | "RSS" | "LISTING" | "URL_LIST" | "WXR" | "BLOGGER_XML" | "FEED_FILE" | "MEDIUM_ZIP" | "SUBSTACK_ZIP" | "TUMBLR_ZIP" | "WEEBLY_ARCHIVE" | "GHOST_JSON" | "CSV_HTML" | "MARKDOWN" | "HTML" | "CONTACTS_CSV" | "VCARD" | "PRODUCTS_CSV" | "UNKNOWN"requiredbatch.status"PENDING" | "DISCOVERING" | "PARSING" | "REVIEW" | "APPLYING" | "POSTPROCESSING" | "DONE" | "FAILED" | "CANCELLED"requiredREVIEW means parsing is done and the batch waits for imports.apply: a human confirms the list (rows carry warnings such as duplicate_of, title_generated, empty_content).
batch.stagestring | nullrequiredbatch.siteUrlstring | nullrequiredbatch.fileNamestring | nullrequiredbatch.totalsobjectrequiredbatch.totals.discoveredintegerrequiredbatch.totals.selectedintegerrequiredbatch.totals.readyintegerrequiredbatch.totals.duplicatesintegerrequiredbatch.totals.importedintegerrequiredbatch.totals.skippedintegerrequiredbatch.totals.failedintegerrequiredbatch.totals.discardedintegerrequiredbatch.totals.linksRewrittenintegerrequiredbatch.totals.pagesintegerrequiredPages found in the source that are not imported (only posts are).
batch.totals.attachmentsintegerrequiredbatch.progressobject | nullrequiredbatch.progress.currentintegerrequiredbatch.progress.totalinteger | nullrequiredbatch.errorCodestring | nullrequiredbatch.createdAtstringrequiredbatch.updatedAtstringrequiredbatch.completedAtstring | nullrequiredbatch.expiresAtstring | nullrequiredBatch rows and the uploaded file are deleted after this time (7 days).
Errors
FORBIDDEN403VALIDATION400IMPORT_IN_PROGRESS409 · details.batchIdIMPORT_DAILY_LIMIT_REACHED429SITE_UNREACHABLE422NO_LISTING422
MCP tool imports_create
curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/imports" \
-H "Authorization: Bearer $KANORIO_TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"siteUrl":"https://old-blog.example.com","keepPublishedAt":true}'{
"batch": {
"id": "imp_example01",
"operationId": "op_import_job_imp_example01",
"domain": "POSTS",
"inputKind": "URL",
"platform": "WORDPRESS",
"source": "WP_REST",
"status": "PENDING",
"stage": "parse",
"siteUrl": "https://old-blog.example.com",
"fileName": null,
"totals": {
"discovered": 0,
"selected": 42,
"ready": 0,
"duplicates": 0,
"imported": 0,
"skipped": 0,
"failed": 0,
"discarded": 0,
"linksRewritten": 0,
"pages": 6,
"attachments": 120
},
"progress": null,
"errorCode": null,
"createdAt": "2026-10-01T02:30:00.000Z",
"updatedAt": "2026-10-06T08:00:00.000Z",
"completedAt": null,
"expiresAt": "2026-10-13T02:30:00.000Z"
}
}Identify which platform an old website runs on (WordPress, Wix, Weebly, Squarespace, Blogger, Substack, Ghost, Medium…) by fetching its homepage once. Use it to tell the user what was found before calling imports.discover or imports.create. supportsUrlDiscovery=false (Medium) means posts can only be imported from an export file in the dashboard. Errors: FORBIDDEN, VALIDATION.
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
urlstring · queryrequiredPublic URL of the old site (homepage is enough), e.g. https://example.com.
Response 200
siteUrlstringrequiredplatform"WORDPRESS" | "WIX" | "WEEBLY" | "SQUARESPACE" | "BLOGGER" | "SUBSTACK" | "GHOST" | "MEDIUM" | "TUMBLR" | "WEBFLOW" | "HUBSPOT" | "SHOPIFY" | "WOOCOMMERCE" | "MAILCHIMP" | "KLAVIYO" | "GOOGLE_CONTACTS" | "OUTLOOK" | "GENERIC" | "UNKNOWN"requiredreachablebooleanrequiredsupportsUrlDiscoverybooleanrequired
Errors
FORBIDDEN403VALIDATION400
MCP tool imports_detect
curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/imports/detect?url=https%3A%2F%2Fold-blog.example.com" \
-H "Authorization: Bearer $KANORIO_TOKEN"{
"siteUrl": "https://old-blog.example.com",
"platform": "WORDPRESS",
"reachable": true,
"supportsUrlDiscovery": true
}List the posts an old site exposes publicly (WordPress REST, Squarespace JSON, Blogger Atom, sitemap, RSS or listing pages, chosen per platform). Nothing is written. Returns up to 2000 items; when the site is large or slow, mode=background is returned and imports.create should be called with the siteUrl so the worker discovers in the background. Errors: FORBIDDEN, VALIDATION, SITE_UNREACHABLE, NO_LISTING (no public post list; use an export file in the dashboard).
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
urlstring · queryrequiredPublic URL of the old site (homepage is enough), e.g. https://example.com.
Response 200
mode"list" | "background"requiredplatform"WORDPRESS" | "WIX" | "WEEBLY" | "SQUARESPACE" | "BLOGGER" | "SUBSTACK" | "GHOST" | "MEDIUM" | "TUMBLR" | "WEBFLOW" | "HUBSPOT" | "SHOPIFY" | "WOOCOMMERCE" | "MAILCHIMP" | "KLAVIYO" | "GOOGLE_CONTACTS" | "OUTLOOK" | "GENERIC" | "UNKNOWN"requiredsource"WP_REST" | "SQUARESPACE_JSON" | "BLOGGER_ATOM" | "GHOST_API" | "SITEMAP" | "RSS" | "LISTING" | "URL_LIST" | "WXR" | "BLOGGER_XML" | "FEED_FILE" | "MEDIUM_ZIP" | "SUBSTACK_ZIP" | "TUMBLR_ZIP" | "WEEBLY_ARCHIVE" | "GHOST_JSON" | "CSV_HTML" | "MARKDOWN" | "HTML" | "CONTACTS_CSV" | "VCARD" | "PRODUCTS_CSV" | "UNKNOWN" | nullrequireditemsobject[]requireditems[].sourceKeystringrequireditems[].urlstringrequireditems[].titlestringitems[].publishedAtstringitems[].kind"post" | "page" | "attachment" | "other"requiredtruncatedbooleanrequiredestimatedinteger | nullrequiredWhen mode=background: how many posts were seen before stopping.
warningsstring[]required
Errors
FORBIDDEN403VALIDATION400SITE_UNREACHABLE422NO_LISTING422 · no public post list; use an export file in the dashboard
MCP tool imports_discover
curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/imports/discover?url=https%3A%2F%2Fold-blog.example.com" \
-H "Authorization: Bearer $KANORIO_TOKEN"{
"mode": "list",
"platform": "WORDPRESS",
"source": "WP_REST",
"items": [
{
"sourceKey": "https://old-blog.example.com/2024/05/how-we-feed-our-starter",
"url": "https://old-blog.example.com/2024/05/how-we-feed-our-starter",
"title": "How we feed our sourdough starter",
"publishedAt": "2024-05-01T12:00:00.000Z",
"kind": "post"
},
{
"sourceKey": "https://old-blog.example.com/2024/06/untitled-draft",
"url": "https://old-blog.example.com/2024/06/untitled-draft",
"kind": "post"
}
],
"truncated": false,
"estimated": null,
"warnings": []
}Get one import batch with its rows (title, status, warnings, created post id and path). Row bodies are never returned. Filter rows with statuses (e.g. DUPLICATE,FAILED); rows is a page, pass limit and cursor (rows.nextCursor) to continue. Errors: FORBIDDEN, IMPORT_BATCH_NOT_FOUND, INVALID_CURSOR.
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
batchIdstring · pathrequiredImport batch id. Get it from imports.create or imports.list.
statuses"DISCOVERED" | "SELECTED" | "READY" | "INCOMPLETE" | "DUPLICATE" | "IMPORTED" | "SKIPPED" | "FAILED" | "DISCARDED"[] · querylimitinteger · queryMaximum number of items to return, 1–100. Defaults to 20.
cursorstring · queryOpaque cursor from the previous page's nextCursor. Omit for the first page.
Response 200
batchobjectrequiredbatch.idstringrequiredbatch.operationIdstringrequiredPass to operations.get to poll; equals op_import_job_<id>.
batch.domain"POSTS" | "PRODUCTS" | "CONTACTS" | "COLLECTION_ITEMS"requiredbatch.inputKind"URL" | "FILE"requiredbatch.platform"WORDPRESS" | "WIX" | "WEEBLY" | "SQUARESPACE" | "BLOGGER" | "SUBSTACK" | "GHOST" | "MEDIUM" | "TUMBLR" | "WEBFLOW" | "HUBSPOT" | "SHOPIFY" | "WOOCOMMERCE" | "MAILCHIMP" | "KLAVIYO" | "GOOGLE_CONTACTS" | "OUTLOOK" | "GENERIC" | "UNKNOWN"requiredbatch.source"WP_REST" | "SQUARESPACE_JSON" | "BLOGGER_ATOM" | "GHOST_API" | "SITEMAP" | "RSS" | "LISTING" | "URL_LIST" | "WXR" | "BLOGGER_XML" | "FEED_FILE" | "MEDIUM_ZIP" | "SUBSTACK_ZIP" | "TUMBLR_ZIP" | "WEEBLY_ARCHIVE" | "GHOST_JSON" | "CSV_HTML" | "MARKDOWN" | "HTML" | "CONTACTS_CSV" | "VCARD" | "PRODUCTS_CSV" | "UNKNOWN"requiredbatch.status"PENDING" | "DISCOVERING" | "PARSING" | "REVIEW" | "APPLYING" | "POSTPROCESSING" | "DONE" | "FAILED" | "CANCELLED"requiredREVIEW means parsing is done and the batch waits for imports.apply: a human confirms the list (rows carry warnings such as duplicate_of, title_generated, empty_content).
batch.stagestring | nullrequiredbatch.siteUrlstring | nullrequiredbatch.fileNamestring | nullrequiredbatch.totalsobjectrequiredbatch.totals.discoveredintegerrequiredbatch.totals.selectedintegerrequiredbatch.totals.readyintegerrequiredbatch.totals.duplicatesintegerrequiredbatch.totals.importedintegerrequiredbatch.totals.skippedintegerrequiredbatch.totals.failedintegerrequiredbatch.totals.discardedintegerrequiredbatch.totals.linksRewrittenintegerrequiredbatch.totals.pagesintegerrequiredPages found in the source that are not imported (only posts are).
batch.totals.attachmentsintegerrequiredbatch.progressobject | nullrequiredbatch.progress.currentintegerrequiredbatch.progress.totalinteger | nullrequiredbatch.errorCodestring | nullrequiredbatch.createdAtstringrequiredbatch.updatedAtstringrequiredbatch.completedAtstring | nullrequiredbatch.expiresAtstring | nullrequiredBatch rows and the uploaded file are deleted after this time (7 days).
rowsobjectrequiredrows.dataobject[]requiredrows.data[].idstringrequiredrows.data[].indexintegerrequiredrows.data[].sourceKeystringrequiredSource identity: the normalized URL for URL imports, or a prefixed key such as wxr:<guid> for files.
rows.data[].titlestring | nullrequiredrows.data[].urlstring | nullrequiredrows.data[].status"DISCOVERED" | "SELECTED" | "READY" | "INCOMPLETE" | "DUPLICATE" | "IMPORTED" | "SKIPPED" | "FAILED" | "DISCARDED"requiredrows.data[].warningsstring[]requiredrows.data[].targetIdstring | nullrequiredThe created post id once IMPORTED.
rows.data[].targetPathstring | nullrequiredPublic path of the created post, e.g. /blog/my-post.
rows.data[].errorCodestring | nullrequiredrows.hasMorebooleanrequiredTrue when another page exists; pass nextCursor to fetch it.
rows.nextCursorstring | nullrequiredCursor for the next page, or null on the last page.
Errors
FORBIDDEN403IMPORT_BATCH_NOT_FOUND404INVALID_CURSOR400
MCP tool imports_get
curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/imports/{batchId}" \
-H "Authorization: Bearer $KANORIO_TOKEN"{
"batch": {
"id": "imp_example01",
"operationId": "op_import_job_imp_example01",
"domain": "POSTS",
"inputKind": "URL",
"platform": "WORDPRESS",
"source": "WP_REST",
"status": "DONE",
"stage": null,
"siteUrl": "https://old-blog.example.com",
"fileName": null,
"totals": {
"discovered": 0,
"selected": 0,
"ready": 0,
"duplicates": 0,
"imported": 41,
"skipped": 0,
"failed": 0,
"discarded": 0,
"linksRewritten": 17,
"pages": 6,
"attachments": 120
},
"progress": {
"current": 42,
"total": 42
},
"errorCode": null,
"createdAt": "2026-10-01T02:30:00.000Z",
"updatedAt": "2026-10-06T08:00:00.000Z",
"completedAt": "2026-10-06T08:00:00.000Z",
"expiresAt": "2026-10-13T02:30:00.000Z"
},
"rows": {
"data": [
{
"id": "row_example01",
"index": 0,
"sourceKey": "https://old-blog.example.com/2024/05/how-we-feed-our-starter",
"title": "How we feed our sourdough starter",
"url": "https://old-blog.example.com/2024/05/how-we-feed-our-starter",
"status": "IMPORTED",
"warnings": [],
"targetId": "post_example01",
"targetPath": "/blog/how-we-feed-our-starter",
"errorCode": null
},
{
"id": "row_example02",
"index": 1,
"sourceKey": "https://old-blog.example.com/2024/06/untitled-draft",
"title": null,
"url": "https://old-blog.example.com/2024/06/untitled-draft",
"status": "READY",
"warnings": [
"title_generated",
"no_published_date"
],
"targetId": null,
"targetPath": null,
"errorCode": null
}
],
"hasMore": true,
"nextCursor": "eyJvIjoyMCwicyI6IiJ9"
}
}Confirm a batch that stopped at REVIEW: write the READY rows (and any DUPLICATE rows you explicitly pass in rowIds). Omit rowIds to import every READY row; rows you leave out are discarded. For background-discovered batches, rowIds selects which discovered posts to fetch and import. Rows with warnings (title_generated, empty_content) are written as-is; edit the drafts afterwards. Errors: FORBIDDEN, IMPORT_BATCH_NOT_FOUND, IMPORT_INVALID_STATE (batch is not in REVIEW).
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
batchIdstring · pathrequiredImport batch id. Get it from imports.create or imports.list.
Request body
rowIdsstring[]
Response 200
batchobjectrequiredbatch.idstringrequiredbatch.operationIdstringrequiredPass to operations.get to poll; equals op_import_job_<id>.
batch.domain"POSTS" | "PRODUCTS" | "CONTACTS" | "COLLECTION_ITEMS"requiredbatch.inputKind"URL" | "FILE"requiredbatch.platform"WORDPRESS" | "WIX" | "WEEBLY" | "SQUARESPACE" | "BLOGGER" | "SUBSTACK" | "GHOST" | "MEDIUM" | "TUMBLR" | "WEBFLOW" | "HUBSPOT" | "SHOPIFY" | "WOOCOMMERCE" | "MAILCHIMP" | "KLAVIYO" | "GOOGLE_CONTACTS" | "OUTLOOK" | "GENERIC" | "UNKNOWN"requiredbatch.source"WP_REST" | "SQUARESPACE_JSON" | "BLOGGER_ATOM" | "GHOST_API" | "SITEMAP" | "RSS" | "LISTING" | "URL_LIST" | "WXR" | "BLOGGER_XML" | "FEED_FILE" | "MEDIUM_ZIP" | "SUBSTACK_ZIP" | "TUMBLR_ZIP" | "WEEBLY_ARCHIVE" | "GHOST_JSON" | "CSV_HTML" | "MARKDOWN" | "HTML" | "CONTACTS_CSV" | "VCARD" | "PRODUCTS_CSV" | "UNKNOWN"requiredbatch.status"PENDING" | "DISCOVERING" | "PARSING" | "REVIEW" | "APPLYING" | "POSTPROCESSING" | "DONE" | "FAILED" | "CANCELLED"requiredREVIEW means parsing is done and the batch waits for imports.apply: a human confirms the list (rows carry warnings such as duplicate_of, title_generated, empty_content).
batch.stagestring | nullrequiredbatch.siteUrlstring | nullrequiredbatch.fileNamestring | nullrequiredbatch.totalsobjectrequiredbatch.totals.discoveredintegerrequiredbatch.totals.selectedintegerrequiredbatch.totals.readyintegerrequiredbatch.totals.duplicatesintegerrequiredbatch.totals.importedintegerrequiredbatch.totals.skippedintegerrequiredbatch.totals.failedintegerrequiredbatch.totals.discardedintegerrequiredbatch.totals.linksRewrittenintegerrequiredbatch.totals.pagesintegerrequiredPages found in the source that are not imported (only posts are).
batch.totals.attachmentsintegerrequiredbatch.progressobject | nullrequiredbatch.progress.currentintegerrequiredbatch.progress.totalinteger | nullrequiredbatch.errorCodestring | nullrequiredbatch.createdAtstringrequiredbatch.updatedAtstringrequiredbatch.completedAtstring | nullrequiredbatch.expiresAtstring | nullrequiredBatch rows and the uploaded file are deleted after this time (7 days).
Errors
FORBIDDEN403IMPORT_BATCH_NOT_FOUND404IMPORT_INVALID_STATE409 · batch is not in REVIEW
MCP tool imports_apply
curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/imports/{batchId}/apply" \
-H "Authorization: Bearer $KANORIO_TOKEN" \
-H "Content-Type: application/json" \
-d '{"rowIds":["row_example01"]}'{
"batch": {
"id": "imp_example01",
"operationId": "op_import_job_imp_example01",
"domain": "POSTS",
"inputKind": "URL",
"platform": "WORDPRESS",
"source": "WP_REST",
"status": "PENDING",
"stage": "apply",
"siteUrl": "https://old-blog.example.com",
"fileName": null,
"totals": {
"discovered": 0,
"selected": 0,
"ready": 0,
"duplicates": 0,
"imported": 41,
"skipped": 0,
"failed": 0,
"discarded": 0,
"linksRewritten": 17,
"pages": 6,
"attachments": 120
},
"progress": {
"current": 42,
"total": 42
},
"errorCode": null,
"createdAt": "2026-10-01T02:30:00.000Z",
"updatedAt": "2026-10-06T08:00:00.000Z",
"completedAt": null,
"expiresAt": "2026-10-13T02:30:00.000Z"
}
}Cancel an import
/sites/{id}/imports/{batchId}/cancelCancel an active import batch between rows. Posts already written stay as drafts; delete them from the posts list if unwanted. Errors: FORBIDDEN, IMPORT_BATCH_NOT_FOUND, IMPORT_INVALID_STATE.
Parameters
idstring · pathrequiredWebsite id. Get it from sites.list or from sites.create.
batchIdstring · pathrequiredImport batch id. Get it from imports.create or imports.list.
Response 200
batchobjectrequiredbatch.idstringrequiredbatch.operationIdstringrequiredPass to operations.get to poll; equals op_import_job_<id>.
batch.domain"POSTS" | "PRODUCTS" | "CONTACTS" | "COLLECTION_ITEMS"requiredbatch.inputKind"URL" | "FILE"requiredbatch.platform"WORDPRESS" | "WIX" | "WEEBLY" | "SQUARESPACE" | "BLOGGER" | "SUBSTACK" | "GHOST" | "MEDIUM" | "TUMBLR" | "WEBFLOW" | "HUBSPOT" | "SHOPIFY" | "WOOCOMMERCE" | "MAILCHIMP" | "KLAVIYO" | "GOOGLE_CONTACTS" | "OUTLOOK" | "GENERIC" | "UNKNOWN"requiredbatch.source"WP_REST" | "SQUARESPACE_JSON" | "BLOGGER_ATOM" | "GHOST_API" | "SITEMAP" | "RSS" | "LISTING" | "URL_LIST" | "WXR" | "BLOGGER_XML" | "FEED_FILE" | "MEDIUM_ZIP" | "SUBSTACK_ZIP" | "TUMBLR_ZIP" | "WEEBLY_ARCHIVE" | "GHOST_JSON" | "CSV_HTML" | "MARKDOWN" | "HTML" | "CONTACTS_CSV" | "VCARD" | "PRODUCTS_CSV" | "UNKNOWN"requiredbatch.status"PENDING" | "DISCOVERING" | "PARSING" | "REVIEW" | "APPLYING" | "POSTPROCESSING" | "DONE" | "FAILED" | "CANCELLED"requiredREVIEW means parsing is done and the batch waits for imports.apply: a human confirms the list (rows carry warnings such as duplicate_of, title_generated, empty_content).
batch.stagestring | nullrequiredbatch.siteUrlstring | nullrequiredbatch.fileNamestring | nullrequiredbatch.totalsobjectrequiredbatch.totals.discoveredintegerrequiredbatch.totals.selectedintegerrequiredbatch.totals.readyintegerrequiredbatch.totals.duplicatesintegerrequiredbatch.totals.importedintegerrequiredbatch.totals.skippedintegerrequiredbatch.totals.failedintegerrequiredbatch.totals.discardedintegerrequiredbatch.totals.linksRewrittenintegerrequiredbatch.totals.pagesintegerrequiredPages found in the source that are not imported (only posts are).
batch.totals.attachmentsintegerrequiredbatch.progressobject | nullrequiredbatch.progress.currentintegerrequiredbatch.progress.totalinteger | nullrequiredbatch.errorCodestring | nullrequiredbatch.createdAtstringrequiredbatch.updatedAtstringrequiredbatch.completedAtstring | nullrequiredbatch.expiresAtstring | nullrequiredBatch rows and the uploaded file are deleted after this time (7 days).
Errors
FORBIDDEN403IMPORT_BATCH_NOT_FOUND404IMPORT_INVALID_STATE409
MCP tool imports_cancel
curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/imports/{batchId}/cancel" \
-H "Authorization: Bearer $KANORIO_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'{
"batch": {
"id": "imp_example01",
"operationId": "op_import_job_imp_example01",
"domain": "POSTS",
"inputKind": "URL",
"platform": "WORDPRESS",
"source": "WP_REST",
"status": "CANCELLED",
"stage": null,
"siteUrl": "https://old-blog.example.com",
"fileName": null,
"totals": {
"discovered": 0,
"selected": 0,
"ready": 0,
"duplicates": 0,
"imported": 41,
"skipped": 0,
"failed": 0,
"discarded": 0,
"linksRewritten": 17,
"pages": 6,
"attachments": 120
},
"progress": {
"current": 42,
"total": 42
},
"errorCode": null,
"createdAt": "2026-10-01T02:30:00.000Z",
"updatedAt": "2026-10-06T08:00:00.000Z",
"completedAt": null,
"expiresAt": "2026-10-13T02:30:00.000Z"
}
}