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

# Get Export Status

> Check the status of a video export and get the download URL when complete

## Overview

Check the progress of an export job for a project. When the export is complete, this endpoint returns a download URL for the final video.

## Request

### Path Parameters

<ParamField path="projectId" type="string" required>
  The project ID
</ParamField>

### Headers

<ParamField header="Authorization" type="string" required>
  Bearer token with your API key
</ParamField>

## Response

<ResponseField name="status" type="string">
  Current export status: `queued`, `processing`, `completed`, or `failed`
</ResponseField>

<ResponseField name="download_url" type="string | null">
  URL to download the completed video (only present when `status` is `completed`, otherwise `null`)
</ResponseField>

<ResponseField name="error" type="string">
  Error message if export failed (only present when `status` is `failed`)
</ResponseField>

## Examples

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.babou.ai/api/v1/projects/prj_abc123xyz/export \
    -H "Authorization: Bearer $BABOU_API_KEY"
  ```

  ```typescript TypeScript theme={null}
  async function getExportStatus(projectId: string) {
    const response = await fetch(
      `https://api.babou.ai/api/v1/projects/${projectId}/export`,
      {
        headers: {
          'Authorization': `Bearer ${process.env.BABOU_API_KEY}`
        }
      }
    );

    return await response.json();
  }

  // Check status
  const status = await getExportStatus('prj_abc123xyz');
  console.log(`Export status: ${status.status}`);

  if (status.status === 'completed') {
    console.log(`Download: ${status.download_url}`);
  }
  ```

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

  def get_export_status(project_id):
      response = requests.get(
          f'https://api.babou.ai/api/v1/projects/{project_id}/export',
          headers={'Authorization': f'Bearer {os.environ["BABOU_API_KEY"]}'}
      )
      return response.json()

  # Check status
  status = get_export_status('prj_abc123xyz')
  print(f'Export status: {status["status"]}')

  if status['status'] == 'completed':
      print(f'Download: {status["download_url"]}')
  ```
</CodeGroup>

## Response Examples

### Export in Progress

```json theme={null}
{
  "status": "processing",
  "download_url": null
}
```

### Export Completed

```json theme={null}
{
  "status": "completed",
  "download_url": "https://assets.babou.ai/exports/prj_abc123xyz.mp4"
}
```

### Export Failed

```json theme={null}
{
  "status": "failed",
  "error": "Failed to render chapter 2"
}
```

## Polling for Completion

To wait for an export to complete, poll this endpoint periodically:

<CodeGroup>
  ```typescript TypeScript theme={null}
  async function waitForExport(
    projectId: string,
    pollInterval = 5000,
    timeout = 600000
  ) {
    const startTime = Date.now();

    while (Date.now() - startTime < timeout) {
      const status = await getExportStatus(projectId);

      if (status.status === 'completed') {
        return status;
      }

      if (status.status === 'failed') {
        throw new Error(`Export failed: ${status.error}`);
      }

      console.log(`Export ${status.status}... (${Math.round((Date.now() - startTime) / 1000)}s elapsed)`);
      await new Promise(resolve => setTimeout(resolve, pollInterval));
    }

    throw new Error('Export timeout after 10 minutes');
  }

  // Use it
  const result = await waitForExport('prj_abc123xyz');
  console.log('✓ Video ready!');
  console.log(`Download: ${result.download_url}`);
  console.log(`Took ${result.duration_seconds} seconds`);
  ```

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

  def wait_for_export(project_id, poll_interval=5, timeout=600):
      """Wait for export to complete with timeout"""
      start_time = time.time()

      while time.time() - start_time < timeout:
          status = get_export_status(project_id)

          if status['status'] == 'completed':
              return status

          if status['status'] == 'failed':
              raise Exception(f'Export failed: {status.get("error", "Unknown error")}')

          elapsed = int(time.time() - start_time)
          print(f'Export {status["status"]}... ({elapsed}s elapsed)')
          time.sleep(poll_interval)

      raise Exception('Export timeout after 10 minutes')

  # Use it
  result = wait_for_export('prj_abc123xyz')
  print('✓ Video ready!')
  print(f'Download: {result["download_url"]}')
  print(f'Took {result["duration_seconds"]} seconds')
  ```
</CodeGroup>

## Downloading the Video

Once the export is complete, download the video file:

<CodeGroup>
  ```bash curl theme={null}
  # Get the download URL
  DOWNLOAD_URL=$(curl -s https://api.babou.ai/api/v1/projects/prj_abc123xyz/export \
    -H "Authorization: Bearer $BABOU_API_KEY" | jq -r '.download_url')

  # Download the video
  curl -o video.mp4 "$DOWNLOAD_URL"
  ```

  ```typescript TypeScript theme={null}
  import fs from 'fs';

  async function downloadVideo(projectId: string, outputPath: string) {
    // Wait for export to complete
    const status = await waitForExport(projectId);

    // Download the video
    const response = await fetch(status.download_url);
    const buffer = await response.arrayBuffer();

    // Save to file
    fs.writeFileSync(outputPath, Buffer.from(buffer));
    console.log(`✓ Video saved to ${outputPath}`);
  }

  await downloadVideo('prj_abc123xyz', './my-video.mp4');
  ```

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

  def download_video(project_id, output_path):
      # Wait for export to complete
      status = wait_for_export(project_id)

      # Download the video
      response = requests.get(status['download_url'])

      # Save to file
      with open(output_path, 'wb') as f:
          f.write(response.content)

      print(f'✓ Video saved to {output_path}')

  download_video('prj_abc123xyz', './my-video.mp4')
  ```
</CodeGroup>

## Error Responses

<ResponseField name="NOT_FOUND" type="404">
  No export found for this project

  ```json theme={null}
  {
    "error": "No export found for this project",
    "code": "NOT_FOUND",
    "hint": "Start an export first using POST /api/v1/projects/{projectId}/export"
  }
  ```
</ResponseField>

## Best Practices

<AccordionGroup>
  <Accordion title="Implement exponential backoff">
    Use increasing intervals when polling to reduce API load:

    ```typescript theme={null}
    async function waitForExportWithBackoff(projectId: string) {
      let interval = 2000; // Start at 2 seconds
      const maxInterval = 30000; // Cap at 30 seconds
      const startTime = Date.now();

      while (true) {
        const status = await getExportStatus(projectId);

        if (status.status === 'completed') return status;
        if (status.status === 'failed') throw new Error('Export failed');

        await new Promise(r => setTimeout(r, interval));

        // Increase interval (exponential backoff)
        interval = Math.min(interval * 1.5, maxInterval);
      }
    }
    ```
  </Accordion>

  <Accordion title="Handle download URL expiration">
    Download URLs may expire after a certain time. Download the video promptly:

    ```python theme={null}
    def download_with_retry(url, output_path, max_retries=3):
        for attempt in range(max_retries):
            try:
                response = requests.get(url, timeout=60)
                response.raise_for_status()

                with open(output_path, 'wb') as f:
                    f.write(response.content)

                return True
            except Exception as e:
                if attempt == max_retries - 1:
                    raise
                print(f'Download failed, retrying... ({attempt + 1}/{max_retries})')
                time.sleep(2 ** attempt)
    ```
  </Accordion>

  <Accordion title="Show progress to users">
    Keep users informed during the export wait:

    ```typescript theme={null}
    async function exportWithProgress(projectId: string) {
      console.log('Starting export...');
      await startExport(projectId);

      let lastStatus = '';
      const result = await waitForExport(projectId, 5000, 600000);

      console.log('✓ Export completed!');
      console.log(`  Duration: ${result.duration_seconds}s`);
      console.log(`  Download: ${result.download_url}`);

      return result;
    }
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Start Export" icon="file-export" href="/api-reference/exports/start">
    Start a new export
  </Card>

  <Card title="Create New Project" icon="plus" href="/api-reference/projects/create">
    Create another video project
  </Card>
</CardGroup>
