> ## Documentation Index
> Fetch the complete documentation index at: https://maps.solvice.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Api services guide

# 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:

```http theme={null}
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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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:**

```json theme={null}
// 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:

```json theme={null}
// 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:**

```json theme={null}
{
  "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:**

```json theme={null}
{
  "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

```json theme={null}
{
  "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:**

```python theme={null}
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:**

```http theme={null}
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:**
   ```json theme={null}
   // 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:**
   ```json theme={null}
   // 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:**

```json theme={null}
{
  "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

```javascript theme={null}
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

```python theme={null}
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:**

```bash theme={null}
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:**

```bash theme={null}
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:**

```bash theme={null}
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.
