What is the SDK?
The Kittl SDK is the bridge between your sandboxed app and the editor host. It exposes async APIs through:
kittl.designfor design operationskittl.statefor editor/app statekittl.uploadfor image uploadskittl.authfor OAuth helper flows
Add the SDK to your app
You can load the SDK in two ways.
Option 1: Package manager (recommended)
pnpm add @kittl/sdk
import { kittl } from '@kittl/sdk';
Option 2: Script tag
<script src="https://static.kittl.com/sdk/staging/v0/sdk.js"></script>
The URL uses staging and the major version (v0 for 0.x). Use window.kittl in this mode:
const { kittl } = window;
Wait for readiness
Call SDK APIs only after the bridge is ready:
import { kittl } from '@kittl/sdk';
kittl.onReady(async () => {
const result = await kittl.state.getSelectedObjectsIds();
if (result.isOk) {
console.log('Selected object IDs:', result.result);
}
});
Response format
All SDK calls return a SdkResult object: { isOk: true, result: T } on success, or { isOk: false, error: E } on failure. Check isOk and use result before accessing the value:
const addResult = await kittl.design.text.addText({ ... });
if (addResult.isOk) {
const text = addResult.result;
await kittl.state.setSelectedObjectsIds([text.id]);
}
Error types
For APIs that return SdkError (for example, most design APIs), the error property is a discriminated union you can narrow by error.name. Some SDK methods (e.g. font.createFont, ai.spendCredits) instead return a generic Error, so error.name should only be used as a discriminator when the specific API documents SdkError:
| Error Type | name | When |
|---|---|---|
SdkBadInputError | 'SdkBadInputError' | Invalid or missing parameters (validation failure) |
SdkInternalError | 'SdkInternalError' | Unexpected internal error in the SDK or host |
These SdkError variants extend Error and include message and an optional cause:
const result = await kittl.design.image.addImage({ ... });
if (!result.isOk) {
const { error } = result;
if (error.name === 'SdkBadInputError') {
console.error('Invalid input:', error.message);
} else if (error.name === 'SdkInternalError') {
console.error('Internal error:', error.message);
}
// Optionally inspect the underlying cause
if (error.cause) {
console.error('Caused by:', error.cause);
}
}
Async vs Sync results
Most SDK methods return SdkResultAsync<T> (a Promise). Some synchronous design methods return SdkResult<T> directly — both have the same { isOk, result, error } shape.
Minimal example
import { kittl } from '@kittl/sdk';
kittl.onReady(async () => {
const addResult = await kittl.design.text.addText({
text: 'Hello from my app',
position: { absolute: { left: 120, top: 120 } },
size: { width: 320, height: 80 },
});
if (addResult.isOk) {
await kittl.state.setSelectedObjectsIds([addResult.result.id]);
}
});
Image upload example
Use kittl.upload.image.upload to upload a blob, then add it to the canvas with kittl.design.image.addImage:
const uploadResult = await kittl.upload.image.upload({ blob });
if (uploadResult.isOk) {
const { objectName } = uploadResult.result[0];
await kittl.design.image.addImage({
src: objectName,
size: { width: 200, height: 200, applyViewportScale: false },
position: { relative: { to: 'viewport', location: 'center' } },
});
}
Notes
- The SDK is designed for sandboxed app frames.
- Every API call is async in app context.
- Declare required SDK permissions in your manifest
metadata.scopes; see SDK scopes.