> For the complete documentation index, see [llms.txt](https://docs.apismart.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apismart.ai/code-examples-and-migration/python.md).

# Python

Learn how to call ApiSmart APIs with Python, including model discovery, Chat Completions, streaming, image generation, local image uploads, and asynchronous video tasks.

Use Python to integrate ApiSmart into backend services, scripts, automation workflows, and AI-powered applications.

This guide uses the popular `requests` library to demonstrate how to authenticate requests, retrieve available models, generate text and images, and create asynchronous video tasks.

### 🚀 Before You Start

Make sure you have:

* Python 3 installed
* An ApiSmart account
* An active API Key
* Sufficient wallet balance for paid requests

Install `requests`:

```bash
pip install requests
```

### 🔑 Set Your API Key

Avoid hard-coding your API Key directly in application source code.

Set it as an environment variable instead.

#### macOS and Linux

```bash
export APISMART_API_KEY="your-api-key"
```

#### Windows PowerShell

```powershell
$env:APISMART_API_KEY="your-api-key"
```

Then read it in Python:

```python
import os

API_KEY = os.environ["APISMART_API_KEY"]
```

The standard ApiSmart API Base URL is:

```python
BASE_URL = "https://gw.apismart.ai/v1"
```

Create reusable request headers:

```python
HEADERS = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}
```

Keep your API Key private and never commit it to a public repository.

### 🧩 Get Available Models

Before sending a generation request, you can retrieve the current model IDs:

```python
import os
import requests

API_KEY = os.environ["APISMART_API_KEY"]
BASE_URL = "https://gw.apismart.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
}

response = requests.get(
    f"{BASE_URL}/models",
    headers=headers,
)

response.raise_for_status()

data = response.json()

for model in data.get("data", []):
    print(model["id"])
```

The API returns model entries in `data[]`.

Use:

```
data[].id
```

as the `model` value in supported API requests.

Model IDs must match exactly. Do not change periods (`.`), hyphens (`-`), or version numbers.

For model categories and IDs, see [**Models and Model IDs**](/models-and-pricing/models-and-model-ids.md).

### 💬 Chat Completions

Use:

`POST /v1/chat/completions`

Example:

```python
import os
import requests

API_KEY = os.environ["APISMART_API_KEY"]
BASE_URL = "https://gw.apismart.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

payload = {
    "model": "deepseek-v4-flash",
    "messages": [
        {
            "role": "user",
            "content": "Hello! Please introduce yourself.",
        }
    ],
}

response = requests.post(
    f"{BASE_URL}/chat/completions",
    headers=headers,
    json=payload,
)

response.raise_for_status()

print(response.json())
```

The `model` value must be a valid ApiSmart model ID.

For complete request behavior, see [**Chat Completions API**](/api-guides/chat-completions-api.md).

### 🌊 Stream a Text Response

Chat Completions supports streaming by setting:

```json
{
  "stream": true
}
```

With Python `requests`, enable streamed response handling with `stream=True`:

```python
import os
import requests

API_KEY = os.environ["APISMART_API_KEY"]
BASE_URL = "https://gw.apismart.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

payload = {
    "model": "deepseek-v4-flash",
    "messages": [
        {
            "role": "user",
            "content": "Write a short story.",
        }
    ],
    "stream": True,
}

with requests.post(
    f"{BASE_URL}/chat/completions",
    headers=headers,
    json=payload,
    stream=True,
) as response:
    response.raise_for_status()

    for line in response.iter_lines(decode_unicode=True):
        if line:
            print(line)
```

This example prints streamed data as it arrives.

The exact processing logic you use depends on how your application wants to consume and display the streamed response.

For an overview of ApiSmart response behavior, see [**Response Modes**](/api-guides/response-modes.md).

### 🖼️ Generate an Image

Use:

`POST /v1/images/generations`

Example:

```python
import os
import requests

API_KEY = os.environ["APISMART_API_KEY"]
BASE_URL = "https://gw.apismart.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

payload = {
    "model": "doubao-seedream-5-0",
    "prompt": "A mountain village at sunrise, watercolor style",
    "size": "2K",
    "watermark": False,
}

response = requests.post(
    f"{BASE_URL}/images/generations",
    headers=headers,
    json=payload,
    timeout=120,
)

response.raise_for_status()

result = response.json()

print(result)
```

Image generation is synchronous by default.

A single generation commonly takes approximately 20–40 seconds, and high-resolution or multi-image requests may take longer.

Use a client timeout of at least **90 seconds**. The example above uses:

```python
timeout=120
```

to provide additional time for generation.

### 🔄 Generate from a Reference Image

Provide a public image URL using `image`:

```python
payload = {
    "model": "doubao-seedream-5-0",
    "prompt": "Transform this image into a watercolor painting",
    "image": "https://example.com/input.jpg",
    "size": "2048x2048",
}

response = requests.post(
    f"{BASE_URL}/images/generations",
    headers=headers,
    json=payload,
    timeout=120,
)

response.raise_for_status()

print(response.json())
```

Multiple reference images can also be provided as an array where supported.

For image limits and parameters, see [**Image Generation API**](/api-guides/image-generation-api.md).

### 📤 Upload a Local Image

Local image uploads use:

`POST /v1/images/edits`

This endpoint uses multipart form data instead of a JSON request body.

```python
import os
import requests

API_KEY = os.environ["APISMART_API_KEY"]
BASE_URL = "https://gw.apismart.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
}

data = {
    "model": "doubao-seedream-5-0",
    "prompt": "Place the character in a cyberpunk environment",
    "size": "2K",
    "response_format": "url",
}

with open("character.png", "rb") as image_file:
    files = {
        "image": ("character.png", image_file),
    }

    response = requests.post(
        f"{BASE_URL}/images/edits",
        headers=headers,
        data=data,
        files=files,
        timeout=120,
    )

response.raise_for_status()

print(response.json())
```

Do not manually set:

```
Content-Type: application/json
```

for multipart file uploads.

The `requests` library automatically creates the appropriate multipart content type when you use `files=`.

Each uploaded image must meet the limits documented in [**Image Generation API**](/api-guides/image-generation-api.md).

### 🎬 Create a Video Task

Video generation is asynchronous.

Create a task with:

`POST /v1/video/tasks`

Example:

```python
import os
import requests

API_KEY = os.environ["APISMART_API_KEY"]
BASE_URL = "https://gw.apismart.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

payload = {
    "model": "happyhorse-1.0",
    "prompt": "A miniature city at night with a train moving through the streets",
    "duration": 5,
    "size": "720p",
}

response = requests.post(
    f"{BASE_URL}/video/tasks",
    headers=headers,
    json=payload,
)

response.raise_for_status()

task = response.json()

print(task)
```

Save the task ID returned by the API so that you can query the generation status.

For models where resolution and duration affect billing, explicitly provide these values instead of relying on defaults.

### 🔄 Query a Video Task

Use:

`GET /v1/video/tasks/{id}`

Example:

```python
task_id = "task_xxxxxx"

response = requests.get(
    f"{BASE_URL}/video/tasks/{task_id}",
    headers={
        "Authorization": f"Bearer {API_KEY}",
    },
)

response.raise_for_status()

print(response.json())
```

Possible task statuses include:

* `queued`
* `running`
* `succeeded`
* `failed`
* `cancelled`
* `expired`

### ⏳ Poll Until Video Generation Completes

You can poll the task until it reaches a final state:

```python
import os
import time
import requests

API_KEY = os.environ["APISMART_API_KEY"]
BASE_URL = "https://gw.apismart.ai/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
}

task_id = "task_xxxxxx"

while True:
    response = requests.get(
        f"{BASE_URL}/video/tasks/{task_id}",
        headers=headers,
    )

    response.raise_for_status()

    task = response.json()
    status = task.get("status")

    print("Status:", status)

    if status == "succeeded":
        print("Result:", task)
        break

    if status in {"failed", "cancelled", "expired"}:
        print("Task ended:", task)
        break

    time.sleep(5)
```

This example waits 5 seconds between status checks.

For complete HappyHorse and Seedance workflows, see [**Video Generation API**](/api-guides/video-generation-api.md).

### 🕘 Retrieve Recent Generated Images

Use:

`GET /v1/images`

```python
response = requests.get(
    f"{BASE_URL}/images",
    headers={
        "Authorization": f"Bearer {API_KEY}",
    },
    params={
        "page": 1,
        "page_size": 20,
    },
)

response.raise_for_status()

print(response.json())
```

### 🕘 Retrieve Recent Generated Videos

Use:

`GET /v1/videos`

```python
response = requests.get(
    f"{BASE_URL}/videos",
    headers={
        "Authorization": f"Bearer {API_KEY}",
    },
    params={
        "page": 1,
        "page_size": 20,
    },
)

response.raise_for_status()

print(response.json())
```

For history fields and availability limits, see [**Generated Media History**](/api-usage/generated-media-history.md).

### ⚠️ Handle API Errors

Use `raise_for_status()` to detect unsuccessful HTTP responses:

```python
response = requests.get(
    f"{BASE_URL}/models",
    headers={
        "Authorization": f"Bearer {API_KEY}",
    },
)

try:
    response.raise_for_status()
except requests.HTTPError:
    print("HTTP status:", response.status_code)
    print("Response:", response.text)
    raise
```

Common API responses include:

| Status        | Example Code            | Meaning                                               |
| ------------- | ----------------------- | ----------------------------------------------------- |
| `400`         | `invalid_request_error` | Invalid request                                       |
| `401`         | `invalid_api_key`       | Invalid API Key                                       |
| `402`         | `insufficient_quota`    | Insufficient balance                                  |
| `403`         | `model_not_allowed`     | Model is not available to the API Key                 |
| `429`         | `rate_limit_error`      | Request rate limit exceeded                           |
| `502` / `504` | Gateway errors          | Temporary upstream or network problem                 |
| `503`         | Service unavailable     | Provider or dependent service temporarily unavailable |

For complete error handling guidance, see [**HTTP Status Codes and API Errors**](/troubleshooting/http-status-codes-and-api-errors.md).

### 🔁 Retry Temporary Failures

Some `5xx` errors may be temporary.

When retrying temporary failures:

* Add a delay between attempts
* Use exponential backoff for repeated retries
* Follow `Retry-After` when the API provides it
* Do not automatically retry invalid parameters or authentication errors without fixing the request

A simple retry structure can look like:

```python
import time
import requests

for attempt in range(3):
    response = requests.get(
        f"{BASE_URL}/models",
        headers={
            "Authorization": f"Bearer {API_KEY}",
        },
    )

    if response.status_code < 500:
        break

    time.sleep(2 ** attempt)

response.raise_for_status()
```

Adapt retry behavior to the endpoint and your application's requirements.

### ✅ Python Integration Checklist

Before deploying your integration, verify that:

* Your API Key is stored securely
* The Base URL is correct
* Model IDs are copied exactly
* JSON requests use the correct headers
* Multipart uploads do not force `application/json`
* Image requests use an appropriate timeout
* Video requests store and poll the returned task ID
* Temporary errors use an appropriate retry strategy
* Your account has sufficient wallet balance

### ➡️ Next Steps

Continue with:

* [**API Basics**](/api-guides/api-basics.md) — Learn common API conventions
* [**Models and Model IDs**](/models-and-pricing/models-and-model-ids.md) — Find valid model IDs
* [**Chat Completions API**](/api-guides/chat-completions-api.md) — Review text generation behavior
* [**Image Generation API**](/api-guides/image-generation-api.md) — Explore image generation and editing
* [**Video Generation API**](/api-guides/video-generation-api.md) — Build asynchronous video workflows
* [**Response Modes**](/api-guides/response-modes.md) — Understand standard, streaming, and asynchronous responses
* [**Generated Media History**](/api-usage/generated-media-history.md) — Retrieve recent generated media
