Solvice Maps: API Services Guide

API Architecture Overview

Solvice Maps provides a comprehensive suite of RESTful APIs designed for high-performance routing, distance calculations, and geospatial analysis. The API architecture is built around three core service categories, each optimized for specific use cases and performance requirements.

Base URL and Authentication

Production API Base URL:
https://routing.solvice.io
Staging API Base URL:
https://mapr-gateway-staging-181354976021.europe-west1.run.app
Authentication: All API requests require authentication via API key in the header:
X-API-Key: your-api-key-here
Content-Type: application/json

Core API Services

1. Route API - Turn-by-Turn Directions

Purpose: Generate detailed turn-by-turn directions with geometry between two or more points.

Single Route Calculation

Endpoint: POST /route Request Body:
{
  "coordinates": [
    [4.3517, 50.8503],  // Brussels (longitude, latitude)
    [2.3522, 48.8566]   // Paris
  ],
  "profile": "car",
  "options": {
    "steps": true,
    "geometries": "geojson",
    "overview": "full",
    "continue_straight": true
  }
}
Response:
{
  "routes": [
    {
      "geometry": {
        "type": "LineString",
        "coordinates": [[4.3517, 50.8503], ...]
      },
      "legs": [
        {
          "distance": 264.1,
          "duration": 87.9,
          "steps": [
            {
              "distance": 50.3,
              "duration": 12.1,
              "geometry": {
                "type": "LineString", 
                "coordinates": [[4.3517, 50.8503], ...]
              },
              "name": "Rue de la Loi",
              "maneuver": {
                "type": "turn",
                "modifier": "left",
                "location": [4.3517, 50.8503]
              }
            }
          ]
        }
      ],
      "distance": 264100,
      "duration": 8790,
      "weight": 8790
    }
  ],
  "waypoints": [
    {
      "hint": "...",
      "location": [4.3517, 50.8503],
      "name": "Rue de la Loi"
    }
  ]
}

Batch Route Processing

Endpoint: POST /route/batch Request Body:
{
  "requests": [
    {
      "coordinates": [[4.3517, 50.8503], [2.3522, 48.8566]],
      "profile": "car"
    },
    {
      "coordinates": [[2.3522, 48.8566], [3.0686, 50.6365]],
      "profile": "car"
    }
  ],
  "options": {
    "steps": false,
    "geometries": "geojson"
  }
}
Response:
{
  "routes": [
    {
      "success": true,
      "route": {
        "distance": 264100,
        "duration": 8790,
        "geometry": {...}
      }
    },
    {
      "success": true,
      "route": {
        "distance": 123400,
        "duration": 5420,
        "geometry": {...}
      }
    }
  ]
}

2. Table API - Distance Matrix

Purpose: Calculate travel times and distances between multiple origins and destinations.

Synchronous Table (Real-time)

Endpoint: POST /table/sync Use Case: Small matrices requiring immediate response (< 1000 coordinate pairs) Request Body:
{
  "sources": [
    [4.3517, 50.8503],  // Brussels
    [2.3522, 48.8566],  // Paris
    [3.0686, 50.6365]   // Lille
  ],
  "destinations": [
    [1.0952, 49.4431],  // Rouen
    [7.7521, 48.5734],  // Strasbourg
    [5.3698, 43.2965]   // Marseille
  ],
  "profile": "car",
  "annotations": ["duration", "distance"]
}
Response:
{
  "durations": [
    [6420, 12300, 25200],  // From Brussels
    [4320, 9840, 22680],   // From Paris
    [5280, 11400, 24120]   // From Lille
  ],
  "distances": [
    [324000, 567000, 1032000],  // From Brussels (meters)
    [256000, 487000, 923000],   // From Paris
    [298000, 534000, 978000]    // From Lille
  ],
  "sources": [
    {"hint": "...", "location": [4.3517, 50.8503]},
    {"hint": "...", "location": [2.3522, 48.8566]},
    {"hint": "...", "location": [3.0686, 50.6365]}
  ],
  "destinations": [
    {"hint": "...", "location": [1.0952, 49.4431]},
    {"hint": "...", "location": [7.7521, 48.5734]},
    {"hint": "...", "location": [5.3698, 43.2965]}
  ]
}

Asynchronous Table (Large datasets)

Endpoint: POST /table Use Case: Large matrices requiring background processing (> 1000 coordinate pairs) Request Body:
{
  "sources": [...], // Array of up to 10,000 coordinates
  "destinations": [...], // Array of up to 10,000 coordinates
  "profile": "car",
  "annotations": ["duration", "distance"],
  "engine": "osm",
  "fallback_speed": 50.0
}
Response:
{
  "id": "table_123456789",
  "status": "IN_PROGRESS",
  "created_at": "2024-01-15T10:30:00Z",
  "estimated_completion": "2024-01-15T10:35:00Z",
  "progress_url": "/table/123456789/progress",
  "result_url": "/table/123456789/response"
}

Monitor Table Progress

Endpoint: GET /table/{id}/progress Response:
{
  "id": "table_123456789",
  "status": "IN_PROGRESS",
  "progress": {
    "completed_requests": 45,
    "total_requests": 100,
    "percentage": 45.0,
    "estimated_completion": "2024-01-15T10:33:00Z"
  },
  "created_at": "2024-01-15T10:30:00Z",
  "updated_at": "2024-01-15T10:32:15Z"
}

Retrieve Table Results

Endpoint: GET /table/{id}/response Response: Same format as synchronous table response, but potentially much larger. For very large responses (> 10MB): Endpoint: GET /table/{id}/response/signed-url Response:
{
  "signed_url": "https://storage.googleapis.com/mapr-results/table_123456789.json?X-Goog-Algorithm=...",
  "expires_at": "2024-01-15T11:30:00Z",
  "size_bytes": 52428800,
  "content_type": "application/json"
}

3. Cube API - Time-Dependent Travel Matrix

Purpose: Generate travel time matrices across multiple time periods throughout the day.

Create Cube Request

Endpoint: POST /cube Request Body:
{
  "sources": [
    [4.3517, 50.8503],
    [2.3522, 48.8566]
  ],
  "destinations": [
    [1.0952, 49.4431],
    [7.7521, 48.5734],
    [5.3698, 43.2965]
  ],
  "profile": "car",
  "time_slices": [
    {"slice": 0, "time": "06:00"},
    {"slice": 1, "time": "08:00"},
    {"slice": 2, "time": "10:00"},
    {"slice": 3, "time": "12:00"},
    {"slice": 4, "time": "14:00"},
    {"slice": 5, "time": "16:00"},
    {"slice": 6, "time": "18:00"},
    {"slice": 7, "time": "20:00"}
  ],
  "day_type": "weekday",
  "generate_polynomials": true
}
Response:
{
  "id": "cube_987654321",
  "status": "IN_PROGRESS",
  "created_at": "2024-01-15T10:30:00Z",
  "time_slices": 8,
  "sources_count": 2,
  "destinations_count": 3,
  "total_tables": 8,
  "estimated_completion": "2024-01-15T10:45:00Z",
  "progress_url": "/cube/987654321/progress",
  "result_url": "/cube/987654321/response"
}

Monitor Cube Progress

Endpoint: GET /cube/{id}/progress Response:
{
  "id": "cube_987654321",
  "status": "IN_PROGRESS",
  "progress": {
    "completed_tables": 3,
    "total_tables": 8,
    "percentage": 37.5,
    "current_slice": 3,
    "estimated_completion": "2024-01-15T10:42:00Z"
  },
  "table_progress": [
    {"slice": 0, "status": "SUCCEEDED", "duration": 45.2},
    {"slice": 1, "status": "SUCCEEDED", "duration": 52.1},
    {"slice": 2, "status": "SUCCEEDED", "duration": 48.7},
    {"slice": 3, "status": "IN_PROGRESS", "progress": 0.6},
    {"slice": 4, "status": "PENDING"},
    {"slice": 5, "status": "PENDING"},
    {"slice": 6, "status": "PENDING"},
    {"slice": 7, "status": "PENDING"}
  ]
}

Retrieve Cube Results

Endpoint: GET /cube/{id}/response Response:
{
  "id": "cube_987654321",
  "status": "SUCCEEDED",
  "sources": [...],
  "destinations": [...],
  "time_slices": [
    {
      "slice": 0,
      "time": "06:00",
      "durations": [
        [6420, 12300, 25200],
        [4320, 9840, 22680]
      ],
      "distances": [
        [324000, 567000, 1032000],
        [256000, 487000, 923000]
      ]
    },
    // ... additional time slices
  ],
  "polynomials": {
    "duration_coefficients": [
      [
        // Polynomial coefficients for source 0 → destination 0
        [6420, 1200, -300, 50],  // a₀ + a₁t + a₂t² + a₃t³
        // Coefficients for source 0 → destination 1
        [12300, 2400, -600, 100],
        // ... more destinations
      ],
      // ... more sources
    ]
  },
  "created_at": "2024-01-15T10:30:00Z",
  "completed_at": "2024-01-15T10:43:22Z",
  "processing_duration": 802.3
}

Advanced Features

1. Request Splitting and Optimization

Automatic Request Splitting: The API automatically splits large requests that exceed routing engine limits:
  • OSRM: 1000 coordinates per request
  • TomTom: 1000 coordinates per request
  • AnyMap: 100 coordinates per request
  • Google Maps: 1000 coordinates per request
Split Strategy:
// Original request: 2000 sources × 1500 destinations = 3M combinations
{
  "sources": [...], // 2000 coordinates
  "destinations": [...] // 1500 coordinates
}

// Automatically split into 6 child requests:
// Child 1: 1000 sources × 1000 destinations
// Child 2: 1000 sources × 500 destinations  
// Child 3: 1000 sources × 1000 destinations
// Child 4: 1000 sources × 500 destinations
// etc.

2. Content-Based Caching

Cache Key Generation: The system generates cache keys based on request content, enabling efficient deduplication:
// These requests will use the same cached result:
{
  "sources": [[4.3517, 50.8503], [2.3522, 48.8566]],
  "destinations": [[1.0952, 49.4431], [7.7521, 48.5734]],
  "profile": "car"
}

{
  "sources": [[2.3522, 48.8566], [4.3517, 50.8503]], // Different order
  "destinations": [[7.7521, 48.5734], [1.0952, 49.4431]], // Different order
  "profile": "car"
}
Cache Benefits:
  • Immediate response for duplicate requests (< 10ms)
  • 60-80% cache hit rate for typical workloads
  • Significant cost reduction for repeated calculations

3. Multi-Engine Support

Engine Selection:
{
  "sources": [...],
  "destinations": [...],
  "engine": "osm",     // Explicitly specify engine
  "fallback_engine": "tomtom", // Fallback if primary fails
  "profile": "car"
}
Available Engines:
  • osm: OpenStreetMap/OSRM (free, good coverage)
  • tomtom: TomTom API (commercial, real-time traffic)
  • anymap: AnyMap service (European focus)
  • google: Google Maps API (premium coverage)

4. Time-Dependent Routing

Traffic Slice Selection:
{
  "sources": [...],
  "destinations": [...],
  "profile": "car",
  "traffic_slice": 2.5,  // Decimal slice (interpolated)
  "day_type": "weekday"   // "weekday" or "weekend"
}
Traffic Slice Mapping:
Slice 0:  06:00 (Early morning)
Slice 1:  07:00 (Morning commute start)
Slice 2:  08:00 (Peak morning traffic)
Slice 3:  09:00 (Late morning)
Slice 4:  10:00 (Mid-morning)
Slice 5:  11:00 (Pre-lunch)
Slice 6:  12:00 (Lunch hour)
Slice 7:  13:00 (Post-lunch)
Slice 8:  14:00 (Afternoon)
Slice 9:  15:00 (Pre-evening)
Slice 10: 16:00 (Evening commute start)
Slice 11: 17:00 (Peak evening traffic)
Slice 12: 18:00 (Late evening)

Error Handling

Standard Error Response Format

{
  "error": {
    "code": "INVALID_COORDINATES",
    "message": "One or more coordinates are invalid or unreachable",
    "details": {
      "invalid_coordinates": [
        {"index": 5, "coordinate": [0.0, 0.0], "reason": "Ocean location"}
      ]
    },
    "timestamp": "2024-01-15T10:30:00Z",
    "request_id": "req_123456789"
  }
}

Common Error Codes

Authentication Errors:
  • INVALID_API_KEY: API key is missing or invalid
  • RATE_LIMIT_EXCEEDED: Request rate limit exceeded
  • QUOTA_EXCEEDED: Monthly quota exceeded
Request Errors:
  • INVALID_REQUEST: Malformed request body
  • INVALID_COORDINATES: Invalid coordinate format or unreachable locations
  • REQUEST_TOO_LARGE: Request exceeds maximum size limits
  • INVALID_PROFILE: Unsupported transportation profile
Processing Errors:
  • ROUTING_ENGINE_ERROR: External routing engine failure
  • TIMEOUT: Request processing timeout
  • INTERNAL_ERROR: Unexpected server error
Resource Errors:
  • RESOURCE_NOT_FOUND: Requested table/cube ID not found
  • RESOURCE_EXPIRED: Results have expired and been deleted

Retry Logic

Recommended Retry Strategy:
import time
import random

def retry_with_backoff(func, max_retries=3):
    for attempt in range(max_retries):
        try:
            return func()
        except Exception as e:
            if attempt == max_retries - 1:
                raise e
            
            if e.status_code in [429, 502, 503, 504]:  # Retriable errors
                backoff = (2 ** attempt) + random.uniform(0, 1)
                time.sleep(backoff)
            else:
                raise e  # Don't retry client errors

Rate Limits and Quotas

Request Rate Limits

Standard Limits:
  • Authenticated requests: 1000 requests/minute
  • Table requests: 100 requests/minute
  • Cube requests: 10 requests/minute
Enterprise Limits:
  • Custom rate limits: Configurable per customer
  • Burst allowance: Handle traffic spikes
  • Priority queues: Faster processing for enterprise customers

Usage Quotas

Monthly Quotas:
  • Route calculations: Unlimited for standard plans
  • Table requests: Based on coordinate combinations
  • Storage: 30-day retention for results
Quota Headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 987
X-RateLimit-Reset: 1642251600
X-Quota-Limit: 1000000
X-Quota-Remaining: 876543
X-Quota-Reset: 1644843600

Performance Optimization

Request Optimization Tips

  1. Batch Similar Requests:
    // Instead of multiple single requests
    POST /route (request 1)
    POST /route (request 2)
    
    // Use batch endpoint
    POST /route/batch (both requests)
    
  2. Use Appropriate Endpoints:
    • Small tables (< 100 coords): Use /table/sync
    • Large tables (> 1000 coords): Use /table (async)
    • Time analysis: Use /cube for multiple time periods
  3. Leverage Caching:
    // Order coordinates consistently for better cache hits
    {
      "sources": [[2.3522, 48.8566], [4.3517, 50.8503]], // Sorted
      "destinations": [[1.0952, 49.4431], [7.7521, 48.5734]] // Sorted
    }
    
  4. Choose Optimal Engines:
    • Development/Testing: Use osm (free)
    • Production (Europe): Use anymap for best accuracy
    • Global Coverage: Use google or tomtom
    • Real-time Traffic: Use tomtom or google

Response Size Optimization

Large Response Handling:
  • Responses > 10MB automatically use signed URLs
  • Use compression for data transfer
  • Consider pagination for very large datasets
Selective Data Retrieval:
{
  "annotations": ["duration"], // Only duration, not distance
  "geometries": "false",        // Skip geometry data
  "steps": false               // Skip turn-by-turn steps
}

SDK and Integration Examples

JavaScript/Node.js

const SolviceMaps = require('@solvice/maps-sdk');

const client = new SolviceMaps({
  apiKey: 'your-api-key',
  baseURL: 'https://routing.solvice.io'
});

// Simple route
const route = await client.route.calculate({
  coordinates: [[4.3517, 50.8503], [2.3522, 48.8566]],
  profile: 'car',
  steps: true
});

// Distance matrix
const table = await client.table.calculate({
  sources: [[4.3517, 50.8503], [2.3522, 48.8566]],
  destinations: [[1.0952, 49.4431], [7.7521, 48.5734]],
  profile: 'car'
});

// Async table with polling
const largeTable = await client.table.calculateAsync({
  sources: largeSourceArray,
  destinations: largeDestinationArray,
  profile: 'car'
});

// Wait for completion
const result = await client.table.waitForCompletion(largeTable.id, {
  pollInterval: 5000, // 5 seconds
  timeout: 300000     // 5 minutes
});

Python

from solvice_maps import SolviceMapsClient

client = SolviceMapsClient(
    api_key='your-api-key',
    base_url='https://routing.solvice.io'
)

# Simple route
route = client.route.calculate(
    coordinates=[[4.3517, 50.8503], [2.3522, 48.8566]],
    profile='car',
    steps=True
)

# Distance matrix
table = client.table.calculate(
    sources=[[4.3517, 50.8503], [2.3522, 48.8566]],
    destinations=[[1.0952, 49.4431], [7.7521, 48.5734]],
    profile='car'
)

# Async table processing
large_table = client.table.calculate_async(
    sources=large_source_array,
    destinations=large_destination_array,
    profile='car'
)

# Poll for results
result = client.table.wait_for_completion(
    large_table.id,
    poll_interval=5,
    timeout=300
)

cURL Examples

Simple Route:
curl -X POST https://routing.solvice.io/route \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "coordinates": [[4.3517, 50.8503], [2.3522, 48.8566]],
    "profile": "car",
    "steps": true
  }'
Distance Matrix:
curl -X POST https://routing.solvice.io/table/sync \
  -H "X-API-Key: your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "sources": [[4.3517, 50.8503], [2.3522, 48.8566]],
    "destinations": [[1.0952, 49.4431], [7.7521, 48.5734]],
    "profile": "car",
    "annotations": ["duration", "distance"]
  }'
Check Progress:
curl -X GET https://routing.solvice.io/table/123456789/progress \
  -H "X-API-Key: your-api-key"
This comprehensive API guide provides all the technical details needed to effectively integrate with and utilize the Solvice Maps routing services.