Skip to main content

StackShift Python SDK

Official Python SDK for StackShift.

Install

pip install stackshift

Send email

from stackshift import StackShift

stackshift = StackShift()

message = stackshift.mail.send(
    from_="StackShift <noreply@mail.stackshift.cloud>",
    to="ada@example.com",
    subject="Welcome",
    text="Welcome to StackShift.",
    idempotency_key="welcome:user_123",
)

print(message["id"], message["status"], message["idempotencyStatus"])

Inspect message status:

messages = stackshift.mail.messages.list(status="mta_accepted", limit=20)
detail = stackshift.mail.messages.get(messages["data"][0]["id"])
attempts = stackshift.mail.messages.attempts(detail["id"])
logs = stackshift.mail.messages.logs(detail["id"])

mta_accepted means the message was accepted by StackShift's outbound MTA. It does not mean recipient-MX acceptance, inbox placement, opens, clicks, or spam placement. Recipient records later transition independently to delayed, delivered, bounced, failed, suppressed, or complained.

Events and webhooks

events = stackshift.mail.events.list(
    type="mail.message.bounced",
    message_id="msg_123",
    limit=20,
)

event = stackshift.mail.events.get("evt_123")
timeline = stackshift.mail.messages.timeline("msg_123")

webhook = stackshift.mail.webhooks.create(
    url="https://example.com/stackshift-mail",
    event_types=["mail.message.bounced", "mail.otp.verified"],
)
print(webhook["id"], webhook["secret"])  # Secret is only returned on create/rotate.

deliveries = stackshift.mail.webhooks.deliveries(webhook["id"], status="failed")
retried = stackshift.mail.webhooks.retry_delivery(deliveries["data"][0]["id"])

Verify a webhook signature before processing the payload:

valid = stackshift.mail.webhooks.verify_signature(
    raw_body=request.get_data(),
    signature_header=request.headers.get("StackShift-Signature"),
    timestamp_header=request.headers.get("StackShift-Timestamp"),
    secret=os.environ["STACKSHIFT_WEBHOOK_SECRET"],
)

Webhook handlers should be idempotent. StackShift retries non-2xx responses. Delivery events do not include full email bodies or OTP codes by default.

Send a template

Templates are rendered by StackShift servers. The Python SDK only calls the REST API.

stackshift.mail.templates.create(
    name="Welcome Email",
    slug="welcome-email",
    subject="Welcome, {{name}}",
    text="Welcome, {{name}}",
)

preview = stackshift.mail.templates.preview(
    "welcome-email",
    data={"name": "Ada"},
)

message = stackshift.mail.send_template(
    template="welcome-email",
    to="ada@example.com",
    from_="Acme <noreply@acme.com>",
    data={"name": "Ada"},
    idempotency_key="welcome:user_123",
)

Missing variables fail before a message is queued. Template sends use the same sender-domain, suppression, idempotency, Durable Jobs, and Postfix handoff pipeline as mail.send.

Bounces and suppressions

suppressions = stackshift.mail.suppressions.list()

manual = stackshift.mail.suppressions.create(
    email="bad@example.com",
    reason="manual",
)

stackshift.mail.suppressions.delete(manual["id"])

bounces = stackshift.mail.bounces.list(type="hard")
message_bounces = stackshift.mail.messages.bounces("msg_123")

Hard bounces are automatically suppressed by the backend. Suppressions are workspace scoped and checked before a message is queued.

Verify a sending domain

domain = stackshift.mail.domains.create("acme.com")
print(domain["records"])

stackshift.mail.domains.verify(domain["id"])

message = stackshift.mail.send(
    from_="Acme <noreply@acme.com>",
    to="user@example.com",
    subject="Welcome",
    html="<h1>Welcome</h1>",
    text="Welcome",
)

Add the returned SPF, DKIM, and return-path DNS records before verification. DMARC is recommended unless your environment sets MAIL_DMARC_REQUIRED=true. DNS propagation can take time.

Upload an asset

from stackshift import StackShift

stackshift = StackShift()

asset = stackshift.assets.upload(
    "avatar.png",
    folder="avatars",
    visibility="public",
    metadata={"user_id": "user_123"},
)

print(asset["url"])

You do not pass a deployed StackShift project ID. The API key identifies the StackShift account, and StackShift resolves the default asset space internally.

Private asset URL

signed = stackshift.assets.signed_url(
    asset["id"],
    expires_in="10m",
    max_downloads=1,
)

print(signed["url"])

Image transformations

Use built-in presets or create your own named transformations.

from stackshift import StackShift, asset_transform_options, get_asset_transform_preset

stackshift = StackShift()
hero = get_asset_transform_preset("hero")
hero_options = asset_transform_options(hero)

stackshift.assets.create_transformation(hero["name"], **hero_options)

named = stackshift.assets.named_url("asset_123", hero["name"])
signed = stackshift.assets.signed_transform_url("asset_123", **hero_options, expiresIn="10m")

stackshift.assets.delete_transformation("old-preset")
print(named, signed["url"])

Direct browser uploads

Create the upload session on your Python backend:

upload = stackshift.assets.signed_upload_url(
    bucket="avatars",
    key="users/user_123.png",
    visibility="public",
    expiresIn="10m",
    maxBytes=5_000_000,
)

Then upload the browser File to upload["url"] from your frontend. Do not expose your StackShift API key to browser code.

The SDK only talks to the StackShift REST API. Storage placement, replication, disks, and repair are StackShift internals.

Metadata

Release files for stackshift 1.0.1

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

Source distribution (sdist)

Source distribution for stackshift 1.0.1
File Size Uploaded Provenance Actions
stackshift-1.0.1.tar.gz 21.3 kB Without provenance Details for stackshift-1.0.1.tar.gz

Built distribution (wheel)

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

Total release size: 39.2 kB

Release files / stackshift-1.0.1.tar.gz

Download URL stackshift-1.0.1.tar.gz
Size 21.3 kB
Tags Source
SHA-256 checksum
How to use checksums
c4b01aa8911482b5f6ae850c1b7fc01066573ebdc7a2c5ff209dc368b95845ac
BLAKE2b-256 checksum
How to use checksums
83822d7d4dbe95d898cb47f44a4572417b82c5fd0d8200a1efc6e8593ac511f9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.2

Release files / stackshift-1.0.1-py3-none-any.whl

Download URL stackshift-1.0.1-py3-none-any.whl
Size 17.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1f6cb44e92885918784185818fad344c6410fa9f27b5f88e462f7401ed244a88
BLAKE2b-256 checksum
How to use checksums
ac396f4407478d760380c2166254ae0fb166afa28bf90f9f5ae354c97a7af6cb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.2

Security for stackshift 1.0.1

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.

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