Skip to content
Claim your free business email
Email API for Python

Send email from Python with an email API

Send email from Python over HTTPS with httpx: post one message, read the id back and follow every delivery event on a signed webhook.

Pythonpip install httpx
# pip install httpximport os
import httpx
response = httpx.post(    "https://api.rasket.com/emails",    headers={        "Authorization": "Bearer "        + os.environ["RASKET_API_KEY"],        # Required on every request.        "User-Agent": "acme-billing/1.0",        # A retry with this key cannot send twice.        "Idempotency-Key": "order-1042",    },    json={        "from": "Acme <orders@send.acme.example>",        "to": ["ronald.williams@example.com"],        "subject": "Your order has shipped",        "html": "<p>Order 1042 shipped today.</p>",    },)response.raise_for_status()
print(response.json()["id"])

What sending from Python actually involves

To send email from Python you can reach for smtplib and run your own relay, or you can make one HTTPS request and let an email API own the delivery. Rasket is the second. The sample below uses httpx; requests works the same way, because the whole send is one POST with a JSON body and four headers. A typed Python client, the rasket package, is coming soon.

Last updated 2026-09-29. Every field, header and limit below is the one the emails reference carries.

What you get with the key

Five things that arrive with the first request rather than with a later plan.

  • Idempotent sends

    Put an Idempotency-Key on a send and repeat it as often as you like. For 24 hours the same key and payload return the first response instead of a second email, and a different payload under that key is refused rather than sent.

  • Signed webhooks you can replay

    Delivery, bounce, complaint, open and click posted to your endpoint with a timestamp and a signature, retried on failure and replayable from the dashboard.

  • Inbound mail on your own domain

    Receive at your domain on every plan. Each message arrives on a signed webhook with its headers, text and HTML, and its attachments behind signed links.

  • Templates with typed variables

    Publish a template, then send it by ID or alias with the values it declares. Every email records the exact version it was rendered from.

  • Campaigns and automations

    Contacts with typed properties, topics people subscribe to, and per-contact workflows that wait, branch and send — through the same pipeline as the rest of your mail.

How to send email from Python

Six steps, in this order. Everything before the fifth is done once, and only the fifth is about the language you write in.

  1. 1

    Create an API key

    Open API keys in the dashboard and create one. It is shown once and stored hashed, so copy it then. Put it in your environment as RASKET_API_KEY and read it from there; a key committed to a repository is a key you have to rotate.

  2. 2

    Add a sending domain

    POST /domains with a domain you control. A subdomain such as send.acme.example is the usual choice, because it keeps this mail's reputation separate from the address your people write from. The response carries a records array.

  3. 3

    Publish the DNS records

    Every row of records goes into your DNS: the DKIM TXT record at rasket._domainkey, and the CNAME that gives the domain its own return path. Nothing sends from the domain until they resolve.

  4. 4

    Verify the domain

    POST /domains/{domain_id}/verify. The domain comes back with a status on each record, and once it reads verified you can send from any address on it. An unverified sender is refused rather than quietly dropped.

  5. 5

    Send your first email from Python

    Post the message with the sample above. Carry an Idempotency-Key — yours or your queue's retry cannot then turn into a second email — and a User-Agent, which every request has to have. A 200 with an id means we have taken responsibility for the message.

  6. 6

    Subscribe a webhook and check its signature

    POST /webhooks with an https endpoint and the events you care about. Delivery, bounce, complaint, open and click arrive there with svix-id, svix-timestamp and svix-signature; verify against the raw body before anything parses it.

Verify webhooks in Python

Read the raw body before anything parses it — request.get_data() in Flask, await request.body() in an async framework — and pass it with the headers to the svix package's Webhook(secret).verify(). request.get_json() has already parsed, and the signature is over what arrived rather than over what a parser reconstructed.

The five steps a verifier performs, in seven languages, are on the webhooks reference.

Read the long version

Sending email from Python: the full guide covers attachments, scheduling, suppressions and what to do when a message bounces.

Questions about Python

Do I need an SMTP server to send email from Python?

No, and that is the point of using an API instead of smtplib: no port 587 to open outbound and no credentials in a config file beyond one key. If a library you depend on can only speak SMTP, Rasket's SMTP relay takes it, with the key as the password.

Where do I keep the API key in a Python app?

In the environment, read as os.environ["RASKET_API_KEY"] so a missing key raises at import rather than at the first send. Send it as a bearer token in the Authorization header on every request, and never log the headers or write the key anywhere.

How do I stop a retry from sending the same email twice?

Send an Idempotency-Key header and reuse the same string for every retry of the same work. For 24 hours a repeat returns the first response instead of sending again, and a different payload under that key is refused rather than sent.

How do I verify a Rasket webhook in Python?

pip install svix, read the raw body first, then Webhook(secret).verify(raw_body, dict(request.headers)). It checks svix-id, svix-timestamp and svix-signature and raises WebhookVerificationError when any of them is wrong. Only parse the JSON after that call returns.

Can I send a template or a batch from Python?

Yes. A send can carry "template": {"id": …, "variables": {…}} instead of html or text, and the batch route, POST /emails/batch, takes up to a hundred messages in one request, validated all or none while naming the index that failed.

Make your first send

Create a key, verify a domain, and post your first message from Python. The free plan does not expire.