Metadata-Version: 2.4
Name: fittins
Version: 1.0.0
Summary: Official Python library for the Fittins AI API: premium AI fashion photos and videos from your product photos.
Author-email: Fittins AI <support@fittins.ai>
License-Expression: MIT
Project-URL: Homepage, https://fittins.ai
Project-URL: Documentation, https://fittins.ai/docs/api
Project-URL: Support, https://fittins.ai/support
Keywords: fittins,ai,fashion,on-model,virtual-try-on,product-photos,fashion-video,api,sdk
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Typing :: Typed
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# Fittins AI for Python

The official library for the [Fittins AI API](https://fittins.ai/docs/api). Fittins AI is a premium AI fashion generation service: studio-quality on-model photos up to 8K and fashion videos up to 4K, made from your product photos.

The API is included in the Pro, Business and Enterprise plans and uses the same credits as the website. Create a key in **Profile → API keys** on [fittins.ai](https://fittins.ai).

```bash
pip install fittins
```

Needs Python 3.10 or later, and has no dependencies. Use it on your server: never put an API key in a web page or an app.

## Create a photo

```python
from fittins import Fittins

fittins = Fittins()  # reads FITTINS_API_KEY

generation = fittins.images.create(
    product_images=[{"url": "https://cdn.mystore.com/p/dress.jpg"}],
    model_id="mdl_lib_DM5rQvl3KtlR7nqumd6I",
    prompt="full body, soft studio light, front view",
    aspect_ratio="3:4",
    quality="4k",
    metadata={"sku": "DRESS-RED-M"},
)

done = fittins.generations.wait(generation["id"])

if done["status"] == "succeeded":
    print(done["output"]["url"])  # a download link, valid for 24 hours
else:
    print(done["error"]["code"], done["error"]["message"])
```

## What's included

| | |
|---|---|
| `images.create` · `videos.create` | Start a photo or a video |
| `generations.get` · `list` · `list_all` · `wait` · `delete` | Follow, list and delete results |
| `uploads.create` | Upload a product photo (a path, bytes or an open file) |
| `files.download` | Get a result's bytes |
| `models` · `locations` | `list`, `get`, and `create` a custom one |
| `webhook_endpoints` | `create`, `list`, `delete`, `rotate_secret` |
| `usage.get` · `account.get` | Calls and credits per day, and plan and balance |

Answers are plain dictionaries, with type hints in `fittins.types`. Field names are the same as in the [API reference](https://fittins.ai/docs/api).

## Retries and safe creates

Failed requests are sent up to 2 more times, with a growing pause. After a 429, the library waits for the time in `Retry-After`.

Each create gets an `Idempotency-Key` that its retries reuse, so a retry can't charge twice. To protect against your own job running twice, pass a key you can repeat:

```python
fittins.images.create(idempotency_key=f"photo-{sku}", **params)
```

Uploads, webhook endpoint changes and deletes are only retried after a 429, because sending them twice could do the work twice.

Set your own limits with `Fittins(max_retries=4, timeout=60.0)`.

## Errors

```python
from fittins import APIError

try:
    fittins.images.create(**params)
except APIError as error:
    if error.code == "insufficient_credits":
        ...  # error.status, error.code, error.message, error.param, error.request_id
    else:
        raise
```

`APIConnectionError` means no answer arrived. `WaitTimeoutError` means `generations.wait` ran out of time; the generation may still finish. A generation that fails after being accepted isn't raised: check `status` and `error`.

## Webhooks

```python
import os

from flask import Flask, request
from fittins import WebhookVerificationError, verify_webhook

app = Flask(__name__)

@app.post("/webhooks/fittins")
def fittins_webhook():
    try:
        event = verify_webhook(
            request.get_data(),
            request.headers.get("Fittins-Signature"),
            os.environ["FITTINS_WEBHOOK_SECRET"],
        )
    except WebhookVerificationError:
        return "", 400
    if event["type"] == "generation.succeeded":
        print(event["data"]["object"]["output"]["url"])
    return "", 200
```

Pass the body exactly as received, before any JSON parsing.

## Testing without credits

Keys that start with `fit_test_` run the checks on your request and return a sample result, without using the AI or any credits.

## More

[API documentation](https://fittins.ai/docs/api) · [Support](https://fittins.ai/support)
