REST API Reference
Admin OnlyBase URL: https://sogtracker.com/api/v1 · Version 1.0 · March 2026
Overview
The SOG Tracker REST API allows external systems to submit and retrieve performance metrics on behalf of a member company. It is designed for machine-to-machine integrations with accounting and field service platforms such as QuickBooks, ServiceTitan, and ConnectWise.
Authentication
Pass your API key as a Bearer token in every request:
Authorization: Bearer sog_yourprivatekeyhere Content-Type: application/json
Rate Limits
| Window | Limit | Response Header |
|---|---|---|
| Per minute | 60 requests | X-RateLimit-Remaining-Minute |
| Per hour | 500 requests | X-RateLimit-Remaining-Hour |
When exceeded, returns HTTP 429 with a Retry-After header (seconds to wait).
Response Format
All responses are JSON. Errors include an error string.
// Success
{ "success": true, "message": "Metrics saved successfully.", "data": { ... } }
// Error
{ "error": "Month must be between 1 and 12." }
| Code | Meaning |
|---|---|
200 | Success |
400 | Missing or invalid parameters |
401 | Invalid or missing API key |
404 | Record not found |
429 | Rate limit exceeded |
500 | Server error |
Endpoints
Health Check
curl -H "Authorization: Bearer sog_yourkey" https://sogtracker.com/api/v1/status
Submit Metrics
Required: month (1–12) and year. All other fields optional. KPIs are auto-calculated.
POST /api/v1/metrics
Authorization: Bearer sog_yourkey
Content-Type: application/json
{
"month": 3,
"year": 2025,
"revenue": 187500,
"cogs": 112000,
"billable_hours": 1240,
"gross_profit": 75500,
"total_num_employees": 14
}
Update Metrics (Partial)
Only the fields you include are changed. All others retain existing values. Returns 404 if the month doesn't exist yet — use POST first.
PUT /api/v1/metrics/2025/3
Authorization: Bearer sog_yourkey
Content-Type: application/json
{ "revenue": 195000, "cogs": 115000 }
List All Months
Optional query params: limit (default 24, max 120) and offset (default 0).
GET /api/v1/metrics?limit=12&offset=0
Latest Month
GET /api/v1/metrics/latest
Get Specific Month
GET /api/v1/metrics/2025/3
Input Field Reference
All fields are numeric. Omit fields your system doesn't track — KPIs are only calculated when their required inputs are present.
Gross Profit Margin
| Field | Description | Example |
|---|---|---|
revenue | Total revenue for the month | 187500 |
cogs | Cost of goods sold | 112000 |
billable_hours | Total billable hours delivered | 1240 |
gross_profit | Gross profit (revenue − COGS) | 75500 |
Sales Efforts
| Field | Description | Example |
|---|---|---|
quote_dollars_generated | Total value of quotes generated | 320000 |
num_unique_quotes | Number of unique quotes issued | 47 |
recurring_revenue_quoted | Recurring revenue included in quotes | 45000 |
num_months_quoted | Months of recurring revenue quoted | 12 |
Project Hours Variance
| Field | Description | Example |
|---|---|---|
actual_hours | Actual hours worked on projects | 1380 |
planned_hours | Originally planned project hours | 1300 |
num_billable_employees | Number of billable/field employees | 8 |
work_hours_per_week | Standard hours per week per employee | 40 |
weeks_in_period | Weeks in the reporting period | 4.33 |
Labor Efficiency
| Field | Description | Example |
|---|---|---|
total_num_employees | Total headcount | 14 |
total_labor_revenue | Revenue attributable to labor | 140000 |
Cash Management
| Field | Description | Example |
|---|---|---|
net_income | Net income for the month | 22000 |
non_cash_expenses | Depreciation and non-cash expenses | 3500 |
month_ending_balance | Bank balance at end of month | 185000 |
month_beginning_balance | Bank balance at start of month | 172000 |
accounts_receivable | Outstanding accounts receivable | 94000 |
num_days_in_month | Days in the reporting month | 31 |
cash_liquid_assets | Total liquid cash and near-cash assets | 210000 |
operating_expenses_cm | Operating expenses (cash management calc) | 68000 |
Expense Management
| Field | Description | Example |
|---|---|---|
operating_expenses_em | Operating expenses (expense ratio calc) | 68000 |
current_month_op_expenses | This month's operating expenses | 68000 |
previous_month_op_expenses | Prior month's operating expenses | 65000 |
budgeted_op_expenses | Budgeted operating expenses | 70000 |
Revenue Mix
| Field | Description | Example |
|---|---|---|
service_revenue | Revenue from service/repair work | 52000 |
recurring_revenue | Monthly recurring revenue | 38000 |
revenue_from_parts | Revenue from parts and materials | 21000 |
revenue_from_labor | Revenue from labor charges | 76500 |
Auto-Calculated KPIs
These are returned in calculated_kpis — you never submit them.
| KPI Field | Formula |
|---|---|
gross_profit_margin_pct | (Revenue − COGS) ÷ Revenue × 100 |
gross_profit_per_hour | (Revenue − COGS) ÷ Billable Hours |
hours_variance_pct | (Actual − Planned) ÷ Planned × 100 |
labor_utilization_pct | Billable Hours ÷ (Employees × Hrs/Wk × Weeks) × 100 |
gross_profit_per_employee | Gross Profit ÷ Total Employees |
cash_flow_operations | Net Income + Non-Cash + Change in Bank Balance |
avg_days_to_pay | (AR ÷ Revenue) × Days in Month |
cash_reserves_months | Liquid Assets ÷ Operating Expenses (CM) |
operating_expense_ratio_pct | Op Expenses (EM) ÷ Revenue × 100 |
expense_growth_rate_pct | (Current − Previous Op Expenses) ÷ Previous × 100 |
project_revenue_pct | Project Revenue ÷ Total Revenue Mix × 100 |
service_revenue_pct | Service Revenue ÷ Total Revenue Mix × 100 |
recurring_revenue_pct | Recurring Revenue ÷ Total Revenue Mix × 100 |
parts_to_labor_ratio | Parts Revenue ÷ Labor Revenue |
QuickBooks Integration
| SOG Tracker Field | QuickBooks Source | Report |
|---|---|---|
revenue | Total Income | P&L → Income total |
cogs | Total COGS | P&L → Cost of Goods Sold |
gross_profit | Gross Profit | P&L → Gross Profit line |
net_income | Net Income | P&L → Net Income |
operating_expenses_em | Total Expenses (below gross profit) | P&L → Expenses total |
current_month_op_expenses | Total Expenses (this period) | P&L current month |
previous_month_op_expenses | Total Expenses (prior period) | P&L prior month |
accounts_receivable | Accounts Receivable | Balance Sheet → A/R |
month_ending_balance | Bank balance (end of month) | Balance Sheet → end date |
month_beginning_balance | Bank balance (start of month) | Balance Sheet → start date |
cash_liquid_assets | Cash + Short-term Investments | Balance Sheet → Current Assets |
non_cash_expenses | Depreciation & Amortization | P&L → Expenses → Depreciation |
service_revenue | Service Income accounts | P&L → Income breakdown |
recurring_revenue | Monitoring/RMR income | P&L → Income breakdown |
revenue_from_parts | Parts/Materials Sales | P&L → Income breakdown |
revenue_from_labor | Labor/Installation income | P&L → Income breakdown |
ServiceTitan Integration
| SOG Tracker Field | ServiceTitan Source | Report / API |
|---|---|---|
revenue | Total Revenue | Revenue Report → Total |
cogs | Total Job Costs | Job Cost Report |
billable_hours | Tech Hours (billed) | Labor Report → Billable Hours |
actual_hours | Total Hours Worked | Payroll Report → Total Hours |
planned_hours | Estimated Job Hours | Job Report → Estimated Hours |
num_billable_employees | Active Technician Count | Technician List → Active |
total_num_employees | Total Active Employees | Employee Report → Active |
revenue_from_labor | Labor Revenue | Revenue Report → Labor |
revenue_from_parts | Material/Parts Revenue | Revenue Report → Materials |
service_revenue | Service Revenue | Revenue Report → Service |
recurring_revenue | Membership / Agreement Revenue | Membership Report → MRR |
quote_dollars_generated | Total Estimate Value | Estimate Report → Total Value |
num_unique_quotes | Estimates Sent | Estimate Report → Count |
ConnectWise Integration
| SOG Tracker Field | ConnectWise Source | Module / Report |
|---|---|---|
revenue | Total Invoiced Revenue | Finance → Invoice Report |
billable_hours | Billable Time Entries | Time → Time Entry → Billable |
actual_hours | All Time Entries | Time → Time Entry → Total |
planned_hours | Budget Hours on Projects | Project → Budget Report |
num_billable_employees | Active Billable Members | System → Member Report |
total_num_employees | Total Active Members | System → Member Report |
revenue_from_labor | Labor Invoice Revenue | Invoice Report → Labor |
revenue_from_parts | Product/Parts Invoice Revenue | Invoice Report → Products |
service_revenue | Service Ticket Revenue | Invoice Report → Service Board |
recurring_revenue | Agreement Revenue | Finance → Agreement Invoices |
quote_dollars_generated | Total Opportunity Value | Sales → Opportunity Report |
num_unique_quotes | Opportunities Created | Sales → Opportunity Report |
Example Integration Script
// sog-tracker-submit.js
const API_KEY = process.env.SOG_API_KEY; // Never hardcode keys
const BASE_URL = 'https://sogtracker.com/api/v1';
async function submitMonthlyMetrics(month, year, data) {
const response = await fetch(`${BASE_URL}/metrics`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ month, year, ...data })
});
if (!response.ok) {
const err = await response.json();
throw new Error(`SOG Tracker error: ${err.error}`);
}
const result = await response.json();
console.log('KPIs:', result.data.calculated_kpis);
return result;
}
submitMonthlyMetrics(3, 2025, {
revenue: 187500, cogs: 112000, gross_profit: 75500,
billable_hours: 1240, net_income: 22000,
accounts_receivable: 94000, num_days_in_month: 31,
month_ending_balance: 185000, month_beginning_balance: 172000,
cash_liquid_assets: 210000, operating_expenses_em: 68000,
current_month_op_expenses: 68000, previous_month_op_expenses: 65000,
total_num_employees: 14, service_revenue: 52000,
recurring_revenue: 38000, revenue_from_parts: 21000, revenue_from_labor: 76500,
});
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
401 Unauthorized | Invalid or revoked key | Generate a new key in Users tab → API Keys |
401 Keys begin with sog_ | Wrong key format | Use the full sog_... key, not the prefix |
404 on PUT | Month doesn't exist yet | Use POST first to create the record |
429 Too Many Requests | Rate limit exceeded | Check Retry-After header and wait |
KPIs showing null | Required input fields missing | Check field reference — each KPI needs specific inputs |
| Data not in dashboard | Key belongs to wrong company | Check GET /api/v1/status to verify company |