Kanorio

API reference

Deliverables

Management API: GET /sites/{id}/deliverables, POST /sites/{id}/deliverables, GET /sites/{id}/deliverables/{deliverableId}, …

Base URL https://app.kanorio.com/api/v1ErrorsPagination

List deliverables

GET/sites/{id}/deliverables
betastore:viewdefault (120/minute per token)

List deliverables (courses, e-books, audio series, template packs) with unit counts and linked products. A deliverable is what a buyer receives; products only sell it. Errors: FORBIDDEN, INVALID_CURSOR.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • limitinteger · query

    Maximum number of items to return, 1–100. Defaults to 20.

  • cursorstring · query

    Opaque cursor from the previous page's nextCursor. Omit for the first page.

  • status"ALL" | "ACTIVE" | "ARCHIVED" · query
  • searchstring · query

Response 200

  • dataobject[]required
  • data[].idstringrequired
  • data[].titlestringrequired
  • data[].descriptionstring | nullrequired
  • data[].coverAssetIdstring | nullrequired
  • data[].structure"COURSE" | "DOWNLOAD"required

    COURSE has chapters and tracks progress; DOWNLOAD is a flat file list (no progress, new units allow download by default). Access rules are identical.

  • data[].status"ACTIVE" | "ARCHIVED"required
  • data[].grantsstring[]required

    Commercial feature keys (e.g. ["premium"]) granted when a buyer purchases or is granted this deliverable; matched by ContentCollection.accessPolicy and entitlements.check.

  • data[].authorIdsstring[]required

    Authors/instructors shown on the sales page and the learner page, in order. Ids come from the site's shared author list (also used by posts; managed in the console under Posts › Settings).

  • data[].unitCountintegerrequired

    Leaf units only; chapters are not counted.

  • data[].productIdsstring[]required

    Products that grant this deliverable on purchase (see products.update deliverables).

  • data[].createdAtstringrequired
  • data[].updatedAtstringrequired
  • hasMorebooleanrequired

    True when another page exists; pass nextCursor to fetch it.

  • nextCursorstring | nullrequired

    Cursor for the next page, or null on the last page.

Errors

  • FORBIDDEN 403
  • INVALID_CURSOR 400

MCP tool deliverables_list

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/deliverables" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "data": [
    {
      "id": "dlv_example01",
      "title": "Sourdough Fundamentals",
      "description": "Six-week video course with downloadable recipe cards.",
      "coverAssetId": "asset_example01",
      "structure": "COURSE",
      "status": "ACTIVE",
      "grants": [
        "premium"
      ],
      "authorIds": [
        "author_headbaker01"
      ],
      "unitCount": 3,
      "productIds": [
        "prod_example01"
      ],
      "createdAt": "2026-10-01T02:30:00.000Z",
      "updatedAt": "2026-10-06T08:00:00.000Z"
    }
  ],
  "hasMore": false,
  "nextCursor": null
}

Create a deliverable

POST/sites/{id}/deliverables
betacommerce:managedefault (120/minute per token)

Create a deliverable. Add chapters and units with deliverable_units.replace_tree, then link it to a product with products.update({ deliverables }) or grant it directly with entitlements.grant. Use structure DOWNLOAD for a plain file bundle (e-book, template pack) and COURSE when learners should see chapters and progress. The structure cannot be changed later; to switch, copy the deliverable with deliverables.duplicate. Errors: FORBIDDEN, DELIVERABLE_NOT_FOUND, VALIDATION (details.issues), ASSET_NOT_FOUND (details.assetIds: not in the media library, in the trash or an older version), ASSET_NOT_ALLOWED (coverAssetId, certificate.signatureAssetId or certificate.backgroundAssetId is not a public image), AUTHOR_NOT_FOUND (details.authorIds: not in the site's author list).

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

Request body

  • titlestringrequired
  • descriptionstring | null
  • coverAssetIdstring | null
  • structure"COURSE" | "DOWNLOAD"

    COURSE (default) for chapters/progress; DOWNLOAD for a flat file list. Fixed after creation.

  • grantsstring[]

    Optional feature keys (e.g. ["premium"]) unlocked by this deliverable for collection accessPolicy and entitlements.check.

  • authorIdsstring[]

    Authors/instructors (ids from the site's shared author list, replaced as a whole, order kept). Unknown ids fail with AUTHOR_NOT_FOUND.

  • settingsobject
  • settings.completionRuleobject
  • settings.completionRule.type"all_units"required
  • settings.certificateobject

    When enabled, a certificate (serial + issue date) is issued the first time a learner completes the deliverable; learners fetch it with Customer API GET /deliverables/:id/certificate. The PDF is generated on download from the current settings, course title, learner name and site branding (logo, brand colour), so edits apply to every certificate; only the serial and issue date are fixed. Send every certificate field when updating it. Use deliverables.certificate_preview to see it.

  • settings.certificate.enabledbooleanrequired
  • settings.certificate.titlestring | nullrequired

    Certificate heading; null = the site-language default ("Certificate of Completion").

  • settings.certificate.signatureNamestring | nullrequired

    Signer's name or organisation; null = no signature block.

  • settings.certificate.signatureTitlestring | nullrequired

    Signer's title printed under the name, e.g. "Lead instructor".

  • settings.certificate.signatureAssetIdstring | nullrequired

    Signature image: a public image asset id (same rule as coverAssetId); printed above the signature line.

  • settings.certificate.showLogobooleanrequired

    Print the site's brand logo (site settings) at the top; icon logos are skipped.

  • settings.certificate.notestring | nullrequired

    One line printed under the course title, e.g. "12 hours of instruction".

  • settings.certificate.backgroundAssetIdstring | nullrequired

    Background image: a public image asset id (same rule as coverAssetId), centred and cropped to fill an A4 landscape page (recommended 3508 × 2480 px). When set, the default border is not drawn; text positions stay fixed, so keep the centre of the design clear.

  • settings.certificate.backgroundOverlaybooleanrequired

    Lay a semi-transparent white layer over the background image so text stays readable on busy designs; no effect without a background image.

  • settings.commentsobject
  • settings.comments.enabledbooleanrequired
  • settings.comments.threadedbooleanrequired
  • settings.comments.requireReviewbooleanrequired
  • settings.comments.reactionsbooleanrequired
  • settings.requireSequentialboolean

    Learners must complete each unit before opening the next (free-preview units are exempt). Locked units come back with access.reason prerequisite.

  • settings.mediaCompletionPercentinteger

    Share of a video/audio unit a learner must actually watch for it to count as completed (50-100, step 5, default 90). Measured from the segments played, so skipping to the end does not count; 100 keeps a 2-second tolerance at the end. Custom players that only report positionSeconds are measured by the furthest position. Raising it never un-completes learners.

  • fieldDataobject | null

Response 201

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • coverAssetIdstring | nullrequired
  • structure"COURSE" | "DOWNLOAD"required

    COURSE has chapters and tracks progress; DOWNLOAD is a flat file list (no progress, new units allow download by default). Access rules are identical.

  • status"ACTIVE" | "ARCHIVED"required
  • grantsstring[]required

    Commercial feature keys (e.g. ["premium"]) granted when a buyer purchases or is granted this deliverable; matched by ContentCollection.accessPolicy and entitlements.check.

  • authorIdsstring[]required

    Authors/instructors shown on the sales page and the learner page, in order. Ids come from the site's shared author list (also used by posts; managed in the console under Posts › Settings).

  • unitCountintegerrequired

    Leaf units only; chapters are not counted.

  • productIdsstring[]required

    Products that grant this deliverable on purchase (see products.update deliverables).

  • createdAtstringrequired
  • updatedAtstringrequired
  • settingsobjectrequired
  • settings.completionRuleobjectrequired
  • settings.completionRule.type"all_units"required
  • settings.certificateobjectrequired

    When enabled, a certificate (serial + issue date) is issued the first time a learner completes the deliverable; learners fetch it with Customer API GET /deliverables/:id/certificate. The PDF is generated on download from the current settings, course title, learner name and site branding (logo, brand colour), so edits apply to every certificate; only the serial and issue date are fixed. Send every certificate field when updating it. Use deliverables.certificate_preview to see it.

  • settings.certificate.enabledbooleanrequired
  • settings.certificate.titlestring | nullrequired

    Certificate heading; null = the site-language default ("Certificate of Completion").

  • settings.certificate.signatureNamestring | nullrequired

    Signer's name or organisation; null = no signature block.

  • settings.certificate.signatureTitlestring | nullrequired

    Signer's title printed under the name, e.g. "Lead instructor".

  • settings.certificate.signatureAssetIdstring | nullrequired

    Signature image: a public image asset id (same rule as coverAssetId); printed above the signature line.

  • settings.certificate.showLogobooleanrequired

    Print the site's brand logo (site settings) at the top; icon logos are skipped.

  • settings.certificate.notestring | nullrequired

    One line printed under the course title, e.g. "12 hours of instruction".

  • settings.certificate.backgroundAssetIdstring | nullrequired

    Background image: a public image asset id (same rule as coverAssetId), centred and cropped to fill an A4 landscape page (recommended 3508 × 2480 px). When set, the default border is not drawn; text positions stay fixed, so keep the centre of the design clear.

  • settings.certificate.backgroundOverlaybooleanrequired

    Lay a semi-transparent white layer over the background image so text stays readable on busy designs; no effect without a background image.

  • settings.commentsobjectrequired
  • settings.comments.enabledbooleanrequired
  • settings.comments.threadedbooleanrequired
  • settings.comments.requireReviewbooleanrequired
  • settings.comments.reactionsbooleanrequired
  • settings.requireSequentialbooleanrequired

    Learners must complete each unit before opening the next (free-preview units are exempt). Locked units come back with access.reason prerequisite.

  • settings.mediaCompletionPercentintegerrequired

    Share of a video/audio unit a learner must actually watch for it to count as completed (50-100, step 5, default 90). Measured from the segments played, so skipping to the end does not count; 100 keeps a 2-second tolerance at the end. Custom players that only report positionSeconds are measured by the furthest position. Raising it never un-completes learners.

  • fieldDataobject | nullrequired
  • unitsobject[]required

    Flat list ordered by chapter then unit; use parentId to rebuild the tree.

  • units[].idstringrequired
  • units[].parentIdstring | nullrequired

    Chapter id for units inside a chapter; null for top-level chapters or flat units.

  • units[].orderintegerrequired
  • units[].kindstringrequired

    Open string. Known values: video, audio, file, text, quiz; "chapter" for grouping rows. Unknown kinds render as a download card.

  • units[].titlestring | nullrequired
  • units[].descriptionstring | nullrequired
  • units[].primaryAssetIdstring | nullrequired

    Media-library asset (private products bucket). Upload with media.upload first.

  • units[].attachmentAssetIdsstring[]required
  • units[].fileUrlstring | nullrequired

    Only for Kanorio template sample media (not a media-library asset). Real files are referenced by primaryAssetId.

  • units[].embedobject | nullrequired

    External video embed (youtube/vimeo/loom). Not protected by Kanorio; use for FREE sites that cannot host video.

  • units[].embed.providerstringrequired
  • units[].embed.idstringrequired
  • units[].bodyanyrequired

    text units: { markdown }. quiz units: { questions: [{ id, type: "single" | "multiple" | "true_false", prompt, options: [{ id, text, correct: boolean }], explanation? }], settings: { passingPercent (0-100, default 70), maxAttempts (1-99 or null = unlimited), showAnswers: "never" | "after_pass" | "always" } }; validated on write (UNIT_TREE_INVALID quiz_body_invalid). Learners never see correct/explanation; the server grades Customer API POST /units/:id/quiz.

  • units[].isPreviewbooleanrequired

    Free preview: anonymous visitors can open it.

  • units[].visibility"VISIBLE" | "HIDDEN"required
  • units[].releaseAtstring | nullrequired

    Absolute unlock time.

  • units[].releaseAfterDaysinteger | nullrequired

    Unlock N days after the learner's entitlement started.

  • units[].allowDownloadbooleanrequired
  • units[].countsTowardCompletionbooleanrequired

    false = bonus unit: not counted in percent or completion, never locked by requireSequential and never a gate for later units.

  • units[].isPrerequisitebooleanrequired

    Units after this one stay locked until the learner completes it, even when requireSequential is off.

  • productsobject[]required

    Products (variants) that grant this deliverable; tierId null = every variant. Access duration is pricingTiers[].accessDays on the product.

  • products[].productIdstringrequired
  • products[].tierIdstring | nullrequired

Errors

  • FORBIDDEN 403
  • DELIVERABLE_NOT_FOUND 404
  • VALIDATION 400 · details.issues
  • ASSET_NOT_FOUND 404 · details.assetIds: not in the media library, in the trash or an older version
  • ASSET_NOT_ALLOWED 422 · coverAssetId, certificate.signatureAssetId or certificate.backgroundAssetId is not a public image
  • AUTHOR_NOT_FOUND 404 · details.authorIds: not in the site's author list

MCP tool deliverables_create

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/deliverables" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Sourdough Fundamentals","description":"Six-week video course with downloadable recipe cards.","coverAssetId":"asset_example01","structure":"COURSE"}'
Response
{
  "id": "dlv_example01",
  "title": "Sourdough Fundamentals",
  "description": "Six-week video course with downloadable recipe cards.",
  "coverAssetId": "asset_example01",
  "structure": "COURSE",
  "status": "ACTIVE",
  "grants": [
    "premium"
  ],
  "authorIds": [
    "author_headbaker01"
  ],
  "unitCount": 0,
  "productIds": [],
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z",
  "settings": {
    "completionRule": {
      "type": "all_units"
    },
    "certificate": {
      "enabled": false,
      "title": null,
      "signatureName": null,
      "signatureTitle": null,
      "signatureAssetId": null,
      "showLogo": true,
      "note": null,
      "backgroundAssetId": null,
      "backgroundOverlay": false
    },
    "comments": {
      "enabled": false,
      "threaded": true,
      "requireReview": true,
      "reactions": false
    },
    "requireSequential": false,
    "mediaCompletionPercent": 90
  },
  "fieldData": null,
  "units": [],
  "products": []
}

Retrieve a deliverable

GET/sites/{id}/deliverables/{deliverableId}
betastore:viewdefault (120/minute per token)

Get one deliverable with settings and the full chapter/unit tree (no signed file URLs). Errors: FORBIDDEN, DELIVERABLE_NOT_FOUND.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • deliverableIdstring · pathrequired

    Deliverable id. Get it from deliverables.list.

Response 200

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • coverAssetIdstring | nullrequired
  • structure"COURSE" | "DOWNLOAD"required

    COURSE has chapters and tracks progress; DOWNLOAD is a flat file list (no progress, new units allow download by default). Access rules are identical.

  • status"ACTIVE" | "ARCHIVED"required
  • grantsstring[]required

    Commercial feature keys (e.g. ["premium"]) granted when a buyer purchases or is granted this deliverable; matched by ContentCollection.accessPolicy and entitlements.check.

  • authorIdsstring[]required

    Authors/instructors shown on the sales page and the learner page, in order. Ids come from the site's shared author list (also used by posts; managed in the console under Posts › Settings).

  • unitCountintegerrequired

    Leaf units only; chapters are not counted.

  • productIdsstring[]required

    Products that grant this deliverable on purchase (see products.update deliverables).

  • createdAtstringrequired
  • updatedAtstringrequired
  • settingsobjectrequired
  • settings.completionRuleobjectrequired
  • settings.completionRule.type"all_units"required
  • settings.certificateobjectrequired

    When enabled, a certificate (serial + issue date) is issued the first time a learner completes the deliverable; learners fetch it with Customer API GET /deliverables/:id/certificate. The PDF is generated on download from the current settings, course title, learner name and site branding (logo, brand colour), so edits apply to every certificate; only the serial and issue date are fixed. Send every certificate field when updating it. Use deliverables.certificate_preview to see it.

  • settings.certificate.enabledbooleanrequired
  • settings.certificate.titlestring | nullrequired

    Certificate heading; null = the site-language default ("Certificate of Completion").

  • settings.certificate.signatureNamestring | nullrequired

    Signer's name or organisation; null = no signature block.

  • settings.certificate.signatureTitlestring | nullrequired

    Signer's title printed under the name, e.g. "Lead instructor".

  • settings.certificate.signatureAssetIdstring | nullrequired

    Signature image: a public image asset id (same rule as coverAssetId); printed above the signature line.

  • settings.certificate.showLogobooleanrequired

    Print the site's brand logo (site settings) at the top; icon logos are skipped.

  • settings.certificate.notestring | nullrequired

    One line printed under the course title, e.g. "12 hours of instruction".

  • settings.certificate.backgroundAssetIdstring | nullrequired

    Background image: a public image asset id (same rule as coverAssetId), centred and cropped to fill an A4 landscape page (recommended 3508 × 2480 px). When set, the default border is not drawn; text positions stay fixed, so keep the centre of the design clear.

  • settings.certificate.backgroundOverlaybooleanrequired

    Lay a semi-transparent white layer over the background image so text stays readable on busy designs; no effect without a background image.

  • settings.commentsobjectrequired
  • settings.comments.enabledbooleanrequired
  • settings.comments.threadedbooleanrequired
  • settings.comments.requireReviewbooleanrequired
  • settings.comments.reactionsbooleanrequired
  • settings.requireSequentialbooleanrequired

    Learners must complete each unit before opening the next (free-preview units are exempt). Locked units come back with access.reason prerequisite.

  • settings.mediaCompletionPercentintegerrequired

    Share of a video/audio unit a learner must actually watch for it to count as completed (50-100, step 5, default 90). Measured from the segments played, so skipping to the end does not count; 100 keeps a 2-second tolerance at the end. Custom players that only report positionSeconds are measured by the furthest position. Raising it never un-completes learners.

  • fieldDataobject | nullrequired
  • unitsobject[]required

    Flat list ordered by chapter then unit; use parentId to rebuild the tree.

  • units[].idstringrequired
  • units[].parentIdstring | nullrequired

    Chapter id for units inside a chapter; null for top-level chapters or flat units.

  • units[].orderintegerrequired
  • units[].kindstringrequired

    Open string. Known values: video, audio, file, text, quiz; "chapter" for grouping rows. Unknown kinds render as a download card.

  • units[].titlestring | nullrequired
  • units[].descriptionstring | nullrequired
  • units[].primaryAssetIdstring | nullrequired

    Media-library asset (private products bucket). Upload with media.upload first.

  • units[].attachmentAssetIdsstring[]required
  • units[].fileUrlstring | nullrequired

    Only for Kanorio template sample media (not a media-library asset). Real files are referenced by primaryAssetId.

  • units[].embedobject | nullrequired

    External video embed (youtube/vimeo/loom). Not protected by Kanorio; use for FREE sites that cannot host video.

  • units[].embed.providerstringrequired
  • units[].embed.idstringrequired
  • units[].bodyanyrequired

    text units: { markdown }. quiz units: { questions: [{ id, type: "single" | "multiple" | "true_false", prompt, options: [{ id, text, correct: boolean }], explanation? }], settings: { passingPercent (0-100, default 70), maxAttempts (1-99 or null = unlimited), showAnswers: "never" | "after_pass" | "always" } }; validated on write (UNIT_TREE_INVALID quiz_body_invalid). Learners never see correct/explanation; the server grades Customer API POST /units/:id/quiz.

  • units[].isPreviewbooleanrequired

    Free preview: anonymous visitors can open it.

  • units[].visibility"VISIBLE" | "HIDDEN"required
  • units[].releaseAtstring | nullrequired

    Absolute unlock time.

  • units[].releaseAfterDaysinteger | nullrequired

    Unlock N days after the learner's entitlement started.

  • units[].allowDownloadbooleanrequired
  • units[].countsTowardCompletionbooleanrequired

    false = bonus unit: not counted in percent or completion, never locked by requireSequential and never a gate for later units.

  • units[].isPrerequisitebooleanrequired

    Units after this one stay locked until the learner completes it, even when requireSequential is off.

  • productsobject[]required

    Products (variants) that grant this deliverable; tierId null = every variant. Access duration is pricingTiers[].accessDays on the product.

  • products[].productIdstringrequired
  • products[].tierIdstring | nullrequired

Errors

  • FORBIDDEN 403
  • DELIVERABLE_NOT_FOUND 404

MCP tool deliverables_get

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/deliverables/{deliverableId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "id": "dlv_example01",
  "title": "Sourdough Fundamentals",
  "description": "Six-week video course with downloadable recipe cards.",
  "coverAssetId": "asset_example01",
  "structure": "COURSE",
  "status": "ACTIVE",
  "grants": [
    "premium"
  ],
  "authorIds": [
    "author_headbaker01"
  ],
  "unitCount": 3,
  "productIds": [
    "prod_example01"
  ],
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z",
  "settings": {
    "completionRule": {
      "type": "all_units"
    },
    "certificate": {
      "enabled": false,
      "title": null,
      "signatureName": null,
      "signatureTitle": null,
      "signatureAssetId": null,
      "showLogo": true,
      "note": null,
      "backgroundAssetId": null,
      "backgroundOverlay": false
    },
    "comments": {
      "enabled": false,
      "threaded": true,
      "requireReview": true,
      "reactions": false
    },
    "requireSequential": false,
    "mediaCompletionPercent": 90
  },
  "fieldData": null,
  "units": [
    {
      "id": "unit_chapter01",
      "parentId": null,
      "order": 0,
      "kind": "chapter",
      "title": "Week 1 · Getting started",
      "description": null,
      "primaryAssetId": null,
      "attachmentAssetIds": [],
      "fileUrl": null,
      "embed": null,
      "body": null,
      "isPreview": false,
      "visibility": "VISIBLE",
      "releaseAt": null,
      "releaseAfterDays": null,
      "allowDownload": false,
      "countsTowardCompletion": true,
      "isPrerequisite": false
    },
    {
      "id": "unit_video01",
      "parentId": "unit_chapter01",
      "order": 0,
      "kind": "video",
      "title": "Welcome and course overview",
      "description": "What you will build in six weeks.",
      "primaryAssetId": "asset_example01",
      "attachmentAssetIds": [],
      "fileUrl": null,
      "embed": null,
      "body": null,
      "isPreview": true,
      "visibility": "VISIBLE",
      "releaseAt": null,
      "releaseAfterDays": null,
      "allowDownload": false,
      "countsTowardCompletion": true,
      "isPrerequisite": false
    },
    {
      "id": "unit_text01",
      "parentId": "unit_chapter01",
      "order": 1,
      "kind": "text",
      "title": "Set up your workspace",
      "description": null,
      "primaryAssetId": null,
      "attachmentAssetIds": [],
      "fileUrl": null,
      "embed": null,
      "body": {
        "markdown": "## Install\n\n1. Download the starter kit…"
      },
      "isPreview": false,
      "visibility": "VISIBLE",
      "releaseAt": null,
      "releaseAfterDays": 2,
      "allowDownload": false,
      "countsTowardCompletion": true,
      "isPrerequisite": false
    }
  ],
  "products": [
    {
      "productId": "prod_example01",
      "tierId": null
    }
  ]
}

Update a deliverable

PATCH/sites/{id}/deliverables/{deliverableId}
betacommerce:managedefault (120/minute per token)

Partially update a deliverable (title, description, cover, settings such as completionRule/certificate/comments). Units are managed with deliverable_units.*. The structure is fixed after creation: sending a different structure fails with STRUCTURE_LOCKED; copy it with deliverables.duplicate instead. Errors: FORBIDDEN, DELIVERABLE_NOT_FOUND, VALIDATION (details.issues), ASSET_NOT_FOUND (details.assetIds: not in the media library, in the trash or an older version), ASSET_NOT_ALLOWED (coverAssetId, certificate.signatureAssetId or certificate.backgroundAssetId is not a public image), AUTHOR_NOT_FOUND (details.authorIds: not in the site's author list).

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • deliverableIdstring · pathrequired

    Deliverable id. Get it from deliverables.list.

Request body

  • titlestring
  • descriptionstring | null
  • coverAssetIdstring | null
  • structure"COURSE" | "DOWNLOAD"

    Must equal the current structure (fixed after creation); omit it.

  • grantsstring[]

    Optional feature keys (e.g. ["premium"]) unlocked by this deliverable for collection accessPolicy and entitlements.check.

  • authorIdsstring[]

    Authors/instructors (ids from the site's shared author list, replaced as a whole, order kept). Unknown ids fail with AUTHOR_NOT_FOUND.

  • settingsobject
  • settings.completionRuleobject
  • settings.completionRule.type"all_units"required
  • settings.certificateobject

    When enabled, a certificate (serial + issue date) is issued the first time a learner completes the deliverable; learners fetch it with Customer API GET /deliverables/:id/certificate. The PDF is generated on download from the current settings, course title, learner name and site branding (logo, brand colour), so edits apply to every certificate; only the serial and issue date are fixed. Send every certificate field when updating it. Use deliverables.certificate_preview to see it.

  • settings.certificate.enabledbooleanrequired
  • settings.certificate.titlestring | nullrequired

    Certificate heading; null = the site-language default ("Certificate of Completion").

  • settings.certificate.signatureNamestring | nullrequired

    Signer's name or organisation; null = no signature block.

  • settings.certificate.signatureTitlestring | nullrequired

    Signer's title printed under the name, e.g. "Lead instructor".

  • settings.certificate.signatureAssetIdstring | nullrequired

    Signature image: a public image asset id (same rule as coverAssetId); printed above the signature line.

  • settings.certificate.showLogobooleanrequired

    Print the site's brand logo (site settings) at the top; icon logos are skipped.

  • settings.certificate.notestring | nullrequired

    One line printed under the course title, e.g. "12 hours of instruction".

  • settings.certificate.backgroundAssetIdstring | nullrequired

    Background image: a public image asset id (same rule as coverAssetId), centred and cropped to fill an A4 landscape page (recommended 3508 × 2480 px). When set, the default border is not drawn; text positions stay fixed, so keep the centre of the design clear.

  • settings.certificate.backgroundOverlaybooleanrequired

    Lay a semi-transparent white layer over the background image so text stays readable on busy designs; no effect without a background image.

  • settings.commentsobject
  • settings.comments.enabledbooleanrequired
  • settings.comments.threadedbooleanrequired
  • settings.comments.requireReviewbooleanrequired
  • settings.comments.reactionsbooleanrequired
  • settings.requireSequentialboolean

    Learners must complete each unit before opening the next (free-preview units are exempt). Locked units come back with access.reason prerequisite.

  • settings.mediaCompletionPercentinteger

    Share of a video/audio unit a learner must actually watch for it to count as completed (50-100, step 5, default 90). Measured from the segments played, so skipping to the end does not count; 100 keeps a 2-second tolerance at the end. Custom players that only report positionSeconds are measured by the furthest position. Raising it never un-completes learners.

  • fieldDataobject | null

Response 200

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • coverAssetIdstring | nullrequired
  • structure"COURSE" | "DOWNLOAD"required

    COURSE has chapters and tracks progress; DOWNLOAD is a flat file list (no progress, new units allow download by default). Access rules are identical.

  • status"ACTIVE" | "ARCHIVED"required
  • grantsstring[]required

    Commercial feature keys (e.g. ["premium"]) granted when a buyer purchases or is granted this deliverable; matched by ContentCollection.accessPolicy and entitlements.check.

  • authorIdsstring[]required

    Authors/instructors shown on the sales page and the learner page, in order. Ids come from the site's shared author list (also used by posts; managed in the console under Posts › Settings).

  • unitCountintegerrequired

    Leaf units only; chapters are not counted.

  • productIdsstring[]required

    Products that grant this deliverable on purchase (see products.update deliverables).

  • createdAtstringrequired
  • updatedAtstringrequired
  • settingsobjectrequired
  • settings.completionRuleobjectrequired
  • settings.completionRule.type"all_units"required
  • settings.certificateobjectrequired

    When enabled, a certificate (serial + issue date) is issued the first time a learner completes the deliverable; learners fetch it with Customer API GET /deliverables/:id/certificate. The PDF is generated on download from the current settings, course title, learner name and site branding (logo, brand colour), so edits apply to every certificate; only the serial and issue date are fixed. Send every certificate field when updating it. Use deliverables.certificate_preview to see it.

  • settings.certificate.enabledbooleanrequired
  • settings.certificate.titlestring | nullrequired

    Certificate heading; null = the site-language default ("Certificate of Completion").

  • settings.certificate.signatureNamestring | nullrequired

    Signer's name or organisation; null = no signature block.

  • settings.certificate.signatureTitlestring | nullrequired

    Signer's title printed under the name, e.g. "Lead instructor".

  • settings.certificate.signatureAssetIdstring | nullrequired

    Signature image: a public image asset id (same rule as coverAssetId); printed above the signature line.

  • settings.certificate.showLogobooleanrequired

    Print the site's brand logo (site settings) at the top; icon logos are skipped.

  • settings.certificate.notestring | nullrequired

    One line printed under the course title, e.g. "12 hours of instruction".

  • settings.certificate.backgroundAssetIdstring | nullrequired

    Background image: a public image asset id (same rule as coverAssetId), centred and cropped to fill an A4 landscape page (recommended 3508 × 2480 px). When set, the default border is not drawn; text positions stay fixed, so keep the centre of the design clear.

  • settings.certificate.backgroundOverlaybooleanrequired

    Lay a semi-transparent white layer over the background image so text stays readable on busy designs; no effect without a background image.

  • settings.commentsobjectrequired
  • settings.comments.enabledbooleanrequired
  • settings.comments.threadedbooleanrequired
  • settings.comments.requireReviewbooleanrequired
  • settings.comments.reactionsbooleanrequired
  • settings.requireSequentialbooleanrequired

    Learners must complete each unit before opening the next (free-preview units are exempt). Locked units come back with access.reason prerequisite.

  • settings.mediaCompletionPercentintegerrequired

    Share of a video/audio unit a learner must actually watch for it to count as completed (50-100, step 5, default 90). Measured from the segments played, so skipping to the end does not count; 100 keeps a 2-second tolerance at the end. Custom players that only report positionSeconds are measured by the furthest position. Raising it never un-completes learners.

  • fieldDataobject | nullrequired
  • unitsobject[]required

    Flat list ordered by chapter then unit; use parentId to rebuild the tree.

  • units[].idstringrequired
  • units[].parentIdstring | nullrequired

    Chapter id for units inside a chapter; null for top-level chapters or flat units.

  • units[].orderintegerrequired
  • units[].kindstringrequired

    Open string. Known values: video, audio, file, text, quiz; "chapter" for grouping rows. Unknown kinds render as a download card.

  • units[].titlestring | nullrequired
  • units[].descriptionstring | nullrequired
  • units[].primaryAssetIdstring | nullrequired

    Media-library asset (private products bucket). Upload with media.upload first.

  • units[].attachmentAssetIdsstring[]required
  • units[].fileUrlstring | nullrequired

    Only for Kanorio template sample media (not a media-library asset). Real files are referenced by primaryAssetId.

  • units[].embedobject | nullrequired

    External video embed (youtube/vimeo/loom). Not protected by Kanorio; use for FREE sites that cannot host video.

  • units[].embed.providerstringrequired
  • units[].embed.idstringrequired
  • units[].bodyanyrequired

    text units: { markdown }. quiz units: { questions: [{ id, type: "single" | "multiple" | "true_false", prompt, options: [{ id, text, correct: boolean }], explanation? }], settings: { passingPercent (0-100, default 70), maxAttempts (1-99 or null = unlimited), showAnswers: "never" | "after_pass" | "always" } }; validated on write (UNIT_TREE_INVALID quiz_body_invalid). Learners never see correct/explanation; the server grades Customer API POST /units/:id/quiz.

  • units[].isPreviewbooleanrequired

    Free preview: anonymous visitors can open it.

  • units[].visibility"VISIBLE" | "HIDDEN"required
  • units[].releaseAtstring | nullrequired

    Absolute unlock time.

  • units[].releaseAfterDaysinteger | nullrequired

    Unlock N days after the learner's entitlement started.

  • units[].allowDownloadbooleanrequired
  • units[].countsTowardCompletionbooleanrequired

    false = bonus unit: not counted in percent or completion, never locked by requireSequential and never a gate for later units.

  • units[].isPrerequisitebooleanrequired

    Units after this one stay locked until the learner completes it, even when requireSequential is off.

  • productsobject[]required

    Products (variants) that grant this deliverable; tierId null = every variant. Access duration is pricingTiers[].accessDays on the product.

  • products[].productIdstringrequired
  • products[].tierIdstring | nullrequired

Errors

  • FORBIDDEN 403
  • DELIVERABLE_NOT_FOUND 404
  • VALIDATION 400 · details.issues
  • ASSET_NOT_FOUND 404 · details.assetIds: not in the media library, in the trash or an older version
  • ASSET_NOT_ALLOWED 422 · coverAssetId, certificate.signatureAssetId or certificate.backgroundAssetId is not a public image
  • AUTHOR_NOT_FOUND 404 · details.authorIds: not in the site's author list

MCP tool deliverables_update

curl -X PATCH "https://app.kanorio.com/api/v1/sites/{id}/deliverables/{deliverableId}" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"settings":{"completionRule":{"type":"percent","percent":80},"certificate":{"enabled":true,"title":"Certificate of Completion","signatureName":"Head Baker","signatureTitle":"Lead instructor","signatureAssetId":null,"showLogo":true,"note":"12 hours of instruction","backgroundAssetId":"asset_example01","backgroundOverlay":true}}}'
Response
{
  "id": "dlv_example01",
  "title": "Sourdough Fundamentals",
  "description": "Six-week video course with downloadable recipe cards.",
  "coverAssetId": "asset_example01",
  "structure": "COURSE",
  "status": "ACTIVE",
  "grants": [
    "premium"
  ],
  "authorIds": [
    "author_headbaker01"
  ],
  "unitCount": 3,
  "productIds": [
    "prod_example01"
  ],
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z",
  "settings": {
    "completionRule": {
      "type": "percent",
      "percent": 80
    },
    "certificate": {
      "enabled": true,
      "title": "Certificate of Completion",
      "signatureName": "Head Baker",
      "signatureTitle": "Lead instructor",
      "signatureAssetId": null,
      "showLogo": true,
      "note": "12 hours of instruction",
      "backgroundAssetId": "asset_example01",
      "backgroundOverlay": true
    },
    "comments": {
      "enabled": false,
      "threaded": true,
      "requireReview": true,
      "reactions": false
    },
    "requireSequential": false,
    "mediaCompletionPercent": 90
  },
  "fieldData": null,
  "units": [
    {
      "id": "unit_chapter01",
      "parentId": null,
      "order": 0,
      "kind": "chapter",
      "title": "Week 1 · Getting started",
      "description": null,
      "primaryAssetId": null,
      "attachmentAssetIds": [],
      "fileUrl": null,
      "embed": null,
      "body": null,
      "isPreview": false,
      "visibility": "VISIBLE",
      "releaseAt": null,
      "releaseAfterDays": null,
      "allowDownload": false,
      "countsTowardCompletion": true,
      "isPrerequisite": false
    },
    {
      "id": "unit_video01",
      "parentId": "unit_chapter01",
      "order": 0,
      "kind": "video",
      "title": "Welcome and course overview",
      "description": "What you will build in six weeks.",
      "primaryAssetId": "asset_example01",
      "attachmentAssetIds": [],
      "fileUrl": null,
      "embed": null,
      "body": null,
      "isPreview": true,
      "visibility": "VISIBLE",
      "releaseAt": null,
      "releaseAfterDays": null,
      "allowDownload": false,
      "countsTowardCompletion": true,
      "isPrerequisite": false
    },
    {
      "id": "unit_text01",
      "parentId": "unit_chapter01",
      "order": 1,
      "kind": "text",
      "title": "Set up your workspace",
      "description": null,
      "primaryAssetId": null,
      "attachmentAssetIds": [],
      "fileUrl": null,
      "embed": null,
      "body": {
        "markdown": "## Install\n\n1. Download the starter kit…"
      },
      "isPreview": false,
      "visibility": "VISIBLE",
      "releaseAt": null,
      "releaseAfterDays": 2,
      "allowDownload": false,
      "countsTowardCompletion": true,
      "isPrerequisite": false
    }
  ],
  "products": [
    {
      "productId": "prod_example01",
      "tierId": null
    }
  ]
}

Duplicate a deliverable

POST/sites/{id}/deliverables/{deliverableId}/duplicate
betacommerce:managedefault (120/minute per token)

Copy a deliverable with its settings and the whole chapter/unit tree (files are shared, not copied). Product links, entitlements, learner progress and downloads are not copied: the copy starts with no learners. Pass a different structure to switch between COURSE and DOWNLOAD (the structure is fixed after creation); COURSE to DOWNLOAD drops the chapters and keeps their units in the same order. Errors: FORBIDDEN, DELIVERABLE_NOT_FOUND, VALIDATION (details.issues).

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • deliverableIdstring · pathrequired

    Deliverable to copy

Request body

  • titlestringrequired

    Title of the copy

  • structure"COURSE" | "DOWNLOAD"

    Structure of the copy; defaults to the source's.

Response 201

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • coverAssetIdstring | nullrequired
  • structure"COURSE" | "DOWNLOAD"required

    COURSE has chapters and tracks progress; DOWNLOAD is a flat file list (no progress, new units allow download by default). Access rules are identical.

  • status"ACTIVE" | "ARCHIVED"required
  • grantsstring[]required

    Commercial feature keys (e.g. ["premium"]) granted when a buyer purchases or is granted this deliverable; matched by ContentCollection.accessPolicy and entitlements.check.

  • authorIdsstring[]required

    Authors/instructors shown on the sales page and the learner page, in order. Ids come from the site's shared author list (also used by posts; managed in the console under Posts › Settings).

  • unitCountintegerrequired

    Leaf units only; chapters are not counted.

  • productIdsstring[]required

    Products that grant this deliverable on purchase (see products.update deliverables).

  • createdAtstringrequired
  • updatedAtstringrequired
  • settingsobjectrequired
  • settings.completionRuleobjectrequired
  • settings.completionRule.type"all_units"required
  • settings.certificateobjectrequired

    When enabled, a certificate (serial + issue date) is issued the first time a learner completes the deliverable; learners fetch it with Customer API GET /deliverables/:id/certificate. The PDF is generated on download from the current settings, course title, learner name and site branding (logo, brand colour), so edits apply to every certificate; only the serial and issue date are fixed. Send every certificate field when updating it. Use deliverables.certificate_preview to see it.

  • settings.certificate.enabledbooleanrequired
  • settings.certificate.titlestring | nullrequired

    Certificate heading; null = the site-language default ("Certificate of Completion").

  • settings.certificate.signatureNamestring | nullrequired

    Signer's name or organisation; null = no signature block.

  • settings.certificate.signatureTitlestring | nullrequired

    Signer's title printed under the name, e.g. "Lead instructor".

  • settings.certificate.signatureAssetIdstring | nullrequired

    Signature image: a public image asset id (same rule as coverAssetId); printed above the signature line.

  • settings.certificate.showLogobooleanrequired

    Print the site's brand logo (site settings) at the top; icon logos are skipped.

  • settings.certificate.notestring | nullrequired

    One line printed under the course title, e.g. "12 hours of instruction".

  • settings.certificate.backgroundAssetIdstring | nullrequired

    Background image: a public image asset id (same rule as coverAssetId), centred and cropped to fill an A4 landscape page (recommended 3508 × 2480 px). When set, the default border is not drawn; text positions stay fixed, so keep the centre of the design clear.

  • settings.certificate.backgroundOverlaybooleanrequired

    Lay a semi-transparent white layer over the background image so text stays readable on busy designs; no effect without a background image.

  • settings.commentsobjectrequired
  • settings.comments.enabledbooleanrequired
  • settings.comments.threadedbooleanrequired
  • settings.comments.requireReviewbooleanrequired
  • settings.comments.reactionsbooleanrequired
  • settings.requireSequentialbooleanrequired

    Learners must complete each unit before opening the next (free-preview units are exempt). Locked units come back with access.reason prerequisite.

  • settings.mediaCompletionPercentintegerrequired

    Share of a video/audio unit a learner must actually watch for it to count as completed (50-100, step 5, default 90). Measured from the segments played, so skipping to the end does not count; 100 keeps a 2-second tolerance at the end. Custom players that only report positionSeconds are measured by the furthest position. Raising it never un-completes learners.

  • fieldDataobject | nullrequired
  • unitsobject[]required

    Flat list ordered by chapter then unit; use parentId to rebuild the tree.

  • units[].idstringrequired
  • units[].parentIdstring | nullrequired

    Chapter id for units inside a chapter; null for top-level chapters or flat units.

  • units[].orderintegerrequired
  • units[].kindstringrequired

    Open string. Known values: video, audio, file, text, quiz; "chapter" for grouping rows. Unknown kinds render as a download card.

  • units[].titlestring | nullrequired
  • units[].descriptionstring | nullrequired
  • units[].primaryAssetIdstring | nullrequired

    Media-library asset (private products bucket). Upload with media.upload first.

  • units[].attachmentAssetIdsstring[]required
  • units[].fileUrlstring | nullrequired

    Only for Kanorio template sample media (not a media-library asset). Real files are referenced by primaryAssetId.

  • units[].embedobject | nullrequired

    External video embed (youtube/vimeo/loom). Not protected by Kanorio; use for FREE sites that cannot host video.

  • units[].embed.providerstringrequired
  • units[].embed.idstringrequired
  • units[].bodyanyrequired

    text units: { markdown }. quiz units: { questions: [{ id, type: "single" | "multiple" | "true_false", prompt, options: [{ id, text, correct: boolean }], explanation? }], settings: { passingPercent (0-100, default 70), maxAttempts (1-99 or null = unlimited), showAnswers: "never" | "after_pass" | "always" } }; validated on write (UNIT_TREE_INVALID quiz_body_invalid). Learners never see correct/explanation; the server grades Customer API POST /units/:id/quiz.

  • units[].isPreviewbooleanrequired

    Free preview: anonymous visitors can open it.

  • units[].visibility"VISIBLE" | "HIDDEN"required
  • units[].releaseAtstring | nullrequired

    Absolute unlock time.

  • units[].releaseAfterDaysinteger | nullrequired

    Unlock N days after the learner's entitlement started.

  • units[].allowDownloadbooleanrequired
  • units[].countsTowardCompletionbooleanrequired

    false = bonus unit: not counted in percent or completion, never locked by requireSequential and never a gate for later units.

  • units[].isPrerequisitebooleanrequired

    Units after this one stay locked until the learner completes it, even when requireSequential is off.

  • productsobject[]required

    Products (variants) that grant this deliverable; tierId null = every variant. Access duration is pricingTiers[].accessDays on the product.

  • products[].productIdstringrequired
  • products[].tierIdstring | nullrequired
  • duplicatedFromstringrequired

Errors

  • FORBIDDEN 403
  • DELIVERABLE_NOT_FOUND 404
  • VALIDATION 400 · details.issues

MCP tool deliverables_duplicate

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/deliverables/{deliverableId}/duplicate" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Sourdough Fundamentals (recipe cards)","structure":"DOWNLOAD"}'
Response
{
  "id": "dlv_example02",
  "title": "Sourdough Fundamentals (recipe cards)",
  "description": "Six-week video course with downloadable recipe cards.",
  "coverAssetId": "asset_example01",
  "structure": "DOWNLOAD",
  "status": "ACTIVE",
  "grants": [
    "premium"
  ],
  "authorIds": [
    "author_headbaker01"
  ],
  "unitCount": 2,
  "productIds": [],
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z",
  "settings": {
    "completionRule": {
      "type": "all_units"
    },
    "certificate": {
      "enabled": false,
      "title": null,
      "signatureName": null,
      "signatureTitle": null,
      "signatureAssetId": null,
      "showLogo": true,
      "note": null,
      "backgroundAssetId": null,
      "backgroundOverlay": false
    },
    "comments": {
      "enabled": false,
      "threaded": true,
      "requireReview": true,
      "reactions": false
    },
    "requireSequential": false,
    "mediaCompletionPercent": 90
  },
  "fieldData": null,
  "units": [
    {
      "id": "unit_video02",
      "parentId": null,
      "order": 0,
      "kind": "video",
      "title": "Welcome and course overview",
      "description": "What you will build in six weeks.",
      "primaryAssetId": "asset_example01",
      "attachmentAssetIds": [],
      "fileUrl": null,
      "embed": null,
      "body": null,
      "isPreview": true,
      "visibility": "VISIBLE",
      "releaseAt": null,
      "releaseAfterDays": null,
      "allowDownload": false,
      "countsTowardCompletion": true,
      "isPrerequisite": false
    },
    {
      "id": "unit_text02",
      "parentId": null,
      "order": 1,
      "kind": "text",
      "title": "Set up your workspace",
      "description": null,
      "primaryAssetId": null,
      "attachmentAssetIds": [],
      "fileUrl": null,
      "embed": null,
      "body": {
        "markdown": "## Install\n\n1. Download the starter kit…"
      },
      "isPreview": false,
      "visibility": "VISIBLE",
      "releaseAt": null,
      "releaseAfterDays": 2,
      "allowDownload": false,
      "countsTowardCompletion": true,
      "isPrerequisite": false
    }
  ],
  "products": [],
  "duplicatedFrom": "dlv_example01"
}

Archive a deliverable

POST/sites/{id}/deliverables/{deliverableId}/archive
betacommerce:managedefault (120/minute per token)

Archive a deliverable: it can no longer be granted or sold, existing learners keep access until you revoke their entitlements. Deliverables are never deleted. Errors: FORBIDDEN, DELIVERABLE_NOT_FOUND.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • deliverableIdstring · pathrequired

    Deliverable id. Get it from deliverables.list.

Response 200

  • idstringrequired
  • titlestringrequired
  • descriptionstring | nullrequired
  • coverAssetIdstring | nullrequired
  • structure"COURSE" | "DOWNLOAD"required

    COURSE has chapters and tracks progress; DOWNLOAD is a flat file list (no progress, new units allow download by default). Access rules are identical.

  • status"ACTIVE" | "ARCHIVED"required
  • grantsstring[]required

    Commercial feature keys (e.g. ["premium"]) granted when a buyer purchases or is granted this deliverable; matched by ContentCollection.accessPolicy and entitlements.check.

  • authorIdsstring[]required

    Authors/instructors shown on the sales page and the learner page, in order. Ids come from the site's shared author list (also used by posts; managed in the console under Posts › Settings).

  • unitCountintegerrequired

    Leaf units only; chapters are not counted.

  • productIdsstring[]required

    Products that grant this deliverable on purchase (see products.update deliverables).

  • createdAtstringrequired
  • updatedAtstringrequired

Errors

  • FORBIDDEN 403
  • DELIVERABLE_NOT_FOUND 404

MCP tool deliverables_archive

curl -X POST "https://app.kanorio.com/api/v1/sites/{id}/deliverables/{deliverableId}/archive" \
  -H "Authorization: Bearer $KANORIO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Response
{
  "id": "dlv_example01",
  "title": "Sourdough Fundamentals",
  "description": "Six-week video course with downloadable recipe cards.",
  "coverAssetId": "asset_example01",
  "structure": "COURSE",
  "status": "ARCHIVED",
  "grants": [
    "premium"
  ],
  "authorIds": [
    "author_headbaker01"
  ],
  "unitCount": 3,
  "productIds": [
    "prod_example01"
  ],
  "createdAt": "2026-10-01T02:30:00.000Z",
  "updatedAt": "2026-10-06T08:00:00.000Z"
}

Certificate preview

GET/sites/{id}/deliverables/{deliverableId}/certificate-preview
betastore:viewdefault (120/minute per token)

Short-lived URL (10 minutes) of a sample certificate PDF for one course deliverable, rendered exactly like a learner's certificate from the saved settings and site branding, with a "Preview" watermark and no serial. Nothing is issued or stored. Pass learnerName to see how a long or non-Latin name fits. Errors: FORBIDDEN, DELIVERABLE_NOT_FOUND, NOT_A_COURSE (download packs have no certificates).

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • deliverableIdstring · pathrequired

    Deliverable id. Get it from deliverables.list.

  • learnerNamestring · query

    Sample learner name; omitted = the site-language sample name.

Response 200

  • urlstringrequired

    Open or download the PDF; no auth needed, expires with expiresAt.

  • expiresInintegerrequired

    Seconds until the URL stops working.

  • expiresAtstringrequired

    ISO-8601 timestamp with timezone, e.g. 2026-10-05T12:34:56.789Z.

Errors

  • FORBIDDEN 403
  • DELIVERABLE_NOT_FOUND 404
  • NOT_A_COURSE 422 · download packs have no certificates

MCP tool deliverables_certificate_preview

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/deliverables/{deliverableId}/certificate-preview?learnerName=Alex+Chen" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "url": "https://app.kanorio.com/api/certificates/eyJrIjoicCJ9.3f1c…",
  "expiresIn": 600,
  "expiresAt": "2026-10-06T08:00:00.000Z"
}

Deliverable insights

GET/sites/{id}/deliverable-insights
betastore:viewdefault (120/minute per token)

Learning insights for one course or all courses: current state (learner statuses, stalled count, completion rate, median days to complete, quiz pass rate, certificates, expiring learners) plus period activity (active learners, new starts, completions, hours watched, daily actives). With deliverableId: that course's outline (reached/completed per unit, biggest drop) and progress distribution; without it: one row per course for comparison. Numbers that do not apply are null, never 0 (e.g. quizPassRate when the course has no quiz). No learner names: use progress.list for individual learners. Errors: FORBIDDEN, DELIVERABLE_NOT_FOUND, VALIDATION.

Parameters

  • idstring · pathrequired

    Website id. Get it from sites.list or from sites.create.

  • deliverableIdstring · query

    One course; omit for every course on the site.

  • daysinteger · query

    Number of calendar days ending today in the website's timezone (1 to 365, defaults to 30). Ignored when from and to are provided.

  • fromstring · query

    Start calendar date (YYYY-MM-DD) in the website's timezone, inclusive. Must be paired with to.

  • tostring · query

    End calendar date (YYYY-MM-DD) in the website's timezone, inclusive, up to today. Must be paired with from.

Response 200

  • rangeobjectrequired
  • range.fromstringrequired

    First calendar date of the period (website timezone).

  • range.tostringrequired

    Last calendar date of the period (website timezone).

  • range.timezonestringrequired
  • currentobjectrequired
  • current.learnersintegerrequired

    Contacts with an active entitlement (counted once per course).

  • current.statusesobjectrequired
  • current.statuses.notStartedintegerrequired
  • current.statuses.inProgressintegerrequired
  • current.statuses.completedintegerrequired
  • current.statuses.expiredIncompleteintegerrequired
  • current.stalledintegerrequired

    Not started 14 days after being granted, or no activity for 7 days with progress; learners idle more than 90 days are not counted.

  • current.expiringIncompleteintegerrequired

    Access ends within 14 days and the course is not completed.

  • current.completedintegerrequired
  • current.completionRatenumber | nullrequired

    0-1; null when there are no learners.

  • current.medianDaysToCompletenumber | nullrequired

    null until someone has completed.

  • current.quizPassRatenumber | nullrequired

    0-1; null when there is no quiz or nobody has attempted one.

  • current.certificatesinteger | nullrequired

    Certificates issued; null when no course in scope issues certificates.

  • periodobjectrequired
  • period.activeintegerrequired

    Learners with any progress, playback or download in the period.

  • period.newStartsintegerrequired
  • period.completesintegerrequired
  • period.watchedSecondsinteger | nullrequired

    Wall-clock playback in the period; null when there are no media units.

  • period.dailyActiveobject[]required
  • period.dailyActive[].datestringrequired
  • period.dailyActive[].activeintegerrequired
  • outlineobject | nullrequired

    Only with deliverableId.

  • outline.unitsobject[]required
  • outline.units[].unitIdstringrequired
  • outline.units[].titlestringrequired
  • outline.units[].chapterTitlestring | nullrequired
  • outline.units[].kindstringrequired
  • outline.units[].countsTowardCompletionbooleanrequired
  • outline.units[].reachedintegerrequired

    Learners who opened the unit (cumulative).

  • outline.units[].completedintegerrequired
  • outline.units[].avgCoveredPercentnumber | nullrequired

    Media units: mean share watched per learner, 0-100; otherwise null.

  • outline.units[].durationnumber | nullrequired
  • outline.biggestDropUnitIdstring | nullrequired
  • distributionobjectrequired
  • distribution.histogramany[]required

    Learners by progress band: 0-25, 25-50, 50-75, 75-100 percent.

  • distribution.typicalobject[]required

    Median progress N days after being granted.

  • distribution.typical[].dayintegerrequired
  • distribution.typical[].medianPercentnumber | nullrequired
  • distribution.typical[].sampleintegerrequired
  • distribution.sampleintegerrequired
  • coursesobject[] | nullrequired

    One row per course; only without deliverableId.

Errors

  • FORBIDDEN 403
  • DELIVERABLE_NOT_FOUND 404
  • VALIDATION 400

MCP tool deliverables_insights

curl -X GET "https://app.kanorio.com/api/v1/sites/{id}/deliverable-insights?deliverableId=dlv_example01&days=30" \
  -H "Authorization: Bearer $KANORIO_TOKEN"
Response
{
  "range": {
    "from": "2026-09-07",
    "to": "2026-10-06",
    "timezone": "Asia/Taipei"
  },
  "current": {
    "learners": 60,
    "statuses": {
      "notStarted": 13,
      "inProgress": 35,
      "completed": 10,
      "expiredIncomplete": 2
    },
    "stalled": 23,
    "expiringIncomplete": 6,
    "completed": 10,
    "completionRate": 0.17,
    "medianDaysToComplete": 12,
    "quizPassRate": 0.8,
    "certificates": 10
  },
  "period": {
    "active": 41,
    "newStarts": 9,
    "completes": 4,
    "watchedSeconds": 98400,
    "dailyActive": [
      {
        "date": "2026-10-05",
        "active": 7
      },
      {
        "date": "2026-10-06",
        "active": 9
      }
    ]
  },
  "outline": {
    "units": [
      {
        "unitId": "unit_video01",
        "title": "Welcome",
        "chapterTitle": "Week 1 · Getting started",
        "kind": "video",
        "countsTowardCompletion": true,
        "reached": 47,
        "completed": 38,
        "avgCoveredPercent": 86,
        "duration": 612
      },
      {
        "unitId": "unit_text01",
        "title": "Reading list",
        "chapterTitle": "Week 1 · Getting started",
        "kind": "text",
        "countsTowardCompletion": true,
        "reached": 31,
        "completed": 24,
        "avgCoveredPercent": null,
        "duration": null
      }
    ],
    "biggestDropUnitId": "unit_text01"
  },
  "distribution": {
    "histogram": [
      18,
      14,
      13,
      15
    ],
    "typical": [
      {
        "day": 7,
        "medianPercent": 25,
        "sample": 52
      },
      {
        "day": 30,
        "medianPercent": 60,
        "sample": 31
      }
    ],
    "sample": 60
  },
  "courses": null
}