Getting Started with Conduit
Conduit bridges inbound email to HTTP webhooks. When an email arrives at your Conduit address, Conduit immediately delivers it as an HTTP POST to a URL you configure. This guide walks you through creating an account and setting up your first webhook.
1. Create an account
Using the web UI
- Open your Conduit instance in a browser and go to
/app/signup. - Enter your email address and choose a password of at least 12 characters.
- Click Create account.
You are signed in automatically and taken to the dashboard.
Using the API
POST /api/v1/accounts
Content-Type: application/json
{
"email": "you@example.com",
"password": "correct-horse-battery-staple"
}
A successful response returns your account details:
{
"id": "acc_01HX...",
"email": "you@example.com",
"created_at": "2024-01-15T10:00:00Z"
}
2. Sign in
Using the web UI
Go to /app/signin, enter your email and password, and click Sign in.
If two-factor authentication is enabled on your account you are prompted for a code from your authenticator app before being taken to the dashboard.
Using the API
Exchange your credentials for a short-lived access token and a refresh token:
POST /api/v1/sessions
Content-Type: application/json
{
"email": "you@example.com",
"password": "correct-horse-battery-staple"
}
{
"access_token": "eyJ...",
"refresh_token": "eyJ...",
"expires_in": 900
}
The access_token is valid for 15 minutes. Use the refresh_token to obtain a
new access token without signing in again:
POST /api/v1/sessions/refresh
Content-Type: application/json
{
"refresh_token": "eyJ..."
}
Include the access token in the Authorization header for all subsequent
requests:
Authorization: Bearer <access_token>
Two-factor authentication (TOTP)
If 2FA is enabled, the sign-in response returns a TOTP challenge rather than tokens:
{
"totp_required": true,
"totp_token": "..."
}
Complete the challenge with a code from your authenticator app:
POST /api/v1/sessions/2fa
Content-Type: application/json
{
"totp_token": "...",
"code": "123456"
}
3. Create your first webhook
A webhook maps an email address to an HTTP endpoint. When an email arrives at the address, Conduit posts the message to your endpoint.
Public domain vs. custom domain
Conduit has one public domain (by default incoming.conduit.email). Every
account can create webhooks on it for free — no verification required. When you
use the public domain, the local part (the part before @) is derived
automatically from the webhook ID and cannot be changed:
webhook-01HX...@incoming.conduit.email
If you need a memorable address like orders@mail.yourcompany.com, you must
first claim and verify your own domain. See
Using a Custom Domain for details.
Using the web UI
- Go to Webhooks (
/app/webhooks) and click + New. - To use the public domain, leave the domain selector set to Public — the
address is assigned automatically after you save.
To use one of your verified private domains, select Private domain and
enter the full email address (e.g.
alerts@mail.yourcompany.com). - Enter the target HTTPS URL that should receive the webhook payload.
- Click Create webhook.
The webhook detail page shows the generated secret. Copy this secret now — it is not shown again. You need it to verify the signature on your endpoint.
Using the API
Public domain webhook (omit address):
POST /api/v1/webhooks
Authorization: Bearer <access_token>
Content-Type: application/json
{
"target_url": "https://myapp.example.com/hooks/email"
}
Conduit assigns an address automatically:
{
"id": "wh_01HX...",
"address": "webhook-01HX...@incoming.conduit.email",
"target_url": "https://myapp.example.com/hooks/email",
"secret": "whsec_...",
"active": true,
"rate_limit": 0,
"created_at": "2024-01-15T10:01:00Z",
"updated_at": "2024-01-15T10:01:00Z"
}
Private domain webhook (requires a verified domain):
POST /api/v1/webhooks
Authorization: Bearer <access_token>
Content-Type: application/json
{
"address": "alerts@mail.yourcompany.com",
"target_url": "https://myapp.example.com/hooks/email"
}
The secret field is only returned at creation time. Copy it now.
4. Verify the signature on your endpoint
Every delivery from Conduit includes an X-Conduit-Signature header containing
an HMAC-SHA256 signature of the raw request body, keyed with your webhook
secret:
X-Conduit-Signature: sha256=<hex-encoded-digest>
Verify this signature in your endpoint before processing the payload:
import hmac
import hashlib
def verify_signature(body: bytes, secret: str, header: str) -> bool:
expected = "sha256=" + hmac.new(
secret.encode(), body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, header)
Reject requests where the signature does not match.
If you need to rotate the secret, use the Rotate secret button on the
webhook detail page in the UI, or call PUT /api/v1/webhooks/{id} with a new
secret value.
5. Send a test email
Point any mail client or mail server at the Conduit SMTP gateway (default port
2525) and send an email to your webhook address. Conduit will forward the
message as a JSON POST to your endpoint and return the SMTP response code that
reflects the delivery outcome:
| Outcome | SMTP code | Meaning |
|---|---|---|
| Success (HTTP 2xx) | 250 |
Message accepted |
| Transient failure (HTTP 5xx / timeout) | 450 |
MTA will retry |
| Permanent failure (HTTP 4xx) | 550 |
MTA will bounce |
To review delivery attempts, open the webhook detail page in the UI and click
Logs, or call GET /api/v1/webhooks/{id}/logs.
Next steps
- Using a Custom Domain — verify a domain you own so you can use your own addresses.
- Configuring an SMTP Security Policy — restrict who can send email to your webhooks.
- Using the API — full reference for all API endpoints.
- Controlling SMTP Responses with HTTP Headers — return custom SMTP codes from your endpoint.