tosvg 1.0.0
Official Python SDK for the ToSVG API — convert images to SVG, remove backgrounds, and resize images.
Requires Python: >=3.9
Keywords: api, background-removal, convert, image, resize, sdk, svg, tosvg

# ToSVG Python SDK

Official Python SDK for the [ToSVG API](https://tosvg.com) — convert images to SVG, remove backgrounds, and resize images.

[![PyPI version](https://img.shields.io/pypi/v/tosvg.svg)](https://pypi.org/project/tosvg/)
[![Python 3.9+](https://img.shields.io/badge/python-3.9%2B-blue.svg)](https://www.python.org/)
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)

## Installation

```bash
pip install tosvg
```

## Quick Start

```python
from tosvg import ToSVG

client = ToSVG(api_key="tosvg_live_your_api_key_here")

# Convert an image to SVG
result = client.convert.image_to_svg("photo.png")
print(result.svg[:100])
print(f"File size: {result.file_size} bytes")
print(f"Conversion time: {result.conversion_time}s")
```

## Authentication

Get your API key from [tosvg.com](https://tosvg.com). Keys use the format `tosvg_live_*` (production) or `tosvg_test_*` (sandbox).

```python
from tosvg import ToSVG

# The API key is sent via the X-API-Key header automatically
client = ToSVG(api_key="tosvg_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
```

### Client Options

```python
client = ToSVG(
    api_key="tosvg_live_xxx",
    base_url="https://tosvg.com/api/v1",  # default
    timeout=30,                            # seconds (default: 30)
    retry_on_rate_limit=True,              # auto-retry on 429 (default: True)
    max_retries=3,                         # max retry attempts (default: 3)
)
```

## API Methods

### Image to SVG Conversion

Convert raster images (PNG, JPG, BMP, GIF, TIFF, WebP) to vector SVG format.

```python
from tosvg import ToSVG, ColorMode, ConversionMode

client = ToSVG(api_key="tosvg_live_xxx")

# Basic conversion
result = client.convert.image_to_svg("photo.png")

# With options
result = client.convert.image_to_svg(
    "photo.png",
    color_mode=ColorMode.BW,         # "color" or "bw"
    mode=ConversionMode.SPLINE,      # "polygon" or "spline"
    filter_speckle=4,                # 0-20 (noise filter)
    corner_threshold=60,             # 0-180 (corner angle)
    color_precision=8,               # 1-10 (color detail)
)

print(result.svg)              # SVG XML string
print(result.file_size)        # bytes
print(result.conversion_time)  # seconds
```

### Remove Background

Remove backgrounds from images using AI models.

```python
from tosvg import ToSVG, BackgroundProvider, BackgroundModel, ImageFormat

client = ToSVG(api_key="tosvg_live_xxx")

# Basic removal (returns server-side file path)
result = client.background.remove("photo.jpg")
print(result.filename)  # "abc123.png"
print(result.path)      # "removed-background/abc123.png"

# With base64 output
result = client.background.remove(
    "photo.jpg",
    provider=BackgroundProvider.REMBG,
    model=BackgroundModel.U2NET_HUMAN_SEG,
    format=ImageFormat.PNG,
    return_base64=True,
)
print(result.image)  # base64-encoded string

# Common fields (always present)
print(result.file_size)        # bytes
print(result.processing_time)  # seconds
print(result.provider)         # "rembg"
```

### Resize Image

Resize images to specified dimensions.

```python
from tosvg import ToSVG, ResizeFormat

client = ToSVG(api_key="tosvg_live_xxx")

result = client.resize.image(
    "photo.png",
    width=800,                             # required, 1-4096
    height=600,                            # required, 1-4096
    quality=85,                            # 1-100 (default: 90)
    format=ResizeFormat.WEBP,              # "png", "jpg", "jpeg", "webp"
    maintain_aspect_ratio=True,            # default: True
)

print(result.path)               # server-side file path
print(result.size)               # bytes
print(result.dimensions.width)   # output width
print(result.dimensions.height)  # output height
print(result.processing_time)    # seconds
```

### Information Endpoints

```python
client = ToSVG(api_key="tosvg_live_xxx")

# Health check (no auth required)
health = client.health_check()
print(health.status)     # "healthy"
print(health.services)   # {"image_conversion": "operational", ...}

# Supported formats (auth required)
formats = client.convert.supported_formats()
print(formats.formats)          # {"png": FormatInfo(...), ...}
print(formats.max_file_size)    # "10MB"

# Background removal models (auth required)
models = client.background.models()
print(models.models)             # ["u2net", "silueta", ...]
print(models.available_providers)  # ["rembg", "withoutbg"]

# Resize limits (auth required)
limits = client.resize.limits()
print(limits.max_width)   # 4096
print(limits.max_height)  # 4096
```

## File Input Types

All image parameters accept multiple input types:

```python
from pathlib import Path
from io import BytesIO

# String file path
result = client.convert.image_to_svg("/path/to/image.png")

# pathlib.Path
result = client.convert.image_to_svg(Path("image.png"))

# Raw bytes
with open("image.png", "rb") as f:
    image_bytes = f.read()
result = client.convert.image_to_svg(image_bytes)

# BytesIO
buffer = BytesIO(image_bytes)
result = client.convert.image_to_svg(buffer)

# Any file-like object (IO[bytes])
with open("image.png", "rb") as f:
    result = client.convert.image_to_svg(f)
```

## Async Support

All methods are available in async form via `AsyncToSVG`:

```python
import asyncio
from tosvg import AsyncToSVG, ColorMode

async def main():
    async with AsyncToSVG(api_key="tosvg_live_xxx") as client:
        # Convert
        result = await client.convert.image_to_svg(
            "photo.png",
            color_mode=ColorMode.BW,
        )
        print(result.svg[:80])

        # Remove background
        bg_result = await client.background.remove("photo.jpg", return_base64=True)

        # Resize
        resize_result = await client.resize.image("photo.png", width=800, height=600)

        # Health check
        health = await client.health_check()
        print(health.status)

asyncio.run(main())
```

## Error Handling

The SDK provides typed exceptions for all API error scenarios:

```python
from tosvg import ToSVG
from tosvg.exceptions import (
    ToSVGError,          # base exception
    AuthenticationError, # 401 — invalid/missing API key
    ForbiddenError,      # 403 — IP restriction / subscription required
    BadRequestError,     # 400 — bad request / unsupported format
    ValidationError,     # 422 — parameter validation failure
    RateLimitError,      # 429 — rate limit exceeded
    ServerError,         # 500/502/503/504 — server error
    NetworkError,        # connection failure / timeout
)

client = ToSVG(api_key="tosvg_live_xxx")

try:
    result = client.convert.image_to_svg("photo.png")
except AuthenticationError as e:
    print(f"Auth failed: {e.message}")
    print(f"Error code: {e.error_code}")  # e.g. "INVALID_API_KEY"
except ValidationError as e:
    print(f"Validation failed: {e.message}")
    print(f"Field errors: {e.errors}")     # {"image": ["The image field is required."]}
except RateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds")
except ServerError as e:
    print(f"Server error ({e.status_code}): {e.message}")
except NetworkError as e:
    print(f"Connection problem: {e.message}")
except ToSVGError as e:
    print(f"SDK error: {e.message}")
```

## Rate Limiting

The SDK automatically handles rate limiting:

- **Auto-retry:** When `retry_on_rate_limit=True` (default), 429 responses are retried automatically
- **Retry delay priority:** response body `retry_after` → `Retry-After` header → 60s fallback
- **5xx retry:** 502/503/504 responses are retried with exponential back-off

### Checking Rate Limit Status

```python
# After any API call, rate limit info is available:
info = client.get_rate_limit_info()
if info:
    print(f"Limit: {info.limit}")
    print(f"Remaining: {info.remaining}")
    print(f"Resets at: {info.reset_at}")  # Unix timestamp
```

## Enums

The SDK provides enums for all fixed-value parameters:

| Enum                 | Values                                                     | Used In               |
| -------------------- | ---------------------------------------------------------- | --------------------- |
| `ColorMode`          | `COLOR`, `BW`                                              | `image_to_svg()`      |
| `ConversionMode`     | `POLYGON`, `SPLINE`                                        | `image_to_svg()`      |
| `BackgroundProvider` | `REMBG`, `WITHOUTBG`                                       | `background.remove()` |
| `BackgroundModel`    | `U2NET`, `SILUETA`, `U2NET_HUMAN_SEG`, `ISNET_GENERAL_USE` | `background.remove()` |
| `ImageFormat`        | `PNG`, `JPG`, `JPEG`                                       | `background.remove()` |
| `ResizeFormat`       | `PNG`, `JPG`, `JPEG`, `WEBP`                               | `resize.image()`      |

All enums also accept plain strings:

```python
# These are equivalent:
client.convert.image_to_svg("photo.png", color_mode=ColorMode.BW)
client.convert.image_to_svg("photo.png", color_mode="bw")
```

## Requirements

- Python 3.9+
- [httpx](https://www.python-httpx.org/) ≥ 0.27

## License

MIT — see [LICENSE](LICENSE) for details.