Skip to main content

SlideCold Python SDK

The official Python client for the SlideCold API (Instagram cold-DM outreach): SlideCold and AsyncSlideCold clients with typed methods for every API operation, generated from the OpenAPI spec.

Looking for a command line or an MCP server? They live in their own repos:

Install

pip install slidecold    # Python 3.9+, the only dependency is httpx

Create an API key at https://slidecold.com/settings. Keys look like cs_....

Authentication

The API key is resolved in this order:

  1. the api_key= argument
  2. the SLIDECOLD_API_KEY environment variable
  3. the config file written by slidecold login from slidecold-cli: ~/.config/slidecold/config.json ($XDG_CONFIG_HOME/slidecold/config.json if set, %APPDATA%\slidecold\config.json on Windows)

The base URL follows the same order (base_url=, SLIDECOLD_BASE_URL, config baseUrl), then defaults to https://slidecold.com/api/v1. The config file is {"apiKey": "cs_...", "baseUrl": "..."}. The SDK only reads it; it never writes it.

SDK quickstart

from slidecold import SlideCold

with SlideCold() as client:  # or SlideCold(api_key="cs_...")
    for campaign in client.campaigns.list():
        print(campaign["id"], campaign["name"], campaign["status"])

    campaign = client.campaigns.create(
        name="Spring outreach",
        audienceIds=["aud_123"],
        accountIds=["acc_456"],
        templates=[{"body": "Hey, quick question about your page"}],
    )
    print(client.campaigns.stats(campaign["id"]))

    csv_text = client.audiences.export("aud_123")  # str
    members = client.audiences.list_members("aud_123", min_followers=1000, limit=50)
    client.conversations.send_reply("conv_789", message="Thanks, sending details now")
    client.conversations.send_photo("conv_789", file="offer.jpg")

Request bodies use the API's field names. Pass them as keyword arguments, as a dict, or both: client.campaigns.update(id, {"status": "ACTIVE"}) is the same as client.campaigns.update(id, status="ACTIVE"). Path parameters are positional and query parameters are snake_case keyword arguments. Every method's docstring lists the scope it needs. Responses are plain dicts and lists, typed with the TypedDicts in slidecold.types.

Async

import asyncio
from slidecold import AsyncSlideCold


async def main():
    async with AsyncSlideCold() as client:
        accounts, campaigns = await asyncio.gather(client.accounts.list(), client.campaigns.list())


asyncio.run(main())

Instagram login jobs

Adding an account, re-logging in and session checks run in the background and return {"jobId": ...}. wait_for_login_job polls accounts.login_status until the job finishes:

job = client.accounts.create(username="mybrand", password="...", proxyId="prx_1")
status = client.wait_for_login_job(job["jobId"], interval=2, timeout=120)
if status["state"] == "failed":
    print(status.get("error"))

It returns the final status (completed, failed or unknown) and raises TimeoutError after timeout seconds. AsyncSlideCold.wait_for_login_job is the async version.

Options

SlideCold(api_key=None, base_url=None, timeout=30, max_retries=2). GET requests are retried on 429, 5xx and connection errors with exponential backoff (honouring Retry-After). Other methods are never retried, so a DM is never sent twice. client.request("operationId", path=..., query=..., body=...) calls any operation by its OpenAPI operationId.

Scopes

Each API key has scopes of the form <resource>:<read|write> for accounts, audiences, campaigns and conversations. A :write scope also grants :read. Proxies use the accounts scopes. The scope for each operation is shown in its method docstring.

Errors

All errors derive from slidecold.SlideColdError and carry status, message (the API's error string) and body (the parsed response).

Exception When
AuthenticationError 401: the key is missing or invalid
PermissionDeniedError 403: the key lacks a scope (This API key is missing the campaigns:write scope) or a plan limit was hit
NotFoundError 404
RateLimitError 429
APIError any other error status (base class of the four above)
APIConnectionError no response: DNS, connection or timeout
from slidecold import PermissionDeniedError

try:
    client.campaigns.delete("cmp_1")
except PermissionDeniedError as e:
    print(e.status, e.message)

Webhooks

SlideCold signs each webhook with an X-SlideCold-Signature header: the hex HMAC-SHA256 of the raw JSON body, keyed with the endpoint secret (whsec_...). Verify it against the raw bytes, before parsing:

from slidecold import verify_webhook_signature


@app.post("/webhooks/slidecold")  # Flask
def slidecold_webhook():
    if not verify_webhook_signature(
        request.get_data(), request.headers.get("X-SlideCold-Signature", ""), WHSEC
    ):
        abort(401)
    event = request.get_json()
    ...

Development

uv sync
uv run python scripts/generate.py          # regenerate from openapi.yaml
uv run ruff check . && uv run ruff format --check . && uv run mypy && uv run pytest

src/slidecold/_operations.py, _resources.py and types.py are generated from openapi.yaml and committed. CI fails if they are stale.

License

MIT

Metadata

Release files for slidecold 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for slidecold 0.2.0
File Size Uploaded Provenance Actions
slidecold-0.2.0.tar.gz 40.0 kB Without provenance Details for slidecold-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for slidecold 0.2.0
File Interpreter ABI Platform Actions
slidecold-0.2.0-py3-none-any.whl Python 3 none any Details for slidecold-0.2.0-py3-none-any.whl

Total release size: 67.1 kB

Release files / slidecold-0.2.0.tar.gz

Download URL slidecold-0.2.0.tar.gz
Size 40.0 kB
Tags Source
SHA-256 checksum
How to use checksums
a476959cadb46bc725b0104035661f9155da408e84f89b82ac6acbf6c04e0a5b
BLAKE2b-256 checksum
How to use checksums
61109bb8f547d9627f487869867619784a99ef078c8245f38f100176b9b0563d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / slidecold-0.2.0-py3-none-any.whl

Download URL slidecold-0.2.0-py3-none-any.whl
Size 27.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8ac07e12d8b40863962207e1221535e9f6a3d18c6f70282ec96799444e99a14e
BLAKE2b-256 checksum
How to use checksums
e4631badf7e95c3b57cede18f1f78ab712144561fb9d4043e7371681171a51e5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for slidecold 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page