Docs / Start here

Make one safe send. Then build the system.

Use one API for transactional, lifecycle, and broadcast email. Start with synthetic recipients, inspect the evidence, and promote only when your domain and Project are ready.

01

Get a Project key

Sign in, create a Test Project, then open Settings → Developer. Create a named API key and copy the secret when it appears. Linnet stores only its hash and cannot show the secret again.

Keep the boundary clear.

Use a Project API key for your application. Use a separately scoped Agent key for Claude, Codex, or another MCP client. Never give an agent your API key.

export LINNET_API_KEY='ln_test_…'

02

Send a test email

Every request creates one Message for one recipient. Supply an idempotency key so a retry returns the same result instead of creating a duplicate.

curl https://app.linnetmail.com/v1/emails \
  -H "Authorization: Bearer $LINNET_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: first-send-001" \
  -d '{
    "from": "hello@test.linnet.invalid",
    "to": "you@test.linnet.invalid",
    "subject": "Hello from Linnet",
    "text": "Your first test email.",
    "stream": "transactional"
  }'

Open Activity → Emails to inspect acceptance, attempts, and delivery evidence. In a Test Project, delivery is simulated and labeled as test evidence.

03

Choose the right stream

Transactional

Account and service messages expected by the recipient. Suppress marketing without breaking receipts or security mail.

Lifecycle

Messages triggered by customer behavior or product events. Permission is checked again before every email.

Broadcast

Campaigns to a reviewed Audience Snapshot. The audience, exclusions, content, and schedule are frozen at approval.

04

Start a journey from your product

Import or link the Contact first with your stable user ID and the permission evidence you collected. Events never grant consent.

curl https://app.linnetmail.com/v1/events \
  -H "Authorization: Bearer $LINNET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "signup-user_123",
    "name": "user.signed_up",
    "contact_id": "user_123",
    "properties": { "plan": "trial" }
  }'
  • id makes the event replay-safe.
  • contact_id is your stable user ID, never an email address.
  • In Create → Journeys, choose the start event and an optional goal such as workspace.activated.

05

Receive signed delivery events

Open Settings → Developer, add a public HTTPS endpoint, choose Linnet or Resend-compatible formatting, and copy the one-time signing secret. Webhook work is durable and retried outside the Message worker.

Use the webhook attempt ledger and linked request receipt to troubleshoot a non-2xx response without exposing message bodies in operational logs.

06

Connect Claude or Codex

Create a named Agent credential under Home → Agents. Keep the secret in the environment that starts your MCP client; the saved command should contain only the environment-variable reference.

export LINNET_AGENT_KEY='ln_agent_…'

codex mcp add linnet \
  --url https://app.linnetmail.com/mcp \
  --bearer-token-env-var LINNET_AGENT_KEY

The agent can inspect bounded evidence and prepare Campaigns, journeys, popups, and routines. It cannot approve, publish, schedule, or send consequential work. Those actions stay in the human workspace.

07

Promote with evidence

  1. Add a Sending Domain and publish the exact DKIM, SPF, return-path, and DMARC records Linnet shows.
  2. Confirm the Project’s data location, sending route, quota headroom, event coverage, and suppression behavior.
  3. Run a named seed-inbox test. Treat provider acceptance, delivery, inbox placement, and human engagement as different facts.
  4. Approve the exact production Campaign, journey Version, or API path only after its audience and safety checks are current.

08

When a request fails

Use the error code and HTTP status in your integration. Keep the request_id when contacting support; it lets us locate the exact attempt without asking for a key or message body.

Error reference

Find the next step for an API error

Open this page from a Linnet API response to see guidance for its code.

Do not retry blindly. Check whether the response asks you to change the request, wait, or inspect the current resource first.

For an error not yet covered here, include its code, HTTP status, and request ID in a support request. Do not send your API key, OAuth secret, or customer data.