✦Spectra SDK Docs

SDK UX Contract v1

Status: product contract. This document defines the default developer-facing SDK UX. It does not claim that every server, package, provider, and public endpoint is already aligned. Implementation and E2E status stays in each service/SDK repository and work log.

Goal

The default SDK experience should start from what the app developer wants to do, not from Spectra's server topology.

Project ID, Secret Key, and Service Toggles

The primary developer-facing key model is Project ID + Secret Key.

Secret Key is a secret value. Console/API shows the raw value only once, immediately after first issue or regeneration. After that, the raw value cannot be viewed again, so the user must store it. A Project has exactly one active Secret Key.

The Project Secret Key is bound to one environment: test or live. Before first issue, the user can choose the environment. On regeneration, the user can choose the environment for the new Secret Key. Regeneration activates the new Secret Key and the previous Secret Key must no longer be usable.

The Project Secret Key itself has no expiration date. Access is controlled by key regeneration, revocation, or disabling the relevant Project service toggle. User-facing Secret Key docs and UI should not expose an expiration-date input or display. Do not document expires_at or similar expiry fields as part of the user-facing Project Secret Key contract.

Secret Key does not store feature permissions. Email, Push, Storage, Chat, and Call availability is controlled by Project dashboard service toggles. A server request proves the Project and Secret Key environment with projectId + secretKey; the producer then checks whether the requested service is enabled. If the service is disabled, the producer returns a service-disabled error even when the Secret Key is valid.

Public-client configuration is not a primary user-managed key in the new product contract. Current SDK/API fields may still expose publicClientId until implementation alignment is complete; document it only as current package compatibility, not as a product key users need to understand.

Legacy or advanced docs may mention older key/token/preset names for compatibility, migration, or diagnostics. Expiry fields on app-user tokens, verification codes, service tokens, socket tickets, or call participant tokens remain valid in those separate token contracts; they are not Project Secret Key expiry.

Basic App Setup

Default browser and mobile SDK examples use public configuration only.

const auth = new SpectraAuthClient({
  projectId,
  // publicClientId may remain in current packages as a compatibility field
  // until the SDK/API implementation aligns with the Project ID + Secret Key contract.
  publicClientId,
  environment,
  redirectUri,
});

const storage = new SpectraStorageClient({ projectId, auth });
const chat = new SpectraChatClient({ projectId, auth });

Default SDK docs should not require values like deliveryBaseURL, service token audience, SMTP credentials, APNs/FCM server credentials, object-store credentials, or a Secret Key for the first browser/mobile setup. They should state that the Secret Key is environment-bound, secret, has no expiration date, and is shown only once after issue/regeneration.

Basic Server Setup

Trusted backends can read the Secret Key from a server secret store or environment variable. Whether a consuming project exposes the Secret Key to browser/mobile code is an app architecture decision; this contract only requires that docs describe it as an environment-bound no-expiry secret value that is shown once.

const projectId = process.env.SPECTRA_PROJECT_ID;
const secretKey = process.env.SPECTRA_SECRET_KEY;
const environment = process.env.SPECTRA_ENVIRONMENT ?? "test";

Service toggles decide which server operations are allowed. For example, the same valid Secret Key can prove the Project for Email and Storage requests, but Email requests are accepted only when Email is enabled and Storage requests are accepted only when Storage is enabled. Producers may still validate internal scopes/audiences for app-user tokens or service internals, but the user-facing Secret Key does not carry feature flags or expiry.

Email

Email default UX is simple direct sending from a server-side SDK or trusted backend. A developer should be able to send a plain message without creating a template first.

await email.send({
  to: "user@example.com",
  from: "no-reply@spectra.kr",
  subject: "Welcome to Spectra",
  text: "Your workspace is ready.",
});

The default server-side contract is:

send({
  to,
  from?,
  subject,
  text?,
  html?,
  contentType?,
})

Rules:

Email Verification

Verification email UX also defaults to direct body input. The SDK or server can inject the generated code into the direct body, but developers should not need to create a template for the first verification flow.

const challenge = await email.verifications.send({
  to: "user@example.com",
  subject: "Your sign-in code",
  text: "Your code is {{code}}.",
  expiresInSeconds: 600,
});

await email.verifications.verify({
  verificationId: challenge.verificationId,
  code,
});

If a browser/mobile Notification SDK exposes email verification, its basic docs should describe direct fields such as email or to, subject, text, html, and expiresInSeconds. templateId remains an advanced optional field for teams that already operate managed templates.

Storage

Storage default UX should make file visibility explicit and readable.

await storage.uploadFile({
  file,
  path: "/avatars/me.png",
  visibility: "private",
});

await storage.uploadFile({
  file,
  path: "/public/profile-card.png",
  visibility: "public_read",
});

The basic visibility contract is:

visibility: "private" | "public_read"

Rules:

Chat Files

Chat file sending should be a Chat SDK experience. The app should not have to manually compose Storage SDK upload, Storage object reference mapping, and Chat message payload for the default flow.

Target default UX:

await chat.sendMessageWithFiles(roomId, {
  text: "사진 첨부",
  files: [
    {
      file,
      visibility: "private",
    },
  ],
});

Rules:

Advanced Surface

Advanced docs may expose the following, but first-run docs should not depend on them:

When an implementation currently requires one of these values for a basic use case, treat it as SDK/service alignment work rather than a consumer responsibility.

Documentation Acceptance

Default developer docs should pass these checks: