# Python package for social media posting

Canonical: https://status200uploads.com/integrations/python

Checked on 26 October 2026.

status200uploads is our Python package for the REST API. Install it with pip install status200uploads (Python 3.11 or newer), put your API key in STATUS200_API_KEY, and Status200().publish() posts to a network you connected. It sends a safe-retry key with every post by itself, retries only what the API allows, and can wait until the network is done. Version 0.1.0 is on PyPI.

Tested on 28 September 2026 with Python 3.11 and the status200uploads 0.1.0 package.

## What you need

- On every plan, Free included.
- **Python:** Python 3.11 or newer. The package depends only on httpx and attrs.
- **The package:** status200uploads 0.1.0 on PyPI (https://pypi.org/project/status200uploads/); its source is in the public repository at https://github.com/iBoyDroid/status-200-uploads/tree/main/python.
- **An API key:** An rl_ key from the dashboard, under API (Generate Key), in the STATUS200_API_KEY environment variable or passed as Status200(api_key=...). The package never prints it.
- **Connected networks:** Connect each network once in the dashboard under Connections; the package posts from those profiles.

## Steps

1. **Install the package** Run pip install status200uploads in a Python 3.11 or newer environment (a virtual environment is best).
2. **Give it your key** Set the STATUS200_API_KEY environment variable to your rl_ key, or pass it as Status200(api_key="rl_..."). Keep the key out of your code and out of git.
3. **Find your profile** s200.list_accounts() lists your profiles, their handles and the networks connected to each. Use the handle (such as "@myprofile") or the profile_id as the post's accountId.
4. **Publish and wait for the outcome** s200.publish(post, wait=True) sends the post with an automatic Idempotency-Key, then reads it back every 30 seconds, for up to 10 minutes, until the network is done. result.final holds its status and its link.

## What it can do

- **Publish now:** publish(post) sends one post to one network from one profile. The post is the same JSON as the REST API's post object.
- **Safe retries by default:** Every publish carries an Idempotency-Key made once for that post. A retry after a timeout or a lost answer gets the first answer back, never a second post; the package resends only what the API's retry table allows.
- **Wait for the outcome:** publish(post, wait=True), or wait_for(result) later, reads the post every 30 seconds until it is done, for up to 10 minutes.
- **Schedule and cancel:** publish(post, scheduled_for=...) with a datetime that has a time zone schedules it, up to 365 days ahead; result.code is "scheduled". cancel(result.status200.scheduled_post_id) stops it before it goes out.
- **Import media:** import_media(url) imports an image or a video from a public address and waits until it is ready. Put its file_id in the post's content.mediaID list.
- **Read posts:** list_posts() reads one page of your posts and scheduled posts, iter_posts() walks every page, newest first, and get_post(post_id) reads one post with its status and link.
- **Clear errors:** A refusal raises Status200Error with the API's code and message. OutcomeUnknown means no clear answer came back and the post may have gone out: look at list_posts() before you send it again.

## A worked example: a LinkedIn post

The release test ran this flow: list the profiles, publish a LinkedIn text post, wait for the outcome. The same post sent three times with one key went out once; the second and third tries got the first answer back.

Publish and wait (the key comes from STATUS200_API_KEY)

```python
from status200uploads import OutcomeUnknown, Status200, Status200Error

s200 = Status200()  # the key comes from STATUS200_API_KEY

try:
    # 1. Your profiles, and the networks connected to each
    for account in s200.list_accounts():
        print(account["handle"], [network["platform"] for network in account["networks"]])

    # 2. Publish, then read the post every 30 seconds until the network is done (10 minutes at most)
    post = {"accountId": "@myprofile", "platform": "linkedin", "content": {"text": "Hello from Python"}}
    result = s200.publish(post, wait=True)
    if result.final:  # the post as last read: its status and link
        print(result.final.get("status"), result.final.get("permalink"))
    else:  # scheduled or queued (result.code says which), or it could not be read back
        print(result.code)
except OutcomeUnknown as error:
    print(error.message)  # no clear answer: it may have gone out, check s200.list_posts() first
except Status200Error as error:
    print(error.code, error.message)  # refused, or a wrong key (unauthorized): the message says why
```

## Limits and safe retries

- The package works within the REST API's limits: one post to one network per call, posts to the same network 20 seconds apart, and 60 reads a minute per account for all your keys together.
- A 202 is never a failure: publish() returns a Result whose code says the case (scheduled, queued_for_next_day, still_publishing). Do not send that post again.
- The API remembers an Idempotency-Key for 24 hours. A key you pass yourself (idempotency_key=...) must come with the same post on every try: the same key with a changed post is refused, and a new key is a new post.
- Your plan's posts and daily limits apply. A post over the day's limit is queued for the next day, and result.code is queued_for_next_day.

## Troubleshooting

**Status200Error with the code unauthorized.** STATUS200_API_KEY is not set, or the key is mistyped or revoked. Copy it again from the dashboard under API.

**OutcomeUnknown was raised.** No clear answer came back, and the post may have gone out. Look at s200.list_posts() or History in the dashboard before you send it again.

**result.final is None.** The post was scheduled or queued (result.code says which), or it could not be read back in time. Read it later with s200.get_post(result.status200.post_id).

**pip cannot find a version that satisfies the requirement.** The package needs Python 3.11 or newer. Check python --version, and install it in a newer environment.

## Questions

### Which Python version does the package need?

Python 3.11 or newer. Install it with pip install status200uploads; it depends only on httpx and attrs.

### Does it work on the Free plan?

Yes. The package uses the REST API, which is on every plan, Free included. Your plan's posts and daily limits apply.

### Can a retry post twice?

No. Every publish carries an Idempotency-Key made once for that post, so a retry after a timeout gets the first answer back instead of a second post. The release test sent one post three times with one key and it went out once.

### Can it schedule posts?

Yes. Pass scheduled_for with a datetime that has a time zone, and cancel(scheduled_post_id) stops the post before it goes out.

### Can it upload a file from my computer?

Not in version 0.1.0. It imports media from a public address with import_media(url). To post a file from your computer, upload it in the dashboard under Media, or use the REST API's upload links on a paid plan.

### Do I need the package to use Python?

No. Any HTTP library works: the API reference has the same flow with requests, and the OpenAPI file at https://status200uploads.com/openapi.yaml can generate a client.

## Related

- [LinkedIn](https://status200uploads.com/platforms/linkedin)
- [TikTok](https://status200uploads.com/platforms/tiktok)
- [YouTube](https://status200uploads.com/platforms/youtube)
- [REST API](https://status200uploads.com/integrations/rest-api)
- [n8n](https://status200uploads.com/integrations/n8n)
- [Using Python, in the API reference](https://status200uploads.com/docs/api#guide-python)
- [Safe retries, in the API reference](https://status200uploads.com/docs/api#safe-retries)
- [Pricing](https://status200uploads.com/pricing)
