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

Organization

Organization profile, members, configuration, audit and credentials.

17 endpoints

Get the organization

GET/organization

The API key's organization, with headline usage numbers. WARNING: usage.revenue is a size signal, not a quotable amount — it sums the minor units of every currency the org sells in without converting them. Never state it as money; read listSales (revenueByCurrency) or getPayouts instead.

Responses

200Get the organization.
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/organization \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "cover": "string",
    "id": "string",
    "name": "string",
    "requireCheckoutTaxId": true,
    "slug": "string",
    "usage": {
      "contents": 0,
      "enrollments": 0,
      "revenue": 0
    }
  }
}

Update the organization

PATCH/organization

Updates the org's public profile — name, bio, logo, storefront cover — and the checkout tax-id requirement. Only the fields you send are changed. The slug is NOT editable here BY DESIGN: it is the org's subdomain identity ({slug} on the root domain), so renaming it breaks every existing link, and it can only be changed from the dashboard. Images must be an https URL or a previously uploaded avatar path.

Request body

biostring | null

Free-text about section. Null (or empty) clears it.

coverstring | null

Banner image on the org's public storefront. An https URL or an uploaded avatar path. Null clears it.

logostring | null

An https URL or an uploaded avatar path. Null clears it.

namestring
requireCheckoutTaxIdboolean

When true, buyers must enter a tax id to complete checkout. Turning it on adds friction to every purchase — usually driven by the org's invoicing obligations.

Responses

200Update the organization.
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/organization \
  --request PATCH \
  --header 'Authorization: Bearer cr_live_…' \
  --header 'Content-Type: application/json' \
  --data '{
  "bio": "string",
  "cover": "string",
  "logo": "string",
  "name": "string",
  "requireCheckoutTaxId": true
}'
{
  "data": {
    "bio": "string",
    "cover": "string",
    "id": "string",
    "logo": "string",
    "name": "string",
    "requireCheckoutTaxId": true,
    "slug": "string"
  }
}

Get organization minor-access settings

GET/organization/minor-access

Responses

200Get organization minor-access settings.
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/organization/minor-access \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "enabled": true,
    "policyReviewedAt": "2026-01-31T12:00:00.000Z",
    "safetyContactEmail": "learner@example.com"
  }
}

Update organization minor-access settings

PATCH/organization/minor-access

Request body

enabledbooleanrequired
policyReviewedbooleanrequired
safetyContactEmailemail | nullrequired

Responses

200Update organization minor-access 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/organization/minor-access \
  --request PATCH \
  --header 'Authorization: Bearer cr_live_…' \
  --header 'Content-Type: application/json' \
  --data '{
  "enabled": true,
  "policyReviewed": true,
  "safetyContactEmail": "learner@example.com"
}'
{
  "data": {
    "enabled": true,
    "policyReviewedAt": "2026-01-31T12:00:00.000Z",
    "safetyContactEmail": "learner@example.com"
  }
}

Get the legal seller profile

GET/organization/seller-profile

Returns the legal identity and consumer-support details published to buyers. A paid offer cannot sell until every required field is complete.

Responses

200Get the legal seller profile.
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/organization/seller-profile \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "address": {
      "city": "string",
      "country": "string",
      "line1": "string",
      "postalCode": "string",
      "region": "string",
      "line2": "string"
    },
    "legalName": "string",
    "ready": true,
    "reviewedAt": "2026-01-31T12:00:00.000Z",
    "supportEmail": "learner@example.com",
    "supportPhone": "string",
    "supportUrl": "string",
    "taxId": "string",
    "taxIdType": "br_cpf"
  }
}

Update the legal seller profile

PUT/organization/seller-profile

Stores the school's country-aware legal seller identity. Public identifiers are disclosed before checkout and snapshotted on each purchase; US EIN remains private and individual SSN/ITIN verification stays with Stripe.

Request body

addressobjectrequired
legalNamestringrequired
supportEmailemailrequired
taxIdstring | nullrequired
taxIdTypeenumrequired

br_cpfbr_cnpjus_einus_individualeu_vatnational

supportPhonestring | null
supportUrluri | null

Responses

200Update the legal seller profile.
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/organization/seller-profile \
  --request PUT \
  --header 'Authorization: Bearer cr_live_…' \
  --header 'Content-Type: application/json' \
  --data '{
  "address": {
    "city": "string",
    "country": "string",
    "line1": "string",
    "postalCode": "string",
    "region": "string",
    "line2": "string"
  },
  "legalName": "string",
  "supportEmail": "learner@example.com",
  "taxId": "string",
  "taxIdType": "br_cpf",
  "supportPhone": "string",
  "supportUrl": "https://example.com"
}'
{
  "data": {
    "address": {
      "city": "string",
      "country": "string",
      "line1": "string",
      "postalCode": "string",
      "region": "string",
      "line2": "string"
    },
    "legalName": "string",
    "ready": true,
    "reviewedAt": "2026-01-31T12:00:00.000Z",
    "supportEmail": "learner@example.com",
    "supportPhone": "string",
    "supportUrl": "string",
    "taxId": "string",
    "taxIdType": "br_cpf"
  }
}

List staff members

GET/members

The org's staff directory — every member with their org-level role. List-only: inviting or removing members happens in the dashboard (membership is managed by the auth layer, not this API).

Responses

200List staff members.
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/members \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": [
    {
      "email": "learner@example.com",
      "name": "string",
      "role": "owner",
      "userId": "string"
    }
  ]
}

Get the organization's shape

GET/organization/shape

Live signals describing what KIND of organization this is — how many members, teams and courses it has, whether payments are connected, and whether it is still a solo operation. Everything is derived from current data, never stored, so it cannot go stale. Useful as a cheap first call to orient yourself before deciding what to suggest or do: a solo org with no payments connected needs very different help from a ten-person business.

Responses

200Get the organization's shape.
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/organization/shape \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "contentCount": 0,
    "memberCount": 0,
    "paymentsConnected": true,
    "pendingInvites": 0,
    "solo": true,
    "teamCount": 0
  }
}

Resolve a human reference to an id

GET/resolve

Given a human name, slug, or email, get the id that other tools need — CALL THIS FIRST, before any tool that takes an id you do not already have. It replaces brute-forcing the list endpoints: one call searches the organization's content (title + slug), learners and staff members (name + email), teams, tags, and offers, and returns a flat ranked list of candidates with exact and prefix matches first. Scoped to the caller's organization; it never reaches across orgs. Results are a disambiguation aid, not full records — take the id and call the resource's own GET for detail. When several candidates come back and the choice is not obvious, ask the user which one they meant rather than guessing; when nothing comes back, the thing does not exist under that name — do not invent an id. type narrows the search to a single kind, which is both faster and less ambiguous when you already know what you are looking for (e.g. type=team for "the Backend team"). Note that cohort is searched ONLY when you pass type=cohort: cohorts live per offered root, so they cost a bounded scan of the organization's recent content and may miss cohorts on older ones — fall back to listContentCohorts for an exhaustive list.

Query parameters

qstringrequired

The human reference to look up: a content title or slug, a person's name or email, a team/tag/offer/cohort name. Matching is case-insensitive and partial.

limitinteger

Maximum candidates to return. Keep it small — this is for disambiguation.

typeenum

Restrict to one kind of resource. Omit to search every kind except cohort.

contentlearnermemberteamcohortoffer

Responses

200Resolve a human reference to an id.
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/resolve \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "matches": [
      {
        "href": "string",
        "id": "string",
        "label": "string",
        "sublabel": "string",
        "type": "content"
      }
    ],
    "query": "string",
    "truncated": true
  }
}

Get the custom domain

GET/organization/custom-domain

The org's custom-domain status. While unverified, dns lists the records to add at your DNS provider. The {slug}.cursare.com subdomain keeps working either way.

Responses

200Get the custom domain.
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/organization/custom-domain \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "dns": {
      "cnameHost": "string",
      "cnameTarget": "string",
      "ttl": "string",
      "txtHost": "string",
      "txtValue": "string"
    },
    "domain": "string",
    "verified": true
  }
}

Set the custom domain

PUT/organization/custom-domain

Connect (or replace) the org's custom domain. The domain is normalized and validated — platform subdomains and domains already connected to another organization are rejected. Returns the CNAME and ownership TXT records to add (use the suggested TTL), then call verify. Connecting a custom domain never removes the org's cursare.com subdomain.

Request body

domainstringrequired

The domain to connect, e.g. courses.example.com.

Responses

200Set the custom domain.
400Validation failed or the request body is malformed.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/organization/custom-domain \
  --request PUT \
  --header 'Authorization: Bearer cr_live_…' \
  --header 'Content-Type: application/json' \
  --data '{
  "domain": "string"
}'
{
  "data": {
    "dns": {
      "cnameHost": "string",
      "cnameTarget": "string",
      "ttl": "string",
      "txtHost": "string",
      "txtValue": "string"
    },
    "domain": "string",
    "verified": true
  }
}

Disconnect the custom domain

DELETE/organization/custom-domain

Removes the custom domain entirely. Learners keep reaching the org at its {slug}.cursare.com subdomain.

Responses

200Disconnect the custom domain.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/organization/custom-domain \
  --request DELETE \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "deleted": true
  }
}

Verify the custom domain

POST/organization/custom-domain/verify

Performs a live DNS lookup of the _cursare-verify TXT record (counts against the write rate limit). On a match the domain is marked verified and registered for TLS + routing. On a mismatch this returns 400 — DNS records can take a few minutes (up to the record's TTL) to propagate, so retry later.

Responses

200Verify the custom domain.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/organization/custom-domain/verify \
  --request POST \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "verified": true
  }
}

List audit events

GET/audit-events

The organization's administrative trail, newest first — who did what, when. This is what answers “what changed in my org this week?”: course publishes and deletions, price and offer changes, learner grants and removals, refunds, team and member changes, integration connects and disconnects. Org-admin only. Read-only: events are written by the actions themselves and cannot be edited through the API. Use the export endpoint when the requested period is outside recent history.

Query parameters

cursorstring

Opaque continuation cursor returned by the previous page. Do not construct or modify it.

limitinteger

How many events to return, newest first. Applied AFTER since/until, so a full page back means the window holds more — narrow it and read again.

sincedate-time

Only events at or after this instant — this is how you scope to a period (since = 7 days ago answers “what changed this week?”). Omit for the whole trail.

untildate-time

Only events at or before this instant.

Responses

200List audit events.
400Validation failed or the request body is malformed.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/audit-events \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "items": [
      {
        "action": "string",
        "actorName": "string",
        "actorUserId": "string",
        "createdAt": "2026-01-31T12:00:00.000Z",
        "detail": {},
        "id": "string",
        "targetId": "string"
      }
    ],
    "nextCursor": "string"
  }
}

Export audit history

GET/audit-events/export

Streams the authorized organization's verified audit history as JSON Lines for a required date range. The stream merges archived and recent events exactly once and never exposes private storage paths, provider URLs, credentials, actor profile snapshots, or secrets. Organization owner or admin only.

Query parameters

sincedate-timerequired

Inclusive UTC start instant for the required export range.

untildate-timerequired

Exclusive UTC end instant for the required export range.

Responses

200Export audit history.
400Validation failed or the request body is malformed.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/audit-events/export \
  --header 'Authorization: Bearer cr_live_…'

List API keys

GET/api-keys

The org's live (non-revoked) developer keys — never the secret itself, only its prefix, name and last-used time. Use it to audit which credentials exist and which have gone stale. To tell which row is the credential you are calling with, match prefix against the first 12 characters of your own bearer token; revoking that one cuts off the current session (see revokeApiKey). If you authenticated with an OAuth access token rather than a cr_live_… key, none of these rows is yours and revoking any of them cannot lock you out. New keys are minted in the dashboard (Settings → Developer → API keys) on purpose: a key grants full org-admin authority and outlives the session that created it, so it is not something an assistant issues.

Responses

200List API keys.
401Missing, invalid or revoked API key.
403The key's organization does not own this resource.
429Rate limit exceeded (240 reads/min, 60 writes/min per key).
500Unexpected server error.
curl https://api.cursare.com/v1/api-keys \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": [
    {
      "createdAt": "2026-01-31T12:00:00.000Z",
      "expiresAt": "2026-01-31T12:00:00.000Z",
      "id": "string",
      "lastUsedAt": "2026-01-31T12:00:00.000Z",
      "name": "string",
      "prefix": "string"
    }
  ]
}

Revoke an API key

DELETE/api-keys/{id}

Immediately and permanently disables the key — every integration still using it starts getting 401s on the next request. There is no un-revoke. Confirm with the operator which key is safe to kill (check lastUsedAt from listApiKeys) before calling this; revoking the key that authenticates the current session will end it.

Path parameters

idstring

The API key id (from listApiKeys) — not the secret.

Responses

200Revoke an API key.
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/api-keys/{id} \
  --request DELETE \
  --header 'Authorization: Bearer cr_live_…'
{
  "data": {
    "id": "string",
    "revoked": true
  }
}

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.