Getting Started with Conduit

Conduit is a hosted service that 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

  1. Go to conduit.email/app/signup.
  2. Enter your email address and choose a password of at least 12 characters.
  3. Click Create account.

Conduit sends a confirmation email. Open the link in that email before signing in for the first time.

Sign up with Google or GitHub

If the deployment has Google or GitHub OAuth enabled, you can click Sign up with Google or Sign up with GitHub instead. This creates an account automatically using your provider-verified email address — no password or email confirmation is required.

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"
}

Conduit sends a confirmation email and blocks sign-in until the link in that email has been opened.


2. Sign in

Using the web UI

Go to conduit.email/app/signin, enter your email and password, and click Sign in.

Sign in with Google or GitHub

If the deployment has Google or GitHub OAuth enabled, you can click Sign in with Google or Sign in with GitHub to sign in without a password. If your email address matches an existing account, the OAuth provider is linked to that account — your password is not needed and is not affected.

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.

If your email address is still unconfirmed, the sign-in page also includes a form to request another confirmation link.

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
}

If the account exists but the email address has not been confirmed yet, the API returns 401 Unauthorized with code email_not_confirmed.

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 (incoming.conduit.email). Every account can create webhooks on it — 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

  1. Go to Webhooks (/app/webhooks) and click + New.
  2. 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).
  3. Enter the target HTTPS URL that should receive the webhook payload.
  4. 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

The Conduit SMTP gateway listens at mx.conduit.email on port 25. STARTTLS is supported. Point any mail client or sending system at that host and address your email to the webhook address.

Quick test with swaks

swaks is a command-line SMTP testing tool available on most platforms (brew install swaks, apt install swaks):

swaks \
  --to webhook-01HX...@incoming.conduit.email \
  --from you@example.com \
  --server mx.conduit.email \
  --port 25 \
  --body "Hello from swaks"

SMTP response codes

Conduit returns an SMTP status 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.


Password resets

Request a password reset from conduit.email/app/reset-password in the web UI or by calling POST /api/v1/accounts/me/password-reset. Conduit sends a reset email with a single-use link to choose a new password.


Next steps