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

# Téléverser une image

> Téléversez une image pour obtenir une URL utilisable avec les API de génération d'images/vidéos

<Note>
  **Le Playground de la documentation ne prend pas en charge le téléversement de fichiers** : utilisez les exemples de code cURL, Python ou JavaScript ci-dessous pour effectuer vos tests.
</Note>

<Warning>
  **Changement important :** Pour améliorer les performances et maîtriser les coûts, nous ne prenons plus en charge la transmission de données d'image en base64 directement dans les API de génération. Veuillez utiliser cette API pour téléverser des images, récupérer leur URL, puis appeler l'API de génération.
</Warning>

## Pourquoi téléverser les images d'abord ?

1. **Optimisation des performances** — l'encodage base64 augmente la taille des données de 33 % ; téléverser d'abord réduit considérablement la taille du corps de la requête
2. **Réutilisation des images** — téléversez une fois, réutilisez l'URL plusieurs fois sans transfert redondant

## Workflow

```mermaid theme={null}
sequenceDiagram
    participant Client
    participant GccAi
    participant Storage

    Client->>GccAi: POST /v1/uploads/images (Upload image file)
    GccAi->>Storage: Save image
    Storage-->>GccAi: Return storage path
    GccAi-->>Client: Return image URL
    Client->>GccAi: POST /v1/images/generations (Use image URL)
```

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://gccai.heqingsong.uk/v1/uploads/images \
    --header 'Authorization: Bearer <token>' \
    --form 'file=@/path/to/your/image.jpg'
  ```

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

  # Upload image
  with open('image.jpg', 'rb') as f:
      response = requests.post(
          "https://gccai.heqingsong.uk/v1/uploads/images",
          headers={
              "Authorization": "Bearer <token>"
          },
          files={
              "file": f
          }
      )

  result = response.json()
  image_url = result['url']
  print(f"Image URL: {image_url}")

  # Use the uploaded image for generation
  response = requests.post(
      "https://gccai.heqingsong.uk/v1/images/generations",
      headers={
          "Authorization": "Bearer <token>",
          "Content-Type": "application/json"
      },
      json={
          "model": "gemini-3-pro-image-preview",
          "prompt": "Create a variation based on this image",
          "image_urls": [{"url": image_url}]
      }
  )
  ```

  ```javascript JavaScript theme={null}
  // Upload image
  const formData = new FormData();
  formData.append('file', fileInput.files[0]);

  const uploadResponse = await fetch('https://gccai.heqingsong.uk/v1/uploads/images', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer <token>'
    },
    body: formData
  });

  const uploadResult = await uploadResponse.json();
  const imageUrl = uploadResult.url;
  console.log(`Image URL: ${imageUrl}`);

  // Use the uploaded image for generation
  const genResponse = await fetch('https://gccai.heqingsong.uk/v1/images/generations', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer <token>',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      model: 'gemini-3-pro-image-preview',
      prompt: 'Create a variation based on this image',
      image_urls: [{url: imageUrl}]
    })
  });
  ```
</RequestExample>

<ResponseExample>
  ```json 200 theme={null}
  {
    "url": "https://upload.gccai.ai/f/image/9990000123456-a1b2c3d4-photo.jpg",
    "filename": "photo.jpg",
    "content_type": "image/jpeg",
    "bytes": 235680,
    "created_at": 1743436800
  }
  ```

  ```json 400 - Missing File Field theme={null}
  {
    "error": {
      "message": "missing or invalid file field: http: no such file",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 400 - Unsupported Format theme={null}
  {
    "error": {
      "message": "unsupported image type: application/pdf, allowed: jpeg, png, gif, webp",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 413 - File Too Large theme={null}
  {
    "error": {
      "message": "file size 25165824 exceeds maximum 20971520 bytes",
      "type": "invalid_request_error"
    }
  }
  ```

  ```json 429 - Rate Limit Exceeded theme={null}
  {
    "error": {
      "code": 429,
      "message": "Rate limit exceeded. Please try again later",
      "type": "rate_limit_error"
    }
  }
  ```

  ```json 500 - Upload Failed theme={null}
  {
    "error": {
      "message": "failed to upload image",
      "type": "server_error"
    }
  }
  ```
</ResponseExample>

## Autorisations

<ParamField header="Authorization" type="string" required>
  Toutes les API requièrent une authentification par Bearer Token

  Obtenir la clé API :

  Rendez-vous sur la [page de gestion des clés API](https://gccai.heqingsong.uk/keys) pour obtenir votre clé API

  Ajoutez-la aux en-têtes de la requête :

  ```
  Authorization: Bearer YOUR_API_KEY
  ```
</ParamField>

## Corps

<ParamField body="file" type="file" required>
  Fichier image

  Formats pris en charge : JPEG (.jpg, .jpeg), PNG (.png), WebP (.webp), GIF (.gif)

  Taille maximale du fichier : 20 Mo
</ParamField>

## Réponse

<ResponseField name="url" type="string">
  URL d'accès publique de l'image, utilisable directement dans les API de génération (valide 72 heures)
</ResponseField>

<ResponseField name="filename" type="string">
  Nom de fichier d'origine
</ResponseField>

<ResponseField name="content_type" type="string">
  Type MIME détecté, par exemple `image/jpeg`
</ResponseField>

<ResponseField name="bytes" type="integer">
  Taille du fichier en octets
</ResponseField>

<ResponseField name="created_at" type="integer">
  Date du téléversement sous forme d'horodatage Unix (en secondes)
</ResponseField>

## Exemple complet : workflow image-to-image

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

API_KEY = "your-GccAi-key"
BASE_URL = "https://gccai.heqingsong.uk"

# Step 1: Upload reference image
def upload_image(file_path):
    with open(file_path, 'rb') as f:
        response = requests.post(
            f"{BASE_URL}/v1/uploads/images",
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": f}
        )
    return response.json()['url']

# Step 2: Create generation task
def create_generation(image_url, prompt):
    response = requests.post(
        f"{BASE_URL}/v1/images/generations",
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json"
        },
        json={
            "model": "gemini-3-pro-image-preview",
            "prompt": prompt,
            "image_urls": [{"url": image_url}],
            "size": "16:9"
        }
    )
    return response.json()['id']

# Step 3: Poll task status
def wait_for_result(task_id):
    while True:
        response = requests.get(
            f"{BASE_URL}/v1/images/generations/{task_id}",
            headers={"Authorization": f"Bearer {API_KEY}"}
        )
        result = response.json()

        if result['status'] == 'completed':
            return result['url']
        elif result['status'] == 'failed':
            raise Exception(f"Generation failed: {result.get('fail_reason')}")

        time.sleep(2)

# Execute workflow
image_url = upload_image("reference.jpg")
print(f"Image uploaded: {image_url}")

task_id = create_generation(image_url, "Transform this photo into Ghibli anime style")
print(f"Task created: {task_id}")

result_url = wait_for_result(task_id)
print(f"Generation complete: {result_url}")
```
