Skip to content

Endpoint: Routing Policies ​

Manage routing policies that control how Veriprompt selects AI providers.

Endpoints ​

MethodPathDescription
GET/api/v1/routing/policiesList all policies
POST/api/v1/routing/policiesCreate a policy
GET/api/v1/routing/policies/:idGet a policy
PATCH/api/v1/routing/policies/:idUpdate a policy
DELETE/api/v1/routing/policies/:idDelete a policy
POST/api/v1/routing/policies/:id/simulateSimulate a policy

Authentication ​

All endpoints require a valid API key or session token. Session-authenticated users also need the matching routing policy permission:

  • routing.policies.view
  • routing.policies.create
  • routing.policies.edit
  • routing.policies.delete
http
Authorization: Bearer YOUR_API_KEY

List Policies ​

http
GET /api/v1/routing/policies

Response ​

json
{
  "success": true,
  "policies": [
    {
      "id": "clxyz123...",
      "name": "US Only Policy",
      "description": "Route to US providers only",
      "scope": "company",
      "isDefault": true,
      "policyJson": {
        "version": "routingPolicyV1",
        "strategy": "BALANCED",
        "geoFenceRules": {
          "allowedCountries": ["US"]
        }
      },
      "createdAt": "2025-01-15T10:00:00Z",
      "updatedAt": "2025-01-15T10:00:00Z"
    }
  ],
  "companyName": "Acme Corp"
}

Create Policy ​

http
POST /api/v1/routing/policies
Content-Type: application/json

Request Body ​

json
{
  "name": "Low Latency EU",
  "description": "Optimized for EU users",
  "scope": "company",
  "isDefault": false,
  "policyJson": {
    "version": "routingPolicyV1",
    "strategy": "LOWEST_LATENCY",
    "sanitization": {
      "mode": "manual",
      "allowedTriggers": ["prompt", "api", "user_action"],
      "sensitivityProfiles": ["personal_information"]
    },
    "hardConstraints": {
      "minAvailability": 0.95,
      "maxLatencyMs": 3000
    },
    "preferences": {
      "weights": {
        "latency": 0.5,
        "cost": 0.2,
        "quality": 0.2,
        "stability": 0.1
      }
    },
    "geoFenceRules": {
      "allowedRegions": ["EU"],
      "requireCompliance": ["GDPR"]
    },
    "providerGroups": [],
    "fallback": {
      "enabled": true,
      "maxRetries": 3,
      "retryDelayMs": 1000
    }
  }
}

Parameters ​

FieldTypeRequiredDescription
namestringYesPolicy name (unique per company)
descriptionstringNoHuman-readable description
scopestringYescompany, user, or prompt
isDefaultbooleanNoSet as default for scope
policyJsonobjectYesPolicy configuration

Policy JSON Schema ​

typescript
interface PolicyJson {
  version: "routingPolicyV1";
  name?: string;
  scope?: string;
  strategy: "BALANCED" | "LOWEST_COST" | "LOWEST_LATENCY" | "HIGHEST_QUALITY" | "ROUND_ROBIN";

  sanitization?: {
    mode: "disabled" | "automatic" | "manual";
    allowedTriggers?: Array<"prompt" | "api" | "user_action">;
    sensitivityProfiles?: string[];
  };

  hardConstraints?: {
    minAvailability?: number;  // 0-1, default 0.95
    maxLatencyMs?: number;     // milliseconds
    maxCostPerToken?: number;  // cost per token
  };

  preferences?: {
    weights?: {
      latency?: number;   // 0-1, default 0.25
      cost?: number;      // 0-1, default 0.25
      quality?: number;   // 0-1, default 0.25
      stability?: number; // 0-1, default 0.25
    };
  };

  geoFenceRules?: {
    allowedRegions?: string[];     // ["US", "EU", "UK", "APAC"]
    blockedRegions?: string[];
    allowedCountries?: string[];   // ["US", "DE", "UK"]
    blockedCountries?: string[];
    requireCompliance?: string[];  // ["GDPR", "SOC2", "HIPAA"]
  };

  providerGroups?: string[];  // Array of provider group IDs

  fallback?: {
    enabled?: boolean;      // default true
    maxRetries?: number;    // default 3
    retryDelayMs?: number;  // default 1000
  };
}

Sanitization Modes ​

  • disabled: the gateway never sanitizes for this policy.
  • automatic: every execution under the policy is sanitized before provider dispatch.
  • manual: sanitization only runs when the request explicitly triggers it and the trigger source is allowed.

Geofencing Validation (Strict) ​

On POST /api/v1/routing/policies and PATCH /api/v1/routing/policies/:id, geofencing arrays are validated against the company's active provider configuration baseline (ProviderModelConfig):

  • geoFenceRules.allowedCountries
  • geoFenceRules.blockedCountries
  • geoFenceRules.allowedRegions
  • geoFenceRules.blockedRegions

Baseline fields:

  • Countries from locationCountry
  • Regions from locationNetwork

If invalid values are submitted, the API returns 400.

Validation Error Example ​

json
{
  "error": "Invalid geofencing values. Countries/regions must match active provider configuration values for this company.",
  "details": [
    {
      "field": "allowedCountries",
      "invalidValues": ["GERMANY"],
      "allowedSample": ["US", "DE", "FR"],
      "allowedCount": 3
    }
  ]
}

Response ​

json
{
  "success": true,
  "policy": {
    "id": "clxyz456...",
    "name": "Low Latency EU",
    "description": "Optimized for EU users",
    "scope": "company",
    "isDefault": false,
    "policyJson": { ... },
    "createdAt": "2025-01-15T10:30:00Z",
    "updatedAt": "2025-01-15T10:30:00Z"
  }
}

Get Policy ​

http
GET /api/v1/routing/policies/:id

Response ​

json
{
  "success": true,
  "policy": {
    "id": "clxyz456...",
    "name": "Low Latency EU",
    ...
  }
}

Update Policy ​

http
PATCH /api/v1/routing/policies/:id
Content-Type: application/json

Request Body ​

Only include fields you want to update:

json
{
  "name": "Low Latency EU v2",
  "policyJson": {
    "strategy": "LOWEST_LATENCY",
    "hardConstraints": {
      "maxLatencyMs": 2000
    }
  }
}

Response ​

json
{
  "success": true,
  "policy": { ... }
}

Delete Policy ​

http
DELETE /api/v1/routing/policies/:id

Response ​

json
{
  "success": true,
  "message": "Policy deleted"
}

Simulate Policy ​

Test how a policy would route requests without executing them.

http
POST /api/v1/routing/policies/:id/simulate

Response ​

json
{
  "success": true,
  "policy": {
    "id": "clxyz456...",
    "name": "Low Latency EU"
  },
  "simulation": {
    "primary": {
      "provider": "anthropic",
      "model": "claude-3-sonnet",
      "estimatedLatency": 450,
      "estimatedCost": 0.000015,
      "qualityScore": 0.92,
      "availability": 0.998,
      "compositeScore": 0.87,
      "reasoning": "Best match for latency-optimized EU routing"
    },
    "fallbacks": [
      {
        "provider": "openai",
        "model": "gpt-4-turbo",
        "estimatedLatency": 620,
        "estimatedCost": 0.00003,
        "qualityScore": 0.95,
        "availability": 0.996,
        "compositeScore": 0.82
      }
    ],
    "totalCandidates": 8,
    "filteredOut": 3
  },
  "metadata": {
    "simulatedAt": "2025-01-15T10:45:00Z",
    "basedOnWindow": "24h"
  }
}

Task-aware simulation (optional request body) ​

Send a JSON body to see how the policy ranks for a task, with and without task-aware routing. An empty body behaves exactly as before. This endpoint (like /api/v1/routing/rank) is used by the policy editor and authenticates with the signed-in session; cookies.txt below stands for that session.

FieldTypeDescription
contentstring (max 20,000 characters)Sample request text, classified with the rule-based classifier only. No model is called, so a simulation costs nothing
taskCodesstring[] or comma-separated stringExplicit task codes (profile source EXPLICIT). Up to 20, each up to 64 characters
taskFit"policy" (default), "off", "on"policy follows the stored policy; off ranks without task fit; on is a what-if as if the policy had task fit enabled. Still subject to the company's package and the confidence threshold
bash
curl -X POST https://app.veriprompt.tech/api/v1/routing/policies/POLICY_ID/simulate \
  -b cookies.txt \
  -H "Content-Type: application/json" \
  -d '{ "content": "Review this contract for liability clauses", "taskFit": "on" }'

When content or taskCodes is sent, the response gains two top-level fields next to simulation (both null otherwise):

json
{
  "success": true,
  "simulation": { "...": "unchanged" },
  "taskProfile": {
    "codes": ["legal", "contract"],
    "dimensions": ["domain_legal", "long_context"],
    "confidence": 0.4,
    "source": "CLASSIFIED",
    "applied": false,
    "classifierVersion": "regex-v1",
    "notes": [ { "key": "taskFitExplainNoteRegex", "vars": {} } ]
  },
  "taskFit": {
    "mode": "on",
    "policyEnabled": false,
    "applied": false,
    "reason": "below-min-confidence",
    "summary": { "applied": false, "source": "CLASSIFIED", "codes": ["legal", "contract"], "dimensions": ["domain_legal", "long_context"], "confidence": 0.4 },
    "ranking": [ { "rank": 1, "provider": "anthropic", "model": "example-model", "compositeScore": 0.87, "qualityScore": 0.7, "taskFit": null, "explanations": [] } ],
    "taskFitOff": [ { "rank": 1, "provider": "anthropic", "model": "example-model", "compositeScore": 0.87, "qualityScore": 0.7, "taskFit": null, "explanations": [] } ],
    "rankChanges": [],
    "explanations": [ { "key": "taskFitExplainLowConfidence", "vars": { "confidence": 40 } } ]
  }
}
  • ranking is the order the runtime would produce under mode; taskFitOff is the same candidate set without task fit; rankChanges lists { provider, model, from, to } for every candidate whose position differs (empty when not applied).
  • applied: false carries a reason: policy-disabled, profile-not-applied, below-min-confidence, not-entitled (the company's package does not include task-fit routing) or mode-off.
  • Each ranked candidate has taskFit with legacyQualityScore, blendedQualityScore, perDimension and provenance (source is internal, external, manual or tier; benchmarks, asOf and n where applicable), and explanations as { key, vars } pairs.
  • A taskCodes or taskFit value of the wrong type returns 400.
  • Permission is the same as for any simulation; the policy must belong to your company.

Rank providers ​

http
POST /api/v1/routing/rank

Ranks providers for a policy. It accepts the same optional taskCodes and content fields as the simulation, and returns taskProfile and taskFit ({ applied, reason?, ...summary, explanations }) next to the existing result. Each ranked candidate carries its evidence provenance under taskFit when task fit applied. Both fields are null when no task fields were sent.

Policy JSON: preferences.taskFit ​

json
{
  "preferences": {
    "weights": { "quality": 0.4, "cost": 0.3, "latency": 0.2, "stability": 0.1 },
    "taskFit": {
      "enabled": true,
      "classifier": "gateway",
      "externalEvidence": "allow",
      "minInternalSamples": 30,
      "staleAfterDays": 120,
      "minConfidence": 0.5,
      "dimensionWeights": { "domain_legal": 2 }
    }
  }
}
FieldTypeDefaultDescription
enabledbooleanfalseMaster switch. Saving true requires the Task-Fit Routing package feature, otherwise 403 with code FEATURE_NOT_ENTITLED
classifier"off", "regex", "gateway""gateway"How the task is detected when not stated. gateway may send one short classification request through your own gateway path
externalEvidence"allow", "deny""allow"Whether third-party benchmarks may influence ranking
minInternalSamplesinteger 1 to 10000030Own evidence outranks external evidence from this many samples
staleAfterDaysinteger 1 to 3650120Older benchmark rows carry no weight
minConfidencenumber 0 to 10.5A detected task below this is recorded but not applied
dimensionWeightsobjectnonePer capability weight 0 to 10: coding, tool_use, reasoning, math, instruction_following, factuality, long_context, multilingual_de, writing, domain_legal, domain_medical, domain_finance, vision, general. Unknown keys are dropped

Out-of-range numbers are clamped rather than rejected. See Task-Aware Routing.


Strategy Values ​

ValueDescription
BALANCEDEqual weight to all factors
LOWEST_COSTPrioritize lowest cost providers
LOWEST_LATENCYPrioritize fastest providers
HIGHEST_QUALITYPrioritize highest quality output
ROUND_ROBINRotate between available providers

Geofencing Codes ​

Regions ​

US, EU, UK, APAC, LATAM, ME, AF

Countries ​

US, CA, UK, DE, FR, NL, IE, JP, AU, SG, IN, BR

Compliance Standards ​

GDPR, SOC2, HIPAA, ISO27001, PCI_DSS


Example: Create US-Only HIPAA Policy ​

bash
curl https://app.veriprompt.tech/api/v1/routing/policies \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "US Healthcare",
    "description": "HIPAA-compliant US-only routing",
    "scope": "company",
    "isDefault": false,
    "policyJson": {
      "version": "routingPolicyV1",
      "strategy": "HIGHEST_QUALITY",
      "hardConstraints": {
        "minAvailability": 0.99
      },
      "geoFenceRules": {
        "allowedCountries": ["US"],
        "requireCompliance": ["HIPAA", "SOC2"]
      },
      "fallback": {
        "enabled": true,
        "maxRetries": 3
      }
    }
  }'

Error Responses ​

400 Bad Request ​

json
{
  "error": "Invalid policy",
  "details": [
    { "path": ["name"], "message": "Required" }
  ]
}

401 Unauthorized ​

json
{
  "error": "Unauthorized"
}

404 Not Found ​

json
{
  "error": "Policy not found"
}

409 Conflict ​

json
{
  "error": "A policy with this name already exists"
}