Skip to content

For Coding Agents

Give your AI coding agent this page and it will have everything it needs to build TopMail integrations.

Share this link with your coding agent

Paste this URL into your conversation with Claude, Codex, Gemini, or any AI coding assistant. The agent will read this page and have full context to write TopMail API calls, handle errors, and build multi-step workflows autonomously.

https://api.topmail.so/developers/coding-agents

That's it. No configuration files, no copy-pasting blocks. Your agent reads the page and does the rest.

API Reference

Complete reference for all TopMail API resources. This is the context your coding agent uses when it reads this page.

TopMail API — Full Reference
# TopMail API Reference

## Base URL
https://api.topmail.so/api/v1

## OpenAPI Spec
https://api.topmail.so/openapi.yaml

## Authentication
All requests require a Bearer token:
Authorization: Bearer tm_live_<your_api_key>

Sandbox/test keys use prefix: tm_test_<key> (skips real email sending, returns mock results)

## TypeScript SDK
npm install @topmail/sdk

import { TopMail } from '@topmail/sdk';
const topmail = new TopMail('tm_live_<your_api_key>');

## Resources

### Contacts
- GET    /contacts              — List contacts (search, subscribed, limit, offset)
- POST   /contacts              — Create contact (email*, first_name, last_name, attributes, subscribed, list_id)
- GET    /contacts/:id          — Get contact with list memberships
- PATCH  /contacts/:id          — Update contact (partial update, attributes merge)
- DELETE /contacts/:id          — Delete contact

Example response (GET /contacts/:id):
{
  "data": {
    "id": "uuid",
    "email": "user@example.com",
    "first_name": "Jane",
    "last_name": "Doe",
    "attributes": { "plan": "pro", "company": "Acme" },
    "subscribed": true,
    "created_at": "2025-01-15T10:30:00.000Z",
    "lists": [{ "id": "uuid", "name": "Newsletter" }]
  }
}

### Lists
- GET    /lists                 — List all lists (type, limit, offset)
- POST   /lists                 — Create list (name*, description, type, conditions)
- GET    /lists/:id             — Get list with member count
- PATCH  /lists/:id             — Update list
- DELETE /lists/:id             — Delete list (members preserved)
- GET    /lists/:id/members     — List members (limit, offset)
- POST   /lists/:id/members     — Add members { contact_ids: ["uuid", ...] }
- DELETE /lists/:id/members     — Remove members { contact_ids: ["uuid", ...] }

### Segments
- GET    /segments              — List segments (search, limit, offset)
- POST   /segments              — Create segment (name*, conditions)
- GET    /segments/:id          — Get segment
- PATCH  /segments/:id          — Update segment
- DELETE /segments/:id          — Delete segment
- POST   /segments/:id/estimate — Estimate matching contacts count
- GET    /segments/:id/contacts — List matching contacts (limit, offset)

Example: Create segment with conditions:
POST /segments { "name": "Active Buyers", "conditions": { "match": "all", "rules": [{ "field": "subscribed", "operator": "equals", "value": true }] } }

### Tags
- GET    /tags                  — List tags with contact_count (search, limit, offset)
- POST   /tags                  — Create tag (name*, color, description)
- GET    /tags/:id              — Get tag
- PATCH  /tags/:id              — Update tag
- DELETE /tags/:id              — Delete tag (cascade removes assignments)
- GET    /tags/:id/contacts     — List tagged contacts
- POST   /tags/:id/contacts     — Assign tag { contact_ids: ["uuid", ...] }
- DELETE /tags/:id/contacts     — Remove tag { contact_ids: ["uuid", ...] }

### Automations
- GET    /automations           — List automations (status, limit, offset)
- GET    /automations/:id       — Get automation with steps and run stats
- PATCH  /automations/:id       — Update name/status (draft→active, active↔paused)
- POST   /automations/:id/trigger — Trigger for contact (contact_id or email, trigger_data)
- GET    /automations/:id/runs  — List runs (status filter: active|completed|failed|paused, limit, offset)

### Campaigns (read-only)
- GET    /campaigns             — List campaigns (status, limit, offset)
- GET    /campaigns/:id         — Get campaign with stats and rates

### Templates (read-only)
- GET    /templates             — List templates
- GET    /templates/:id         — Get template with HTML content

### Email
- POST   /email/send            — Send transactional email (to*, subject*, html*, from, reply_to, tags)
- POST   /email/batch           — Send batch emails (messages[])
- GET    /email/:messageId      — Get delivery status

Example: Send email:
POST /email/send { "to": "user@example.com", "subject": "Welcome!", "html": "<h1>Hello</h1>", "from": "hi@yourdomain.com" }

### Suppressions
- GET    /suppressions          — List suppressed emails (limit, offset)
- POST   /suppressions          — Add to suppression list (email*, reason)
- DELETE /suppressions          — Remove from suppression list (email*)

### Webhooks
- POST   /webhooks              — Subscribe (url*, events[])
- DELETE /webhooks/:id          — Unsubscribe
- POST   /webhooks/:id/test     — Send test event

Webhook event types: email.sent, email.delivered, email.bounced, email.complained, email.opened, email.clicked, contact.subscribed, contact.unsubscribed

### Tracking
- POST   /track/product-view    — Track product view (contact_email*, product_id*, product data)

### Conversions
- GET    /conversions           — List conversions (limit, offset)
- POST   /conversions           — Create conversion (contact_id*, value*, currency, metadata)

### Health
- GET    /health                — API health check (no auth required)

## Response Format
Single resource: { "data": { ... } }
List resource:   { "data": [...], "pagination": { "total": 150, "limit": 100, "offset": 0, "has_more": true } }

## Error Format
{ "error": { "code": "error_code", "message": "Human-readable message" } }

Common codes: validation_error (400), unauthorized (401), not_found (404), conflict (409), rate_limit_exceeded (429), internal_error (500)

## Pagination
Use limit (default: 100, max: 1000) and offset (default: 0) query parameters.

## Idempotency
POST /email/send and /email/batch support Idempotency-Key header to prevent duplicate sends.

## SDK Methods Quick Reference
topmail.contacts.list/get/create/update/delete
topmail.lists.list/get/create/update/delete + topmail.lists.members.add/remove/list
topmail.segments.list/get/create/update/delete/estimateCount/listContacts
topmail.tags.list/get/create/update/delete + topmail.tags.contacts.assign/remove
topmail.automations.list/get/update/activate/pause/trigger/listRuns
topmail.campaigns.list/get
topmail.templates.list/get
topmail.email.send/sendBatch/getStatus
topmail.suppressions.list/add/remove
topmail.webhooks.create/delete/test

Example Workflows

Here are multi-step workflows your coding agent can build using the TopMail SDK.

Create a segment and estimate audience

# Step 1: Create a segment
curl -X POST https://api.topmail.so/api/v1/segments \
-H "Authorization: Bearer tm_live_abc123" \
-H "Content-Type: application/json" \
-d '{
"name": "Active Buyers",
"conditions": {
"match": "all",
"rules": [
{"field": "revenue_potential_score", "operator": "gte", "value": 60},
{"field": "subscribed", "operator": "equals", "value": true}
]
}
}'
# Step 2: Estimate the audience size
curl -X POST https://api.topmail.so/api/v1/segments/SEGMENT_ID/estimate \
-H "Authorization: Bearer tm_live_abc123"

Tag contacts and trigger an automation

# Step 1: Create a tag
curl -X POST https://api.topmail.so/api/v1/tags \
-H "Authorization: Bearer tm_live_abc123" \
-H "Content-Type: application/json" \
-d '{"name": "Upgrade Candidate", "color": "#f59e0b"}'
# Step 2: Assign the tag to contacts
curl -X POST https://api.topmail.so/api/v1/tags/TAG_ID/contacts \
-H "Authorization: Bearer tm_live_abc123" \
-H "Content-Type: application/json" \
-d '{"contact_ids": ["CONTACT_ID_1", "CONTACT_ID_2"]}'
# Step 3: Trigger an automation for each contact
curl -X POST https://api.topmail.so/api/v1/automations/AUTOMATION_ID/trigger \
-H "Authorization: Bearer tm_live_abc123" \
-H "Content-Type: application/json" \
-d '{"contact_id": "CONTACT_ID_1", "trigger_data": {"reason": "upgrade_candidate"}}'

Using the SDK

We recommend using the official TypeScript SDK for agent integrations. It provides full type safety, built-in error handling, and pagination helpers that make it easier for your coding agent to write correct API calls on the first try.

View SDK Documentation
Developer Docs - TopMail