Metadata-Version: 2.4
Name: skytells
Version: 1.0.0
Summary: Official Skytells Python SDK — run AI models with a single function call
Author: Skytells
License: MIT License
        
        Copyright (c) 2026 Skytells
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://skytells.ai
Project-URL: Repository, https://github.com/skytells/python-sdk
Project-URL: Documentation, https://docs.skytells.ai
Project-URL: Bug Tracker, https://github.com/skytells/python-sdk/issues
Keywords: skytells,ai,machine-learning,inference,image-generation,sdk
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Skytells Python SDK
Run AI models with a single function call.

Official Python SDK for the [Skytells](https://skytells.ai) AI platform. Run image, video, audio, music, text, and code models with a single function call.

Zero dependencies — uses Python's stdlib `urllib` for HTTP.

```bash
pip install skytells
```


## Quick Start

First, you'll need to get an API key from the [Skytells Dashboard](https://skytells.ai/dashboard/api-keys).

Then, you can use the SDK to run a model and get the output.

```python
from skytells import SkytellsClient

client = SkytellsClient("sk-your-api-key")

# Run a model and get output
prediction = client.run("truefusion", input={"prompt": "An astronaut riding a rainbow unicorn"})
print(prediction.output)  # "https://..."

# Clean up when done
prediction.delete()
```

Generating a song using [Beatfusion](https://skytells.ai/explore/models/beatfusion-2.0):

```python
prediction = client.run("beatfusion-2.0", input={
    "prompt": "Rap, hip-hop",
    "lyrics": "Let me introduce the voice you hear, Beatfusion by Skytells making it clear.."
})
print(prediction.output)
```

Browse the full model catalog at [skytells.ai/explore/models](https://skytells.ai/explore/models).

> Skytells is committed to the responsible and ethical use of AI. All models are subject to our usage policies and comply with applicable laws and regulations. Learn more at [learn.skytells.ai](https://learn.skytells.ai).



## Installation

```bash
pip install skytells
```

Requires Python 3.8+. No external dependencies.



## Usage

### Client Configuration

```python
from skytells import SkytellsClient

client = SkytellsClient(
    "sk-your-api-key",
    base_url="https://api.skytells.ai/v1",   # optional override
    timeout=30000,                             # ms (default: 60000)
    headers={"X-Custom-Header": "value"},      # extra headers
    retry={"retries": 3, "retry_delay": 1000}, # retry config
)
```

### Run a Model

```python
prediction = client.run("truefusion", input={"prompt": "A sunset over mountains"})
print(prediction.output)   # str or list[str]
print(prediction.id)
print(prediction.status)
```

### Progress Tracking

```python
def on_progress(p):
    print(f"Status: {p['status']}, Progress: {p.get('metrics', {}).get('progress', 'n/a')}")

prediction = client.run(
    "truefusion",
    input={"prompt": "A cat"},
    on_progress=on_progress,
)
```

### Background Predictions

```python
# Create without waiting
response = client.predictions.create({
    "model": "truefusion-ultra",
    "input": {"prompt": "A dog"},
})
print(response["id"], response["status"])  # "pending"

# Wait for completion
result = client.wait(response)
print(result["output"])

# Or poll manually
result = client.predictions.get(response["id"])
```

### Queue & Dispatch

```python
client.queue({"model": "truefusion-ultra", "input": {"prompt": "Cat"}})
client.queue({"model": "flux-pro", "input": {"prompt": "Dog"}})
client.queue({"model": "flux-edge", "input": {"prompt": "Bird"}})

results = client.dispatch()
for pred in results:
    print(pred["id"], pred["status"])
```

### Prediction Lifecycle

```python
# Cancel a running prediction
client.cancel_prediction("pred_abc123")

# Delete a prediction and its assets
client.delete_prediction("pred_abc123")

# Stream endpoint
stream_info = client.stream_prediction("pred_abc123")
print(stream_info["urls"]["stream"])
```

### Models API

```python
# List all models
models = client.models.list()
for model in models:
    print(model["name"], model["type"])

# With schemas
models = client.models.list(fields=["input_schema"])

# Fetch a single model
model = client.models.get("flux-pro")
print(model["name"], model["pricing"])

model = client.models.get("flux-pro", fields=["input_schema", "output_schema"])
print(model["input_schema"])
```

### Predictions API

```python
# List predictions with filters
result = client.predictions.list(model="flux-pro", since="2026-01-01", page=2)
for pred in result["data"]:
    print(pred["id"], pred["status"])

print(result["pagination"])
```



## The Prediction Object

`client.run()` returns a `Prediction` instance:

| Attribute / Method | Description |
|---|---|
| `prediction.id` | Unique prediction ID |
| `prediction.status` | Current status string |
| `prediction.output` | Raw output (`str`, `list[str]`, or `None`) |
| `prediction.outputs()` | Normalised output (unwraps single-element arrays) |
| `prediction.raw()` | Full response dict |
| `prediction.cancel()` | Cancel the prediction |
| `prediction.delete()` | Delete the prediction and its assets |
| `prediction.response` | Full response dict (same as `raw()`) |

### `outputs()` behaviour

| `output` value | `outputs()` returns |
|---|---|
| `None` | `None` |
| `"https://..."` | `"https://..."` |
| `["https://..."]` | `"https://..."` (unwrapped) |
| `["a", "b"]` | `["a", "b"]` |



## Async Client

```python
import asyncio
from skytells import AsyncSkytellsClient

async def main():
    client = AsyncSkytellsClient("sk-your-api-key")
    prediction = await client.run("flux-pro", input={"prompt": "A cat"})
    print(prediction.output)
    await prediction.delete()

asyncio.run(main())
```



## Error Handling

```python
from skytells import SkytellsError

try:
    prediction = client.run("flux-pro", input={"prompt": "test"})
except SkytellsError as e:
    print(e.error_id)    # e.g. "UNAUTHORIZED", "MODEL_NOT_FOUND"
    print(e.http_status) # e.g. 401, 404
    print(e.details)     # human-readable detail string
    print(str(e))        # error message
```

### Error IDs

| Error ID | Source | Meaning |
|---|---|---|
| `UNAUTHORIZED` | API | Invalid or missing API key |
| `INVALID_PARAMETER` | API | A request parameter failed validation |
| `INVALID_DATE_FORMAT` | API | Date string is not `YYYY-MM-DD` |
| `INVALID_DATE_RANGE` | API | `since` is after `until` |
| `MODEL_NOT_FOUND` | API | Model slug does not exist |
| `INTERNAL_ERROR` | API | Unexpected server-side error |
| `INVALID_INPUT` | API | Model input validation failed |
| `INSUFFICIENT_CREDITS` | API | Account has no credits |
| `ACCOUNT_SUSPENDED` | API | Account has been suspended |
| `PAYMENT_REQUIRED` | API | Payment is required to continue |
| `SECURITY_VIOLATION` | API | Request violated a security policy |
| `RATE_LIMIT_EXCEEDED` | API | Too many requests |
| `INFRASTRUCTURE_ERROR` | API | Platform infrastructure failure |
| `PREDICTION_FAILED` | Client | Prediction completed with a failure status |
| `WAIT_TIMEOUT` | Client | `wait()` exceeded `max_wait` |
| `REQUEST_TIMEOUT` | Client | HTTP request timed out |
| `NETWORK_ERROR` | Client | Network-level failure (no HTTP response) |
| `SERVER_ERROR` | Client | Non-JSON or unexpected 5xx response |
| `INVALID_JSON` | Client | Response body could not be parsed as JSON |

For a full reference of API-level and prediction-level errors, see the [Skytells Error Reference](https://learn.skytells.ai/api/v1/errors).



## Client Options

| Option | Type | Default | Description |
|---|---|---|---|
| `api_key` | `str` | `None` | Your Skytells API key (`sk-...`) |
| `base_url` | `str` | `https://api.skytells.ai/v1` | API base URL |
| `timeout` | `int` | `60000` | Request timeout (ms) |
| `headers` | `dict` | `{}` | Extra headers for every request |
| `retry` | `dict` | `{}` | Retry config (`retries`, `retry_delay`, `retry_on`) |



## Type Reference

All types are importable from `skytells.types`:

```python
from skytells.types import (
    PredictionStatus,
    PredictionType,
    PredictionSource,
    ModelType,
    ModelPrivacy,
    PricingUnit,
    ApiErrorId,
)
```

---

## License

MIT — see [LICENSE](LICENSE).
