Developer reference

RoutrIQ API

REST, versioned, predictable. Bearer tokens. Every response is { ok, data, error }.

Authentication

Every request carries Authorization: Bearer ROUTRIQ_API_KEY. Keys are scoped to a single organization and issued from Dashboard → API Keys. Revoke and rotate via /api/v1/auth/apikeys.

Core endpoints

POST   /api/v1/jobs                      — create or upsert a job
GET    /api/v1/jobs                      — list jobs for your org
POST   /api/v1/technicians               — create or upsert a technician
GET    /api/v1/technicians               — list active technicians
POST   /api/v1/dispatch/assign           — AI-score and assign a job
POST   /api/v1/dispatch/emergency        — emergency reroute (priority 1)
GET    /api/v1/dispatch/schedule         — day-view route plan
POST   /api/v1/prediction/duration       — estimate job completion time
GET    /api/v1/sla/at-risk               — jobs at risk of missing window
POST   /api/v1/simulation/run            — scenario modeler
POST   /api/v1/learning/run              — trigger weight retrain

FSM Integration endpoints

Native connectors for ServiceTitan, Jobber, and Housecall Pro. Each provider exposes the same three sync routes — credentials are stored encrypted per org.

POST   /api/v1/integrations/{provider}/sync               — pull jobs
POST   /api/v1/integrations/{provider}/sync-technicians   — pull roster
POST   /api/v1/integrations/{provider}/verify             — test credentials

# Providers: servicetitan | jobber | housecallpro

# Inbound webhooks (ServiceTitan):
POST   /api/v1/integrations/servicetitan/webhook          — HMAC-verified events

Explainable assignment response

Every assignment carries a scored breakdown of why that technician ranked #1. The weightsVersion pin means any decision can be replayed against the exact model that made it.

{
  "assignments": [
    {
      "technicianId": "4a7c...",
      "score": 87.4,
      "rank": 1,
      "reason": {
        "skill_match": 1.0,
        "distance_score": 0.88,
        "priority_weight": 1.0,
        "performance": 0.92,
        "availability": 1.0,
        "predicted_duration_minutes": 72,
        "delay_risk": 0.08
      },
      "weightsVersion": 14
    }
  ]
}

Integrations — credential format

Store credentials via POST /api/v1/integrations, then verify with the provider-specific verify route. Credentials are AES-256-GCM encrypted at rest.

# ServiceTitan
{ "provider": "servicetitan", "label": "Primary",
  "credentials": { "client_id": "...", "client_secret": "...",
                   "tenant_id": "...", "app_key": "..." } }

# Jobber
{ "provider": "jobber", "label": "Primary",
  "credentials": { "access_token": "...", "refresh_token": "..." } }

# Housecall Pro
{ "provider": "housecallpro", "label": "Primary",
  "credentials": { "api_token": "..." } }

Rate limits & errors

Burst: 60 requests / minute per API key (Upstash sliding window). Exceeding the limit returns 429 with a Retry-After header. All errors follow { ok: false, error: "snake_case_code" }.

Full OpenAPI spec at /openapi.yaml. Questions? support@routriq.com