The Lockstep VM backend is a FastAPI application. Every route below is mounted under the
global prefix /api/v1 (API_V1_PREFIX in app/core/config.py), and each router adds
its own sub-prefix on top of that. The paths in the tables are the full paths a client
calls.
Authentication
Except for POST /api/v1/auth/register, POST /api/v1/auth/login, and the public invite
lookup/accept endpoints, every route depends on get_current_user. That dependency accepts
either a Better Auth session cookie or a legacy Authorization: Bearer <JWT> token.
POST /api/v1/auth/bridge-token swaps a Better Auth cookie for a short-lived legacy JWT so
older localStorage-based components keep working.
Tenant scoping
Every authenticated request carries a tenant_id (plus user_id, email, role). All
data access is filtered by tenant_id, so a tenant only ever sees its own devices,
vulnerabilities, integrations, and uploads. Admin-only actions (invites, member management,
org settings) additionally check role in {admin, owner}.
Common integration pattern
The endpoint integrations — SentinelOne, Intune, Rapid7, ConnectWise Automate,
and Entra — all follow the same lifecycle contract. Wherever you see one of these,
the others expose the equivalent route:
| Method | Path suffix | Purpose |
|---|
| GET | /config | Read stored config (secrets redacted) |
| POST | /config | Store/replace credentials for this tenant |
| DELETE | /config | Remove config (and usually the synced data) |
| POST | /test-connection | Validate stored credentials with a live API call |
| POST | /sync | Kick off a background sync job |
| GET | /sync-status | Poll the current sync job status |
| GET | /stats | Summary counts for the integration |
Most of these also expose /devices (or /assets//users), /apps, and a
/device-by-name/{name} lookup used by the asset-detail page.
auth (/api/v1/auth)
| Method | Path | Purpose |
|---|
| POST | /api/v1/auth/register | Register a new user (rate-limited 5/min) |
| POST | /api/v1/auth/login | Exchange email/password for an access token (10/min) |
| GET | /api/v1/auth/me | Current signed-in user record |
| POST | /api/v1/auth/refresh | Issue a fresh access token |
| POST | /api/v1/auth/bridge-token | Swap a Better Auth cookie for a legacy JWT |
tenant (/api/v1/tenant)
| Method | Path | Purpose |
|---|
| GET | /api/v1/tenant/me | Current-tenant summary for the signed-in user |
| PATCH | /api/v1/tenant/me | Update org name / notification email / timezone (admin) |
| GET | /api/v1/tenant/members | List tenant members (Better Auth + legacy, deduped) |
| PATCH | /api/v1/tenant/members/{member_id} | Change a member’s role (admin) |
| DELETE | /api/v1/tenant/members/{member_id} | Remove a member from the tenant (admin) |
invites (/api/v1/invites)
| Method | Path | Purpose |
|---|
| POST | /api/v1/invites | Create + email a team invite (admin, 20/hour) |
| GET | /api/v1/invites | List invites this user issued (admins see all tenant invites) |
| GET | /api/v1/invites/{token} | Public: verify an invite token and pre-fill signup |
| POST | /api/v1/invites/{token}/accept | Public: stamp tenant/role on a freshly signed-up user |
| DELETE | /api/v1/invites/{invite_id} | Revoke a pending invite (admin) |
inventory (/api/v1/inventory)
| Method | Path | Purpose |
|---|
| POST | /api/v1/inventory/upload | Upload a software-inventory CSV (processed in background) |
| GET | /api/v1/inventory/uploads | List inventory uploads |
| GET | /api/v1/inventory/uploads/{upload_id} | Get one upload’s status/details |
| GET | /api/v1/inventory/applications | List applications (search/vendor filter, paginated) |
| POST | /api/v1/inventory/applications/search | Structured query-builder search over applications |
| GET | /api/v1/inventory/applications/{app_id} | Get one application |
| GET | /api/v1/inventory/stats | Inventory stats (apps, devices, vendors, vulns) |
| GET | /api/v1/inventory/items | Inventory items for a device or application |
| GET | /api/v1/inventory/vendors | Distinct vendors with device/app/CVE counts |
| GET | /api/v1/inventory/apps-list | Distinct app names with device + CVE counts (autocomplete) |
devices (/api/v1/devices)
| Method | Path | Purpose |
|---|
| GET | /api/v1/devices/items | List inventory items (paginated, searchable) |
| GET | /api/v1/devices/devices | Unique devices across all sources (Intune + S1 + more) |
| POST | /api/v1/devices/devices/search | Structured query-builder search over assets |
| GET | /api/v1/devices/device/{device_id} | Device detail by Intune device UUID |
| GET | /api/v1/devices/by-name/{device_name} | Device detail by device name |
| GET | /api/v1/devices/stats | Device stats per integration collection |
| GET | /api/v1/devices/by-application/{application_name} | Distinct devices with a given app installed |
vulnerabilities — scan router (/api/v1/vulnerabilities)
The scan router is mounted at /vulnerabilities alongside the vulnerabilities router.
| Method | Path | Purpose |
|---|
| POST | /api/v1/vulnerabilities/scan-device | Trigger a vulnerability scan for all apps on a device |
| GET | /api/v1/vulnerabilities/scans/{scan_id} | Get results of a specific scan |
vulnerabilities (/api/v1/vulnerabilities)
| Method | Path | Purpose |
|---|
| POST | /api/v1/vulnerabilities/scan | Start a vulnerability scan |
| GET | /api/v1/vulnerabilities/scans | List vulnerability scans |
| GET | /api/v1/vulnerabilities/scans/{scan_id} | Get one scan |
| GET | /api/v1/vulnerabilities/scans/{scan_id}/vulnerabilities | Vulnerabilities found in a scan |
| GET | /api/v1/vulnerabilities/scans/{scan_id}/vulnerabilities/{cve_id}/devices | Devices affected by a CVE in a scan |
| GET | /api/v1/vulnerabilities/ | List vulnerabilities |
| GET | /api/v1/vulnerabilities/cve/{cve_id}/devices | All devices affected by a given CVE |
| GET | /api/v1/vulnerabilities/stats | Vulnerability summary statistics |
research (/api/v1/research)
| Method | Path | Purpose |
|---|
| GET | /api/v1/research/cve/{cve_id} | Research a specific CVE |
| GET | /api/v1/research/product | Research a product |
| GET | /api/v1/research/history | Research history |
reports (/api/v1/reports)
Mounted from reports_enhanced.py.
| Method | Path | Purpose |
|---|
| GET | /api/v1/reports/ | List generated reports for the tenant |
| POST | /api/v1/reports/generate | Generate a new report in the background |
| GET | /api/v1/reports/{report_id}/status | Report generation status |
| GET | /api/v1/reports/{report_id}/download | Download a generated report |
| DELETE | /api/v1/reports/{report_id} | Delete a report and its file |
versions (/api/v1/versions)
| Method | Path | Purpose |
|---|
| GET | /api/v1/versions/summary | Version summary |
| GET | /api/v1/versions/compliance | Version compliance |
| GET | /api/v1/versions/outdated | Outdated software |
integrations (/api/v1/integrations)
| Method | Path | Purpose |
|---|
| POST | /api/v1/integrations/credentials | Store credentials for a platform |
| GET | /api/v1/integrations/credentials/{platform} | Get stored credentials for a platform |
| GET | /api/v1/integrations/ | List configured integrations |
| DELETE | /api/v1/integrations/credentials/{platform} | Delete a platform’s credentials |
subscriptions (/api/v1/subscriptions)
| Method | Path | Purpose |
|---|
| GET | /api/v1/subscriptions/ | List subscriptions with CVE counts + last-sync |
| POST | /api/v1/subscriptions/ | Subscribe to a vendor/product and pull CVEs from NVD |
| DELETE | /api/v1/subscriptions/by-name/{sub_type}/{name} | Delete a subscription by type + name |
| DELETE | /api/v1/subscriptions/{subscription_id} | Delete a subscription by id |
| GET | /api/v1/subscriptions/check | Check whether something is subscribed |
| POST | /api/v1/subscriptions/sync | Pull latest NVD CVEs for all active subscriptions |
| GET | /api/v1/subscriptions/cves/search | Search NVD for vendor/product CVEs and save them |
| GET | /api/v1/subscriptions/activity | Recent CVE activity for subscribed vendors/products |
| GET | /api/v1/subscriptions/cpe/search | Search the NVD CPE dictionary (paginated) |
| Method | Path | Purpose |
|---|
| GET | /api/v1/tags/ | List tags for the tenant |
| POST | /api/v1/tags/ | Create a tag |
| PUT | /api/v1/tags/{tag_id} | Update a tag |
| DELETE | /api/v1/tags/{tag_id} | Delete a tag and its assignments |
| POST | /api/v1/tags/{tag_id}/assign | Assign a tag to a CVE |
| DELETE | /api/v1/tags/{tag_id}/assign/{cve_id} | Remove a tag from a CVE |
| GET | /api/v1/tags/entity/bulk | All tag assignments for a given entity type |
| POST | /api/v1/tags/entity/assign | Assign a tag to a vendor/product/CVE by name |
| DELETE | /api/v1/tags/entity/unassign | Remove a tag from a vendor/product/CVE |
| GET | /api/v1/tags/entity/{entity_type}/{entity_name} | Tags for a vendor/product/CVE |
| GET | /api/v1/tags/cve/{cve_id} | Tags assigned to a specific CVE |
weaknesses (/api/v1/weaknesses)
| Method | Path | Purpose |
|---|
| GET | /api/v1/weaknesses/ | List CWE weaknesses with real CVE counts |
| GET | /api/v1/weaknesses/{cwe_id} | CWE detail including associated CVEs |
projects (/api/v1/projects)
| Method | Path | Purpose |
|---|
| GET | /api/v1/projects/ | List projects for the tenant |
| POST | /api/v1/projects/ | Create a project |
| GET | /api/v1/projects/{project_id} | Get a project |
| PUT | /api/v1/projects/{project_id} | Update a project |
| DELETE | /api/v1/projects/{project_id} | Delete a project |
| POST | /api/v1/projects/{project_id}/vendors/{vendor_name} | Add a vendor to a project |
| DELETE | /api/v1/projects/{project_id}/vendors/{vendor_name} | Remove a vendor from a project |
| POST | /api/v1/projects/{project_id}/products/{product_name} | Add a product to a project |
| DELETE | /api/v1/projects/{project_id}/products/{product_name} | Remove a product from a project |
| GET | /api/v1/projects/{project_id}/vulnerabilities | CVEs matching a project’s vendors/products |
sentinelone (/api/v1/sentinelone)
Follows the common integration pattern.
| Method | Path | Purpose |
|---|
| POST | /api/v1/sentinelone/config | Store SentinelOne API credentials |
| GET | /api/v1/sentinelone/config | Get config (token redacted) |
| DELETE | /api/v1/sentinelone/config | Remove config + synced data |
| POST | /api/v1/sentinelone/test-connection | Test stored credentials |
| POST | /api/v1/sentinelone/sync | Kick off a background sync |
| GET | /api/v1/sentinelone/sync-status | Current sync job status |
| GET | /api/v1/sentinelone/devices | List synced S1 agents |
| GET | /api/v1/sentinelone/threats | List synced S1 threats |
| GET | /api/v1/sentinelone/stats | Integration summary stats |
| GET | /api/v1/sentinelone/apps | S1 installed apps aggregated by name |
| GET | /api/v1/sentinelone/device-by-name/{computer_name} | Agent + threats + apps by computer name |
| GET | /api/v1/sentinelone/device/{agent_id} | Single agent with threats and apps |
connectwise (/api/v1/connectwise)
ConnectWise PSA — ticketing and configuration management.
| Method | Path | Purpose |
|---|
| GET | /api/v1/connectwise/status | Check ConnectWise connection status |
| POST | /api/v1/connectwise/auto-config | Persist env-var credentials into DB config |
| GET | /api/v1/connectwise/companies | List companies (clients) |
| GET | /api/v1/connectwise/service/boards | List service boards |
| GET | /api/v1/connectwise/service/tickets/recent | List recent service tickets |
| POST | /api/v1/connectwise/config | Configure the PSA integration |
| GET | /api/v1/connectwise/tickets | List tickets |
| POST | /api/v1/connectwise/tickets | Create a service ticket |
| POST | /api/v1/connectwise/sync | Sync recent tickets |
| GET | /api/v1/connectwise/boards | List available service boards |
| GET | /api/v1/connectwise/priorities | List ticket priorities |
| GET | /api/v1/connectwise/service/tickets/{ticket_id}/full | Full ticket detail (live + cache) |
| GET | /api/v1/connectwise/service/tickets/{ticket_id}/notes | Ticket notes |
| POST | /api/v1/connectwise/service/tickets/{ticket_id}/notes | Add a ticket note |
| GET | /api/v1/connectwise/service/tickets/{ticket_id}/configurations | Linked configurations (assets) |
| POST | /api/v1/connectwise/service/tickets/{ticket_id}/configurations | Link a configuration to a ticket |
| DELETE | /api/v1/connectwise/service/tickets/{ticket_id}/configurations/{config_id} | Unlink a configuration |
| GET | /api/v1/connectwise/service/tickets/{ticket_id}/timeentries | Ticket time entries |
| POST | /api/v1/connectwise/service/tickets/{ticket_id}/time | Log a time entry |
| PATCH | /api/v1/connectwise/service/tickets/{ticket_id} | Patch a ticket (JSON Patch) |
| GET | /api/v1/connectwise/configurations | Search company configurations (devices/assets) |
| GET | /api/v1/connectwise/service/tickets/{ticket_id}/scheduleentries | Ticket schedule entries |
| POST | /api/v1/connectwise/tickets/from-vuln | Create a ticket from vulnerability data |
| GET | /api/v1/connectwise/service/tickets/{ticket_id}/context | Analyst context (CVE, inventory, S1) |
| GET | /api/v1/connectwise/bulk-pull/status | Status of the most recent bulk-pull job |
| GET | /api/v1/connectwise/bulk-tickets | List locally-stored bulk-pulled tickets |
| GET | /api/v1/connectwise/bulk-tickets/export.csv | Export matching bulk tickets as CSV |
| GET | /api/v1/connectwise/bulk-tickets/{ticket_id}/notes | Notes for a bulk-pulled ticket |
| POST | /api/v1/connectwise/bulk-pull | Start a background bulk pull of a board |
connectwise-automate (/api/v1/connectwise-automate)
ConnectWise Automate (RMM). Follows the common integration pattern.
| Method | Path | Purpose |
|---|
| POST | /api/v1/connectwise-automate/config | Store Automate credentials |
| GET | /api/v1/connectwise-automate/config | Get config (secrets redacted) |
| DELETE | /api/v1/connectwise-automate/config | Remove config + synced data |
| GET | /api/v1/connectwise-automate/clients | List Automate clients (companies) to scope ingestion |
| POST | /api/v1/connectwise-automate/test-connection | Test stored credentials |
| POST | /api/v1/connectwise-automate/sync | Kick off a background sync |
| GET | /api/v1/connectwise-automate/sync-status | Current sync job status |
| GET | /api/v1/connectwise-automate/stats | Integration summary stats |
| GET | /api/v1/connectwise-automate/device-by-name/{device_name} | Automate record for one asset (asset-detail) |
| GET | /api/v1/connectwise-automate/devices | List synced devices |
csv-sources (/api/v1/csv-sources)
Generic CSV-ingestion hub. {key} selects a registered source (e.g. autoelevate); each
source declares whether it targets device-enrichment or free-form records.
| Method | Path | Purpose |
|---|
| GET | /api/v1/csv-sources/ | List CSV sources (registry descriptors) with per-tenant stats |
| GET | /api/v1/csv-sources/{key} | Get one source descriptor + stats |
| POST | /api/v1/csv-sources/{key}/upload | Upload + process a CSV for a source |
| GET | /api/v1/csv-sources/{key}/uploads | List a source’s uploads |
| GET | /api/v1/csv-sources/{key}/uploads/{upload_id} | One upload’s job detail + sample rows + fill-rate |
| DELETE | /api/v1/csv-sources/{key}/data | Purge all ingested data for a source |
| GET | /api/v1/csv-sources/{key}/device-by-name/{device_name} | Source’s record for one asset (device-target) |
| GET | /api/v1/csv-sources/{key}/records | Preview parsed records (records-target) |
entra (/api/v1/entra)
Microsoft Entra ID. Follows the common integration pattern.
| Method | Path | Purpose |
|---|
| POST | /api/v1/entra/config | Store Entra credentials |
| GET | /api/v1/entra/config | Get config (secrets redacted) |
| DELETE | /api/v1/entra/config | Remove config + synced data |
| POST | /api/v1/entra/test-connection | Test stored credentials |
| POST | /api/v1/entra/sync | Kick off a background sync |
| GET | /api/v1/entra/sync-status | Current sync job status |
| GET | /api/v1/entra/stats | Integration summary stats |
| GET | /api/v1/entra/users | List synced Entra users |
| GET | /api/v1/entra/user/{upn} | Get one user (with linked devices) by UPN |
rapid7 (/api/v1/rapid7)
Rapid7 InsightVM. Follows the common integration pattern.
| Method | Path | Purpose |
|---|
| GET | /api/v1/rapid7/config | Get config (secrets redacted) |
| POST | /api/v1/rapid7/config | Store Rapid7 credentials |
| DELETE | /api/v1/rapid7/config | Remove config + synced data |
| POST | /api/v1/rapid7/test-connection | Test stored credentials |
| GET | /api/v1/rapid7/sync-status | Current sync job status |
| POST | /api/v1/rapid7/sync | Kick off a background sync |
| GET | /api/v1/rapid7/stats | Integration summary stats |
| GET | /api/v1/rapid7/assets | List synced Rapid7 assets |
| POST | /api/v1/rapid7/research-finding | Resolve a finding’s CVE via NVD lookup |
| GET | /api/v1/rapid7/findings/{asset_id} | Vulnerability findings for an asset |
| GET | /api/v1/rapid7/device-by-name/{hostname} | Rapid7 asset by hostname (full or short match) |
| GET | /api/v1/rapid7/apps | List Rapid7 apps |
threat-intel (/api/v1/threat-intel)
| Method | Path | Purpose |
|---|
| POST | /api/v1/threat-intel/config | Configure threat-intel integrations |
| GET | /api/v1/threat-intel/cve/{cve_id} | Threat intel for a CVE |
| GET | /api/v1/threat-intel/ip/{ip_address} | Threat intel for an IP address |
| GET | /api/v1/threat-intel/hash/{file_hash} | Threat intel for a file hash |
| GET | /api/v1/threat-intel/epss/high-risk | High-risk CVEs by EPSS score |
| POST | /api/v1/threat-intel/enrich/{cve_id} | Enrich a CVE from multiple sources |
| GET | /api/v1/threat-intel/research/{cve_id} | Comprehensive CVE research-panel data |
intune (/api/v1/intune)
Microsoft Intune. Follows the common integration pattern.
| Method | Path | Purpose |
|---|
| POST | /api/v1/intune/config | Store Azure app-registration credentials |
| GET | /api/v1/intune/config | Get config (secrets redacted) |
| DELETE | /api/v1/intune/config | Remove config + synced data |
| POST | /api/v1/intune/test-connection | Test stored credentials via Graph API |
| POST | /api/v1/intune/sync | Kick off a background sync |
| GET | /api/v1/intune/sync-status | Current sync job status |
| GET | /api/v1/intune/devices | List synced managed devices |
| GET | /api/v1/intune/apps | Deduplicated detected apps by device count |
| GET | /api/v1/intune/stats | Integration summary stats |
news-feeds (/api/v1/news-feeds)
Security RSS ingestion + AI classification.
| Method | Path | Purpose |
|---|
| GET | /api/v1/news-feeds/feeds | List configured feeds |
| POST | /api/v1/news-feeds/feeds | Add a feed |
| DELETE | /api/v1/news-feeds/feeds/{feed_id} | Delete a feed |
| POST | /api/v1/news-feeds/feeds/seed | Add all default security feeds |
| POST | /api/v1/news-feeds/feeds/refresh | Refresh all feeds and classify new items |
| POST | /api/v1/news-feeds/classify | Trigger AI classification for a batch of items |
| GET | /api/v1/news-feeds/items | List feed items |
| GET | /api/v1/news-feeds/items/stats | Feed-item stats |
| PUT | /api/v1/news-feeds/items/{item_id}/read | Mark an item read |
| PUT | /api/v1/news-feeds/items/{item_id}/assign | Assign an item |
| POST | /api/v1/news-feeds/items/{item_id}/classify | Force re-classify a single item |
advisories (/api/v1/advisories)
| Method | Path | Purpose |
|---|
| GET | /api/v1/advisories/search/cves | Partial-match search over CVE ids/descriptions |
| GET | /api/v1/advisories/search/apps | Partial-match search over application names |
| POST | /api/v1/advisories/draft | AI-draft advisory content for a CVE/app |
| POST | /api/v1/advisories/affected-users | Find users/devices with the affected apps installed |
| POST | /api/v1/advisories/send | Send advisory email(s) via Resend and record them |
| GET | /api/v1/advisories | List advisories |
| GET | /api/v1/advisories/{advisory_id} | Get one advisory |
dashboards (/api/v1/dashboards)
Configurable dashboards and widgets.
| Method | Path | Purpose |
|---|
| GET | /api/v1/dashboards | List dashboards |
| POST | /api/v1/dashboards | Create a dashboard |
| GET | /api/v1/dashboards/default | Get the user’s default dashboard |
| GET | /api/v1/dashboards/{dashboard_id} | Get a dashboard |
| PATCH | /api/v1/dashboards/{dashboard_id} | Update a dashboard |
| DELETE | /api/v1/dashboards/{dashboard_id} | Delete a dashboard |
| POST | /api/v1/dashboards/{dashboard_id}/clone | Clone a dashboard |
| POST | /api/v1/dashboards/{dashboard_id}/widgets | Add a widget |
| PATCH | /api/v1/dashboards/{dashboard_id}/widgets/{widget_id} | Update a widget |
| DELETE | /api/v1/dashboards/{dashboard_id}/widgets/{widget_id} | Delete a widget |
| POST | /api/v1/dashboards/widgets/{widget_id}/data | Evaluate a saved widget’s data source |
| POST | /api/v1/dashboards/widgets/preview | Evaluate an unsaved data source (editor preview) |
| GET | /api/v1/dashboards/catalog/metrics | Named metric catalog for the widget editor |
| GET | /api/v1/dashboards/catalog/widget-types | Supported widget types |