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

# Task Management

> Task status, polling, and error handling for JavaScript SDK

## apiV1JobJobIdGet()

Get current task status:

```javascript theme={null}
const { Configuration, ImageApi } = require('@legnext-api/js-sdk');

const apiClient = new Configuration();
apiClient.basePath = 'https://api.legnext.ai';
const imageApi = new ImageApi(apiClient);

const apiKey = 'your-api-key-here';
const jobId = 'job-123';

const task = await imageApi.apiV1JobJobIdGet(jobId, apiKey);
console.log('Status:', task.status);
console.log('Progress:', task.progress + '%');

if (task.status === 'completed') {
    console.log('Result:', task.output);
}
```

***

## Polling for Completion

Wait for task completion with polling:

```javascript theme={null}
async function waitForCompletion(
    api,
    jobId,
    apiKey,
    timeoutSeconds = 300,
    pollIntervalSeconds = 3
) {
    const startTime = Date.now();
    const timeout = timeoutSeconds * 1000;

    while (true) {
        const task = await api.apiV1JobJobIdGet(jobId, apiKey);
        console.log('Current status:', task.status);

        if (task.status === 'completed') {
            console.log('Task completed successfully!');
            console.log('Output:', task.output);
            return task;
        } else if (task.status === 'failed') {
            throw new Error(`Task failed: ${task.error}`);
        }

        // Check timeout
        if (Date.now() - startTime > timeout) {
            throw new Error(`Task timeout after ${timeoutSeconds} seconds`);
        }

        // Wait before next poll
        await new Promise(resolve => setTimeout(resolve, pollIntervalSeconds * 1000));
    }
}
```

**Usage:**

```javascript theme={null}
try {
    const result = await waitForCompletion(imageApi, jobId, apiKey, 300, 3);
    console.log('Final result:', result);
} catch (error) {
    console.error('Error:', error.message);
}
```

***

## Complete Example with Error Handling

```javascript theme={null}
const { Configuration, ImageApi } = require('@legnext-api/js-sdk');

async function generateImageWithPolling() {
    const apiClient = new Configuration();
    apiClient.basePath = 'https://api.legnext.ai';
    const imageApi = new ImageApi(apiClient);

    const apiKey = process.env.LEGNEXT_API_KEY;

    try {
        // Step 1: Start generation
        const body = {
            text: 'a beautiful sunset over mountains'
        };

        const response = await imageApi.apiV1DiffusionPost(apiKey, body);
        const jobId = response.jobId;
        console.log('Job started:', jobId);

        // Step 2: Poll for completion
        const result = await waitForCompletion(imageApi, jobId, apiKey, 600, 3);

        // Step 3: Get final result
        console.log('Image URLs:', result.output.imageUrls);

    } catch (error) {
        handleError(error);
    }
}

function handleError(error) {
    if (error.status) {
        const statusCode = error.status;
        const errorBody = error.response?.body;

        switch (statusCode) {
            case 400:
                console.error('Validation error:', errorBody);
                break;
            case 401:
                console.error('Authentication error: Invalid API key');
                break;
            case 404:
                console.error('Resource not found:', errorBody);
                break;
            case 429:
                console.error('Rate limit exceeded. Please retry later.');
                break;
            case 500:
            case 502:
            case 503:
                console.error('Server error:', errorBody);
                break;
            default:
                console.error(`API error (${statusCode}):`, errorBody);
        }
    } else {
        console.error('Unexpected error:', error.message);
    }
}

generateImageWithPolling();
```

***

## Error Handling

**Common HTTP Status Codes:**

| Status Code | Description                | Action                         |
| ----------- | -------------------------- | ------------------------------ |
| 400         | Invalid request parameters | Check request body format      |
| 401         | Invalid API key            | Verify API key is correct      |
| 404         | Resource not found         | Check job ID exists            |
| 429         | Rate limit exceeded        | Wait and retry with backoff    |
| 500/502/503 | Server error               | Retry with exponential backoff |

**Handling Different Error Scenarios:**

```javascript theme={null}
async function callWithRetry(apiCall, maxRetries = 3) {
    for (let i = 0; i < maxRetries; i++) {
        try {
            return await apiCall();
        } catch (error) {
            if (error.status === 429) {
                // Rate limited - wait and retry
                await new Promise(resolve => setTimeout(resolve, 5000));
                continue;
            } else if (error.status >= 500) {
                // Server error - exponential backoff
                const delay = Math.pow(2, i) * 1000;
                await new Promise(resolve => setTimeout(resolve, delay));
                if (i === maxRetries - 1) throw error; // Last retry
                continue;
            } else {
                // Other errors - don't retry
                throw error;
            }
        }
    }
}

// Usage
try {
    const response = await callWithRetry(() =>
        imageApi.apiV1DiffusionPost(apiKey, body)
    );
} catch (error) {
    console.error('Failed after retries:', error);
}
```

***

## Async Operations with Promise.all

For concurrent operations:

```javascript theme={null}
async function generateMultipleImages() {
    const apiClient = new Configuration();
    apiClient.basePath = 'https://api.legnext.ai';
    const imageApi = new ImageApi(apiClient);
    const apiKey = process.env.LEGNEXT_API_KEY;

    const prompts = ['sunset', 'mountains', 'ocean'];

    try {
        // Start all generations concurrently
        const promises = prompts.map(async (prompt) => {
            const body = { text: prompt };
            const response = await imageApi.apiV1DiffusionPost(apiKey, body);

            // Wait for each to complete
            const result = await waitForCompletion(
                imageApi,
                response.jobId,
                apiKey,
                600,
                3
            );

            return result.output.imageUrls[0];
        });

        const imageUrls = await Promise.all(promises);

        imageUrls.forEach((url, index) => {
            console.log(`Image ${index + 1}:`, url);
        });

    } catch (error) {
        console.error('Error:', error);
    }
}

generateMultipleImages();
```

***

## Progress Callbacks

```javascript theme={null}
async function waitForCompletionWithProgress(
    api,
    jobId,
    apiKey,
    onProgress,
    timeoutSeconds = 300,
    pollIntervalSeconds = 3
) {
    const startTime = Date.now();
    const timeout = timeoutSeconds * 1000;

    while (true) {
        const task = await api.apiV1JobJobIdGet(jobId, apiKey);

        // Call progress callback
        if (onProgress) {
            onProgress(task.progress || 0, task.status);
        }

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

        if (Date.now() - startTime > timeout) {
            throw new Error(`Task timeout after ${timeoutSeconds} seconds`);
        }

        await new Promise(resolve => setTimeout(resolve, pollIntervalSeconds * 1000));
    }
}

// Usage
const result = await waitForCompletionWithProgress(
    imageApi,
    jobId,
    apiKey,
    (progress, status) => {
        console.log(`Progress: ${progress}% - Status: ${status}`);
    }
);
```

***

## Learn More

* [Image Generation API](/sdk/javascript/image-generation)
* [Video Generation API](/sdk/javascript/video-generation)
* [Quick Start](/sdk/javascript/quickstart)
