Skip to content
cursareDocs
Sign inGet started
Documentation
  • Overview
  • Index2
  • Organization17
  • Sales6
  • Insights8
  • Reports and safety7
  • Minor accounts8
  • Minor safety3
  • Offers11
  • Media1
  • Contents10
  • Learner delivery1
  • Learner runtime5
  • Learners12
  • Cohorts12
  • Intake forms5
  • Campaigns4
  • Teams8
  • Affiliates7
  • Links7
  • Reviews1
  • Integrations26
  • MCP2
  • Webhooks6

Contents

Reusable content: create, configure, compose, publish and delete.

10 endpoints

List contents

GET/contents

Every content in the org, drafts included — filterable and paginated.

Query parameters

hasUnpublishedChangesenum

Filter independently by pending document changes.

truefalse

isPublishedenum

Filter by whether a published document exists.

truefalse

pageinteger
pageSizeinteger
qstring

Substring match on title or route segment (case-insensitive).

tagstring

Only contents carrying this tag (exact name).

Responses

200List contents.
400Validation failed or the request body is malformed.
401Missing, invalid or revoked API key.
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "contents": [
      {
        "certificateTheme": "classic",
        "createdAt": "2026-01-31T12:00:00.000Z",
        "description": "string",
        "hasUnpublishedChanges": true,
        "id": "string",
        "isPublished": true,
        "ownerId": "string",
        "publishedAt": "2026-01-31T12:00:00.000Z",
        "routeSegment": "string",
        "tags": [
          "string"
        ],
        "teamId": "string",
        "theme": "string",
        "title": "string",
        "updatedAt": "2026-01-31T12:00:00.000Z"
      }
    ],
    "page": 0,
    "pageSize": 0,
    "total": 0
  }
}

Create a draft content

POST/contents

Creates one unpublished content with an organization-unique route segment and no offer. Every document may interleave learning blocks and references. Optional tags are applied after creation; a validation failure removes the draft. Create an offer separately when the content should be enrollable or sellable.

Request body

slugstring
tagsstring[]

Initial tag list (names must exist in the tag registry).

teamIdstring
titlestring

Responses

201Create a draft content.
400Validation failed or the request body is malformed.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
404The resource does not exist (or belongs to another org).
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents \
  --request POST \
  --header 'Authorization: Bearer cr_live_…' \
  --header 'Content-Type: application/json' \
  --data '{
  "slug": "string",
  "tags": [
    "string"
  ],
  "teamId": "string",
  "title": "string"
}'
{
  "data": {
    "certificateTheme": "classic",
    "createdAt": "2026-01-31T12:00:00.000Z",
    "description": "string",
    "hasUnpublishedChanges": true,
    "id": "string",
    "isPublished": true,
    "ownerId": "string",
    "publishedAt": "2026-01-31T12:00:00.000Z",
    "routeSegment": "string",
    "tags": [
      "string"
    ],
    "teamId": "string",
    "theme": "string",
    "title": "string",
    "updatedAt": "2026-01-31T12:00:00.000Z"
  }
}

Get a content

GET/contents/{id}

Path parameters

idstring

The content id.

Responses

200Get a content.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
404The resource does not exist (or belongs to another org).
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents/{id} \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "certificateTheme": "classic",
    "createdAt": "2026-01-31T12:00:00.000Z",
    "description": "string",
    "hasUnpublishedChanges": true,
    "id": "string",
    "isPublished": true,
    "ownerId": "string",
    "publishedAt": "2026-01-31T12:00:00.000Z",
    "routeSegment": "string",
    "tags": [
      "string"
    ],
    "teamId": "string",
    "theme": "string",
    "title": "string",
    "updatedAt": "2026-01-31T12:00:00.000Z"
  }
}

Update content settings

PATCH/contents/{id}

Updates editorial settings only: discovery metadata, tags, content and certificate themes, slug, and ownership. Commercial, entry, capacity, and delivery terms belong to offer resources. Discovery metadata, tags, themes, route segment and ownership apply to every content. Title and description live inside the document header and are edited in the composer and read back via GET /contents/{id}.

Path parameters

idstring

The content id.

Request body

certificateThemeenum

classicmoderneditorialminimal

featuredboolean
noindexboolean
ownerobject | object
seoDescriptionstring | null
seoTitlestring | null
slugstring
tagsstring[]
themeenum | string | any | null

Responses

200Update content settings.
400Validation failed or the request body is malformed.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
404The resource does not exist (or belongs to another org).
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents/{id} \
  --request PATCH \
  --header 'Authorization: Bearer cr_live_…' \
  --header 'Content-Type: application/json' \
  --data '{
  "certificateTheme": "classic",
  "featured": true,
  "noindex": true,
  "owner": {
    "teamId": "string"
  },
  "seoDescription": "string",
  "seoTitle": "string",
  "slug": "string",
  "tags": [
    "string"
  ],
  "theme": "ember"
}'
{
  "data": {
    "certificateTheme": "classic",
    "createdAt": "2026-01-31T12:00:00.000Z",
    "description": "string",
    "hasUnpublishedChanges": true,
    "id": "string",
    "isPublished": true,
    "ownerId": "string",
    "publishedAt": "2026-01-31T12:00:00.000Z",
    "routeSegment": "string",
    "tags": [
      "string"
    ],
    "teamId": "string",
    "theme": "string",
    "title": "string",
    "updatedAt": "2026-01-31T12:00:00.000Z"
  }
}

Delete a content

DELETE/contents/{id}

Deletion is refused if the content is referenced by another or purchased.

Path parameters

idstring

The content id.

Responses

200Delete a content.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
404The resource does not exist (or belongs to another org).
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents/{id} \
  --request DELETE \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "deleted": true,
    "id": "string"
  }
}

Publish the current draft

POST/contents/{id}/publish

Atomically validates the draft, derives its ordered published manifest, and writes both the learner document and manifest. Every reference must target published content in the same organization; self-references and cycles are refused.

Path parameters

idstring

The content id.

Responses

200Publish the current draft.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
404The resource does not exist (or belongs to another org).
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents/{id}/publish \
  --request POST \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "certificateTheme": "classic",
    "createdAt": "2026-01-31T12:00:00.000Z",
    "description": "string",
    "hasUnpublishedChanges": true,
    "id": "string",
    "isPublished": true,
    "ownerId": "string",
    "publishedAt": "2026-01-31T12:00:00.000Z",
    "routeSegment": "string",
    "tags": [
      "string"
    ],
    "teamId": "string",
    "theme": "string",
    "title": "string",
    "updatedAt": "2026-01-31T12:00:00.000Z"
  }
}

Duplicate a content

POST/contents/{id}/duplicate

Creates a fresh unpublished copy with a collision-safe route segment. It copies the document and editorial settings, but never offers, learners, cohorts, reviews, purchases, sales history, or the published snapshot.

Path parameters

idstring

The content id to copy.

Responses

201Duplicate a content.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
404The resource does not exist (or belongs to another org).
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents/{id}/duplicate \
  --request POST \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "certificateTheme": "classic",
    "createdAt": "2026-01-31T12:00:00.000Z",
    "description": "string",
    "hasUnpublishedChanges": true,
    "id": "string",
    "isPublished": true,
    "ownerId": "string",
    "publishedAt": "2026-01-31T12:00:00.000Z",
    "routeSegment": "string",
    "tags": [
      "string"
    ],
    "teamId": "string",
    "theme": "string",
    "title": "string",
    "updatedAt": "2026-01-31T12:00:00.000Z"
  }
}

Get the document authoring guide

GET/document-schema

The shared JSON schema, stable learner identifiers, composition guidance, limits and complete valid documents. MCP clients must call get_document_schema before replace_content_document.

Responses

200Get the document authoring guide.
400Validation failed or the request body is malformed.
401Missing, invalid or revoked API key.
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/document-schema \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "completeDocument": {
      "body": [
        "string"
      ],
      "header": {
        "description": "string",
        "image": {
          "alt": "string",
          "src": "string",
          "assetId": "string",
          "attribution": {
            "creatorName": "string",
            "creatorUrl": "string",
            "sourceUrl": "string"
          },
          "focalPoint": {
            "x": 0,
            "y": 0
          },
          "height": 0,
          "mimeType": "string",
          "width": 0
        },
        "title": "string",
        "layout": [
          null
        ]
      },
      "version": 0
    },
    "compositionGuidelines": [
      "string"
    ],
    "dialect": "string",
    "documentRules": {
      "canonicalization": [
        "string"
      ],
      "ids": "string",
      "limits": {},
      "structure": "string"
    },
    "documentSchema": {},
    "minimalDocument": {
      "body": [
        "string"
      ],
      "header": {
        "description": "string",
        "image": {
          "alt": "string",
          "src": "string",
          "assetId": "string",
          "attribution": {
            "creatorName": "string",
            "creatorUrl": "string",
            "sourceUrl": "string"
          },
          "focalPoint": {
            "x": 0,
            "y": 0
          },
          "height": 0,
          "mimeType": "string",
          "width": 0
        },
        "title": "string",
        "layout": [
          null
        ]
      },
      "version": 0
    },
    "overview": "string",
    "version": 0
  }
}

Get the content document

GET/contents/{id}/document

The editable Cursare JSON draft plus the published document learners currently read. The draft includes grading keys such as quiz correctOptionIds and stable learner state ids for polls, quizzes, headings and references, so treat this payload as org-staff only: never proxy it to learners or embed it in learner-facing pages.

Path parameters

idstring

The content id.

Responses

200Get the content document.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
404The resource does not exist (or belongs to another org).
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents/{id}/document \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "draftDocument": {
      "body": [
        "string"
      ],
      "header": {
        "description": "string",
        "image": {
          "alt": "string",
          "src": "string",
          "assetId": "string",
          "attribution": {
            "creatorName": "string",
            "creatorUrl": "string",
            "sourceUrl": "string"
          },
          "focalPoint": {
            "x": 0,
            "y": 0
          },
          "height": 0,
          "mimeType": "string",
          "width": 0
        },
        "title": "string",
        "layout": [
          null
        ]
      },
      "version": 0
    },
    "publishedAt": "2026-01-31T12:00:00.000Z",
    "publishedDocument": {
      "body": [
        "string"
      ],
      "header": {
        "description": "string",
        "image": {
          "alt": "string",
          "src": "string",
          "assetId": "string",
          "attribution": {
            "creatorName": "string",
            "creatorUrl": "string",
            "sourceUrl": "string"
          },
          "focalPoint": {
            "x": 0,
            "y": 0
          },
          "height": 0,
          "mimeType": "string",
          "width": 0
        },
        "title": "string",
        "layout": [
          null
        ]
      },
      "version": 0
    }
  }
}

Replace the draft document

PUT/contents/{id}/document

Replaces the ENTIRE draft with a version 2 JSON document (max 2 MB); learners see nothing until publish. MCP clients must call get_document_schema for the shared schema and composition guidance. The header contains cover, title and description; body contains ordered typed blocks and recursive references. PRESERVE STABLE IDS when editing: headings, references, polls and quiz ids key learner answers, progress and study position — changing them can orphan that state. The returned draft includes answer keys and must not be proxied to learners.

Path parameters

idstring

The content id.

Request body

documentobjectrequired

The full replacement Cursare JSON draft.

Responses

200Replace the draft document.
400Validation failed or the request body is malformed.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
404The resource does not exist (or belongs to another org).
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/contents/{id}/document \
  --request PUT \
  --header 'Authorization: Bearer cr_live_…' \
  --header 'Content-Type: application/json' \
  --data '{
  "document": {
    "body": [
      "string"
    ],
    "header": {
      "description": "string",
      "image": {
        "alt": "string",
        "src": "string",
        "assetId": "string",
        "attribution": {
          "creatorName": "string",
          "creatorUrl": "string",
          "sourceUrl": "string"
        },
        "focalPoint": {
          "x": 0,
          "y": 0
        },
        "height": 0,
        "mimeType": "string",
        "width": 0
      },
      "title": "string",
      "layout": [
        null
      ]
    },
    "version": 0
  }
}'
{
  "data": {
    "draftDocument": {
      "body": [
        "string"
      ],
      "header": {
        "description": "string",
        "image": {
          "alt": "string",
          "src": "string",
          "assetId": "string",
          "attribution": {
            "creatorName": "string",
            "creatorUrl": "string",
            "sourceUrl": "string"
          },
          "focalPoint": {
            "x": 0,
            "y": 0
          },
          "height": 0,
          "mimeType": "string",
          "width": 0
        },
        "title": "string",
        "layout": [
          null
        ]
      },
      "version": 0
    },
    "publishedAt": "2026-01-31T12:00:00.000Z",
    "publishedDocument": {
      "body": [
        "string"
      ],
      "header": {
        "description": "string",
        "image": {
          "alt": "string",
          "src": "string",
          "assetId": "string",
          "attribution": {
            "creatorName": "string",
            "creatorUrl": "string",
            "sourceUrl": "string"
          },
          "focalPoint": {
            "x": 0,
            "y": 0
          },
          "height": 0,
          "mimeType": "string",
          "width": 0
        },
        "title": "string",
        "layout": [
          null
        ]
      },
      "version": 0
    }
  }
}

Your privacy choices

The technical Tag Manager container is required to apply your choices. Analytics and marketing cookies and storage remain optional and stay off until you authorize them. Privacy Policy.

Sign-in, security, core functions and consent enforcement.

Audience measurement such as Google Analytics.

Marketing storage, campaign attribution and optional tags.