Overview
Sales — Last 7 Days
| Day | Total Sales | Refunded | Completed | Info Needed |
|---|
Sales — By Month
| Month | Total Sales | Refunded | Completed | Info Needed |
|---|
📈 EIN Campaign Analytics
| Rank | State | Known Leads | Partials | Checkout Abandoned | Gross Sales | Refunds | Net Sales | Checkout Conversion | Net Sales / Lead |
|---|
Financial Overview
| Date | Revenue | Spend | Profit | Margin |
|---|
| Payout Date | Est. Amount | Status |
|---|
Payouts are estimates and may vary.
| Category | Amount | Date | Repeats | In Range | Vendor | Note |
|---|
All Leads
| Date | Name / Email | Phone | State | Stage | Source | Campaign | Form % | IP | Device | Actions |
|---|
StepsTracker
The lists we went out to, as opposed to the leads that came in. Drop a day's CSVs here — the
filename says which state and which day, so ar0831-ready.csv and
ar0831-ready-2.csv both file themselves under Arkansas on the 31st. Every number is
matched against the CRM on the phone number, so a file can be judged on the sales it produced
rather than on how many rows it had.
Yesterday's list again, minus everyone who bought, everyone on the blacklist, and every number that was in the day's files twice. A sale counts from the moment the lead reaches Paid, Pending Info, Need Info, Completed, Refunded, Reversal or Error — the same set the Dashboard calls Total Sales — so someone who paid this morning is already out of tonight's send.
By state
| State | Leads | Sold | Rate | Left |
|---|
By carrier
| Carrier | Leads | Sold | Rate | Left |
|---|
Files
| Day | State | File | Rows | Sold | Rate | Left to send | Dropped | Uploaded |
|---|
Automatic Notifications
Notify your team by email when a lead hits a trigger. These go to internal recipients — not to the lead.
Click Tracker
🔗 How to send clicks here
Parameters: m = message label, b = business, u = destination URL (only your own domains allowed), cid = optional custom click id.
Latest Clicks
| Time | Msg | Business | IP | Location | ISP | Device | Browser | Click ID |
|---|
Merchant Gateways
Every product needs at least one live gateway. Weights are relative shares inside a product — 70 and 30 split traffic 70/30, and so do 7 and 3. Set a weight to 0 or flip a gateway off to pull it out of rotation without losing the link.
Your funnel fetches this and picks a gateway itself — no key needed, and it changes the moment you save a weight here.
/api/merchants/config
Live response
{}
Picking a gateway on the front end
const cfg = await fetch('/api/merchants/config').then(r => r.json());
const p = cfg.products[serviceType]; // 'standard' | 'extended'
// One random draw, one winner — the ranges already encode the weights.
const r = Math.random() * p.total_weight;
const gateway = p.gateways.find(g => r >= g.range_start && r < g.range_end) || p.gateways[0];
window.location = gateway.url; // gateway.merchant tells you who took it
Stripe Reconciliation
Every succeeded Stripe charge in the range against every CRM lead in a sales stage (Paid, Pending Info, Need Info, Completed, Refunded, Reversal, Error), dated the same way the Dashboard dates a sale. Anything that exists on one side and not the other is listed below. Nothing here changes a stage — the only write is Link, which records the Stripe id on the lead.
| Issue | Stripe | CRM lead | What to check | |
|---|---|---|---|---|
| Pick a range to run the reconciliation. | ||||
User Management
Create and remove CRM logins, and choose which of them need an emailed code to sign in. Only administrators can see this tab.
Two-factor sign-in fails closed: if this email cannot be delivered, an account with 2FA on cannot sign in at all. Prove delivery here before switching it on for anyone.
Roles & Permissions
A role is a set of permissions. Every protected route checks them on each request, so what you switch off here is refused by the server — not just hidden in the interface.
Activity Log
Every change to a lead, its notes and its documents — who made it, when, and what moved. Entries are append-only: nothing in the CRM edits or removes them, and deleting a lead leaves its history behind. Automated postbacks are recorded too; use People only to see just what staff did.
| When | Who | Action | Lead | Details |
|---|
API Documentation
Postback Endpoint
Send a POST request to create or update a lead. Matches by lead_id first, then email.
/api/postback
Headers
Content-Type: application/json
x-api-key: YOUR_API_KEY (optional when API_KEY=changeme)
Body Fields
| Field | Type | Description |
|---|---|---|
| lead_id | string | Optional. Reuse existing lead UUID to update it. |
| string | Used for dedup if lead_id not provided. | |
| first_name | string | |
| last_name | string | |
| phone | string | |
| company | string | |
| stage | string | One of the pipeline stages below. |
| source | string | e.g. "google", "facebook" |
| domain | string | Landing page domain |
| campaign | string | Campaign name or ID |
| utm_source | string | |
| utm_medium | string | |
| utm_campaign | string | |
| utm_term | string | |
| utm_content | string | |
| referrer | string | Full referrer URL |
| ip_address | string | |
| user_agent | string | |
| browser | string | e.g. "Chrome 124" |
| device_type | string | "desktop" / "mobile" / "tablet" |
| form_completion_percent | number | 0–100 |
| form_fields_completed | number | |
| form_fields_total | number | |
| custom_data | object | Any extra key/value pairs |
| force_stage | boolean | true = allow going backwards in stage |
Pipeline Stages (in order)
Example — Form Started
curl -X POST http://localhost:3000/api/postback \
-H "Content-Type: application/json" \
-d '{
"email": "john@example.com",
"first_name": "John",
"stage": "Form Started",
"source": "google",
"domain": "myeinregistry.com",
"campaign": "llc-spring-2026",
"utm_source": "google",
"utm_medium": "cpc",
"utm_campaign": "llc-spring-2026",
"ip_address": "192.168.1.1",
"browser": "Chrome 124",
"device_type": "desktop",
"form_completion_percent": 10,
"form_fields_total": 12
}'
Example — Application Submitted
curl -X POST http://localhost:3000/api/postback \
-H "Content-Type: application/json" \
-d '{
"email": "john@example.com",
"stage": "Application Submitted",
"form_completion_percent": 100,
"form_fields_completed": 12,
"form_fields_total": 12
}'
Order Status Endpoint
Look up an order's fulfillment status by order number — for your funnel or a customer "track my order" page. Authenticated by API key.
/api/order-status?order=ORD-AB12CD
When status is Completed, the response also includes the delivery_date and the document file_location (currently a placeholder URL).
Example — Completed order
curl "http://localhost:3000/api/order-status?order=ORD-AB12CD" \
-H "x-api-key: YOUR_API_KEY"
{
"found": true,
"order_number": "ORD-AB12CD",
"status": "Completed",
"completed": true,
"last_updated": "2026-07-15T18:30:00.000Z",
"delivery_date": "2026-07-15T18:30:00.000Z",
"ein_number": "12-3456789",
"file_location": "https://myeinregistry.com/documents/ORD-AB12CD"
}
Other Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/order-status | Order status by number. Query: order (API key auth) |
| GET | /api/leads | List leads. Query: stage, search, source, campaign, from, to, page, limit |
| GET | /api/leads/:id | Get single lead + stage history |
| PUT | /api/leads/:id | Edit lead fields (admin). Body: any of email, first_name, last_name, phone, company, order_number, payment_transaction, ein_number, source, domain, campaign, utm_*, notes |
| PUT | /api/leads/:id/stage | Manually update stage. Body: {"stage": "Paid"} |
| DELETE | /api/leads/:id | Delete lead |
| GET | /api/finance | Financial overview: revenue and fees from Stripe, spend from the expense ledger. Query: from, to, refresh (admin) |
| GET | /api/finance/expenses | Expense ledger; POST/PUT/DELETE to manage it. Query: from, to (admin) |
| GET | /api/analytics | Dashboard analytics |
| GET | /api/merchants/config | Checkout routing map per product. Query: product (no key needed) |