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

# Upload Image

> Upload an image to get a URL for use with image/video generation APIs

<Note>
  **The doc Playground does not support file uploads**: Please use the cURL, Python, or JavaScript code examples below to test.
</Note>

<Warning>
  **Important Change:** For better performance and cost control, we no longer support passing base64 image data directly in generation APIs. Please use this API to upload images, get the URL, and then call the generation API.
</Warning>

## Why upload images first?

1. **Performance Optimization** - base64 encoding inflates data by 33%, uploading first significantly reduces request body size
2. **Reuse Images** - Upload once, reuse the URL multiple times without redundant transfers

## Workflow

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

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

<RequestExample>
  ```bash cURL theme={null}
  curl --request POST \
    --url https://api.apimart.ai/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://api.apimart.ai/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://api.apimart.ai/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://api.apimart.ai/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://api.apimart.ai/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.apimart.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>

## Authorizations

<ParamField header="Authorization" type="string" required>
  All APIs require Bearer Token authentication

  Get API Key:

  Visit [API Key Management Page](https://apimart.ai/keys) to get your API Key

  Add to request headers:

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

## Body

<ParamField body="file" type="file" required>
  Image file

  Supported formats: JPEG (.jpg, .jpeg), PNG (.png), WebP (.webp), GIF (.gif)

  Maximum file size: 20MB
</ParamField>

## Response

<ResponseField name="url" type="string">
  Public access URL for the image, can be used directly in generation APIs (valid for 72 hours)
</ResponseField>

<ResponseField name="filename" type="string">
  Original file name
</ResponseField>

<ResponseField name="content_type" type="string">
  Detected MIME type, e.g. `image/jpeg`
</ResponseField>

<ResponseField name="bytes" type="integer">
  File size in bytes
</ResponseField>

<ResponseField name="created_at" type="integer">
  Upload time as Unix timestamp (seconds)
</ResponseField>

## Full Example: Image-to-Image Workflow

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

API_KEY = "your-Apimart-key"
BASE_URL = "https://api.apimart.ai"

# 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}")
```
