What's in your pipeline database
Smartlead, Instantly, HeyReach, PlusVibe, EmailBison, and Prosp all write into the same local SQLite file. One schema. Your agent queries it directly.
This page lists every table, field, type, and an example row so you (or your agent) can write SQL without guessing column names. Data stays on your machine in outreachmagic.db. No hosted CRM, no CSV stitching.
Which table do I need?
| Question | Table |
|---|---|
| Replies, bounces, sends, campaign breakdowns | events |
| Lead list with per-workspace status and sentiment | workspace_leads + leads |
| Clay custom fields or API attributes | lead_personalization |
| LinkedIn connection state per sender | workspace_lead_linkedin_status |
| Hard bounces by sender mailbox | bounce_events |
Core pipeline
Leads, companies, campaigns, and the events timeline. Smartlead, Instantly, HeyReach, PlusVibe, EmailBison, and Prosp webhooks all land here.
leads
One row per contact. Email and/or LinkedIn identity. Org-wide, not workspace-scoped.
| Field | Type | Description |
|---|---|---|
| id | INTEGER | Primary key |
| name | TEXT | Full name |
| company_id | INTEGER | FK to companies.id |
| company | TEXT | Denormalized company name |
| title | TEXT | Job title |
| industry | TEXT | Industry segment |
| headcount | TEXT | Company size band (e.g. 51-200) |
| headcount_numeric | INTEGER | Numeric headcount when known |
| TEXT | Primary email (unique when set) | |
| email_domain | TEXT | Domain part of email |
| linkedin_url | TEXT | LinkedIn profile URL (unique when set) |
| location_city | TEXT | City |
| location_state | TEXT | State or region |
| location_country | TEXT | Country |
| channel | TEXT | Primary channel: email or linkedin |
| stage | TEXT | Pipeline stage (legacy; see workspace_leads for per-workspace status) |
| notes | TEXT | Free-form notes |
| original_source | TEXT | First source that created the lead |
| original_source_detail | TEXT | Detail for original source |
| original_source_platform | TEXT | Platform for original source |
| original_source_at | TEXT | ISO timestamp of first source |
| latest_source | TEXT | Most recent source event |
| latest_source_detail | TEXT | Detail for latest source |
| latest_source_platform | TEXT | Platform for latest source |
| latest_source_at | TEXT | ISO timestamp of latest source |
| email_verification_status | TEXT | Latest verification status summary |
| email_verified_at | TEXT | When email was last verified |
| created_at | TEXT | Row created (ISO) |
| updated_at | TEXT | Row last updated (ISO) |
| last_contact_at | TEXT | Last outbound or inbound touch |
| next_action | TEXT | Suggested next step |
| next_action_at | TEXT | When next action is due |
| cloud_pending | INTEGER | 1 if local changes await cloud sync |
| latest_sender | TEXT | Most recent sender address or profile |
| latest_sender_platform | TEXT | Platform of latest sender |
Example row
{
"id": 1042,
"name": "Jordan Lee",
"company_id": 88,
"company": "Northstar Logistics",
"title": "VP Operations",
"industry": "Logistics",
"headcount": "201-500",
"headcount_numeric": 340,
"email": "jordan.lee@northstarlogistics.com",
"email_domain": "northstarlogistics.com",
"linkedin_url": "https://www.linkedin.com/in/jordan-lee-ops",
"location_city": "Chicago",
"location_state": "IL",
"location_country": "US",
"channel": "email",
"stage": "replied",
"notes": null,
"original_source": "smartlead_import",
"original_source_platform": "smartlead",
"latest_source": "email_reply",
"latest_source_platform": "smartlead",
"email_verification_status": "valid",
"created_at": "2026-05-12T14:22:00Z",
"updated_at": "2026-06-17T09:41:00Z",
"last_contact_at": "2026-06-16T18:03:00Z",
"cloud_pending": 0,
"latest_sender": "alex@agency-mail.com",
"latest_sender_platform": "smartlead"
}companies
Canonical company records linked from leads. Deduped by domain when present.
| Field | Type | Description |
|---|---|---|
| id | INTEGER | Primary key |
| name | TEXT | Company name |
| domain | TEXT | Primary domain (unique when set) |
| industry | TEXT | Industry |
| headcount | TEXT | Size band |
| headcount_numeric | INTEGER | Numeric employee count |
| hq_city | TEXT | HQ city |
| hq_state | TEXT | HQ state |
| hq_country | TEXT | HQ country |
| cloud_pending | INTEGER | 1 if awaiting cloud sync |
| created_at | TEXT | Row created (ISO) |
| updated_at | TEXT | Row updated (ISO) |
Example row
{
"id": 88,
"name": "Northstar Logistics",
"domain": "northstarlogistics.com",
"industry": "Logistics",
"headcount": "201-500",
"headcount_numeric": 340,
"hq_city": "Chicago",
"hq_state": "IL",
"hq_country": "US",
"cloud_pending": 0,
"created_at": "2026-05-12T14:22:00Z",
"updated_at": "2026-06-10T11:00:00Z"
}events
Primary timeline for analytics. Replies, bounces, sends, status labels, and LinkedIn activity from every connected sequencer.
Use events (not workspace_lead_events) for reply rates, campaign breakdowns, and timelines.
| Field | Type | Description |
|---|---|---|
| id | INTEGER | Primary key |
| lead_id | INTEGER | FK to leads.id |
| event_type | TEXT | e.g. email_sent, email_reply, bounce, linkedin_reply |
| direction | TEXT | outbound or inbound |
| channel | TEXT | email or linkedin |
| subject | TEXT | Email subject or LinkedIn thread title |
| body_preview | TEXT | Truncated message preview |
| metadata_json | TEXT | Platform-specific payload (JSON string) |
| campaign_id | INTEGER | FK to campaigns.id |
| sender | TEXT | Sending address or LinkedIn profile |
| created_at | TEXT | When the event occurred (ISO) |
Example row
{
"id": 98231,
"lead_id": 1042,
"event_type": "email_reply",
"direction": "inbound",
"channel": "email",
"subject": "Re: quick question on freight ops",
"body_preview": "Thanks for reaching out. We are evaluating vendors in Q3...",
"metadata_json": "{\"platform\":\"smartlead\",\"campaign_external_id\":\"cmp_abc\"}",
"campaign_id": 14,
"sender": "alex@agency-mail.com",
"created_at": "2026-06-16T18:03:00Z"
}campaigns
Campaign names. In multi-workspace setups, names use a workspace prefix (e.g. northstar | Q2 outbound).
| Field | Type | Description |
|---|---|---|
| id | INTEGER | Primary key |
| name | TEXT | Unique campaign name |
| description | TEXT | Optional description |
| status | TEXT | active, paused, or completed |
| created_at | TEXT | Row created (ISO) |
Example row
{
"id": 14,
"name": "northstar | Q2 freight ops",
"description": "Smartlead campaign for Northstar workspace",
"status": "active",
"created_at": "2026-04-01T10:00:00Z"
}campaign_leads
Many-to-many link between campaigns and leads.
| Field | Type | Description |
|---|---|---|
| campaign_id | INTEGER | FK to campaigns.id |
| lead_id | INTEGER | FK to leads.id |
| added_at | TEXT | When lead was added to campaign (ISO) |
Example row
{
"campaign_id": 14,
"lead_id": 1042,
"added_at": "2026-05-12T14:30:00Z"
}Workspaces and routing
Multi-client setups use workspaces to separate clients. Campaign webhooks route to the right workspace through campaign_workspace_map.
organizations
Top-level org record. One SQLite file per install, usually one org.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Org UUID |
| name | TEXT | Organization name |
| workspace_routing_mode | TEXT | single or multi |
| default_workspace_id | TEXT | Fallback workspace UUID |
| created_at | TEXT | Row created (ISO) |
Example row
{
"id": "org_7f3a9c2e",
"name": "Summit Outbound Agency",
"workspace_routing_mode": "multi",
"default_workspace_id": "ws_northstar",
"created_at": "2026-03-15T08:00:00Z"
}workspaces
Client or brand partition. Status, tags, and reporting filter by workspace.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Workspace UUID |
| org_id | TEXT | FK to organizations.id |
| name | TEXT | Display name |
| slug | TEXT | URL-safe slug (unique per org) |
| cloud_synced | INTEGER | 1 if synced to cloud |
| created_at | TEXT | Row created (ISO) |
| updated_at | TEXT | Row updated (ISO) |
Example row
{
"id": "ws_northstar",
"org_id": "org_7f3a9c2e",
"name": "Northstar Logistics",
"slug": "northstar",
"cloud_synced": 1,
"created_at": "2026-03-15T08:05:00Z",
"updated_at": "2026-06-17T07:00:00Z"
}workspace_leads
Per-workspace lead status, sentiment, owner, and activity timestamps.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Workspace lead UUID |
| org_id | TEXT | Org UUID |
| workspace_id | TEXT | FK to workspaces.id |
| lead_id | INTEGER | FK to leads.id |
| status | TEXT | Pipeline status (prospecting, replied, interested, etc.) |
| owner_user_id | TEXT | Assigned rep |
| stage_entered_at | TEXT | When current status started |
| last_activity_at | TEXT | Last event in this workspace |
| current_status_label | TEXT | Human-readable status from sequencer |
| current_status_sentiment | TEXT | positive, interested, neutral, negative, etc. |
| contact_priority | INTEGER | Sort priority (lower = higher) |
| latest_sender | TEXT | Latest sender in this workspace |
| cloud_pending | INTEGER | 1 if awaiting cloud sync |
| created_at | TEXT | Row created (ISO) |
| updated_at | TEXT | Row updated (ISO) |
Example row
{
"id": "wl_9b2c4d1e",
"org_id": "org_7f3a9c2e",
"workspace_id": "ws_northstar",
"lead_id": 1042,
"status": "replied",
"owner_user_id": "user_alex",
"stage_entered_at": "2026-06-16T18:03:00Z",
"last_activity_at": "2026-06-16T18:03:00Z",
"current_status_label": "Interested",
"current_status_sentiment": "interested",
"contact_priority": 2,
"latest_sender": "alex@agency-mail.com",
"cloud_pending": 0,
"created_at": "2026-05-12T14:30:00Z",
"updated_at": "2026-06-16T18:03:00Z"
}workspace_lead_events
Workspace-scoped ingest audit log. Not the full event volume; use events for analytics.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Event UUID |
| org_id | TEXT | Org UUID |
| workspace_id | TEXT | Workspace UUID |
| lead_id | INTEGER | FK to leads.id |
| workspace_lead_id | TEXT | FK to workspace_leads.id |
| event_type | TEXT | Ingest event type |
| event_at | TEXT | Source event time (ISO) |
| source_platform | TEXT | smartlead, instantly, heyreach, etc. |
| external_event_id | TEXT | Platform event ID |
| idempotency_key | TEXT | Dedup key (unique per org) |
| payload_json | TEXT | Raw ingest payload (JSON string) |
| created_at | TEXT | Row created (ISO) |
Example row
{
"id": "wse_4f8a1b2c",
"org_id": "org_7f3a9c2e",
"workspace_id": "ws_northstar",
"lead_id": 1042,
"workspace_lead_id": "wl_9b2c4d1e",
"event_type": "email_reply",
"event_at": "2026-06-16T18:03:00Z",
"source_platform": "smartlead",
"external_event_id": "sl_evt_88291",
"idempotency_key": "smartlead:sl_evt_88291",
"payload_json": "{\"reply_body\":\"Thanks for reaching out...\"}",
"created_at": "2026-06-16T18:03:12Z"
}campaign_workspace_map
Maps platform campaign IDs or normalized names to a workspace.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Map row UUID |
| org_id | TEXT | Org UUID |
| source_platform | TEXT | Platform identifier |
| campaign_id | TEXT | External campaign ID |
| campaign_name_normalized | TEXT | Lowercase trimmed name for fuzzy match |
| workspace_id | TEXT | FK to workspaces.id |
| match_strategy | TEXT | id_exact or name_normalized |
| priority | INTEGER | Lower wins on conflict |
| is_active | INTEGER | 1 if rule is active |
| cloud_synced | INTEGER | 1 if synced to cloud |
| created_at | TEXT | Row created (ISO) |
| updated_at | TEXT | Row updated (ISO) |
Example row
{
"id": "cwm_1a2b3c4d",
"org_id": "org_7f3a9c2e",
"source_platform": "smartlead",
"campaign_id": "cmp_abc123",
"campaign_name_normalized": "q2 freight ops",
"workspace_id": "ws_northstar",
"match_strategy": "id_exact",
"priority": 100,
"is_active": 1,
"cloud_synced": 1,
"created_at": "2026-04-01T09:00:00Z",
"updated_at": "2026-04-01T09:00:00Z"
}unmapped_campaign_queue
Quarantined webhook events when no workspace mapping exists. Resolve via agent or portal, then sync.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Queue row UUID |
| org_id | TEXT | Org UUID |
| source_platform | TEXT | Platform identifier |
| campaign_id | TEXT | External campaign ID |
| campaign_name_raw | TEXT | Raw campaign name from webhook |
| campaign_name_normalized | TEXT | Normalized name |
| external_event_id | TEXT | Platform event ID |
| reason | TEXT | Why event was quarantined |
| status | TEXT | pending, resolved, or dismissed |
| payload_json | TEXT | Full webhook payload (JSON string) |
| received_at | TEXT | When webhook arrived (ISO) |
| resolved_at | TEXT | When mapping was assigned (ISO) |
| cloud_pending | INTEGER | 1 if resolution awaits cloud sync |
| assigned_workspace | TEXT | Workspace assigned on resolve |
Example row
{
"id": "ucq_5e6f7g8h",
"org_id": "org_7f3a9c2e",
"source_platform": "instantly",
"campaign_id": "inst_cmp_991",
"campaign_name_raw": "New Client Test",
"campaign_name_normalized": "new client test",
"external_event_id": "inst_evt_44102",
"reason": "no_workspace_mapping",
"status": "pending",
"payload_json": "{\"event\":\"reply\",\"lead_email\":\"test@example.com\"}",
"received_at": "2026-06-17T12:00:00Z",
"resolved_at": null,
"cloud_pending": 1,
"assigned_workspace": null
}Identity and deduplication
Cross-platform identity keys, merge history, and webhook dedupe.
lead_identities
Normalized identity keys (email, LinkedIn URL, etc.) per org for dedup and matching.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Identity UUID |
| org_id | TEXT | Org UUID |
| lead_id | INTEGER | FK to leads.id |
| identity_type | TEXT | email, linkedin_url, linkedin_id, etc. |
| identity_value_normalized | TEXT | Lowercase normalized value |
| source | TEXT | Where identity was first seen |
| is_verified | INTEGER | 1 if verified |
| created_at | TEXT | Row created (ISO) |
Example row
{
"id": "lid_3c4d5e6f",
"org_id": "org_7f3a9c2e",
"lead_id": 1042,
"identity_type": "email",
"identity_value_normalized": "jordan.lee@northstarlogistics.com",
"source": "smartlead",
"is_verified": 1,
"created_at": "2026-05-12T14:22:00Z"
}lead_merges
Audit trail when duplicate leads are merged. merge_id is the deleted lead.
| Field | Type | Description |
|---|---|---|
| id | INTEGER | Primary key |
| keep_id | INTEGER | Surviving lead FK |
| merge_id | INTEGER | Merged-away lead ID (no FK) |
| reason | TEXT | Why merge happened |
| merge_entity_key | TEXT | Dedup key used |
| relay_delete_pushed | INTEGER | 1 if cloud delete was sent |
| merged_at | TEXT | Merge timestamp (ISO) |
Example row
{
"id": 42,
"keep_id": 1042,
"merge_id": 1038,
"reason": "duplicate_email",
"merge_entity_key": "email:jordan.lee@northstarlogistics.com",
"relay_delete_pushed": 1,
"merged_at": "2026-05-20T16:45:00Z"
}lead_merge_jobs
Cloud-side merge job records with audit JSON.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Job UUID |
| org_id | TEXT | Org UUID |
| keep_lead_id | INTEGER | Surviving lead |
| merge_lead_id | INTEGER | Merged lead |
| status | TEXT | completed, pending, or failed |
| reason | TEXT | Merge reason |
| audit_json | TEXT | Field-level merge audit (JSON string) |
| created_at | TEXT | Job created (ISO) |
Example row
{
"id": "lmj_8h9i0j1k",
"org_id": "org_7f3a9c2e",
"keep_lead_id": 1042,
"merge_lead_id": 1038,
"status": "completed",
"reason": "sheet_review_approved",
"audit_json": "{\"fields_merged\":[\"title\",\"linkedin_url\"]}",
"created_at": "2026-05-20T16:45:00Z"
}relay_ingested
Webhook dedupe keys. Prevents the same platform event from being applied twice.
| Field | Type | Description |
|---|---|---|
| dedupe_key | TEXT | Primary key (platform:event_id) |
| lead_id | INTEGER | Lead that received the event |
| ingested_at | TEXT | When ingest completed (ISO) |
Example row
{
"dedupe_key": "smartlead:sl_evt_88291",
"lead_id": 1042,
"ingested_at": "2026-06-16T18:03:12Z"
}Enrichment and attributes
Clay imports, custom fields, tags, and LinkedIn connection state per sender profile.
lead_personalization
Key-value custom fields on leads (Clay columns, API attributes, etc.).
| Field | Type | Description |
|---|---|---|
| lead_id | INTEGER | FK to leads.id (PK part) |
| field_name | TEXT | Attribute key (PK part) |
| field_value | TEXT | Attribute value |
| field_date | TEXT | Optional date associated with value |
| source_hash | TEXT | Hash of source row for change detection |
| processed_at | TEXT | When field was last written (ISO) |
| cloud_pending | INTEGER | 1 if awaiting cloud sync |
Example row
{
"lead_id": 1042,
"field_name": "icp_tier",
"field_value": "A",
"field_date": null,
"source_hash": "clay_row_99102",
"processed_at": "2026-06-01T10:00:00Z",
"cloud_pending": 0
}company_personalization
Key-value custom fields on companies.
| Field | Type | Description |
|---|---|---|
| company_id | INTEGER | FK to companies.id (PK part) |
| field_name | TEXT | Attribute key (PK part) |
| field_value | TEXT | Attribute value |
| field_date | TEXT | Optional date |
| source_hash | TEXT | Source row hash |
| processed_at | TEXT | Last written (ISO) |
| cloud_pending | INTEGER | 1 if awaiting cloud sync |
Example row
{
"company_id": 88,
"field_name": "tech_stack",
"field_value": "Salesforce, NetSuite",
"field_date": null,
"source_hash": "clay_co_4410",
"processed_at": "2026-06-01T10:00:00Z",
"cloud_pending": 0
}workspace_lead_linkedin_status
LinkedIn connection state per lead, workspace, and sender profile (HeyReach, Prosp).
| Field | Type | Description |
|---|---|---|
| id | TEXT | Status row UUID |
| workspace_id | TEXT | FK to workspaces.id |
| lead_id | INTEGER | FK to leads.id |
| sender_profile | TEXT | LinkedIn sender account URL or ID |
| is_connected | INTEGER | 1 if connected |
| is_request_pending | INTEGER | 1 if invite pending |
| connected_at | TEXT | When connection was accepted (ISO) |
| request_sent_at | TEXT | When invite was sent (ISO) |
| updated_at | TEXT | Row updated (ISO) |
Example row
{
"id": "llis_6e7f8g9h",
"workspace_id": "ws_northstar",
"lead_id": 1042,
"sender_profile": "https://www.linkedin.com/in/alex-sender",
"is_connected": 1,
"is_request_pending": 0,
"connected_at": "2026-06-10T14:00:00Z",
"request_sent_at": "2026-06-08T09:30:00Z",
"updated_at": "2026-06-10T14:00:00Z"
}Deliverability
Email verification results and bounce tracking across senders and platforms.
lead_email_verification
Verification results from Prospeo, Icypeas, Clay, or bounce-driven updates.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Verification UUID |
| org_id | TEXT | Org UUID |
| lead_id | INTEGER | FK to leads.id |
| TEXT | Verified address | |
| status | TEXT | valid, invalid, catch_all, unknown |
| sub_status | TEXT | Provider-specific detail |
| source | TEXT | prospeo, icypeas, bounce, etc. |
| source_detail | TEXT | Provider response snippet |
| bounce_message | TEXT | SMTP bounce text if applicable |
| free_email | INTEGER | 1 if free provider (Gmail, etc.) |
| mx_found | INTEGER | 1 if MX records exist |
| smtp_provider | TEXT | Detected mail host |
| verified_at | TEXT | Verification time (ISO) |
| created_at | TEXT | Row created (ISO) |
Example row
{
"id": "lev_1x2y3z4a",
"org_id": "org_7f3a9c2e",
"lead_id": 1042,
"email": "jordan.lee@northstarlogistics.com",
"status": "valid",
"sub_status": "ok",
"source": "prospeo",
"source_detail": "smtp_check_passed",
"bounce_message": null,
"free_email": 0,
"mx_found": 1,
"smtp_provider": "Google Workspace",
"verified_at": "2026-05-12T14:25:00Z",
"created_at": "2026-05-12T14:25:00Z"
}bounce_events
Aggregated bounce records per lead and sender. Links back to events for forensics.
| Field | Type | Description |
|---|---|---|
| id | TEXT | Bounce row UUID |
| org_id | TEXT | Org UUID |
| lead_id | INTEGER | FK to leads.id |
| first_event_id | INTEGER | FK to first events.id |
| latest_event_id | INTEGER | FK to latest events.id |
| platform | TEXT | smartlead, instantly, etc. |
| sender_email | TEXT | Sending mailbox |
| lead_email | TEXT | Bounced recipient |
| bounce_type | TEXT | hard, soft, or unknown |
| bounce_message | TEXT | SMTP diagnostic |
| smtp_code | TEXT | SMTP status code |
| recipient_mx | TEXT | Recipient mail host |
| sender_mx | TEXT | Sender mail host |
| campaign_id | INTEGER | FK to campaigns.id |
| campaign_name | TEXT | Denormalized campaign name |
| workspace_id | TEXT | Workspace UUID |
| relay_id | TEXT | Internal ingest ID |
| occurrence_count | INTEGER | Times this bounce repeated |
| first_seen_at | TEXT | First bounce (ISO) |
| last_seen_at | TEXT | Most recent bounce (ISO) |
| created_at | TEXT | Row created (ISO) |
| updated_at | TEXT | Row updated (ISO) |
Example row
{
"id": "be_9k8j7h6g",
"org_id": "org_7f3a9c2e",
"lead_id": 991,
"first_event_id": 97001,
"latest_event_id": 97001,
"platform": "instantly",
"sender_email": "outreach@agency-mail.com",
"lead_email": "bad-address@oldcorp.com",
"bounce_type": "hard",
"bounce_message": "550 5.1.1 User unknown",
"smtp_code": "550",
"recipient_mx": "oldcorp.com",
"sender_mx": "agency-mail.com",
"campaign_id": 22,
"campaign_name": "northstar | re-engage list",
"workspace_id": "ws_northstar",
"relay_id": "rly_88210",
"occurrence_count": 1,
"first_seen_at": "2026-06-15T11:22:00Z",
"last_seen_at": "2026-06-15T11:22:00Z",
"created_at": "2026-06-15T11:22:05Z",
"updated_at": "2026-06-15T11:22:05Z"
}Analytics views
Read-only SQL views applied on init and migrate. Not tables, but queryable like tables.
v_inbound_events_by_campaign
Pre-joined view of inbound events with campaign names. Faster reply and engagement queries.
| Field | Type | Description |
|---|---|---|
| event_id | INTEGER | events.id |
| lead_id | INTEGER | events.lead_id |
| event_type | TEXT | events.event_type |
| direction | TEXT | Always inbound in this view |
| channel | TEXT | email or linkedin |
| created_at | TEXT | Event timestamp |
| campaign_id | INTEGER | campaigns.id (nullable) |
| campaign_name | TEXT | campaigns.name (nullable) |
Example row
{
"event_id": 98231,
"lead_id": 1042,
"event_type": "email_reply",
"direction": "inbound",
"channel": "email",
"created_at": "2026-06-16T18:03:00Z",
"campaign_id": 14,
"campaign_name": "northstar | Q2 freight ops"
}Example SQL queries
Pair these with prompts from the agent prompts guide or ask your agent to run pipeline.py query presets.
Inbound engagement by campaign (last 48 hours)
SELECT c.name, e.event_type, COUNT(*) AS count
FROM events e
LEFT JOIN campaigns c ON e.campaign_id = c.id
WHERE c.name LIKE 'northstar |%'
AND e.created_at >= datetime('now', '-48 hours')
AND lower(coalesce(e.direction, '')) = 'inbound'
GROUP BY c.name, e.event_type
ORDER BY count DESC;Reply count by campaign (last 7 days)
SELECT c.name, COUNT(*) AS replies
FROM events e
LEFT JOIN campaigns c ON e.campaign_id = c.id
WHERE c.name LIKE 'northstar |%'
AND (
lower(e.event_type) IN ('email_reply', 'linkedin_reply')
OR (lower(e.direction) = 'inbound' AND lower(e.event_type) = 'email')
)
AND e.created_at >= datetime('now', '-7 days')
GROUP BY c.name
ORDER BY replies DESC;Recent timeline for one lead
SELECT event_type, direction, subject, created_at
FROM events
WHERE lead_id = 1042
ORDER BY created_at DESC
LIMIT 50;Workspace lead status with sentiment
SELECT l.name, l.email, wl.status, wl.current_status_sentiment, wl.last_activity_at
FROM workspace_leads wl
JOIN leads l ON l.id = wl.lead_id
WHERE wl.workspace_id = 'ws_northstar'
ORDER BY wl.last_activity_at DESC
LIMIT 25;Hard bounces this week by sender
SELECT sender_email, COUNT(*) AS hard_bounces
FROM bounce_events
WHERE bounce_type = 'hard'
AND last_seen_at >= datetime('now', '-7 days')
GROUP BY sender_email
ORDER BY hard_bounces DESC;Common questions
Where does Outreach Magic store my lead data?
In a local SQLite file on your machine (typically outreachmagic.db under the skill home). Webhooks route through our servers on the way in, but the pipeline database stays local. Your agent queries the file directly.
Which table should I query for replies and bounces?
Use the events table for reply rates, campaign breakdowns, and timelines. bounce_events aggregates hard and soft bounces per lead and sender. workspace_lead_events is an ingest audit log, not the full event volume.
How do workspaces relate to campaigns?
Each workspace is a client or brand partition. campaign_workspace_map routes platform campaign IDs or names to a workspace. Campaign names in the campaigns table often use a workspace prefix like northstar | campaign name.
Does every sequencer write the same event types?
Event types vary by platform (Smartlead, Instantly, HeyReach, PlusVibe, EmailBison, Prosp), but all normalize into the same events and leads tables. Check metadata_json on events for platform-specific fields.
Related resources
- Campaign Stats & Reporting
Multi-sequencer reports in Google Sheets or agent chat
- Agent Prompts & Workflows
Copy-paste prompts for daily digest, bounce analysis, and client snapshots
- For Agent Builders
Why local SQLite beats another hosted CRM for agent workflows
- Getting Started
Install the skill, connect webhooks, run your first query
Ready to query your pipeline?
Install the skill, connect a sequencer webhook, and ask your agent who replied today.