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 · Errors

Failures are typed, bounded, and safe to correlate.

Every valid API failure uses casset.error.v1. The SDK converts that contract into a CassetApiError subclass with a sanitized message, HTTP status, request ID, retryability, and bounded retry delay.

Handle behavior from code and retryable. Show users a calm product message. Log the request ID—not the credential, Authorization header, response body, or private application state.

Current HTTP availability

The public v1 GET routes are deployed and unauthenticated, but they are not supported for production use. A 503 ResourceUnavailable is an intentional fail-closed availability state. No uptime, availability, or production-use commitment is offered; production developer credentials remain unavailable. The credentialed sandbox remains loopback-only.

Error envelope

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

{
  "schema": "casset.error.v1",
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Try again after the retry window.",
    "requestId": "errors-rate-001",
    "retryable": true
  }
}
Error envelope fields
FieldMeaningClient behavior
schemaExact contract name: casset.error.v1Unknown schemas fail strict parsing.
error.codeStable machine-readable error categoryMapped to a typed CassetApiError subclass.
error.messageSafe API explanation for this responseThe SDK does not expose it as the thrown message; it uses a fixed sanitized message.
error.requestIdCorrelation ID for the requestMust match the x-request-id response header exactly.
error.retryableWhether this specific failure may be retriedA transient HTTP status is retried only when this is true, or when no valid envelope exists.

Complete error reference

Headless API and SDK errors
Code / SDK classHTTPMeaning and likely causesRetry?Developer actionUser-facing recommendation
INVALID_REQUEST
InvalidRequest
400; SDK also maps 422. Sandbox conflict uses 409.The handle, client configuration, request ID, body, or console action does not match the contract.NoFix the input. Validate handles before accepting them and treat configuration errors as build-time defects.“This request could not be completed. Check the artist address and try again.”
INVALID_CREDENTIAL
InvalidCredential
401The local sandbox Bearer credential is missing, malformed, unknown, or revoked. Public v1 does not require a credential.NoRemove credentials from public v1 calls. For local sandbox calls, issue a new one-time credential and keep it server-side.“This local connection is no longer authorized.”
PERMISSION_DENIED
PermissionDenied
403The authenticated sandbox actor does not own or cannot access the requested sandbox resource. It is also an exact mock state.NoCheck local App ownership and the action being rehearsed. Do not retry with the same authorization state.“This integration does not have access to that resource.”
ENTITLEMENT_REQUIRED
EntitlementRequired
402The SDK and exact mock vocabulary can represent an entitlement gate. No current public v1 or local sandbox Artist/Catalog route emits it.NoTreat it as an unavailable gated resource. Do not imply that a production entitlement purchase flow exists.“This resource is not available for this integration.”
RESOURCE_UNAVAILABLE
ResourceUnavailable
404; SDK fallback also maps 503 and 504The artist is unknown, private, or unpublished; the local sandbox is disabled; or a service dependency is unavailable.404: no. 503/504: yes by SDK fallback. Always follow the envelope.For 404, stop and render no data. For a retryable service failure, allow the SDK policy to finish before showing a fallback.404: “Artist unavailable.” Temporary: “Casset is temporarily unavailable. Try again shortly.”
RATE_LIMITED
RateLimited
429Public v1 exceeded 60 requests per IP in a 60-second window, or an exact mock is exercising rate-limit behavior.YesUse the SDK retry policy, respect the bounded Retry-After value, reduce duplicate reads, and avoid immediate manual loops.“Too many requests. Please wait a moment and try again.”
INTEGRATION_FAILURE
IntegrationFailure
502 sandbox; 503 public; SDK fallback for other failuresTransport, timeout, service, malformed JSON, schema mismatch, or request-ID protocol failure.Depends. Transport and service failures default to yes; contract and request-ID failures are no.Inspect status, retryable, and requestId. Fix non-retryable contract failures before retrying.Retryable: “Casset is temporarily unavailable.” Non-retryable: “This integration could not read the response.”

Parser error

CassetContractError is not an HTTP error code. Direct calls toparsePublicArtistResponse, parsePublicCatalogResponse, or parseHeadlessApiErrorEnvelope throw it when a value violates the exact schema. Its issues array contains only field paths and bounded validation messages. When the HTTP client encounters the same problem, it throws a non-retryable IntegrationFailure instead.

Handle errors in TypeScript

import {
  CassetApiError,
  InvalidCredential,
  InvalidRequest,
  RateLimited,
  ResourceUnavailable,
} from "@casset/apps"

try {
  const catalog = await casset.getCatalog("connor")
  return catalog.tracks
} catch (error) {
  if (error instanceof InvalidRequest) {
    throw new Error("Invalid integration input")
  }

  if (error instanceof InvalidCredential) {
    return { state: "reauthorize-local-sandbox" }
  }

  if (error instanceof ResourceUnavailable && error.status === 404) {
    return { state: "artist-unavailable" }
  }

  if (error instanceof RateLimited) {
    return { state: "try-later", requestId: error.requestId }
  }

  if (error instanceof CassetApiError) {
    console.info("Casset request failed", {
      code: error.code,
      status: error.status,
      retryable: error.retryable,
      requestId: error.requestId,
    })
    return { state: "temporarily-unavailable" }
  }

  throw error
}

Request IDs and correlation

Casset uses one correlation value: x-request-id. There is no separate public correlation-ID header. If you send a valid ID, the server mirrors it in the response header and error body. Otherwise, the server generates a req_* value. The SDK generates one sdk-*value and reuses it across all retry attempts.

  • Accepted length: 8–120 characters.
  • Accepted characters: letters, digits, period, underscore, colon, and hyphen.
  • Secret-like prefixes, JWT-shaped values, control characters, and whitespace are rejected.
  • A response header/body mismatch or a response ID that differs from the request becomes a non-retryable integration failure.

Debugging workflow

  1. Capture code, status, retryable, and requestId.
  2. Confirm whether the request targeted public v1, the local sandbox, or an exact mock.
  3. For 400/401/403/404, fix state or render the appropriate terminal fallback; do not loop.
  4. For 429 or retryable 5xx, let the SDK finish its bounded attempts before adding application-level recovery.
  5. For non-retryable IntegrationFailure, compare the exact response schema and request-ID header. Treat drift as an integration defect.
  6. Share the request ID and sanitized metadata with the Casset maintainer. Never share the Bearer value or webhook signing secret.

Safe logs only

Safe: request ID, error class name, method, normalized route template, status, latency, and stable error code. Never log App IDs, credential prefixes, Authorization values, plaintext credentials, hashes, webhook secrets, exact webhook bodies, full request or response bodies, private handles or query strings, internal database IDs, or media URLs.

See Retries for exact attempt and delay behavior, or Observability for the full safe-logging boundary.

© Casset 2026
Trust & PrivacyTerms