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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.