NetOSField accessMenu
Signed in user unavailable
Documentation/API & Integrations
Download PDF

Xiber NetOS — API & Integrations Guide

REST API endpoints, MCP tools, and external system integration map.


REST API

SettingValue
Base URLhttp://localhost:8000/api/v1
Production Base URLhttps://netos.xiberian.net/api/v1
Docs (Swagger)https://netos.xiberian.net/docs-api/
OpenAPI Schemahttps://netos.xiberian.net/openapi.json
Content Typeapplication/json

Authentication

Browser users authenticate through Microsoft SSO. Machine users and coding agents should use NetOS API access tokens.

Use either header format:

Authorization: Bearer ntos_live_...

or:

X-NetOS-API-Key: ntos_live_...

API tokens are bound to an internal NetOS user. The token authenticates the machine, then NetOS applies that user's normal RBAC roles, scopes, and field-level permissions. Frontend visibility is irrelevant for machine access; backend permissions are still authoritative.

Development environments may also allow dev headers when ALLOW_DEV_AUTH=true:

x-user-email: dev@example.com
x-user-role: exec

Do not use dev headers in production.

Creating Machine Access Tokens

Only users with users_edit can create or revoke API tokens.

POST /api/v1/authz/api-tokens
{
  "user_id": "00000000-0000-0000-0000-000000000000",
  "name": "agent01 quote importer",
  "expires_at": "2026-09-01T00:00:00Z"
}

The response includes the full token once:

{
  "api_token_id": "11111111-1111-1111-1111-111111111111",
  "user_id": "00000000-0000-0000-0000-000000000000",
  "user_email": "agent-netos@xiber.net",
  "name": "agent01 quote importer",
  "token_prefix": "ntos_live_abcd...",
  "expires_at": "2026-09-01T00:00:00+00:00",
  "token": "ntos_live_full_secret_value_returned_once"
}

Store the token immediately in the calling system's secret manager. NetOS stores only a hash and cannot display the full token again.

List tokens:

GET /api/v1/authz/api-tokens

Revoke a token:

DELETE /api/v1/authz/api-tokens/{api_token_id}

Rotate a token:

POST /api/v1/authz/api-tokens/{api_token_id}/rotate

Rotation keeps the same token record but replaces the secret. The previous token stops working immediately, and the new token is returned once.

Machine Access Example

export NETOS_API_TOKEN='ntos_live_...'

curl -sS \
  -H "Authorization: Bearer $NETOS_API_TOKEN" \
  https://netos.xiberian.net/api/v1/authz/me

Prompt For Another Coding Agent

You are integrating with Xiber NetOS.

Base URL:
https://netos.xiberian.net/api/v1

API docs:
https://netos.xiberian.net/docs-api/

OpenAPI schema:
https://netos.xiberian.net/openapi.json

Authenticate every API request with:
Authorization: Bearer <NETOS_API_TOKEN>

The token is bound to an internal NetOS user. Do not try to bypass RBAC. If an endpoint returns 401 or 403, report the missing permission or authorization failure.

Useful endpoints:
- GET /authz/me
- GET /search
- GET /quotes
- POST /quotes/extract
- GET /quotes/drafts
- POST /quotes/drafts
- PATCH /quotes/drafts/{draft_id}
- POST /quotes/drafts/{draft_id}/reject
- POST /quotes/drafts/{draft_id}/commit
- POST /quotes
- POST /quotes/{quote_id}/documents
- POST /quotes/{quote_id}/documents/text
- POST /quotes/{quote_id}/documents/{document_id}/reanalyze
- GET /circuits
- GET /infrastructure
- GET /customers
- GET /rf-links
- GET /electrical-services

Vendor quote model:
- One quote represents one vendor/path/service.
- Term pricing is stored in pricing_options.
- NNI is a valid quote service type and represents an EVPL landing point.
- `target_type` identifies the quote scope. Use `circuit` for transport/path quotes with A and Z endpoints. Use values such as `infrastructure`, `tower`, `rooftop`, `datacenter`, `electrical`, `rf_link`, or `other` for single-site/service quotes that only need a target site/location.
- Quote attachments are stored on the quote record. Uploaded vendor PDFs, images, order forms, and proposals are analyzed in the background when an AI provider is configured; AI summaries and notes are searchable at low search priority.
- Pasted vendor emails or unstructured quote notes can be saved as text quote attachments through `POST /quotes/{quote_id}/documents/text`. NetOS persists the text as a quote document, preserves line breaks for later viewing, queues AI analysis, and includes the text/AI notes in search.
- Claude Desktop and other MCP users should create quote drafts, not committed quotes. NetOS users review drafts in Vendor Quotes -> Draft Inbox, edit the form, then commit or reject them.

Endpoints

Health Check

GET /healthz
{"status": "ok"}

No authentication required.


List Circuits

GET /api/v1/circuits

Query Parameters:

ParamTypeDescription
carrierstringFilter by carrier name
statusstringFilter by status enum
searchstringFull-text search across circuit label, carrier circuit ID, carrier name

Response: Array of circuit objects with nested carrier, contract, A endpoint, and Z endpoint data.

Example:

curl -H "x-user-role: exec" \
  "http://localhost:8000/api/v1/circuits?status=active&carrier=Lumen"

Get Circuit Detail

GET /api/v1/circuits/{circuit_id}

Response includes:

  • Circuit attributes (label, carrier circuit ID, service type, bandwidth, status, MRC, NRC)
  • Carrier details (name, NOC phone, portal URL)
  • Contract details (term dates, renewal type, ETF, escalator)
  • A and Z endpoints (name, address, coordinates)
  • Exact monitoring URL and generated monitoring search fallback
  • Provider portal URL
  • Lifecycle events (ordered by date)

Create Circuit

POST /api/v1/circuits

Requires: Write role (exec, finance, network_eng, operations, pm)

Request Body:

{
  "xiber_circuit_label": "XIB-LUM-0042",
  "carrier_circuit_id": "DHEC.123456",
  "carrier_name": "Lumen",
  "service_type": "wave",
  "bandwidth_mbps": 10000,
  "status": "active",
  "monitoring_url": "https://librenms.xiber.local/device/123",
  "mrc_usd": 2500.00,
  "nrc_usd": 5000.00,
  "a_endpoint_name": "Xiber HQ",
  "z_endpoint_name": "Cologix COL1"
}

The manual UI now uses Infrastructure and Customer site selectors for circuit A/Z locations. The REST API still accepts endpoint fields so imports and integrations can create endpoint snapshots. For attribution, creating a circuit is not enough by itself; create a subtended_links relationship to state which infrastructure asset is the upstream donor and which downstream structure or customer endpoint is served over that circuit.

For DIA and broadband services, NetOS treats the circuit as single-site and clears the Z endpoint.


Customer, RF Link, Electrical, and Attribution APIs

Customers

GET /api/v1/customers
POST /api/v1/customers
GET /api/v1/customers/{customer_id}
PATCH /api/v1/customers/{customer_id}
DELETE /api/v1/customers/{customer_id}

Customer records represent commercial and MFC customer sites. They can be selected by circuits, RF Links, and subtended links. Customer detail responses include associated circuits, RF Links, serving paths, inherited donor cost, customer revenue, attributed cost, and gross margin.

RF Links

GET /api/v1/rf-links
POST /api/v1/rf-links
PATCH /api/v1/rf-links/{rf_link_id}
DELETE /api/v1/rf-links/{rf_link_id}
POST /api/v1/rf-links/{rf_link_id}/documents

RF Links are built from existing infrastructure and customer sites. Links between two infrastructure assets are backhaul. Links from infrastructure to a customer site are customer endlinks. When a customer endlink is saved, NetOS synchronizes the matching subtended customer endpoint relationship so attribution can show RF transport.

RF System Catalog

GET /api/v1/rf-systems
POST /api/v1/rf-systems
PATCH /api/v1/rf-systems/{rf_system_id}
DELETE /api/v1/rf-systems/{rf_system_id}

RF systems define selectable defaults such as name, description, frequency used, capacity, cost, PTP/PtMP type, equipment role, and PtMP compatibility. PtMP source nodes must reference RF systems with role ptmp_base. PtMP customer RF Links must reference a subscriber/client RF system with role ptmp_subscriber; if the subscriber has compatible base system IDs, the selected PtMP source node's base system must be included.

Electrical Services

GET /api/v1/electrical-services
POST /api/v1/electrical-services
PATCH /api/v1/electrical-services/{electrical_service_id}
DELETE /api/v1/electrical-services/{electrical_service_id}
POST /api/v1/electrical-services/{electrical_service_id}/documents

Electrical services attach to exactly one Infrastructure or Customer site. They store provider, service type, account and meter numbers, voltage, amperage, phase, delivery location, service address, average monthly cost, start date, monitoring URL, notes, and supporting documents.

Infrastructure Subtended Links

POST /api/v1/infrastructure/{infrastructure_id}/subtended-links
PATCH /api/v1/infrastructure/{infrastructure_id}/subtended-links/{link_id}
DELETE /api/v1/infrastructure/{infrastructure_id}/subtended-links/{link_id}

Subtended links explicitly define the financial hierarchy. Use them to attach customer endpoints, downstream structures, existing circuits, or RF Links to a parent infrastructure asset. This is what drives the attribution tree, dashboard attribution cards, customer inherited-cost drilldowns, and infrastructure financial summaries.


Bulk Update Circuits

PATCH /api/v1/circuits/bulk

Requires: Write role (exec, finance, network_eng, operations, pm)

Request Body:

{
  "circuit_ids": ["8d8e4333-8182-4443-8e0d-f2307276db52"],
  "updates": {
    "status": "active",
    "carrier_name": "Lumen",
    "service_type": "dia",
    "mrc_usd": 1850.00,
    "nrc_usd": 0,
    "contract_term_end_date": "2027-12-31",
    "notes": "Updated through bulk action"
  }
}

Only fields included in updates are changed. Each affected circuit receives an audit entry.

Response:

{"updated": 1, "requested": 1}

Bulk Delete Circuits

POST /api/v1/circuits/bulk-delete

Soft-deletes circuits by setting deleted_at. Records remain available for audit and historical reporting.

Request Body:

{
  "circuit_ids": ["8d8e4333-8182-4443-8e0d-f2307276db52"]
}

Response:

{"deleted": 1, "requested": 1}

Map Data

GET /api/v1/circuits/map

Query Parameters:

ParamTypeDescription
carrierstringFilter by carrier
service_typestringFilter by service type enum
statusstringFilter by status enum
statestringFilter by endpoint state (US state)

Response:

{
  "circuits": [
    {
      "id": "uuid",
      "label": "XIB-LUM-0042",
      "carrier": "Lumen",
      "service_type": "wave",
      "bandwidth_mbps": 10000,
      "status": "active",
      "a_endpoint": {"name": "...", "lat": 39.96, "lng": -82.99},
      "z_endpoint": {"name": "...", "lat": 39.95, "lng": -83.00},
      "geometry": {"type": "LineString", "coordinates": [[-82.99, 39.96], [-83.00, 39.95]]}
    }
  ],
  "endpoints": [
    {
      "id": "uuid",
      "name": "Xiber HQ",
      "type": "pop",
      "geometry": {"type": "Point", "coordinates": [-82.99, 39.96]}
    }
  ],
  "infrastructure": [
    {
      "id": "uuid",
      "name": "Cologix COL1",
      "type": "data_center",
      "geometry": {"type": "Point", "coordinates": [-83.00, 39.95]}
    }
  ],
  "filters": {
    "carriers": ["Lumen", "Zayo", "Cogent"],
    "service_types": ["wave", "dia", "dark_fiber"],
    "statuses": ["active", "ordered"],
    "states": ["OH", "GA", "IL"]
  }
}

Dashboard Summary

GET /api/v1/dashboard/summary

Response includes:

SectionFields
kpistotal_circuits, active_circuits, infrastructure_count, circuit_mrc, facility_mrc, total_mrc, modeled_mrr, modeled_margin, renewal_window_count
spend_by_carrierArray of {carrier, mrc, circuit_count}
service_mixArray of {service_type, count}
state_mixArray of {state, count}
renewal_pipelineArray of {state, count}
margin_histogramArray of {bucket, count}
at_risk_circuitsArray of circuit summaries
top_expensiveArray of circuit summaries
lowest_marginArray of circuit summaries

Import Preview

POST /api/v1/imports/circuits/preview
Content-Type: multipart/form-data

Upload a CSV or XLSX file. Returns import job ID, detected column mapping, headers, sample rows, and validation summary.

Example:

curl -H "x-user-role: exec" \
  -F "file=@examples/sample_circuits.csv" \
  http://localhost:8000/api/v1/imports/circuits/preview

Import Commit

POST /api/v1/imports/circuits/{import_job_id}/commit

Commits all valid staged rows. Returns insert/update/invalid counts.

Example:

curl -H "x-user-role: exec" \
  -X POST \
  http://localhost:8000/api/v1/imports/circuits/{import_job_id}/commit

List Service Providers

GET /api/v1/service-providers

Returns carrier records with circuit count, infrastructure count, and total spend.


Get Service Provider

GET /api/v1/service-providers/{carrier_id}

Returns provider detail with related circuits and infrastructure assets.


List Infrastructure Assets

GET /api/v1/infrastructure

Returns infrastructure asset records with facility type, provider, costs, terms, and monitoring_url.


Bulk Update Infrastructure Assets

PATCH /api/v1/infrastructure/bulk

Request Body:

{
  "infrastructure_ids": ["ae30e22f-565d-46f3-be94-9d0e001a59de"],
  "updates": {
    "status": "active",
    "provider_name": "American Tower",
    "site_type": "tower",
    "mrc_usd": 2200.00,
    "price_escalator_pct": 3.0,
    "term_end_date": "2028-12-31",
    "notes": "Updated through bulk action"
  }
}

Only fields included in updates are changed. Each affected asset receives an audit entry.

Response:

{"updated": 1, "requested": 1}

Bulk Delete Infrastructure Assets

POST /api/v1/infrastructure/bulk-delete

Soft-deletes infrastructure assets by setting deleted_at.

Request Body:

{
  "infrastructure_ids": ["ae30e22f-565d-46f3-be94-9d0e001a59de"]
}

Response:

{"deleted": 1, "requested": 1}

Audit Activity

GET /api/v1/audit/activity

Returns recent request/write activity including user, role, IP, event type, action, entity, changed fields, and response status.


Feedback Queue

GET /api/v1/feedback
POST /api/v1/feedback
PATCH /api/v1/feedback/{feedback_id}
POST /api/v1/feedback/{feedback_id}/comments

Feedback requests support priority, status, and progress comments. Public comments attempt to notify the requester by email when SMTP is configured.


MCP Server

Location: apps/mcp/

The MCP server exposes NetOS data to XOS agents (ExecOS, department agents, Claude Desktop users).

Current Tools

The MCP server is intentionally a thin, permission-aware layer over the NetOS REST API. It does not read the database directly. API-token RBAC controls which rows and fields are returned.

ToolDescription
netos_auth_meVerify the configured NetOS API identity, roles, and permissions
search_netosUniversal search across inventory, sites, customers, documents, and providers
list_circuitsList wholesale circuits with optional API filters
get_circuitGet a circuit detail record
list_infrastructureList infrastructure sites, with simple client-side filters
get_infrastructure_contextGet full infrastructure context, relationships, economics allowed by RBAC, and compact document/photo metadata
list_customersList customer sites, with simple client-side filters
get_customer_contextGet customer context including contacts, access notes, service paths, and compact document/photo metadata
get_site_documentsReturn metadata, user notes, and AI summaries for site documents/photos
list_rf_linksList RF links, including PTP/PtMP path metadata
get_rf_linkGet one RF link by UUID via list filtering
list_quotesList vendor quotes using supported API filters
get_quoteGet quote detail, pricing options, and status history when permitted
quote_aggregationSite-level vendor quote aggregation for NNI/port planning signals
create_quote_draftCreate a vendor quote draft for human review without writing to quote history
list_quote_draftsList vendor quote drafts by review status
get_quote_draftGet one vendor quote draft by UUID
update_quote_draftCorrect a draft payload before review/commit
reject_quote_draftReject a duplicate, stale, or invalid draft with a reason
get_carrier_summaryProvider/carrier summary with circuit count, MRC totals, ETF exposure, contacts, portals, circuits, and infrastructure
get_renewal_pipelineCircuit and infrastructure renewal deadlines by state for a lookahead window
get_field_recordField-oriented context by kind: circuit, infrastructure, customer, or rf_link

Planned Tools

ToolDescription
get_circuit_plPer-circuit P&L with revenue attribution
get_outage_historyOutage events for a circuit
Write toolsCreate/update with explicit agent confirmation flow and audit trail

Authentication

Production MCP deployments should use a NetOS API token generated in Admin. Configure the MCP process with:

NETOS_API_BASE_URL=http://10.10.67.118:8010
NETOS_API_TOKEN=ntos_live_...

Use the protected internal API endpoint for machine clients. The public browser hostname https://netos.xiberian.net is fronted by Microsoft SSO through oauth2-proxy and will return an HTML sign-in page before NetOS can validate an API token.

Every MCP request is sent to the REST API with:

Authorization: Bearer <NETOS_API_TOKEN>

The token user's RBAC permissions determine what the tools can see. Financial fields, executive summaries, document metadata, and search results follow the same field-level masking rules as the REST API.

For local development only, the MCP server can fall back to trusted dev headers:

NETOS_MCP_AGENT_EMAIL=xos-agent@xiber.com
NETOS_MCP_AGENT_ROLE=agent

This fallback should not be used for production gateway access.

Registration with XOS Gateway

The MCP server should be registered with the Xiber MCP Gateway (gateway.xiberian.net) so it's available to all XOS agents and Claude Desktop users via the SSE bridge. This is not yet configured.


External System Integration Map

SystemDirectionPurposeStatus
SonarPullCustomer accounts, MRR, revenue attribution per circuitPlanned
Monday.comBidirectionalRenewal tasks, variance tasks, circuit order workflowPlanned
WisdmPullTower and network site geometry for map overlaysPlanned
LibreNMS / Prometheus / LokiPullUtilization data, outage detection, monitoring deep linksPlanned
DocuSealPushGenerate termination notices and contract execution envelopesPlanned
Microsoft 365 / Entra IDPullSSO, user identity, calendar/Teams/SharePoint referencesPlanned
XOS (MCP Gateway)ExposeAgent-readable circuit tools for automated reporting and decisionsSkeleton
Lumen Control CenterPullCircuit status sync from carrier portalNot started
Zayo TranzactPullCircuit status sync from carrier portalNot started
Cogent PortalPullCircuit status sync from carrier portalNot started

Planned Webhooks (Outbound)

EventTriggerDestination
circuit.installedCircuit status → activeMonday.com, Slack
circuit.decommissionedCircuit status → decommissionedMonday.com, Slack
renewal.state_changedRenewal state transitionMonday.com, Email, Slack
invoice.variance_detectedInvoiced MRC ≠ contracted MRCMonday.com (task for finance)

*Webhooks are not yet implemented.*