casset/docs
FeaturesOpen app
docs indexreference
00Overview01Thesis02Architecture03System reality04Roadmap05Investor brief06Technical brief07Full tech HTML08Casset Apps09Headless API10Playback11Audio pipeline12Commerce13Base anchoring14Hook system15Music video16Theming17Creator guide18Glossary
Headless APIDeployed · unsupported
QuickstartExamplesAPI ReferenceSDK
Advanced
React adapterStarter detailsError handlingRetries & timeoutsUse casesRequest IDs & safe loggingAPI versioningLocal sandboxLocal webhooksAvailability & limitationsFAQChangelogDesign principles
Headless API · v1 reference

Headless API v1 reference.

Two unauthenticated GET routes: one public Artist and one public Catalog.

These routes are deployed, but they are not currently available for supported production use. Requests may intentionally fail closed with 503 ResourceUnavailable. No uptime, availability, or production-use commitment is offered.

Endpoints

GET /api/v1/artists/{handle}
GET /api/v1/artists/{handle}/catalog

Before you call the API

Headless API conventions
Concernv1 behavior
Base URLThe deployed /api/v1 route family is unsupported for production use and may fail closed with 503. Use exact mocks or a local Casset origin for reliable evaluation.
MethodGET only. The SDK exposes no write operation.
AuthenticationNone on /api/v1. A Bearer credential is required only on /api/sandbox/v1 counterparts.
Handle3–30 lowercase letters, digits, underscores, or hyphens: ^[a-z0-9_-]{3,30}$.
Content typeapplication/json
Success cachepublic, max-age=0, must-revalidate
Error cacheprivate, no-store
Rate limit60 requests per IP per 60 seconds. The check runs before handle validation, so 429—or a production limiter 503—can preempt 400. 429 includes Retry-After.
CorrelationSend x-request-id. Casset mirrors a valid value or generates one.

Get public artist

GET /api/v1/artists/{handle}

Returns bounded public identity for one published, non-private Profile World. It never returns an internal artist or user ID.

curl

curl --include \
  --header "Accept: application/json" \
  --header "X-Request-Id: reference-artist-001" \
  http://127.0.0.1:3000/api/v1/artists/connor

TypeScript

const artist = await casset.getArtist("connor", {
  requestId: "reference-artist-001",
})

console.log(artist.artist.displayName)
console.log(artist.links.catalog)

200 response

HTTP/1.1 200 OK
Cache-Control: public, max-age=0, must-revalidate
Content-Type: application/json
X-Request-Id: reference-artist-001

{
  "schema": "casset.public-artist.v1",
  "artist": {
    "handle": "connor",
    "displayName": "Connor James",
    "bio": "Multi-instrumentalist, singer/songwriter, and producer.",
    "verified": true
  },
  "links": {
    "profile": "http://127.0.0.1:3000/connor",
    "catalog": "http://127.0.0.1:3000/api/v1/artists/connor/catalog"
  }
}

Empty response

No empty Artist success

The Artist route has no empty 200 representation. If the handle is unknown, private, or unpublished, the route returns the same non-retryable404 RESOURCE_UNAVAILABLE. A missing biography is represented asbio: null.

Fields

Public Artist response fields
FieldTypeMeaningLimit
schemaliteralcasset.public-artist.v1Exact
artist.handlestringCanonical public handle3–30
artist.displayNamestringPublic display name160
artist.biostring | nullPublic biography when present2,000
artist.verifiedbooleanPublic verified stateExact
links.profileHTTPS, loopback HTTP, or root-relative linkCanonical Profile World2,048
links.catalogHTTPS, loopback HTTP, or root-relative linkCanonical v1 Catalog read2,048

Get public Catalog

GET /api/v1/artists/{handle}/catalog

Returns one bounded page of active public Track metadata. It contains no cursor, filter, audio, artwork, lyric, storage, or playback field.

curl

curl --include \
  --header "Accept: application/json" \
  --header "X-Request-Id: reference-catalog-001" \
  http://127.0.0.1:3000/api/v1/artists/connor/catalog

TypeScript

const catalog = await casset.getCatalog("connor", {
  requestId: "reference-catalog-001",
})

for (const track of catalog.tracks) {
  console.log(track.title, track.kind, track.durationSec)
}

200 response

HTTP/1.1 200 OK
Cache-Control: public, max-age=0, must-revalidate
Content-Type: application/json
X-Request-Id: reference-catalog-001

{
  "schema": "casset.public-catalog.v1",
  "artist": {
    "handle": "connor",
    "displayName": "Connor James"
  },
  "tracks": [
    {
      "title": "Baby Blue",
      "kind": "ORIGINAL",
      "durationSec": 213
    }
  ],
  "page": { "count": 1 }
}

Empty 200 response

HTTP/1.1 200 OK
Cache-Control: public, max-age=0, must-revalidate
Content-Type: application/json
X-Request-Id: reference-catalog-empty-001

{
  "schema": "casset.public-catalog.v1",
  "artist": {
    "handle": "connor",
    "displayName": "Connor James"
  },
  "tracks": [],
  "page": { "count": 0 }
}

Fields

Public Catalog response fields
FieldTypeMeaningLimit
schemaliteralcasset.public-catalog.v1Exact
artist.handlestringCanonical public handle3–30
artist.displayNamestringPublic display name160
tracksarrayActive public Track metadata0–500
tracks[].titlestringPublic Track title240
tracks[].kindORIGINAL | GENERATIONPublic provenance kindExact
tracks[].durationSecnumber | nullDuration in whole or fractional seconds when valid0–86,400
page.countnumberMust equal tracks.length0–500

Failure matrix for both endpoints

The following responses apply to both public paths. Their sandbox read counterparts add credential failure and return the same error schema; ownership failures belong to the separate sandbox console.

Endpoint status behavior
StatusPublic /api/v1Local /api/sandbox/v1Retry
400Malformed handleMalformed handle or requestNo
401Not emitted; public v1 has no credentialMissing, invalid, or revoked sandbox credentialNo
403Not emitted by current public readsNot emitted by the two sandbox reads; authenticated console ownership/session actions can emit itNo
404Unknown, private, or unpublished artistUnavailable sandbox or missing public artistNo
429Per-IP public rate limitNot emitted by the two sandbox readsYes when the envelope says retryable
502Not emittedSandbox integration failureFollow envelope.retryable
503Public data could not be prepared, or the production rate limiter is unavailableNot emitted by the two sandbox readsYes when the envelope says retryable
5xx otherNot currently emitted by these public routesNot currently emitted by these sandbox readsSDK retries only 500–599 when retryable is true or no valid envelope exists

400 — invalid handle

HTTP/1.1 400 Bad Request
Cache-Control: private, no-store
Content-Type: application/json
X-Request-Id: reference-invalid-001

{
  "schema": "casset.error.v1",
  "error": {
    "code": "INVALID_REQUEST",
    "message": "A valid artist handle is required.",
    "requestId": "reference-invalid-001",
    "retryable": false
  }
}

404 — unknown, private, or unpublished

HTTP/1.1 404 Not Found
Cache-Control: private, no-store
Content-Type: application/json
X-Request-Id: reference-not-found-001

{
  "schema": "casset.error.v1",
  "error": {
    "code": "RESOURCE_UNAVAILABLE",
    "message": "Artist not found.",
    "requestId": "reference-not-found-001",
    "retryable": false
  }
}

401 — local sandbox only

HTTP/1.1 401 Unauthorized
Cache-Control: no-store, private
Content-Type: application/json
X-Request-Id: sandbox-auth-001

{
  "schema": "casset.error.v1",
  "error": {
    "code": "INVALID_CREDENTIAL",
    "message": "A valid Bearer sandbox credential is required.",
    "requestId": "sandbox-auth-001",
    "retryable": false
  }
}

403 — local sandbox console permission failure only

HTTP/1.1 403 Forbidden
Cache-Control: no-store, private
Content-Type: application/json
X-Request-Id: sandbox-permission-001

{
  "schema": "casset.error.v1",
  "error": {
    "code": "PERMISSION_DENIED",
    "message": "The app belongs to a different sandbox developer.",
    "requestId": "sandbox-permission-001",
    "retryable": false
  }
}

429 — public rate limit

HTTP/1.1 429 Too Many Requests
Cache-Control: private, no-store
Content-Type: application/json
Retry-After: 17
X-Request-Id: reference-rate-001

{
  "schema": "casset.error.v1",
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Try again after the retry window.",
    "requestId": "reference-rate-001",
    "retryable": true
  }
}

503 — public service failure

HTTP/1.1 503 Service Unavailable
Cache-Control: private, no-store
Content-Type: application/json
X-Request-Id: reference-service-001

{
  "schema": "casset.error.v1",
  "error": {
    "code": "INTEGRATION_FAILURE",
    "message": "The public catalog service is temporarily unavailable.",
    "requestId": "reference-service-001",
    "retryable": true
  }
}

Public 401 and 403

Do not add a Bearer credential to public v1 requests. The 401 and 403 examples document the wider local sandbox error contract so clients can rehearse those typed failures. The Artist and Catalog read counterparts emit 401, not 403; the example 403 belongs to authenticated console ownership/session actions. Neither is a claimed response from the unauthenticated public routes.

Privacy behavior

  • Private, unpublished, and unknown artists are indistinguishable at the HTTP boundary.
  • Catalog reads select only active Track title, kind, and duration.
  • Strict SDK parsers reject unknown response fields instead of silently accepting data expansion.
  • Error responses use private, no-store; sandbox responses use no-store, private.

Read Errors for the full typed-error matrix and Retries before implementing custom transport behavior.

© Casset 2026
Trust & PrivacyTerms