TypeScript SDK for Mobius 3D Transfer API - Convert images to 3D models
npm install @cymmetrik-dev/3d-transfer-sdkTypeScript SDK for Mobius 3D Transfer API - Convert images to 3D models using AI-powered style transfer.
- Full TypeScript support with auto-generated types
- Support for multiple frameworks (Vite, Next.js, Expo, Node.js)
- Environment variable based configuration
- Axios-based HTTP client
- React ModelViewer component for displaying 3D GLB models
- Default style filtering for single-style deployments
- Additional instruction for custom style guidance (max 2000 chars)
- Add-to-cart redirect for seamless shopping cart integration (supports guest users)
- Split 2D/3D workflow - Control when 3D generation starts with auto_3d parameter
``bash`
npm install @cymmetrik-dev/3d-transfer-sdkor
yarn add @cymmetrik-dev/3d-transfer-sdkor
pnpm add @cymmetrik-dev/3d-transfer-sdk
Configure the SDK using environment variables based on your framework:
| Variable | Framework | Description |
|----------|-----------|-------------|
| VITE_TRANSFER_3D_API_URL | Vite | API base URL |VITE_TRANSFER_3D_API_TOKEN
| | Vite | API authentication token |VITE_TRANSFER_3D_DEFAULT_STYLE
| | Vite | Default style (optional) |VITE_DEFAULT_PRODUCT_SLUG
| | Vite | Default product slug (optional) |NEXT_PUBLIC_TRANSFER_3D_API_URL
| | Next.js | API base URL |NEXT_PUBLIC_TRANSFER_3D_API_TOKEN
| | Next.js | API authentication token |NEXT_PUBLIC_TRANSFER_3D_DEFAULT_STYLE
| | Next.js | Default style (optional) |NEXT_PUBLIC_DEFAULT_PRODUCT_SLUG
| | Next.js | Default product slug (optional) |EXPO_PUBLIC_TRANSFER_3D_API_URL
| | Expo | API base URL |EXPO_PUBLIC_TRANSFER_3D_API_TOKEN
| | Expo | API authentication token |EXPO_PUBLIC_TRANSFER_3D_DEFAULT_STYLE
| | Expo | Default style (optional) |EXPO_PUBLIC_DEFAULT_PRODUCT_SLUG
| | Expo | Default product slug (optional) |TRANSFER_3D_API_URL
| | Node.js | API base URL |TRANSFER_3D_API_TOKEN
| | Node.js | API authentication token |TRANSFER_3D_DEFAULT_STYLE
| | Node.js | Default style (optional) |DEFAULT_PRODUCT_SLUG
| | Node.js | Default product slug (optional) |
`bashFor Vite projects
VITE_TRANSFER_3D_API_URL=https://api.example.com/api
VITE_TRANSFER_3D_API_TOKEN=your-api-token-here
VITE_TRANSFER_3D_DEFAULT_STYLE= # Optional: filter to single style
VITE_DEFAULT_PRODUCT_SLUG= # Optional: default product for accessory info
Quick Start
$3
Use
initTransfer3D() to configure the SDK once at app startup. This sets the base URL and token for all subsequent API calls.`typescript
import { initTransfer3D } from '@cymmetrik-dev/3d-transfer-sdk';// Option 1: Auto-detect from environment variables
initTransfer3D();
// Option 2: Explicit configuration
initTransfer3D({
baseURL: 'https://api.example.com/api',
token: 'your-api-token',
});
`In a Vite/React project, create a setup file:
`typescript
// src/lib/transfer3d.ts
import { initTransfer3D } from '@cymmetrik-dev/3d-transfer-sdk';initTransfer3D({
baseURL: import.meta.env.VITE_TRANSFER_3D_API_URL,
token: import.meta.env.VITE_TRANSFER_3D_API_TOKEN,
});
`Then import it early in your app:
`typescript
// src/main.tsx
import './lib/transfer3d'; // Initialize SDK
import { createRoot } from 'react-dom/client';
import App from './App';createRoot(document.getElementById('root')!).render( );
`$3
If you need multiple clients (e.g., different API endpoints), use
createTransfer3DClient():`typescript
import {
createTransfer3DClient,
getTransfer3dStyles,
initiateTransfer3dConversion,
getTransfer3dStatus,
} from '@cymmetrik-dev/3d-transfer-sdk';// Create a custom client instance
const client = createTransfer3DClient({
baseURL: 'https://api.example.com/api',
token: 'your-api-token',
});
// Pass client to each API call
const styles = await getTransfer3dStyles({ client });
`$3
`typescript
import {
createTransfer3DClient,
getTransfer3dStyles,
initiateTransfer3dConversion,
getTransfer3dStatus,
} from '@cymmetrik-dev/3d-transfer-sdk';async function convertImageTo3D(imageFile: File) {
// 1. Initialize client
const client = createTransfer3DClient({
token: 'your-api-token',
});
// 2. Get available styles
const stylesResponse = await getTransfer3dStyles({ client });
console.log('Available styles:', stylesResponse.data);
// Output: [{ mode_key: 'smart', mode_name: 'Q版公仔', ... }]
// 3. Upload image and start conversion
const conversionResponse = await initiateTransfer3dConversion({
client,
body: {
image: imageFile,
style: 'smart', // Use a style from step 2
additional_instruction: '增加金色高光效果', // Optional: custom guidance
},
});
const requestId = conversionResponse.data.data.request_id;
console.log('Conversion started:', requestId);
// 4. Poll for status until completed
let status = 'PENDING';
let result = null;
while (status !== 'COMPLETED' && status !== 'FAILED') {
await new Promise((resolve) => setTimeout(resolve, 2000)); // Wait 2 seconds
const statusResponse = await getTransfer3dStatus({
client,
path: { requestId },
});
const data = statusResponse.data.data;
status = data.status;
console.log('Status:', status, 'Phase:', data.phase, 'Progress:', data.progress);
// 2D preview is available when phase changes to 3d_generation
if (data.result?.preview_2d_url) {
console.log('2D Preview ready:', data.result.preview_2d_url);
}
if (status === 'COMPLETED') {
result = data.result;
}
}
if (result) {
console.log('3D Model URL:', result.model_3d_url);
console.log('GLB File URL:', result.glb_url);
console.log('2D Preview URL:', result.preview_2d_url);
}
return result;
}
`$3
When you want to let users preview the 2D styled image before proceeding to 3D generation:
`typescript
import {
createTransfer3DClient,
initiateTransfer3dConversion,
triggerTransfer3dConversion,
getTransfer3dStatus,
} from '@cymmetrik-dev/3d-transfer-sdk';async function convertWithManual3DTrigger(imageFile: File) {
const client = createTransfer3DClient();
// 1. Start 2D-only conversion
const { data } = await initiateTransfer3dConversion({
client,
body: {
image: imageFile,
style: 'smart',
auto_3d: false, // Don't auto-proceed to 3D
},
});
const requestId = data.data.request_id;
// 2. Poll until 2D completes
let status = 'PENDING';
let preview2dUrl = null;
while (status !== '2D_COMPLETED' && status !== 'FAILED') {
await new Promise((r) => setTimeout(r, 2000));
const { data: statusData } = await getTransfer3dStatus({
client,
path: { requestId },
});
status = statusData.data.status;
if (statusData.data.result?.preview_2d_url) {
preview2dUrl = statusData.data.result.preview_2d_url;
}
}
console.log('2D Preview ready:', preview2dUrl);
// At this point, show preview_2d_url to user and wait for confirmation
// 3. When user confirms, trigger 3D generation
await triggerTransfer3dConversion({
client,
body: { request_id: requestId },
});
// 4. Poll until 3D completes
status = 'IN_PROGRESS';
let glbUrl = null;
while (status !== 'COMPLETED' && status !== 'FAILED') {
await new Promise((r) => setTimeout(r, 2000));
const { data: statusData } = await getTransfer3dStatus({
client,
path: { requestId },
});
status = statusData.data.status;
if (status === 'COMPLETED') {
glbUrl = statusData.data.result?.glb_url;
}
}
return { preview2dUrl, glbUrl };
}
`React Components
$3
The SDK includes a React component for displaying 3D GLB/GLTF models using Google's model-viewer web component.
`tsx
import { ModelViewer } from '@cymmetrik-dev/3d-transfer-sdk/react';function My3DViewer() {
return (
src="https://example.com/model.glb"
alt="3D Model"
cameraControls
autoRotate
style={{ width: '100%', height: '400px' }}
/>
);
}
`#### ModelViewer Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
|
src | string | required | URL to the GLB/GLTF model file |
| alt | string | '3D Model' | Alt text for accessibility |
| cameraControls | boolean | true | Enable camera controls (pan, zoom, rotate) |
| autoRotate | boolean | true | Enable auto rotation |
| shadowIntensity | number | 1 | Shadow intensity (0-1) |
| transparentBackground | boolean | false | Enable transparent background (removes default gradient) |
| poster | string | - | Poster image URL to show while loading |
| className | string | - | CSS class name |
| style | CSSProperties | - | Inline styles |
| loading | 'auto' \| 'lazy' \| 'eager' | 'auto' | Loading strategy |
| reveal | 'auto' \| 'manual' | 'auto' | Reveal strategy |
| onLoad | () => void | - | Callback when model is loaded |
| onError | (error: Error) => void | - | Callback when error occurs |#### Transparent Background Example
To display the 3D model with a transparent background (useful for overlays or custom backgrounds):
`tsx
src="https://example.com/model.glb"
transparentBackground
cameraControls
autoRotate
style={{ width: '200px', height: '200px' }}
/>
`#### Complete React Example with ModelViewer
`tsx
import { useState, useEffect } from 'react';
import {
createTransfer3DClient,
getTransfer3dStyles,
initiateTransfer3dConversion,
getTransfer3dStatus,
} from '@cymmetrik-dev/3d-transfer-sdk';
import { ModelViewer } from '@cymmetrik-dev/3d-transfer-sdk/react';export function ImageTo3DConverter() {
const [status, setStatus] = useState('idle');
const [progress, setProgress] = useState(0);
const [preview2dUrl, setPreview2dUrl] = useState(null);
const [glbUrl, setGlbUrl] = useState(null);
const [webViewUrl, setWebViewUrl] = useState(null);
const handleConvert = async (file: File, style: string) => {
const client = createTransfer3DClient();
setStatus('uploading');
const { data } = await initiateTransfer3dConversion({
client,
body: { image: file, style },
});
const requestId = data.data.request_id;
setStatus('processing');
// Poll for completion
const pollStatus = async () => {
const { data: statusData } = await getTransfer3dStatus({
client,
path: { requestId },
});
const result = statusData.data;
setProgress(result.progress || 0);
// Web view URL for viewing on main site
if (result.web_view_url) {
setWebViewUrl(result.web_view_url);
}
// 2D preview becomes available during 3D generation phase
if (result.result?.preview_2d_url) {
setPreview2dUrl(result.result.preview_2d_url);
}
if (result.status === 'COMPLETED') {
setGlbUrl(result.result.glb_url);
setStatus('completed');
} else if (result.status === 'FAILED') {
setStatus('failed');
} else {
setTimeout(pollStatus, 2000);
}
};
pollStatus();
};
return (
Status: {status} ({progress}%)
{/ Link to view progress on main site /}
{webViewUrl && (
View on main site
)}
{/ 2D styled preview /}
{preview2dUrl && (
2D Style Preview

)} {/ 3D Model Viewer /}
{glbUrl && (
3D Model
src={glbUrl}
alt="Generated 3D Model"
cameraControls
autoRotate
style={{ width: '100%', height: '400px' }}
/>
)}
);
}
`API Reference
$3
Initialize the default SDK client. Call this once at app startup to configure the base URL and authentication token for all API calls.
Parameters:
-
config.baseURL (optional): API base URL. Falls back to environment variables.
- config.token (optional): Bearer authentication token. Falls back to environment variables.Example:
`typescript
import { initTransfer3D, getTransfer3dStyles } from '@cymmetrik-dev/3d-transfer-sdk';// Initialize with explicit config
initTransfer3D({
baseURL: 'https://api.example.com/api',
token: 'your-api-token',
});
// Or auto-detect from environment variables
initTransfer3D();
// Now all API calls use this configuration (no need to pass client)
const styles = await getTransfer3dStyles();
`---
$3
Create a separate API client instance. Use this when you need multiple clients or want to override the default configuration for specific calls.
Parameters:
-
config.baseURL (optional): API base URL
- config.token (optional): Bearer authentication token
- config.timeout (optional): Request timeout in ms (default: 30000)Returns: Configured axios client
---
$3
Get available 3D transfer styles.
Parameters:
-
query.default_style (optional): string - Filter to return only this styleExample:
`typescript
// Get all styles
const allStyles = await getTransfer3dStyles({ client });// Get single style (useful for single-style deployments)
const singleStyle = await getTransfer3dStyles({
client,
query: { default_style: 'smart' },
});
`Returns:
`typescript
{
success: true,
data: Array<{
mode_key: string; // Style identifier (e.g., 'smart')
mode_name: string; // Display name (e.g., 'Q版公仔')
mode_description: string;
preview_image_url: string | null;
}>
}
`> Note: If
default_style is specified but not found, API returns all styles as fallback.---
$3
Upload an image and start the 3D conversion process.
Parameters:
-
body.image: File - Image to convert (max 10MB, supported: jpg, png, webp)
- body.style: string - Style key from getTransfer3dStyles()
- body.additional_instruction (optional): string - Custom style guidance (max 2000 chars)
- body.auto_3d (optional): boolean - Auto-proceed to 3D after 2D completes (default: true)Example:
`typescript
// Basic conversion (auto 2D → 3D)
const result = await initiateTransfer3dConversion({
client,
body: {
image: imageFile,
style: 'smart',
},
});// With additional instruction for fine-tuning
const result = await initiateTransfer3dConversion({
client,
body: {
image: imageFile,
style: 'smart',
additional_instruction: '增加金色高光效果,使用暖色調',
},
});
// 2D-only mode: Stop after 2D style transfer
const result = await initiateTransfer3dConversion({
client,
body: {
image: imageFile,
style: 'smart',
auto_3d: false, // Will stop at 2D_COMPLETED status
},
});
`Additional Instruction Use Cases:
- Fine-tune style output (e.g., "更卡通化", "增加質感")
- Specify colors or materials (e.g., "使用暖色調", "金屬質感")
- Adjust lighting effects (e.g., "增加高光", "柔和陰影")
> Note:
additional_instruction is appended to the style's base instructions, not replaced.Returns:
`typescript
{
success: true,
data: {
request_id: string; // UUID for status polling
chat_thread_id: number; // Internal ChatThread ID (for add-to-cart)
status: 'PENDING';
message: string;
}
}
`---
$3
Trigger 3D generation for a request that completed 2D styling. Use this when you initiated a conversion with
auto_3d: false.Parameters:
-
body.request_id: string - The request ID from the original /convert callExample:
`typescript
// After status shows '2D_COMPLETED', trigger 3D generation
const result = await triggerTransfer3dConversion({
client,
body: {
request_id: 'uuid-xxx',
},
});
`Returns:
`typescript
{
success: true,
data: {
request_id: string;
chat_thread_id: number; // Internal ChatThread ID (for add-to-cart)
status: 'IN_PROGRESS';
message: '3D conversion initiated';
}
}
`Error Responses:
-
400 - 2D style transfer not yet completed
- 400 - 3D conversion already in progress or completed
- 404 - Request not found---
$3
Get the status of a conversion request.
Parameters:
-
path.requestId: string - Request ID from conversion responseReturns:
`typescript
{
success: true,
data: {
request_id: string;
status: 'PENDING' | 'IN_PROGRESS' | '2D_COMPLETED' | 'COMPLETED' | 'FAILED';
phase: '2d_style_transfer' | '3d_generation_pending' | '3d_generation';
progress: number; // 0-100 (2D_COMPLETED = 50%)
web_view_url: string; // URL to view progress on main site
auto_3d?: boolean; // Present for API requests, indicates if 3D will auto-start
result?: {
preview_2d_url: string; // Available when 2D transfer completes
model_3d_url: string; // Available when fully completed
glb_url: string; // GLB file URL (same as model_3d_url)
};
error?: string; // Present if status is FAILED
}
}
`> Note: When
auto_3d: false, the status will be 2D_COMPLETED (not COMPLETED) when 2D styling finishes. Call triggerTransfer3dConversion() to start 3D generation.---
$3
Get product information by slug, including name, description, price, and images.
Parameters:
-
path.slug: string - The product slugExample:
`typescript
import {
createTransfer3DClient,
getTransfer3DProduct,
getDefaultProductSlug,
} from '@cymmetrik-dev/3d-transfer-sdk';const client = createTransfer3DClient();
// Get product by slug
const { data } = await getTransfer3DProduct({
client,
path: { slug: 'my-product-slug' },
});
console.log('Product:', data.data.name);
console.log('Price:', data.data.price?.formatted);
console.log('Main Image:', data.data.main_image_url);
// Or use default product slug from environment
const defaultSlug = getDefaultProductSlug();
if (defaultSlug) {
const { data } = await getTransfer3DProduct({
client,
path: { slug: defaultSlug },
});
}
`Returns:
`typescript
{
success: true,
data: {
slug: string;
name: string;
description: string;
price: {
value: number; // Price in smallest currency unit
formatted: string; // e.g., "NT$1,990"
currency: string; // e.g., "TWD"
} | null;
main_image_url: string | null;
images: Array<{
url: string;
alt: string;
}>;
variants: Array<{
id: number; // Variant ID (use for add-to-cart)
sku: string; // SKU code
options: Array<{ // Variant options (e.g., color, size)
name: string; // Option name (e.g., "顏色")
value: string; // Option value (e.g., "紅色")
}>;
price: {
value: number;
formatted: string;
currency: string;
};
}>;
}
}
`Example with Variants:
`typescript
const { data } = await getTransfer3DProduct({
client,
path: { slug: 'my-product' },
});// Display product with variant selector
console.log('Product:', data.data.name);
data.data.variants.forEach((variant) => {
const optionText = variant.options
.map(o =>
${o.name}: ${o.value})
.join(', ');
console.log(- ${variant.sku} (${optionText}): ${variant.price.formatted});
});// Add specific variant to cart
const selectedVariant = data.data.variants[0];
const cartUrl = buildAddToCartUrl('https://shop.example.com', {
products: [{ model_type: 'product_variant', model_id: selectedVariant.id }],
});
`---
$3
Get the default product slug from environment variables.
Returns:
string | undefinedExample:
`typescript
import { getDefaultProductSlug } from '@cymmetrik-dev/3d-transfer-sdk';const slug = getDefaultProductSlug();
// Returns value from VITE_DEFAULT_PRODUCT_SLUG, NEXT_PUBLIC_DEFAULT_PRODUCT_SLUG, etc.
`---
$3
Get the default style from environment variables.
Returns:
string | undefinedExample:
`typescript
import { getDefaultStyle } from '@cymmetrik-dev/3d-transfer-sdk';const style = getDefaultStyle();
// Returns value from VITE_TRANSFER_3D_DEFAULT_STYLE, etc.
`---
Add to Cart Redirect
The SDK provides helper functions to build URLs that add products to the shopping cart and redirect users. This feature:
- Works for both logged-in users and guest users
- Supports adding multiple products at once
- Allows custom redirect URLs after adding to cart
- No authentication token required (public endpoint)
$3
Build a URL that adds products to cart and redirects.
Parameters:
-
baseURL: string - The shop's base URL (without /api)
- options.products: CartProduct[] - Products to add
- options.redirectUrl: string (optional) - Redirect URL after adding (default: /cart)CartProduct interface:
`typescript
interface CartProduct {
model_type:
| 'Lunar\\Models\\ProductVariant'
| 'Projects\\Frontier\\Models\\FrontierOrder'
| 'Projects\\Frontier\\Models\\ChatThread'; // Auto-creates FrontierOrder
model_id: number;
quantity?: number; // default: 1
}
`Example:
`typescript
import { buildAddToCartUrl } from '@cymmetrik-dev/3d-transfer-sdk';// Add single product
const url = buildAddToCartUrl('https://shop.example.com', {
products: [{ model_type: 'product_variant', model_id: 123 }],
});
// Result: https://shop.example.com/api/3d-transfer/add-to-cart?products=[{"model_type":"product_variant","model_id":123}]
// Add multiple products with quantities
const url = buildAddToCartUrl('https://shop.example.com', {
products: [
{ model_type: 'product_variant', model_id: 123, quantity: 2 },
{ model_type: 'product_variant', model_id: 456, quantity: 1 },
],
});
// With custom redirect URL
const url = buildAddToCartUrl('https://shop.example.com', {
products: [{ model_type: 'product_variant', model_id: 123 }],
redirectUrl: '/checkout',
});
// Add 3D model by ChatThread ID (auto-creates FrontierOrder if needed)
const url = buildAddToCartUrl('https://shop.example.com', {
products: [{ model_type: 'Projects\\Frontier\\Models\\ChatThread', model_id: chatThreadId }],
});
// Or add existing FrontierOrder directly
const url = buildAddToCartUrl('https://shop.example.com', {
products: [{ model_type: 'Projects\\Frontier\\Models\\FrontierOrder', model_id: 789 }],
});
`---
$3
Build add-to-cart URL using the API URL from environment variables.
Parameters:
-
options.products: CartProduct[] - Products to add
- options.redirectUrl: string (optional) - Redirect URL after addingReturns:
string | null - URL or null if API URL not configuredExample:
`typescript
import { buildAddToCartUrlFromEnv } from '@cymmetrik-dev/3d-transfer-sdk';const url = buildAddToCartUrlFromEnv({
products: [{ model_type: 'product_variant', model_id: 123 }],
});
if (url) {
window.location.href = url;
}
`---
$3
`tsx
import { buildAddToCartUrl, getTransfer3DProduct } from '@cymmetrik-dev/3d-transfer-sdk';function BuyButton({ productId }: { productId: number }) {
const handleBuy = () => {
const url = buildAddToCartUrl('https://shop.example.com', {
products: [{ model_type: 'product_variant', model_id: productId }],
redirectUrl: '/checkout',
});
window.location.href = url;
};
return (
);
}
// Or use as a link
function BuyLink({ productId }: { productId: number }) {
const url = buildAddToCartUrl('https://shop.example.com', {
products: [{ model_type: 'product_variant', model_id: productId }],
});
return (
加入購物車
);
}
`---
$3
`html
加入購物車
`---
$3
`tsx
import {
createTransfer3DClient,
initiateTransfer3dConversion,
getTransfer3dStatus,
buildAddToCartUrl,
} from '@cymmetrik-dev/3d-transfer-sdk';// Full workflow: Upload image → Convert → Add to cart
async function convertAndAddToCart(imageFile: File) {
const client = createTransfer3DClient();
// 1. Start conversion and get chat_thread_id
const { data: conversionData } = await initiateTransfer3dConversion({
client,
body: { image: imageFile, style: 'smart' },
});
const { request_id: requestId, chat_thread_id: chatThreadId } = conversionData.data;
console.log('ChatThread ID:', chatThreadId); // Use this for add-to-cart
// 2. Poll until completed
let status = 'PENDING';
while (status !== 'COMPLETED' && status !== 'FAILED') {
await new Promise((r) => setTimeout(r, 2000));
const { data } = await getTransfer3dStatus({ client, path: { requestId } });
status = data.data.status;
}
// 3. Add to cart using ChatThread ID (auto-creates FrontierOrder)
if (status === 'COMPLETED') {
const cartUrl = buildAddToCartUrl('https://shop.example.com', {
products: [{
model_type: 'Projects\\Frontier\\Models\\ChatThread',
model_id: chatThreadId,
}],
});
window.location.href = cartUrl;
}
}
`Conversion Phases
| Phase | Progress | Description |
|-------|----------|-------------|
|
2d_style_transfer | 0-50% | Image is being styled with AI |
| 3d_generation_pending | 50% | 2D complete, waiting for 3D to start |
| 3d_generation | 50-100% | 3D model is being generated |Note: The
preview_2d_url becomes available when the phase changes to 3d_generation_pending or 3d_generation, allowing you to show the styled image while the 3D model is still being generated.Status Values
| Status | Description |
|--------|-------------|
|
PENDING | Conversion request queued |
| IN_PROGRESS | Currently processing (2D or 3D) |
| 2D_COMPLETED | 2D styling finished, waiting for 3D trigger (only when auto_3d: false) |
| COMPLETED | Full conversion finished (2D + 3D) |
| FAILED | An error occurred |> Tip: For
auto_3d: false requests, poll until status === '2D_COMPLETED', show the preview_2d_url, then call triggerTransfer3dConversion() when ready.TypeScript Types
`typescript
import type {
// Request/Response types (auto-generated)
GetTransfer3dStylesResponse,
InitiateTransfer3dConversionData,
InitiateTransfer3dConversionResponse,
TriggerTransfer3dConversionData,
TriggerTransfer3dConversionResponse,
GetTransfer3dStatusData,
GetTransfer3dStatusResponse,
GetTransfer3DProductData,
GetTransfer3DProductResponse,
// Add to cart types
CartProduct,
AddToCartOptions,
} from '@cymmetrik-dev/3d-transfer-sdk';// Helper functions
import {
getDefaultProductSlug,
getDefaultStyle,
buildAddToCartUrl,
buildAddToCartUrlFromEnv,
} from '@cymmetrik-dev/3d-transfer-sdk';
// API functions
import {
getTransfer3dStyles,
initiateTransfer3dConversion,
triggerTransfer3dConversion,
getTransfer3dStatus,
getTransfer3DProduct,
} from '@cymmetrik-dev/3d-transfer-sdk';
// React component types
import type { ModelViewerProps } from '@cymmetrik-dev/3d-transfer-sdk/react';
`Error Handling
`typescript
import { AxiosError } from 'axios';try {
const response = await initiateTransfer3dConversion({
client,
body: { image: file, style: 'smart' },
});
} catch (error) {
if (error instanceof AxiosError) {
if (error.response?.status === 401) {
console.error('Authentication failed. Check your API token.');
} else if (error.response?.status === 422) {
console.error('Validation error:', error.response.data.errors);
} else if (error.response?.status === 429) {
console.error('Rate limit exceeded. Please try again later.');
}
}
throw error;
}
`Demo Application
A complete React demo application is available in the examples/react-demo directory.
To run the demo:
`bash
cd examples/react-demo
pnpm install
cp .env.example .env # Configure your API URL and token
pnpm dev
``---
This SDK is auto-generated from the Mobius Frontier OpenAPI specification using @hey-api/openapi-ts