Metadata-Version: 2.5
Name: onepostly
Version: 0.1.0
Summary: Official Python SDK for the Onepostly API. Publish, schedule, and read results across X, Instagram, LinkedIn, TikTok, YouTube, Facebook, Threads, Pinterest, and Bluesky with one request shape.
Project-URL: Homepage, https://onepostly.com
Author-email: Onepostly <enes@onepostly.com>
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: api,bluesky,facebook,instagram,linkedin,onepostly,pinterest,sdk,social-media,threads,tiktok,twitter,x,youtube
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
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: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24
Requires-Dist: typing-extensions>=4.5; python_version < '3.10'
Description-Content-Type: text/markdown

# onepostly

Official Python SDK for the [Onepostly API](https://onepostly.com/docs) — one client for X, Instagram, LinkedIn, TikTok, YouTube, Facebook, Threads, Pinterest, and Bluesky.

Python 3.9+. The only runtime dependency is `httpx`.

## Installation

```sh
pip install onepostly
```

## Usage

```python
import os
from onepostly import Onepostly

client = Onepostly(api_key=os.environ["ONEPOSTLY_API_KEY"])

result = client.create_post(
    "Hello from Onepostly",
    destinations=[{"connectionId": "…"}],
)
print(result["post"]["id"])
```

The constructor also reads `ONEPOSTLY_API_KEY` from the environment when `api_key` is omitted. Resource methods use the REST field names (camelCase); the `create_post` convenience wrapper accepts snake_case kwargs.

### Scheduling

```python
client.create_post(
    "Tomorrow morning",
    scheduled_for="2026-09-01T09:00:00",  # timezone-naive local time
    timezone="Europe/Istanbul",
    destinations=[{"connectionId": "…"}],
)
```

### Media

```python
with open("photo.jpg", "rb") as f:
    media = client.media.upload(f, filename="photo.jpg")["media"]

client.create_post(
    "With an image",
    media_kind="image",
    media_urls=[media["url"]],
    destinations=[{"connectionId": "…"}],
)
```

### Insights

```python
insights = client.insights.get(post_id)["insights"]
timeline = client.insights.timeline(post_id, from_="2026-08-01", to="2026-08-28")
```

### Error handling

Every non-2xx response raises `OnepostlyError` carrying the API's machine-readable `code` and HTTP `status`:

```python
from onepostly import OnepostlyError, is_insufficient_wallet

try:
    client.create_post("Hello", destinations=[{"connectionId": "…"}])
except OnepostlyError as error:
    if is_insufficient_wallet(error):
        ...  # HTTP 402 — top up the workspace wallet
    print(error.code, error.status, error.message)
```

## API reference

| Resource | Methods |
| --- | --- |
| `client.posts` | `create` `list` `get` `cancel` `remote_delete` |
| `client.media` | `upload` `list` `delete` |
| `client.connections` | `list` `start_oauth` |
| `client.insights` | `get` `timeline` |
| `client.comments` | `list` `create` `delete` |
| `client.engagement` | `list_retweeters` `retweet` `undo_retweet` `like` `unlike` `bookmark` `remove_bookmark` `quote` |
| `client.webhooks` | `event_types` `list` `create` `update` `delete` `rotate_secret` `deliveries` `test` |

Full request/response reference: [onepostly.com/openapi.json](https://onepostly.com/openapi.json)

Runnable scripts live in [`examples/`](./examples). See [CONTRIBUTING.md](./CONTRIBUTING.md) for development and release flow.
