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

# Async Tasks

> Understand the asynchronous task model used by all generation requests

## How It Works

All generation requests in ModelHunter.AI are **asynchronous**. When you submit a request, you receive a task ID immediately. The actual generation happens in the background.

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant ModelHunter
    participant Provider

    Client->>ModelHunter: POST /api/v1/{provider}/{capability}
    ModelHunter-->>Client: 202 Accepted (task_id)
    ModelHunter->>Provider: Forward request
    Provider-->>ModelHunter: Generation complete
    Client->>ModelHunter: GET /api/v1/tasks/{id}
    ModelHunter-->>Client: 200 OK (result)
```

## Task Lifecycle

Every task progresses through these states:

| Status      | Description                                        |
| ----------- | -------------------------------------------------- |
| `pending`   | Request received, queued for processing            |
| `queued`    | Sent to the provider, waiting in their queue       |
| `running`   | Provider is actively generating                    |
| `succeeded` | Generation complete, result available              |
| `failed`    | Generation failed, error details available         |
| `cancelled` | Cancelled by the user before completion            |
| `expired`   | Result URL has expired (re-fetch to get a new one) |

## Getting Results

There are two ways to receive results:

### Option 1: Polling (Simple)

Poll `GET /api/v1/tasks/{id}` until the status is `succeeded` or `failed`.

<CodeGroup>
  ```javascript JavaScript theme={null}
  // Submit a generation request
  const response = await fetch('https://api.modelhunter.ai/api/v1/vidu/text-to-video', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.MODELHUNTER_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'viduq3-turbo',
      input: {
        prompt: 'A sunset over the ocean',
        duration: 4,
      },
    }),
  });

  const task = await response.json();

  // Poll until complete
  const result = await fetch(`https://api.modelhunter.ai/api/v1/tasks/${task.data.id}`, {
    headers: { 'Authorization': `Bearer ${process.env.MODELHUNTER_KEY}` },
  }).then(r => r.json());

  console.log(result.data.result[0].url);
  ```

  ```python Python theme={null}
  import requests

  headers = {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json',
  }

  # Submit a generation request
  response = requests.post(
      'https://api.modelhunter.ai/api/v1/vidu/text-to-video',
      headers=headers,
      json={
          'model': 'viduq3-turbo',
          'input': {
              'prompt': 'A sunset over the ocean',
              'duration': 4,
          },
      },
  )

  task = response.json()

  # Poll until complete
  result = requests.get(
      f"https://api.modelhunter.ai/api/v1/tasks/{task['data']['id']}",
      headers=headers,
  ).json()

  print(result['data']['result'][0]['url'])
  ```
</CodeGroup>

**Recommended polling interval**: Start at 2 seconds, increase to 5 seconds after 30 seconds.

### Option 2: Webhooks (Recommended for Production)

Pass a `webhookUrl` in the generation request. ModelHunter.AI will POST the result directly to your server when the task completes.

```json theme={null}
{
  "model": "viduq3-turbo",
  "input": {
    "prompt": "A sunset over the ocean",
    "duration": 4
  },
  "webhookUrl": "https://your-server.com/webhooks/modelhunter"
}
```

See [Webhooks](/core-concepts/webhooks) for full details on payload format and signature verification.

## Result URLs

Result URLs are **signed URLs** valid for **15 minutes**. If a URL expires, fetch the task again to get a fresh URL.

```bash theme={null}
# Re-fetch to get a new signed URL
curl https://api.modelhunter.ai/api/v1/tasks/{id} \
  -H "Authorization: Bearer river_live_xxx"
```
