@proveanything/smartlinks
Version:
Official JavaScript/TypeScript SDK for the Smartlinks API
1,940 lines (1,748 loc) • 196 kB
Markdown
# Smartlinks API Summary
Version: 1.6.4 | Generated: 2026-02-26T12:33:27.813Z
This is a concise summary of all available API functions and types.
## Documentation
For detailed guides on specific features:
- **[AI & Chat Completions](ai.md)** - Chat completions, RAG (document-grounded Q&A), voice integration, streaming, tool calling, podcast generation
- **[Widgets](widgets.md)** - Embeddable React components for parent applications
- **[Containers](containers.md)** - Building full-app embeddable containers (lazy-loaded)
- **[Realtime](realtime.md)** - Real-time data updates and WebSocket connections
- **[iframe Responder](iframe-responder.md)** - iframe integration and cross-origin communication
- **[i18n](i18n.md)** - Internationalization and localization
- **[Liquid Templates](liquid-templates.md)** - Dynamic templating for content generation
- **[Theme System](theme.system.md)** - Theme configuration and customization
- **[Theme Defaults](theme-defaults.md)** - Default theme values and presets
- **[Proof Claiming Methods](proof-claiming-methods.md)** - All methods for claiming/registering product ownership (NFC tags, serial numbers, auto-generated claims)
- **[App Data Storage](app-data-storage.md)** - User-specific and collection-scoped app data storage
- **[App Objects: Cases, Threads & Records](app-objects.md)** - Generic app-scoped building blocks for support cases, discussions, bookings, registrations, and more
- **[Communications](comms.md)** - Transactional sends, multi-channel broadcasts, consent management, push registration, and analytics
- **[AI Guide Template](ai-guide-template.md)** - A sample for an app on how to build an AI setup guide
## API Namespaces
The Smartlinks SDK is organized into the following namespaces:
— Core Data & Configuration —
- **collection** - Manage collections, settings, and identifiers for your workspace.
- **product** - Create and manage products within a collection; metadata, tags, media.
- **variant** - Manage product variants per product; includes serial number helpers.
- **asset** - Upload and manage media assets for collections, products, and proofs.
- **batch** - Group products into batches; manage serial number ranges and lookups.
- **crate** - Organize products in containers/crates for logistics and grouping.
- **form** - Build and manage dynamic forms used by apps and workflows.
- **appConfiguration** - Read/write app configuration and scoped data (collection/product/proof).
— Identity & Access —
- **auth** - Admin authentication and account ops: login/logout, tokens, account info.
- **authKit** - End‑user auth flows (email/password, OAuth, phone); profiles and verification.
- **contact** - Manage customer contacts; CRUD, lookup, upsert, erase.
— Messaging & Audience —
- **comms** - Send notifications (push, email, wallet); templating, severity, delivery status. → [Guide](comms.md)
- **broadcasts** - Define broadcast campaigns; append recipients/events; analytics and CRUD.
- **segments** - Define dynamic/static audience segments; estimate and list recipients; schedule calculations.
— Analytics & Events —
- **interactions** - Log and analyze interactions/outcomes; aggregates and actor lists; interaction definition CRUD.
— Automation —
- **journeys** - Configure automated flows triggered by events or schedules; steps, rules; full CRUD.
— NFC, Proofs & Claims —
- **nfc** - Claim and validate NFC tags; perform tag lookups.
- **proof** - Create, update, claim, and list product proofs (digital certificates).
- **claimSet** - Manage claim sets and tag assignments; queries, reports, and updates.
- **qr** - Lookup short codes to resolve collection/product/proof context.
— AI & Utilities —
- **ai** - Chat completions, RAG (document Q&A), podcast generation, TTS, content/image generation, voice integration.
- **serialNumber** - Assign, lookup, and manage serial numbers across scopes.
— Other —
- **appObjects** - Functions for appObjects operations
- **async** - Functions for async operations
- **attestation** - Functions for attestation operations
- **jobs** - Functions for jobs operations
- **journeysAnalytics** - Functions for journeysAnalytics operations
- **location** - Functions for location operations
- **order** - Functions for order operations
- **realtime** - Functions for realtime operations
- **tags** - Functions for tags operations
- **template** - Functions for template operations
## HTTP Utilities
Core HTTP functions for API configuration and communication:
**isProxyEnabled**() → `boolean`
Return whether proxy mode is currently enabled.
**initializeApi**(options: {
baseURL: string
apiKey?: string
bearerToken?: string
proxyMode?: boolean
ngrokSkipBrowserWarning?: boolean
extraHeaders?: Record<string, string>
iframeAutoResize?: boolean // default true when in iframe
logger?: Logger // optional console-like or function to enable verbose logging
/**
* When true, bypasses the idempotency guard and forces a full re-initialization.
* Use only when you intentionally need to reset all SDK state (e.g. in tests or
* when switching accounts) → `void`
Call this once (e.g. at app startup) to configure baseURL/auth.
**setNgrokSkipBrowserWarning**(flag: boolean) → `void`
Enable/disable automatic "ngrok-skip-browser-warning" header.
**setExtraHeaders**(headers: Record<string, string>) → `void`
Replace or augment globally applied custom headers.
**setBearerToken**(token: string | undefined) → `void`
Allows setting the bearerToken at runtime (e.g. after login/logout).
**getBaseURL**() → `string | null`
Get the currently configured API base URL. Returns null if initializeApi() has not been called yet.
**isInitialized**() → `boolean`
Returns true if initializeApi() has been called at least once. Useful for guards in widgets or shared modules that want to skip initialization when another module has already done it. ```ts if (!isInitialized()) { initializeApi({ baseURL: 'https://smartlinks.app/api/v1' }) } ```
**hasAuthCredentials**() → `boolean`
Returns true if the SDK currently has any auth credential set (bearer token or API key). Use this as a cheap pre-flight check before calling endpoints that require authentication, to avoid issuing a network request that you already know will return a 401. ```ts if (hasAuthCredentials()) { const account = await auth.getAccount() } ```
**configureSdkCache**(options: {
enabled?: boolean
ttlMs?: number
maxEntries?: number
persistence?: 'none' | 'indexeddb'
persistenceTtlMs?: number
serveStaleOnOffline?: boolean
clearOnPageLoad?: boolean
}) → `void`
Configure the SDK's built-in in-memory GET cache. The cache is transparent — it sits inside the HTTP layer and requires no changes to your existing API calls. All GET requests benefit automatically. Per-resource rules (collections/products → 1 h, proofs → 30 s, etc.) override this value. in-memory only (`'none'`, default). Ignored in Node.js. fallback, from the original fetch time (default: 7 days). `SmartlinksOfflineError` with stale data instead of propagating the network error. caches on page load/refresh. IndexedDB persists for offline. ```ts // Enable IndexedDB persistence for offline support configureSdkCache({ persistence: 'indexeddb' }) // Disable cache entirely in test environments configureSdkCache({ enabled: false }) // Keep caches across page refreshes (not recommended for production) configureSdkCache({ clearOnPageLoad: false }) ```
**invalidateCache**(urlPattern?: string) → `void`
Manually invalidate entries in the SDK's GET cache. *contains* this string is removed. Omit (or pass `undefined`) to wipe the entire cache. ```ts invalidateCache() // clear everything invalidateCache('/collection/abc123') // one specific collection invalidateCache('/product/') // all product responses ```
**proxyUploadFormData**(path: string,
formData: FormData,
onProgress?: (percent: number) → `void`
Upload a FormData payload via proxy with progress events using chunked postMessage. Parent is expected to implement the counterpart protocol.
**request**(path: string) → `Promise<T>`
Internal helper that performs a GET request to `${baseURL}${path}`, injecting headers for apiKey or bearerToken if present. Cache pipeline (when caching is not skipped): L1 hit → return from memory (no I/O) L2 hit → return from IndexedDB, promote to L1 (no network) Miss → fetch from network, store in L1 + L2 Offline → serve stale L2 entry via SmartlinksOfflineError (if persistence enabled) Concurrent identical GETs share one in-flight promise (deduplication). Node-safe: IndexedDB calls are no-ops when IDB is unavailable.
**post**(path: string,
body: any,
extraHeaders?: Record<string, string>) → `Promise<T>`
Internal helper that performs a POST request to `${baseURL}${path}`, injecting headers for apiKey or bearerToken if present. If body is FormData, Content-Type is not set. Returns the parsed JSON as T, or throws an Error.
**put**(path: string,
body: any,
extraHeaders?: Record<string, string>) → `Promise<T>`
Internal helper that performs a PUT request to `${baseURL}${path}`, injecting headers for apiKey or bearerToken if present. If body is FormData, Content-Type is not set. Returns the parsed JSON as T, or throws an Error.
**patch**(path: string,
body: any,
extraHeaders?: Record<string, string>) → `Promise<T>`
Internal helper that performs a PATCH request to `${baseURL}${path}`, injecting headers for apiKey or bearerToken if present. If body is FormData, Content-Type is not set. Returns the parsed JSON as T, or throws an Error.
**requestWithOptions**(path: string,
options: RequestInit) → `Promise<T>`
Internal helper that performs a request to `${baseURL}${path}` with custom options, injecting headers for apiKey or bearerToken if present. Returns the parsed JSON as T, or throws an Error.
**del**(path: string,
extraHeaders?: Record<string, string>) → `Promise<T>`
Internal helper that performs a DELETE request to `${baseURL}${path}`, injecting headers for apiKey or bearerToken if present. Returns the parsed JSON as T, or throws an Error.
**getApiHeaders**() → `Record<string, string>`
Returns the common headers used for API requests, including apiKey and bearerToken if set.
**sendCustomProxyMessage**(request: string, params: any) → `Promise<T>`
Sends a custom proxy message to the parent Smartlinks application when running in an iframe. This function is used to communicate with the parent window when the SDK is embedded in an iframe and proxyMode is enabled. It sends a message to the parent and waits for a response.
## Error Handling
All API functions throw `SmartlinksApiError` when requests fail. This error class provides structured access to HTTP status codes, server error codes, and additional context.
### SmartlinksApiError
**Properties:**
- **message** `string` - Human-readable error message in English (e.g., "Error 400: Not Authorized")
- **statusCode** `number` - HTTP status code (400, 401, 404, 500, etc.)
- **code** `number` - Numeric error code (same as statusCode)
- **details** `Record<string, any> | undefined` - Additional server response data, including string error codes
- **url** `string | undefined` - The URL that was requested
**Helper Methods:**
- **isAuthError()** `boolean` - Returns true for 401 or 403 status codes
- **isNotFound()** `boolean` - Returns true for 404 status code
- **isRateLimited()** `boolean` - Returns true for 429 status code
- **isClientError()** `boolean` - Returns true for 4xx status codes
- **isServerError()** `boolean` - Returns true for 5xx status codes
- **toJSON()** `object` - Returns a serializable object for logging
### Error Format Normalization
The SDK automatically normalizes various server error response formats into a consistent structure. The server may return errors in different formats, but they are all accessible through the same properties.
**Server String Error Codes:**
Server-specific error identifiers are preserved in `error.details`:
- Access via: `error.details?.errorCode` or `error.details?.error`
- Format examples: `"NOT_AUTHORIZED"`, `"broadcasts.topic.invalid"`, `"sendgrid.provision.failed"`
- Use these for programmatic error handling (switch statements, conditional logic)
### Usage Examples
**Basic Error Handling:**
```typescript
import { SmartlinksApiError, product } from '@proveanything/smartlinks'
try {
const item = await product.get('collectionId', 'productId')
} catch (error) {
if (error instanceof SmartlinksApiError) {
console.error('Status:', error.statusCode) // 404
console.error('Message:', error.message) // "Error 404: Not found"
console.error('URL:', error.url) // "/public/collection/..."
}
}
```
**Using Helper Methods:**
```typescript
try {
await product.create('collectionId', data)
} catch (error) {
if (error instanceof SmartlinksApiError) {
if (error.isAuthError()) {
// Handle 401/403 - redirect to login
redirectToLogin()
} else if (error.isNotFound()) {
// Handle 404
showNotFound()
} else if (error.isRateLimited()) {
// Handle 429 - implement retry with backoff
await retryAfterDelay()
} else if (error.isServerError()) {
// Handle 5xx
showMaintenanceMessage()
}
}
}
```
**Accessing Server Error Codes:**
```typescript
try {
await broadcasts.send('collectionId', 'broadcastId', options)
} catch (error) {
if (error instanceof SmartlinksApiError) {
// Extract server-defined string error code
const serverCode = error.details?.errorCode || error.details?.error
switch (serverCode) {
case 'NOT_AUTHORIZED':
redirectToLogin()
break
case 'broadcasts.topic.invalid':
showTopicSelector()
break
case 'sendgrid.provision.failed':
alertAdmin('Email service error')
break
default:
showError(error.message)
}
}
}
```
**Error Logging for Monitoring:**
```typescript
try {
await api.someMethod()
} catch (error) {
if (error instanceof SmartlinksApiError) {
// Log structured error data
logger.error('API Error', error.toJSON())
// Send to monitoring service
Sentry.captureException(error, {
extra: error.toJSON(),
tags: {
statusCode: error.statusCode,
serverErrorCode: error.details?.errorCode || error.details?.error,
}
})
}
}
```
**Handling Validation Errors:**
```typescript
try {
await product.create('collectionId', formData)
} catch (error) {
if (error instanceof SmartlinksApiError && error.statusCode === 400) {
// Access field-specific validation errors if available
if (error.details?.fields) {
Object.entries(error.details.fields).forEach(([field, message]) => {
showFieldError(field, String(message))
})
} else {
showError(error.message)
}
}
}
```
**Retry Logic for Transient Errors:**
```typescript
async function withRetry<T>(fn: () => Promise<T>, maxRetries = 3): Promise<T> {
for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
return await fn()
} catch (error) {
if (error instanceof SmartlinksApiError) {
// Only retry server errors and rate limiting
const shouldRetry = error.isServerError() || error.isRateLimited()
if (!shouldRetry || attempt === maxRetries - 1) {
throw error
}
// Exponential backoff
const delay = 1000 * Math.pow(2, attempt)
await new Promise(resolve => setTimeout(resolve, delay))
} else {
throw error
}
}
}
throw new Error('Max retries exceeded')
}
// Usage
const collections = await withRetry(() => collection.list())
```
### Error Code Reference
**HTTP Status Codes (numeric):**
- `400` - Bad Request (invalid input)
- `401` - Unauthorized (authentication required)
- `403` - Forbidden (insufficient permissions)
- `404` - Not Found (resource doesn't exist)
- `429` - Too Many Requests (rate limited)
- `500` - Internal Server Error
- `502` - Bad Gateway
- `503` - Service Unavailable
**Server Error Codes (strings in `details.errorCode` or `details.error`):**
Examples include:
- `"NOT_AUTHORIZED"` - Not authorized for this action
- `"broadcasts.topic.invalid"` - Invalid communication topic
- `"broadcasts.manual.segment.missing"` - Missing required segment
- `"sendgrid.provision.failed"` - Email service provisioning failed
- `"validation.failed"` - Request validation failed
*Note: Server error codes use either `UPPERCASE_UNDERSCORE` or `dotted.notation` format. Both are supported.*
## Types
### ai
**ContentPart** (interface)
```typescript
interface ContentPart {
type: 'text' | 'image_url'
text?: string
image_url?: {
url: string
detail?: 'auto' | 'low' | 'high'
}
}
```
**FunctionCall** (interface)
```typescript
interface FunctionCall {
name: string
arguments: string
}
```
**ToolCall** (interface)
```typescript
interface ToolCall {
id: string
type: 'function'
function: {
name: string
arguments: string
}
}
```
**ChatMessage** (interface)
```typescript
interface ChatMessage {
role: 'system' | 'user' | 'assistant' | 'function' | 'tool'
content: string | ContentPart[]
name?: string
function_call?: FunctionCall
tool_calls?: ToolCall[]
tool_call_id?: string
}
```
**ToolDefinition** (interface)
```typescript
interface ToolDefinition {
type: 'function'
function: {
name: string
description: string
parameters: {
type: 'object'
properties: Record<string, {
type: string
description?: string
enum?: string[]
}>
required?: string[]
}
}
}
```
**ChatCompletionRequest** (interface)
```typescript
interface ChatCompletionRequest {
messages: ChatMessage[]
model?: string
stream?: boolean
tools?: ToolDefinition[]
tool_choice?: 'none' | 'auto' | 'required' | { type: 'function'; function: { name: string } }
temperature?: number
max_tokens?: number
top_p?: number
frequency_penalty?: number
presence_penalty?: number
response_format?: { type: 'text' | 'json_object' }
user?: string
}
```
**ChatCompletionChoice** (interface)
```typescript
interface ChatCompletionChoice {
index: number
message: ChatMessage
finish_reason: 'stop' | 'length' | 'function_call' | 'tool_calls' | 'content_filter' | null
}
```
**ChatCompletionResponse** (interface)
```typescript
interface ChatCompletionResponse {
id: string
object: 'chat.completion'
created: number
model: string
choices: ChatCompletionChoice[]
usage: {
prompt_tokens: number
completion_tokens: number
total_tokens: number
}
}
```
**ChatCompletionChunk** (interface)
```typescript
interface ChatCompletionChunk {
id: string
object: 'chat.completion.chunk'
created: number
model: string
choices: Array<{
index: number
delta: Partial<ChatMessage>
finish_reason: string | null
}>
}
```
**AIModel** (interface)
```typescript
interface AIModel {
id: string
provider: 'gemini' | 'openai'
modelId: string
name: string
description: string
capabilities: Array<'text' | 'vision' | 'audio' | 'code'>
contextWindow: number
pricing: {
input: number
output: number
cached?: number
}
features: string[]
recommended?: string
}
```
**DocumentChunk** (interface)
```typescript
interface DocumentChunk {
text: string
embedding: number[]
metadata: {
chunkIndex: number
documentId: string
[key: string]: any
}
}
```
**IndexDocumentRequest** (interface)
```typescript
interface IndexDocumentRequest {
productId: string
text?: string
documentUrl?: string
metadata?: Record<string, any>
chunkSize?: number
overlap?: number
provider?: 'openai' | 'gemini'
}
```
**IndexDocumentResponse** (interface)
```typescript
interface IndexDocumentResponse {
success: boolean
productId: string
documentId: string
chunks: number
metadata: {
textLength: number
chunkSize: number
overlap: number
embeddingDimensions: number
}
sample?: {
text: string
chunkIndex: number
}
}
```
**ConfigureAssistantRequest** (interface)
```typescript
interface ConfigureAssistantRequest {
productId: string
systemPrompt?: string
model?: string
maxTokensPerResponse?: number
temperature?: number
rateLimitPerUser?: number
allowedTopics?: string[]
customInstructions?: {
tone?: string
additionalRules?: string
[key: string]: any
}
}
```
**ConfigureAssistantResponse** (interface)
```typescript
interface ConfigureAssistantResponse {
success: boolean
configuration: {
productId: string
systemPrompt: string
model: string
maxTokensPerResponse: number
temperature: number
rateLimitPerUser: number
allowedTopics: string[]
customInstructions?: Record<string, any>
updatedAt: string
}
}
```
**PublicChatRequest** (interface)
```typescript
interface PublicChatRequest {
productId: string
userId: string
message: string
sessionId?: string
stream?: boolean
}
```
**PublicChatResponse** (interface)
```typescript
interface PublicChatResponse {
message: string
sessionId: string
usage: {
prompt_tokens: number
completion_tokens: number
total_tokens: number
}
context?: {
chunksUsed: number
topSimilarity: number
}
}
```
**Session** (interface)
```typescript
interface Session {
sessionId: string
productId: string
userId: string
messageCount: number
createdAt: string
lastActivityAt: string
messages: ChatMessage[]
}
```
**RateLimitStatus** (interface)
```typescript
interface RateLimitStatus {
used: number
remaining: number
resetAt: string
}
```
**SessionStatistics** (interface)
```typescript
interface SessionStatistics {
totalSessions: number
activeSessions: number
totalMessages: number
rateLimitedUsers: number
}
```
**VoiceSessionRequest** (interface)
```typescript
interface VoiceSessionRequest {
productId: string
userId: string
collectionId: string
settings?: {
voice?: string
language?: string
model?: string
}
}
```
**VoiceSessionResponse** (interface)
```typescript
interface VoiceSessionResponse {
token: string
systemInstruction: string
expiresAt: string
productName: string
}
```
**EphemeralTokenRequest** (interface)
```typescript
interface EphemeralTokenRequest {
settings?: {
ttl?: number
voice?: string
language?: string
model?: string
}
}
```
**EphemeralTokenResponse** (interface)
```typescript
interface EphemeralTokenResponse {
token: string
expiresAt: string
}
```
**TranscriptionResponse** (interface)
```typescript
interface TranscriptionResponse {
text: string
}
```
**TTSRequest** (interface)
```typescript
interface TTSRequest {
text: string
voice?: 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer'
speed?: number
format?: 'mp3' | 'opus' | 'aac' | 'flac'
}
```
**GeneratePodcastRequest** (interface)
```typescript
interface GeneratePodcastRequest {
productId: string
documentText?: string
duration?: number
style?: 'casual' | 'professional' | 'educational' | 'entertaining'
voices?: {
host1?: string
host2?: string
}
includeAudio?: boolean
language?: string
customInstructions?: string
}
```
**PodcastScript** (interface)
```typescript
interface PodcastScript {
title: string
description: string
segments: Array<{
speaker: 'host1' | 'host2'
text: string
timestamp?: number
duration?: number
}>
}
```
**GeneratePodcastResponse** (interface)
```typescript
interface GeneratePodcastResponse {
success: boolean
podcastId: string
script: PodcastScript
audio?: {
host1Url?: string
host2Url?: string
mixedUrl?: string
}
metadata: {
duration: number
wordCount: number
generatedAt: string
}
}
```
**PodcastStatus** (interface)
```typescript
interface PodcastStatus {
podcastId: string
status: 'generating_script' | 'generating_audio' | 'mixing' | 'completed' | 'failed'
progress: number
estimatedTimeRemaining?: number
error?: string
result?: GeneratePodcastResponse
}
```
**AIGenerateContentRequest** (interface)
```typescript
interface AIGenerateContentRequest {
contents: string | any
responseMimeType?: string
systemInstruction?: string
provider?: string
model?: string
[key: string]: any
}
```
**AIGenerateImageRequest** (interface)
```typescript
interface AIGenerateImageRequest {
prompt: string
provider?: string
model?: string
* Requested image size.
* OpenAI supported values: '1024x1024', '1024x1792', '1792x1024'
* Other providers may support different sizes.
size?: string
[key: string]: any
}
```
**AISearchPhotosRequest** (interface)
```typescript
interface AISearchPhotosRequest {
query: string
per_page?: number
orientation?: 'landscape' | 'portrait' | 'squarish'
[key: string]: any
}
```
**AISearchPhotosPhoto** (interface)
```typescript
interface AISearchPhotosPhoto {
url: string
alt?: string
photographer?: string
photographerUrl?: string
[key: string]: any
}
```
### appConfiguration
**AppConfigurationResponse** (interface)
```typescript
interface AppConfigurationResponse {
id: string
name: string
settings?: Record<string, any>
}
```
### appManifest
**AppBundle** (interface)
```typescript
interface AppBundle {
js: string | null;
css: string | null;
source?: string;
styles?: string;
}
```
**AppManifestFiles** (interface)
```typescript
interface AppManifestFiles {
js: {
umd: string;
esm?: string;
};
css?: string;
}
```
**AppWidgetComponent** (interface)
```typescript
interface AppWidgetComponent {
name: string;
description?: string;
sizes?: Array<'compact' | 'standard' | 'large' | string>;
props?: {
required?: string[];
optional?: string[];
};
settings?: Record<string, any>;
}
```
**AppContainerComponent** (interface)
```typescript
interface AppContainerComponent {
name: string;
description?: string;
props?: {
required?: string[];
optional?: string[];
};
}
```
**AppAdminConfig** (interface)
```typescript
interface AppAdminConfig {
$schema?: string;
* Path (relative to the app's public root) to an AI guide markdown file.
* Provides natural-language context for AI-assisted configuration.
* @example "ai-guide.md"
aiGuide?: string;
setup?: {
description?: string;
questions?: Array<{
id: string;
prompt: string;
type: string;
default?: any;
required?: boolean;
options?: Array<{ value: string; label: string }>;
}>;
configSchema?: Record<string, any>;
saveWith?: {
method: string;
scope: 'collection' | 'product' | string;
admin?: boolean;
note?: string;
};
contentHints?: Record<string, {
aiGenerate?: boolean;
prompt?: string;
}>;
};
import?: {
description?: string;
scope?: string;
fields?: Array<{
name: string;
type: string;
required?: boolean;
default?: any;
description?: string;
}>;
csvExample?: string;
saveWith?: {
method: string;
scope: string;
admin?: boolean;
note?: string;
};
};
tunable?: {
description?: string;
fields?: Array<{
name: string;
description?: string;
type: string;
options?: string[];
}>;
};
metrics?: {
interactions?: Array<{ id: string; description?: string }>;
kpis?: Array<{ name: string; compute?: string }>;
};
}
```
**AppManifest** (interface)
```typescript
interface AppManifest {
$schema?: string;
meta?: {
name: string;
description?: string;
version: string;
platformRevision?: string;
appId: string;
};
* Relative path to the admin configuration file (e.g. `"app.admin.json"`).
* When present, fetch this file to get the full {@link AppAdminConfig}
* (setup questions, import schema, tunable fields, metrics definitions).
* Absent when the app has no admin UI.
admin?: string;
widgets?: {
files: AppManifestFiles;
components: AppWidgetComponent[];
};
containers?: {
files: AppManifestFiles;
components: AppContainerComponent[];
};
[key: string]: any;
}
```
**CollectionAppWidget** (interface)
```typescript
interface CollectionAppWidget {
appId: string;
manifest: AppManifest;
widget: AppBundle;
container: AppBundle | null;
admin: string | null;
}
```
**CollectionWidgetsResponse** (interface)
```typescript
interface CollectionWidgetsResponse {
apps: CollectionAppWidget[];
}
```
**GetCollectionWidgetsOptions** (interface)
```typescript
interface GetCollectionWidgetsOptions {
force?: boolean;
}
```
### appObjects
**PaginatedResponse<T>** (interface)
```typescript
interface PaginatedResponse<T> {
data: T[]
pagination: {
total: number
limit: number
offset: number
hasMore: boolean
}
}
```
**AggregateRequest** (interface)
```typescript
interface AggregateRequest {
filters?: {
status?: string
category?: string // cases only
record_type?: string // records only
product_id?: string
created_at?: { gte?: string; lte?: string }
closed_at?: '__notnull__' | { gte?: string; lte?: string } // cases only
expires_at?: { lte?: string } // records only
}
groupBy?: string[] // see per-resource allowed values
metrics?: string[] // see per-resource allowed values below
timeSeriesField?: string // e.g. 'created_at'
timeSeriesInterval?: 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'
}
```
**AggregateResponse** (interface)
```typescript
interface AggregateResponse {
groups?: ({ count: number } & Record<string, unknown>)[]
timeSeries?: ({ bucket: string; count: number } & Record<string, unknown>)[]
count?: number
avg_close_time_seconds?: number
p50_close_time_seconds?: number
p95_close_time_seconds?: number
total_replies?: number
avg_replies?: number
}
```
**ListQueryParams** (interface)
```typescript
interface ListQueryParams {
limit?: number // default 50, max 500
offset?: number // default 0
sort?: string // field:asc or field:desc
includeDeleted?: boolean // admin only
status?: string // exact or in:a,b,c
productId?: string
createdAt?: string // gte:2024-01-01, lte:2024-12-31, or ISO date string
updatedAt?: string // same format
}
```
**AppCase** (interface)
```typescript
interface AppCase {
id: string
orgId: string
collectionId: string
appId: string
visibility: Visibility
ref: string | null
status: string // 'open' | 'resolved' | 'closed' | custom
priority: number | null
category: string | null
assignedTo: string | null // admin zone / admin callers only
productId: string | null
proofId: string | null
contactId: string | null
createdAt: string // ISO 8601
updatedAt: string
closedAt: string | null
deletedAt: string | null // admin callers only
data: Record<string, unknown> // visible to all roles
owner: Record<string, unknown> // visible to owner + admin
admin: Record<string, unknown> // visible to admin only
}
```
**CreateCaseInput** (interface)
```typescript
interface CreateCaseInput {
visibility?: Visibility // default 'owner'
ref?: string
status?: string // default 'open'
priority?: number
category?: string
assignedTo?: string // admin only
productId?: string
proofId?: string
contactId?: string
data?: Record<string, unknown>
owner?: Record<string, unknown>
admin?: Record<string, unknown> // admin only
}
```
**UpdateCaseInput** (interface)
```typescript
interface UpdateCaseInput {
data?: Record<string, unknown>
owner?: Record<string, unknown>
admin?: Record<string, unknown>
status?: string
priority?: number
category?: string
assignedTo?: string
ref?: string
}
```
**AppendHistoryInput** (interface)
```typescript
interface AppendHistoryInput {
entry?: Record<string, unknown> // free-form entry object; 'at' is auto-set
historyTarget?: 'owner' | 'admin' // which zone receives the entry (default 'admin')
status?: string // optionally update status atomically
priority?: number
assignedTo?: string
}
```
**CaseSummaryRequest** (interface)
```typescript
interface CaseSummaryRequest {
period?: { from: string; to: string } // ISO 8601 date range
}
```
**CaseSummaryResponse** (interface)
```typescript
interface CaseSummaryResponse {
total: number
byStatus: Record<string, number>
byPriority: Record<string, number>
trend: { week: string; count: number }[]
}
```
**ReplyEntry** (interface)
```typescript
interface ReplyEntry {
at: string // ISO 8601, auto-set
authorId?: string
authorType?: string
[key: string]: unknown
}
```
**AppThread** (interface)
```typescript
interface AppThread {
id: string
orgId: string
collectionId: string
appId: string
visibility: Visibility
slug: string | null
title: string | null
status: string // 'open' | 'closed' | custom
authorId: string | null
authorType: string // default 'user'
productId: string | null
proofId: string | null
contactId: string | null
parentType: string | null
parentId: string | null
replyCount: number
lastReplyAt: string | null
createdAt: string
updatedAt: string
deletedAt: string | null // admin only
body: Record<string, unknown>
replies: ReplyEntry[]
tags: string[]
data: Record<string, unknown>
owner: Record<string, unknown>
admin: Record<string, unknown> // admin only
}
```
**CreateThreadInput** (interface)
```typescript
interface CreateThreadInput {
visibility?: Visibility // default 'owner'
slug?: string
title?: string
status?: string // default 'open'
authorId?: string
authorType?: string
productId?: string
proofId?: string
contactId?: string
parentType?: string
parentId?: string
body?: Record<string, unknown>
tags?: string[]
data?: Record<string, unknown>
owner?: Record<string, unknown>
admin?: Record<string, unknown> // admin only
}
```
**UpdateThreadInput** (interface)
```typescript
interface UpdateThreadInput {
body?: Record<string, unknown>
tags?: string[]
data?: Record<string, unknown>
owner?: Record<string, unknown>
admin?: Record<string, unknown>
title?: string
slug?: string
status?: string
visibility?: Visibility
}
```
**ReplyInput** (interface)
```typescript
interface ReplyInput {
authorId?: string
authorType?: string
[key: string]: unknown // any extra fields stored on the reply object
}
```
**AppRecord** (interface)
```typescript
interface AppRecord {
id: string
orgId: string
collectionId: string
appId: string
visibility: Visibility
recordType: string
ref: string | null
status: string // default 'active'
productId: string | null
proofId: string | null
contactId: string | null
authorId: string | null
authorType: string
parentType: string | null
parentId: string | null
createdAt: string
updatedAt: string
startsAt: string | null
expiresAt: string | null
deletedAt: string | null // admin only
data: Record<string, unknown>
owner: Record<string, unknown>
admin: Record<string, unknown> // admin only
}
```
**CreateRecordInput** (interface)
```typescript
interface CreateRecordInput {
recordType: string
visibility?: Visibility // default 'owner'
ref?: string
status?: string // default 'active'
productId?: string
proofId?: string
contactId?: string
authorId?: string
authorType?: string
parentType?: string
parentId?: string
startsAt?: string // ISO 8601
expiresAt?: string
data?: Record<string, unknown>
owner?: Record<string, unknown>
admin?: Record<string, unknown> // admin only
}
```
**UpdateRecordInput** (interface)
```typescript
interface UpdateRecordInput {
data?: Record<string, unknown>
owner?: Record<string, unknown>
admin?: Record<string, unknown>
status?: string
visibility?: Visibility
ref?: string
recordType?: string
startsAt?: string
expiresAt?: string
}
```
**RelatedResponse** (interface)
```typescript
interface RelatedResponse {
threads: AppThread[]
records: AppRecord[]
}
```
**PublicCreatePolicy** (interface)
```typescript
interface PublicCreatePolicy {
cases?: PublicCreateRule
threads?: PublicCreateRule
records?: PublicCreateRule
}
```
**PublicCreateRule** (interface)
```typescript
interface PublicCreateRule {
allow: {
anonymous?: boolean
authenticated?: boolean
}
enforce?: {
anonymous?: Partial<CreateCaseInput | CreateThreadInput | CreateRecordInput>
authenticated?: Partial<CreateCaseInput | CreateThreadInput | CreateRecordInput>
}
}
```
**Visibility** = `'public' | 'owner' | 'admin'`
**CallerRole** = `'admin' | 'owner' | 'public'`
### asset
**Asset** (interface)
```typescript
interface Asset {
id: string
url: string
name: string
mimeType?: string
size?: number
createdAt?: string
metadata?: Record<string, any>
assetType?: string
type?: string
collectionId?: string
hash?: string
thumbnails?: {
x100?: string
x200?: string
x512?: string
[key: string]: string | undefined
}
site?: string
cleanName?: string
}
```
**UploadAssetOptions** (interface)
```typescript
interface UploadAssetOptions {
file: File
scope:
| { type: 'collection'; collectionId: string }
| { type: 'product'; collectionId: string; productId: string }
| { type: 'proof'; collectionId: string; productId: string; proofId: string }
name?: string
metadata?: Record<string, any>
onProgress?: (percent: number) => void
appId?: string
admin?: boolean
}
```
**UploadFromUrlOptions** (interface)
```typescript
interface UploadFromUrlOptions {
url: string
scope:
| { type: 'collection'; collectionId: string }
| { type: 'product'; collectionId: string; productId: string }
| { type: 'proof'; collectionId: string; productId: string; proofId: string }
folder?: 'images' | 'videos' | 'documents'
metadata?: Record<string, any>
appId?: string
admin?: boolean
}
```
**ListAssetsOptions** (interface)
```typescript
interface ListAssetsOptions {
scope:
| { type: 'collection'; collectionId: string }
| { type: 'product'; collectionId: string; productId: string }
| { type: 'proof'; collectionId: string; productId: string; proofId: string }
appId?: string
mimeTypePrefix?: string
limit?: number
offset?: number
}
```
**GetAssetOptions** (interface)
```typescript
interface GetAssetOptions {
assetId: string
scope:
| { type: 'collection'; collectionId: string }
| { type: 'product'; collectionId: string; productId: string }
| { type: 'proof'; collectionId: string; productId: string; proofId: string }
}
```
**RemoveAssetOptions** (interface)
```typescript
interface RemoveAssetOptions {
assetId: string
scope:
| { type: 'collection'; collectionId: string }
| { type: 'product'; collectionId: string; productId: string }
| { type: 'proof'; collectionId: string; productId: string; proofId: string }
}
```
**AssetResponse** = `Asset`
### attestation
**AttestationResponse** (interface)
```typescript
interface AttestationResponse {
id: string
createdAt: string
updatedAt: string
public: Record<string, any>
private: Record<string, any>
proof: Record<string, any>
}
```
**AttestationCreateRequest** (interface)
```typescript
interface AttestationCreateRequest {
public: Record<string, any>
private: Record<string, any>
proof: Record<string, any>
}
```
**AttestationUpdateRequest** (interface)
```typescript
interface AttestationUpdateRequest {
type?: string
data?: Record<string, any>
}
```
### auth
**UserAccountRegistrationRequest** (interface)
```typescript
interface UserAccountRegistrationRequest {
name: string
email?: string
phone?: string
password?: string
sendAccountConfirmation?: boolean
collectionId?: string,
tokenType?: 'bearer' | 'firebase'
}
```
### authKit
**AuthKitUser** (interface)
```typescript
interface AuthKitUser {
uid: string
email?: string
displayName?: string | null
photoURL?: string | null
phoneNumber?: string | null
emailVerified?: boolean
accountData?: Record<string, any>
}
```
**UserProfile** (interface)
```typescript
interface UserProfile {
uid: string
email?: string
displayName?: string | null
phoneNumber?: string | null
photoURL?: string | null
emailVerified?: boolean
accountData?: Record<string, any>
}
```
**ProfileUpdateData** (interface)
```typescript
interface ProfileUpdateData {
displayName?: string
photoURL?: string
accountData?: Record<string, any>
}
```
**SuccessResponse** (interface)
```typescript
interface SuccessResponse {
success: boolean
message?: string
token?: string // some flows may return a refreshed token
}
```
**AuthLoginResponse** (interface)
```typescript
interface AuthLoginResponse {
token?: string
user: AuthKitUser
accountData?: Record<string, any>
emailVerificationMode?: 'immediate' | 'verify-auto-login' | 'verify-manual-login'
requiresEmailVerification?: boolean // True if email verification is required but not yet completed
emailVerificationDeadline?: number // Unix timestamp - for 'immediate' mode grace period deadline
accountLocked?: boolean // True if account is locked due to expired verification deadline
}
```
**MagicLinkSendResponse** (interface)
```typescript
interface MagicLinkSendResponse {
success: boolean
message: string
}
```
**PhoneSendCodeResponse** (interface)
```typescript
interface PhoneSendCodeResponse {
verificationId: string
message: string
}
```
**PhoneVerifyResponse** (interface)
```typescript
interface PhoneVerifyResponse {
token: string
user: AuthKitUser
}
```
**PasswordResetRequestResponse** (interface)
```typescript
interface PasswordResetRequestResponse {
success: boolean
message: string
}
```
**VerifyResetTokenResponse** (interface)
```typescript
interface VerifyResetTokenResponse {
valid: boolean
email?: string
expiresAt?: number
message?: string
}
```
**PasswordResetCompleteResponse** (interface)
```typescript
interface PasswordResetCompleteResponse {
success: boolean
message: string
}
```
**EmailVerificationActionResponse** (interface)
```typescript
interface EmailVerificationActionResponse {
success: boolean
message: string
}
```
**EmailVerifyTokenResponse** (interface)
```typescript
interface EmailVerifyTokenResponse {
success: boolean
message: string
token?: string
user?: AuthKitUser
accountData?: Record<string, any>
emailVerificationMode?: 'immediate' | 'verify-auto-login' | 'verify-manual-login'
}
```
**AuthKitBrandingConfig** (interface)
```typescript
interface AuthKitBrandingConfig {
logoUrl?: string
title?: string
subtitle?: string
primaryColor?: string
secondaryColor?: string
backgroundColor?: string
buttonStyle?: string
fontFamily?: string
}
```
**AuthKitConfig** (interface)
```typescript
interface AuthKitConfig {
id: string
branding?: AuthKitBrandingConfig
enabledProviders?: string[]
customCss?: string
termsUrl?: string
privacyUrl?: string
supportEmail?: string
redirectUrl?: string
updatedAt?: string
}
```
### batch
**FirebaseTimestamp** (interface)
```typescript
interface FirebaseTimestamp {
seconds: number // Unix timestamp in seconds
nanoseconds?: number // Nanoseconds component
}
```
**BatchResponse** (interface)
```typescript
interface BatchResponse {
id: string // Batch ID
name?: string // Batch name
expiryDate?: FirebaseTimestamp | string // Firebase timestamp or ISO 8601 date
productId?: string // Product ID (for collection-level searches)
collectionId?: string // Collection ID
[key: string]: any // Additional batch fields
}
```
**BatchCreateRequest** (interface)
```typescript
interface BatchCreateRequest {
id: string // Batch ID
name?: string // Batch name
expiryDate?: FirebaseTimestamp | string // Firebase timestamp or ISO 8601 date
[key: string]: any // Additional batch fields
}
```
**BatchUpdateRequest** (interface)
```typescript
interface BatchUpdateRequest {
name?: string // Batch name
expiryDate?: FirebaseTimestamp | string // Firebase timestamp or ISO 8601 date
[key: string]: any // Additional batch fields
}
```
**SearchBatchesRequest** (interface)
```typescript
interface SearchBatchesRequest {
search?: string // Search term (batch ID or name)
productId?: string // Filter by specific product
limit?: number // Max results (default: 100)
}
```
**BatchTag** (interface)
```typescript
interface BatchTag {
code: string // Code/tag ID
claimSetId: string // Claim set ID
collectionId?: string // Collection ID
productId?: string // Associated product ID
batchId?: string // Batch ID
tagId?: string // Tag identifier
index?: number // Position in claim set
}
```
### broadcasts
**ListBroadcastsQuery** (interface)
```typescript
interface ListBroadcastsQuery {
limit?: number
offset?: number
appId?: string
}
```
**BroadcastRecord** (interface)
```typescript
interface BroadcastRecord {
id: string
collectionId: string
appId: string
templateId?: string | null
segmentId?: string | null
status?: string | null
scheduledAt?: string | null
sentAt?: string | null
data?: {
display?: {
title?: string
description?: string
icon?: string
color?: string
}
broadcastType?: string
topic: string
templateParams?: Record<string, unknown>;
channelSettings?: {
mode?: 'preferred' | 'channels' | 'all'
channels?: Array<{
channel: BroadcastChannel
enabled?: boolean
priority?: number
}>
}
[key: string]: unknown
}
createdAt: string
}
```
**BroadcastList** (interface)
```typescript
interface BroadcastList {
items: BroadcastRecord[]
limit: number
offset: number
}
```
**BroadcastRecipientsResponse** (interface)
```typescript
interface BroadcastRecipientsResponse {
items: import('./comms').Recipient[]
total: number
limit: number
offset: number
note?: string
}
```
**BroadcastPreviewRequest** (interface)
```typescript
interface BroadcastPreviewRequest {
contactId?: string
email?: string
phone?: string
props?: Record<string, any>
channelOverride?: BroadcastChannel
hydrate?: boolean
include?: { product?: boolean; proof?: boolean; user?: boolean; [k: string]: boolean | undefined }
}
```
**BroadcastSendTestRequest** (interface)
```typescript
interface BroadcastSendTestRequest {
contactId?: string
email?: string
phone?: string
props?: Record<string, any>
channelOverride?: BroadcastChannel
hydrate?: boolean
include?: { product?: boolean; proof?: boolean; user?: boolean; [k: string]: boolean | undefined }
}
```
**BroadcastSendTestResponse** (interface)
```typescript
interface BroadcastSendTestResponse {
ok: boolean; id?: string; channel?: BroadcastChannel
}
```
**BroadcastSendManualRequest** (interface)
```typescript
interface BroadcastSendManualRequest {
limit?: number
offset?: number
dryRun?: boolean
sharedContext?: Record<string, any>
}
```
**BroadcastSendManualResponse** (interface)
```typescript
interface BroadcastSendManualResponse {
ok: boolean
counts: { sent: number; failed: number; skipped: number }
page: { limit: number; offset: number; total: number }
results: Array<{
contactId: string
status: 'sent' | 'failed' | 'skipped' | 'dry_run'
id?: string
error?: string
message?: string
}>
}
```
**BroadcastSendRequest** (interface)
```typescript
interface BroadcastSendRequest {
pageSize?: number
maxPages?: number
sharedContext?: Record<string, any>
channel?: BroadcastChannel
hydrate?: boolean
include?: { product?: boolean; proof?: boolean; user?: boolean; [k: string]: boolean | undefined }
}
```
**BroadcastAppendEventBody** (interface)
```typescript
interface BroadcastAppendEventBody {
broadcastId: string
contactId?: string
channel?: BroadcastChannel
templateId?: string
eventType: string
outcome?: 'success' | 'failed'
failureReason?: string
metadata?: Record<string, any>
}
```
**BroadcastAppendBulkBody** (interface)
```typescript
interface BroadcastAppendBulkBody {
ids: string[]
idField?: string
params: Record<string, any> // merged with collectionId server-side
}
```
**BroadcastChannel** = `'email' | 'push' | 'sms' | 'wallet'`
**BroadcastPreviewResponse** = ``
### claimSet
**ClaimCodeRef** (interface)
```typescript
interface ClaimCodeRef {
codeId: string
claimId: string
}
```
**UpdateClaimDataRequest** (interface)
```typescript
interface UpdateClaimDataRequest {
data: Record<string, any>
codes: ClaimCodeRef[]
}
```
**AssignClaimsRequest** (interface)
```typescript
interface AssignClaimsRequest {
id: string
collectionId: string
productId: string
batchId?: string
start?: number
end?: number
codeId?: string
data?: Record<string, any>
}
```
### collection
**Collection** (interface)
```typescript
interface Collection {
id: string
title: string
description: string
headerImage?: {
url: string
thumbnails: {
x100: string
x200: string
x512: string
}
}
logoImage?: {
url: string
thumbnails: {
x100: string
x200: string
x512: string
}
}
loaderImage?: {
overwriteName: string
name: string
type: string
url: string
}
languages?: {
code: string
lang: string
supported: boolean
}[],
roles: {
[userId: string]: string
} // User roles mapping with user IDs as keys and role names as values
groupTags?: string[] // Array of group tag names
redirectUrl?: string // Whether the collection has a custom domain
shortId: string, // The shortId of this collection
dark?: boolean // if dark mode is enabled for this collection
primaryColor?: string
secondaryColor?: string
portalUrl?: string // URL for the collection's portal (if applicable)
allowAutoGenerateClaims?: boolean
defaultAuthKitId: string // default auth kit for this collection, used for auth
}
```
**AppConfig** (interface)
```typescript
interface AppCo