> ## Documentation Index
> Fetch the complete documentation index at: https://giselle.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Giselle SDK

> Learn how to use the Giselle SDK to integrate your apps with external applications and services.

> [!WARNING]
>
> This feature is currently in **Private Preview**. Access is limited to selected users. Features and APIs may change without notice.

## Overview

The Giselle SDK (`@giselles-ai/sdk`) provides a simple, type-safe way to interact with the Giselle API from your Node.js applications. It handles authentication, request formatting, and polling for task completion automatically.

> [!WARNING]
>
> The SDK is designed for server-side use only. Never use it in client-side code (browsers) as this would expose your API key.

## Installation

The Giselle SDK is published on npm at [@giselles-ai/sdk](https://www.npmjs.com/package/@giselles-ai/sdk).

Install the SDK using your preferred package manager:

```bash theme={null}
npm install @giselles-ai/sdk
```

```bash theme={null}
yarn add @giselles-ai/sdk
```

```bash theme={null}
pnpm add @giselles-ai/sdk
```

## Quick Start

```typescript theme={null}
import Giselle from "@giselles-ai/sdk";

// Initialize the client
const client = new Giselle({
  apiKey: process.env.GISELLE_API_KEY,
});

// Run an app and wait for results
const { task } = await client.apps.runAndWait({
  appId: "app_xxxxx",
  input: { text: "Hello, Giselle!" },
});

console.log(task.status); // "completed"
console.log(task.outputs); // Array of output results
```

## Configuration

### Constructor Options

```typescript theme={null}
const client = new Giselle({
  apiKey: string;       // Required: Your API key
  baseUrl?: string;     // Optional: API base URL (default: "https://studio.giselles.ai")
  fetch?: typeof fetch; // Optional: Custom fetch implementation
});
```

| Option | Required | Default | Description |
| - | - | - | - |
| `apiKey` | Yes | - | Your Giselle API key. Get one from [API Keys settings](https://giselle.mintlify.site/en/guides/api/api-keys.md). |
| `baseUrl` | No | `https://studio.giselles.ai` | The base URL for API requests. |
| `fetch` | No | Global `fetch` | Custom fetch implementation for specific runtime environments. |

### Environment Variables

We recommend storing your API key in an environment variable:

```bash theme={null}
# .env
GISELLE_API_KEY=gsk_your_api_key_here
```

```typescript theme={null}
const client = new Giselle({
  apiKey: process.env.GISELLE_API_KEY,
});
```

> [!WARNING]
>
> Never commit API keys to version control. Use environment variables or a secrets manager.

## API Reference

### `client.apps.run()`

Starts an app execution and returns immediately with a task ID. Use this when you want to handle polling yourself or don't need to wait for results.

```typescript theme={null}
const { taskId } = await client.apps.run({
  appId: "app_xxxxx",
  input: { text: "Your input text" },
});

console.log(taskId); // "tsk_xxxxx"
```

**Parameters:**

| Parameter | Type | Required | Description |
| - | - | - | - |
| `appId` | `string` | Yes | The ID of the app to run (format: `app_xxxxx`) |
| `input.text` | `string` | Yes | The text input for the app |

**Returns:**

```typescript theme={null}
{
  taskId: string; // The ID of the created task
}
```

### `client.apps.runAndWait()`

Starts an app execution and polls until the task completes. This is the recommended method for most use cases.

```typescript theme={null}
const { task } = await client.apps.runAndWait({
  appId: "app_xxxxx",
  input: { text: "Your input text" },
  pollIntervalMs: 1000,  // Optional: polling interval (default: 1000ms)
  timeoutMs: 60000,      // Optional: timeout (default: 1200000ms / 20 minutes)
});
```

**Parameters:**

| Parameter | Type | Required | Default | Description |
| - | - | - | - | - |
| `appId` | `string` | Yes | - | The ID of the app to run |
| `input.text` | `string` | Yes | - | The text input for the app |
| `pollIntervalMs` | `number` | No | `1000` | How often to check for completion (ms) |
| `timeoutMs` | `number` | No | `1200000` | Maximum time to wait (ms) |
| `schema` | `StandardSchemaV1` | No | - | Validation schema for the output. [Standard Schema v1](https://standardschema.dev/) compatible (Zod, Valibot, etc.). Only applied when the End Node has JSON (Structured Output) configured. |

**Returns:**

The `task` type in the return value differs depending on the End Node's Output Format setting.

**Raw (passthrough):**

```typescript theme={null}
{
  task: {
    id: string;
    workspaceId: string;
    name: string;
    status: "completed" | "failed" | "cancelled";
    outputType: "passthrough";
    steps: Array<{
      title: string;
      status: string;
      items: Array<{
        id: string;
        title: string;
        status: string;
        generationId: string;
        outputs?: unknown[];
        error?: string;
      }>;
    }>;
    outputs: Array<{
      title: string;
      generationId: string;
      outputs: unknown[];
    }>;
  };
}
```

**JSON (object):**

```typescript theme={null}
{
  task: {
    id: string;
    workspaceId: string;
    name: string;
    status: "completed" | "failed" | "cancelled";
    outputType: "object";
    output: T; // Typed by schema if provided, otherwise Record<string, unknown>
    steps: Array<{
      title: string;
      status: string;
      items: Array<{
        id: string;
        title: string;
        status: string;
        generationId: string;
        outputs?: unknown[];
        error?: string;
      }>;
    }>;
  };
}
```

## Finding Your App ID and Code Snippet

The easiest way to get your App ID and a ready-to-use code snippet is from the Workspace:

1. Open your app in the Workspace
2. Click the **Run** button in the top-right corner
3. In the dialog that appears, select the **Code** tab
4. You'll see a complete code snippet with your `appId` already filled in. Simply copy this code and use it in your application.
5. If the End Node has JSON (Structured Output) enabled, the Code tab also displays a code snippet with schema definitions and a preview of the Response JSON structure

> [!NOTE]
>
> The App ID format is `app_` followed by a unique identifier (e.g., `app_abc123xyz`).

## Error Handling

The SDK throws specific error types for different failure scenarios:

```typescript theme={null}
import Giselle, {
  ConfigurationError,
  ApiError,
  TimeoutError,
  UnsupportedFeatureError,
  SchemaValidationError,
} from "@giselles-ai/sdk";

try {
  const { task } = await client.apps.runAndWait({
    appId: "app_xxxxx",
    input: { text: "Hello" },
  });
} catch (error) {
  if (error instanceof ConfigurationError) {
    // Missing or invalid configuration (e.g., no API key)
    console.error("Configuration error:", error.message);
  } else if (error instanceof ApiError) {
    // API request failed
    console.error("API error:", error.status, error.responseText);
  } else if (error instanceof TimeoutError) {
    // Task didn't complete within the timeout
    console.error("Task timed out:", error.message);
  } else if (error instanceof UnsupportedFeatureError) {
    // Attempted to use an unsupported feature
    console.error("Unsupported feature:", error.message);
  } else if (error instanceof SchemaValidationError) {
    // Schema validation failed
    console.error("Schema validation error:", error.message);
  }
}
```

### Error Types

| Error Type | Description |
| - | - |
| `ConfigurationError` | Missing or invalid configuration (e.g., API key not provided) |
| `ApiError` | HTTP request to the API failed. Includes `status` and `responseText` properties. |
| `TimeoutError` | Task didn't complete within the specified timeout |
| `UnsupportedFeatureError` | Attempted to use a feature not yet supported (e.g., file inputs) |
| `SchemaValidationError` | Schema validation failed for the output |

## Examples

### Basic Usage

```typescript theme={null}
import Giselle from "@giselles-ai/sdk";

const client = new Giselle({
  apiKey: process.env.GISELLE_API_KEY,
});

async function runMyApp(userInput: string) {
  const { task } = await client.apps.runAndWait({
    appId: "app_xxxxx",
    input: { text: userInput },
  });

  if (task.status === "completed") {
    return task.outputs;
  } else {
    throw new Error(`Task failed: ${task.status}`);
  }
}
```

### Receiving Structured Output

When the End Node has JSON (Structured Output) enabled, `task.outputType === "object"` and `task.output` contains the structured result.\
Pass a [Standard Schema v1](https://standardschema.dev/) compatible schema to the `schema` parameter to automatically validate the output and get type inference.

Supported libraries: Zod (3.24+), Valibot (1.0+), ArkType (2.0+), Yup (1.7+), Effect Schema (3.13+)

```typescript theme={null}
import { z } from "zod";

const BlogCardSchema = z.object({
  title: z.string(),
  summary: z.string(),
  tags: z.array(z.string()),
});

async function runMyAppWithStructuredOutput(userInput: string) {
  const { task } = await client.apps.runAndWait({
    appId: "app_xxxxx",
    input: { text: userInput },
    schema: BlogCardSchema,
  });

  if (task.status === "completed" && task.outputType === "object") {
    // task.output is typed based on BlogCardSchema
    return task.output;
  }

  throw new Error(`Task failed: ${task.status}`);
}
```

### With Custom Timeout

```typescript theme={null}
const { task } = await client.apps.runAndWait({
  appId: "app_xxxxx",
  input: { text: "Complex query that may take time" },
  timeoutMs: 300000, // 5 minutes
  pollIntervalMs: 2000, // Check every 2 seconds
});
```

### Fire and Forget

```typescript theme={null}
// Start the task but don't wait for completion
const { taskId } = await client.apps.run({
  appId: "app_xxxxx",
  input: { text: "Background processing" },
});

console.log(`Task started: ${taskId}`);
// You can check the task status later via the API or in the Giselle
```

### Express.js Integration

```typescript theme={null}
import express from "express";
import Giselle from "@giselles-ai/sdk";

const app = express();
const client = new Giselle({
  apiKey: process.env.GISELLE_API_KEY,
});

app.use(express.json());

app.post("/api/process", async (req, res) => {
  try {
    const { task } = await client.apps.runAndWait({
      appId: "app_xxxxx",
      input: { text: req.body.text },
      timeoutMs: 60000,
    });

    res.json({
      success: true,
      outputs: task.outputs,
    });
  } catch (error) {
    res.status(500).json({
      success: false,
      error: error.message,
    });
  }
});

app.listen(3000);
```

## Current Limitations

* **Text input only**: Currently, only text input is supported. File inputs will be supported in a future release.
* **Server-side only**: The SDK should only be used in server-side environments to protect your API key.

## Next Steps

* [Create an API key](https://giselle.mintlify.site/en/guides/api/api-keys.md) to get started
* Test your apps in the [Playground](https://giselle.mintlify.site/en/guides/playground.md) before integrating
* Check out [Cookbooks](https://giselle.mintlify.site/en/cookbooks/overview.md) for example apps and workflows


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.