@magic-apps-cloud/sdk
v0.11.0
Published
Magic Apps Cloud SDK for TypeScript/JavaScript
Maintainers
Readme
@magic-apps-cloud/sdk
Official TypeScript/JavaScript SDK for the Magic Apps Cloud platform. Provides tenant-scoped API access with authentication, AI services, device catalogs, templates, endpoints, lookup tables, and more.
Installation
npm install @magic-apps-cloud/sdkQuick Start
import { MagicAppsClient } from "@magic-apps-cloud/sdk";
const client = new MagicAppsClient({
baseUrl: "https://api.yourplatform.com",
appId: "your-app-id",
});
// Health check
const { data: pong } = await client.ping();
console.log(pong.message);
// Get app info
const { data: app } = await client.getAppInfo();
console.log(app.name);
// Get a template
const { data: template } = await client.getTemplate("template-id");
// Get the app catalog
const { data: catalog } = await client.getCatalog();Authentication
Pass an auth token for authenticated endpoints:
const client = new MagicAppsClient({
baseUrl: "https://api.yourplatform.com",
appId: "your-app-id",
authToken: "your-jwt-token",
});
// Update the token later (e.g. after login or refresh)
client.setAuthToken("new-token");
// Clear the token (e.g. on logout)
client.clearAuthToken();Apple Sign-In
const { data: tokens } = await client.appleExchangeToken(
identityToken,
"your-app-id"
);
client.setAuthToken(tokens.token);Google Sign-In
const { data: tokens } = await client.googleExchangeToken(
googleIdToken,
"your-app-id"
);
client.setAuthToken(tokens.token);Passkeys (WebAuthn)
// Registration flow
const { data: options } = await client.getPasskeyRegisterOptions();
// ... use options.challenge with the Web Authentication API ...
const { data: result } = await client.verifyPasskeyRegistration(credential);
// Authentication flow
const { data: authOptions } = await client.getPasskeyAuthOptions();
// ... use authOptions.challenge with the Web Authentication API ...
const { data: authResult } = await client.verifyPasskeyAuth(assertion);Email Magic Link
// Request a magic link
await client.requestEmailMagicLink("[email protected]");
// Verify the token from the link
const { data: tokens } = await client.verifyEmailMagicLink(token);
client.setAuthToken(tokens.token);Token Refresh
const { data: tokens } = await client.refreshToken(refreshToken);
client.setAuthToken(tokens.token);Identity Linking
// Link an external provider to the current account
await client.linkProvider("google", providerToken);Owner Registration
Register device owners for anonymous app usage and migrate them to full accounts:
// Register a device owner (returns an owner token)
const { data: owner } = await client.registerOwner(
"device-uuid",
"your-app-id"
);
// Migrate owner data to a signed-in user
await client.migrateOwnerToUser("device-uuid", "your-app-id");AI Services
The SDK provides access to chat completions, embeddings, image generation, and content moderation via the platform's AI proxy. Requests are routed through the tenant's configured provider (OpenAI, Anthropic, Google).
Chat Completions
import type { ChatMessage, ChatCompletionRequest } from "@magic-apps-cloud/sdk";
// Convenience: pass a messages array
const messages: ChatMessage[] = [
{ role: "system", content: "You are a helpful assistant." },
{ role: "user", content: "Explain serverless architecture." },
];
const { data: chatResult } = await client.chat(messages, { model: "gpt-4" });
console.log(chatResult.choices[0].message.content);
// Full chat completion request
const request: ChatCompletionRequest = {
messages,
model: "gpt-4",
temperature: 0.7,
max_tokens: 500,
};
const { data: completion } = await client.createChatCompletion(request);Embeddings
// Convenience method
const { data: embeddings } = await client.embed("Hello world");
console.log(embeddings.data[0].embedding);
// With model parameter
const { data: embeddingResult } = await client.createEmbedding(
"Some text to embed",
"text-embedding-ada-002"
);Image Generation
// Convenience method
const { data: image } = await client.generateImage("A sunset over mountains");
console.log(image.data[0].url);
// With options
const { data: images } = await client.createImage("A forest landscape", {
n: 2,
size: "1024x1024",
});Content Moderation
// Convenience method
const { data: moderation } = await client.moderate("Some user content");
if (moderation.results[0].flagged) {
console.log("Content flagged!");
}
// With model parameter
const { data: result } = await client.createModeration("Text to check", "text-moderation-stable");Templates and Catalog
// Get a specific template by ID
const { data: template } = await client.getTemplate("template-id");
console.log(template.name);
// Get the full app catalog
const { data: catalog } = await client.getCatalog();Devices
// Fetch the device catalog
const { data: catalog } = await client.getDevices();
console.log(catalog.devices.length);
// Convenience: get a flat list of all devices
const devices = await client.getAllDevices();
for (const device of devices) {
console.log(`${device.device_name}: ${device.device_type}`);
}Endpoints and Events
Webhook endpoint management and event delivery with optional HMAC signing.
// Create a new webhook endpoint
const { data: endpoint } = await client.createEndpoint();
console.log(`Slug: ${endpoint.slug}`);
console.log(`Path: ${endpoint.endpoint_path}`);
// Post an event to an endpoint
const { data: event } = await client.postEvent(endpoint.slug, {
message: "Hello from the SDK",
});
// Consume an event (single-slot, consume-on-read)
const { data: consumed } = await client.consumeEvent(endpoint.slug);
// Revoke and replace an endpoint
const { data: replacement } = await client.revokeAndReplaceEndpoint(
endpoint.slug
);
console.log(`New slug: ${replacement.new_slug}`);
// Revoke an endpoint without replacement
await client.revokeEndpoint(endpoint.slug);HMAC Signing
The SDK provides standalone functions for generating and verifying HMAC signatures on endpoint events. The signature format is HMAC-SHA256(secret, "slug:timestamp:body").
import { generateHmacSignature, verifyHmacSignature } from "@magic-apps-cloud/sdk";
// Generate signature headers for posting a signed event
const headers = await generateHmacSignature(
"my-endpoint-slug",
JSON.stringify({ data: "payload" }),
"hmac-secret-from-endpoint"
);
// Use headers.signature and headers.timestamp in your request
// Verify an incoming webhook signature (constant-time comparison, clock skew check)
const isValid = await verifyHmacSignature(
"my-endpoint-slug",
rawBody,
request.headers["x-signature"],
request.headers["x-timestamp"],
"hmac-secret-from-endpoint",
300 // maxSkewSeconds (default)
);Lookup Tables
Read-only access to lookup tables (reference data configured by tenant admins).
// List available lookup tables
const { data: tables } = await client.listLookupTables();
// Get a specific table's metadata (includes chunk refs)
const { data: detail } = await client.getLookupTable("table-id");
// Fetch an individual data chunk by index
const { data: chunk } = await client.getLookupTableChunk("table-id", 0);
// Fetch with a specific version for cache consistency
const { data: versionedChunk } = await client.getLookupTableChunk(
"table-id",
0,
5
);
// Fetch the complete dataset (all chunks merged)
const { data: fullData } = await client.getFullLookupTableDataset("table-id");User Profiles
// Get the current user's profile
const { data: profile } = await client.getProfile();
console.log(profile.display_name);
// Update the current user's profile
const { data: updated } = await client.updateProfile({
display_name: "Jane Doe",
bio: "Mobile developer",
preferences: { theme: "dark" },
custom_fields: { company: "Acme" },
});
// Get another user's public profile
const { data: publicProfile } = await client.getPublicProfile("user-id");
console.log(publicProfile.display_name);Account Management
// Delete the current user's account (optional reason)
await client.deleteAccount("No longer using the app");
// Delete without a reason
await client.deleteAccount();
// Export account data
const { data: exportData } = await client.exportAccountData();
console.log(exportData.exported_at);
// Get consent preferences
const { data: consent } = await client.getConsent();
console.log(consent.analytics);
// Update consent preferences
await client.updateConsent({
analytics: true,
marketing: false,
third_party: false,
});File Storage
// Get a pre-signed upload URL
const { data: upload } = await client.getFileUploadUrl("photo.jpg", "image/jpeg");
console.log(upload.upload_url);
console.log(upload.file_id);
// Upload the file using the pre-signed URL
await fetch(upload.upload_url, {
method: "PUT",
body: fileData,
headers: { "Content-Type": "image/jpeg" },
});
// List all files
const { data: fileList } = await client.listFiles();
for (const file of fileList.files) {
console.log(`${file.filename}: ${file.content_type}`);
}
// Get a specific file
const { data: file } = await client.getFile("file-id");
// Delete a file
await client.deleteFile("file-id");AI Conversations
Manage persistent AI conversations with message history.
// Create a new conversation
const { data: conversation } = await client.createConversation({
title: "Help me debug",
model: "gpt-4",
system_prompt: "You are a helpful coding assistant.",
});
console.log(conversation.conversation_id);
// List conversations (with optional pagination)
const { data: list } = await client.listConversations();
for (const conv of list.conversations) {
console.log(`${conv.title} (${conv.message_count} messages)`);
}
// Paginate through conversations
const { data: page2 } = await client.listConversations(list.next_token);
// Get a specific conversation
const { data: conv } = await client.getConversation("conversation-id");
// Send a message and get a response
const { data: response } = await client.sendMessage(
"conversation-id",
"How do I fix a memory leak?",
{ temperature: 0.7 },
);
console.log(response.message.content);
// Delete a conversation
await client.deleteConversation("conversation-id");Push Notifications
// Register a device for push notifications
const { data: registration } = await client.registerDevice(
"push-token-from-os",
"ios",
"optional-device-id",
);
console.log(registration.device_id);
// Unregister a device
await client.unregisterDevice("device-id");Settings and Config
// Get/update user settings
const { data: settings } = await client.getSettings();
await client.updateSettings({ theme: "dark", notifications: true });
// Get/update config
const { data: config } = await client.getConfig();
await client.updateConfig({ feature_flags: { beta: true } });
// Integration secrets
const { data: secret } = await client.getIntegrationSecret("integration-id");
await client.uploadIntegrationSecret("integration-id", {
api_key: "sk-...",
});Configuration
| Option | Type | Required | Default | Description |
|--------|------|----------|---------|-------------|
| baseUrl | string | Yes | - | Base URL of the Magic Apps Cloud API |
| appId | string | Yes | - | Your registered application ID |
| authToken | string | No | - | JWT token for authenticated requests |
| timeout | number | No | 30000 | Request timeout in milliseconds |
Error Handling
The SDK provides typed error classes for structured error handling:
import { MagicAppsClient, ApiError, MagicAppsError } from "@magic-apps-cloud/sdk";
try {
const { data } = await client.getAppInfo();
} catch (error) {
if (error instanceof ApiError) {
// HTTP error from the API (4xx, 5xx)
console.error(`API error ${error.statusCode}: ${error.message}`);
console.error("Response body:", error.responseBody);
} else if (error instanceof MagicAppsError) {
// SDK-level error (timeout, network failure, missing config)
console.error(`SDK error: ${error.message}`);
}
}Requirements
- Node.js 18+
- Web Crypto API (available in Node.js 15+, all modern browsers, Deno, Bun, Cloudflare Workers)
License
MIT
