Quick start

From zero to sending email in 5 minutes. This guide covers the minimum steps to get a working setup through the API.

1. Get your API key

Go to Settings > API Keys in your dashboard and create a new key. Copy it immediately. It is only shown once.

export SHIPMAIL_API_KEY="sm_live_..."

2. Add a domain

Register the domain you want to send and receive email on.

curl

curl -X POST https://shipmail.to/api/v1/domains \ -H "Authorization: Bearer $SHIPMAIL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "example.com"}'

TypeScript

import ShipMail from "shipmail"; const shipmail = new ShipMail(process.env.SHIPMAIL_API_KEY); const domain = await shipmail.domains.create({ name: "example.com" }); console.log(domain.id); // dom_...

Python

from shipmail import ShipMail client = ShipMail("sm_live_...") domain = client.domains.create({"name": "example.com"}) print(domain["id"]) # dom_...

The response includes the DNS records you need to add. Save these for the next step.

Alternative: Register a domain

Instead of bringing your own domain, you can search for and register one directly through shipmail. DNS records are configured automatically, so you can skip steps 3 and 4.

TypeScript

// Search for available domains const { results } = await shipmail.domains.search({ keyword: "mycompany" }); const available = results.filter((r) => r.available); // Register a domain (charges your saved payment method) const domain = await shipmail.domains.register({ name: "mycompany.com", contact: { first_name: "Jane", last_name: "Doe", address1: "123 Main St", city: "San Francisco", state: "CA", zip: "94105", country: "US", phone: "+14155551234", email: "jane@example.com", }, }); // Domain is registered, DNS is configured automatically

Python

# Search for available domains result = client.domains.search({"keyword": "mycompany"}) available = [r for r in result["results"] if r["available"]] # Register a domain (charges your saved payment method) domain = client.domains.register({ "name": "mycompany.com", "contact": { "first_name": "Jane", "last_name": "Doe", "address1": "123 Main St", "city": "San Francisco", "state": "CA", "zip": "94105", "country": "US", "phone": "+14155551234", "email": "jane@example.com", }, }) # Domain is registered, DNS is configured automatically

3. Configure DNS

Add the 4 DNS records (MX, SPF, DKIM, DMARC) to your DNS provider. The records are returned in the domain creation response and are visible in your dashboard under the domain row.

See the domain setup guide for details on each record and provider-specific notes.

4. Verify the domain

shipmail automatically polls your DNS records every 30 seconds. Once all 4 pass, the domain status changes to verified. You can also trigger verification manually:

curl

curl -X POST https://shipmail.to/api/v1/domains/DOMAIN_ID/verification \ -H "Authorization: Bearer $SHIPMAIL_API_KEY"

TypeScript

const result = await shipmail.domains.verify(domain.id); console.log(result.all_verified); // true

Python

result = client.domains.verify(domain["id"]) print(result["all_verified"]) # True

Alternative: use a webhook instead of polling

If you are automating domain setup, subscribe to the domain.verified event instead of polling the verification endpoint. Create a webhook before adding your domain, then continue your setup when the event fires.

TypeScript

// 1. Create a webhook for domain events const webhook = await shipmail.webhooks.create({ url: "https://yourapp.com/api/webhooks/shipmail", events: ["domain.verified", "domain.verification_failed"], }); // Save webhook.secret for signature verification // 2. Add the domain const domain = await shipmail.domains.create({ name: "example.com" }); // 3. Add DNS records at your provider, then wait for the webhook // shipmail sends a domain.verified event when all records pass

Python

# 1. Create a webhook for domain events webhook = client.webhooks.create({ "url": "https://yourapp.com/api/webhooks/shipmail", "events": ["domain.verified", "domain.verification_failed"], }) # Save webhook["secret"] for signature verification # 2. Add the domain domain = client.domains.create({"name": "example.com"}) # 3. Add DNS records at your provider, then wait for the webhook # shipmail sends a domain.verified event when all records pass

The webhook payload includes the domain_id and verified_at timestamp. See the webhooks guide for payload details and signature verification.

5. Create a mailbox

Create a mailbox on your verified domain.

curl

curl -X POST https://shipmail.to/api/v1/mailboxes \ -H "Authorization: Bearer $SHIPMAIL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "domain_id": "DOMAIN_ID", "address": "hello", "display_name": "Hello" }'

TypeScript

const mailbox = await shipmail.mailboxes.create({ domain_id: domain.id, address: "hello", display_name: "Hello", }); console.log(mailbox.id); // mbx_...

Python

mailbox = client.mailboxes.create({ "domain_id": domain["id"], "address": "hello", "display_name": "Hello", }) print(mailbox["id"]) # mbx_...

6. Send an email

Send your first email from the mailbox you just created.

curl

curl -X POST https://shipmail.to/api/v1/messages \ -H "Authorization: Bearer $SHIPMAIL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "hello@yourdomain.com", "to": ["recipient@example.com"], "subject": "Hello from shipmail", "text": "It works." }'

TypeScript

const message = await shipmail.messages.send({ from: "hello@yourdomain.com", to: ["recipient@example.com"], subject: "Hello from shipmail", text: "It works.", }); console.log(message.id); // msg_...

Python

message = client.messages.send({ "from": "hello@yourdomain.com", "to": ["recipient@example.com"], "subject": "Hello from shipmail", "text": "It works.", }) print(message["id"]) # msg_...

Next steps

  • Set up webhooks to receive notifications when email arrives or bounces.
  • Use the TypeScript or Python SDK for type-safe access to the full API.
  • Connect an email client to read and send from your mailbox directly.