API Access

API Guide

Postman quick start: Download the Collection, import it into Postman, set base_url, user_name, and api_key variables, then submit a task and poll the result.

Download Postman Collection

1. Authentication

A. Direct API Access (YazRoute)

Include your username and API Key in the request headers:

  • X-User-Name: Your YazRoute account username
  • X-Api-Key: Your API Key (format: yrk_xxxxx...)

How to get an API Key: Sign in with a plan that includes API access, go to Account Center, and generate an API Key. The key is shown only once—save it securely.

B. Calling via RapidAPI

If you are using the API via RapidAPI, authentication is handled by the platform:

  • No need to provide X-User-Name or X-Api-Key headers.
  • RapidAPI will automatically include the necessary credentials via its proxy.

New solve submission limits vary by account plan and apply to the total number of new solve tasks submitted by the same user per minute; result polling is not counted. When the service is busy, the API may return 429 service_busy. Node count, vehicle count, solve time, and monthly quota vary by plan. See pricing page

Requests submitted through the direct YazRoute API (not RapidAPI) and successfully accepted into the queue are automatically written to Account Center history for later review and download.

2. Field Reference

Request Parameters

  • name (string, Optional): Request name (for identification)
  • objective (string, Optional): Optimization objective. Supported values: min_total_distance (minimize total driving distance) or min_total_cost (minimize total cost). Default is min_total_distance.
  • node_num (number, Required): Number of nodes, must be greater than 0
  • node_positions (array, Optional): Node coordinates: [[x1, y1], [x2, y2], ...]. If provided, distances are computed from coordinates; otherwise the distance matrix is used
  • vehicle_num (number, Required): Number of vehicles, must be greater than 0
  • distance_matrix (array, Required): Distance matrix, 2D array, distance_matrix[i][j] represents the distance from node i to node j
  • start_nodes (array, Required): Start node list for each vehicle, length is vehicle_num
  • end_nodes (array, Required): End node list for each vehicle, length is vehicle_num
  • node_demands (array, Required): Demand list for each node, length is node_num All depot nodes used in start_nodes / end_nodes must have demand 0.
  • vehicles_capacity (array, Required): Capacity list for each vehicle, length is vehicle_num
  • vehicle_fixed_costs (array, Optional): Fixed activation cost for each vehicle. Used only when objective=min_total_cost; in that case, the length must match vehicle_num and all values must be non-negative.
  • vehicle_unit_distance_costs (array, Optional): Unit distance travel cost for each vehicle. Used only when objective=min_total_cost; in that case, the length must match vehicle_num and all values must be non-negative.
  • node_time_windows (array, Optional): Time window per node: [[start1, end1], [start2, end2], ...] (in minutes), length is node_num
  • node_service_time (array, Optional): Service time per node (in minutes), length is node_num
  • vehicle_speeds (array, Optional): Speed list for each vehicle, length is vehicle_num
  • max_working_hours (number, Optional): Maximum daily working duration per vehicle (hours, positive number). This constraint takes effect only when time dimension inputs are enabled (node_time_windows, node_service_time, vehicle_speeds). Omit or leave empty for no limit.
  • base_start_time (array, Optional): Base start time, format: [hour, minute, second], default is [9, 0, 0]
  • time_limit_seconds (number, Optional): Caller-configurable max solve time (seconds). If omitted, the system automatically uses your plan default max_solve_time; if the value exceeds your plan limit, it will be capped by the plan limit.
  • late_penalty_per_min (number, Optional): Soft time window penalty cost (currency unit / minute). If provided and greater than 0, soft time windows are enabled: vehicles may arrive late, and each minute of lateness increases the objective by this penalty. When null or omitted, hard time windows (no late arrival allowed) are used. Only effective when node_time_windows, node_service_time, and vehicle_speeds are all provided.
  • callback_url (string, Optional): Webhook callback URL (must start with http:// or https://, max 2048 characters; must not point to localhost, private, or reserved IP addresses). If provided, the server will POST the result to this URL once solving completes; the payload format is identical to the polling success response. If omitted, poll the result endpoint instead.

Important: You can set time_limit_seconds yourself; if omitted, the system uses your plan default maximum solve time.

Webhook note: callback_url is optional. When provided, the server synchronously sends an HTTP POST upon solve completion (blocking the worker for at most 10 seconds), with a single attempt and no retries. Your callback endpoint should respond with 2xx within 10 seconds. If the callback times out or fails, the solve result is unaffected and you can still retrieve it via polling. Note: the callback blocks the worker for up to 10 seconds, so a fast response from your endpoint is recommended.

Response Fields

  • success (boolean): 请求是否成功
  • request_id (string): 请求唯一标识符
  • error (string|null): 错误信息(失败时存在)
  • code (string, optional): Machine-readable error code. For 429 responses, current values may include rate_limit_exceeded, service_busy, or monthly_quota_exceeded.
  • retry_after_seconds (number, optional): Suggested wait time in seconds. Currently returned mainly on 429 responses; 429 responses also set the HTTP Retry-After response header.

Submit endpoint (POST /api/v1/solve) returns:

  • result.status (string): Always accepted, meaning the task is accepted
  • result.phase (string): Always queued, meaning the task has entered the queue and is waiting.
  • result.message (string): Polling hint message

Result endpoint (GET /api/v1/solve/result/{request_id}) returns:

Polling requires any currently valid API Key under the same account; deleted, revoked, disabled, or expired keys cannot access the result.

  • result.status (string): processing means solving is still running
  • result.phase (string): Optional phase info (e.g., queued / solving) for finer progress display.
  • result.queue_depth (number|null): Returned when phase=queued, representing waiting tasks in queue (excluding currently running task).
  • result (object): 求解结果对象(成功时存在)
    • success (boolean): Solver-level flag; true when a feasible solution is found
    • error (string|null): Solver-level error message; null when successful
    • total_cost (number): 总成本/总距离
    • routes (object): 车辆路线字典,格式:{"Vehicle 0": [0, 1, 2, 0], "Vehicle 1": [0, 3, 4, 0], ...},其中 key 为车辆标识(如 "Vehicle 0"),value 为节点索引列表
    • distances (array): 每条被使用路线的总行驶距离数组(非字典)。长度与 routes 中有路线的车辆数一致;顺序与 routes 的 key 按车辆 id 升序排列一致(未使用的空车会被跳过,不出现在 routes 中)。例如 routes 含 "Vehicle 0"、"Vehicle 2" 时,distances[0] 对应 Vehicle 0,distances[1] 对应 Vehicle 2
    • loads (object): 每条路线各节点的累计载重字典,格式:{"Vehicle 0": [0, 10, 20, ...], "Vehicle 1": [0, 10, 30, ...], ...}
    • time_windows (object): 每条路线各节点的时间窗字典,格式:{"Vehicle 0": [['arrive1', 'leave1'], ['arrive2', 'leave2'], ...], ...},其中每个子列表包含到达时间和离开时间(格式:HH:MM:SS)
    • time (number): 求解耗时(秒)
    • request_id (string): Request identifier echoed in the solver result payload

关于 distances 与 routes:routes 按车辆 id 作为 key(如 "Vehicle 7"),distances 为普通数组;只有实际有路线的车辆会出现在 routes 中。读取 distances[i] 时,请取 routes 按车辆 id 升序后的第 i 个 key 所对应的路线距离,不要默认 distances[i] 一定对应 "Vehicle i"。

Note: task results are retained during the TTL window so clients can poll repeatedly; after the TTL expires, polling returns 404.

3. API Call Example

Note:

1. For users calling via RapidAPI, authentication is handled by RapidAPI. You do not need to provide X-User-Name and X-Api-Key headers.

2. The submit endpoint is asynchronous, so POST /api/v1/solve usually only needs a short client timeout; reserve longer time for polling or webhook handling if you need the final result.

3. Solve time is configurable: You can specify solve time via time_limit_seconds; if omitted, your plan max_solve_time is used by default.

4. This API is asynchronous: call POST /api/v1/solve to get request_id, then poll GET /api/v1/solve/result/{request_id} for final result.

5. During polling, use result.phase to distinguish queued vs solving; when queued, use result.queue_depth for queue depth.

请求示例

https://yazroute.com/api/v1/solve POST
Submit endpoint: POST https://yazroute.com/api/v1/solve
Result endpoint: GET https://yazroute.com/api/v1/solve/result/{request_id}
// 接口调用示例(API v1):
// - 先在「账户中心」生成 API Key(仅显示一次)
// - 请求头需携带用户名与 API Key

const userName = 'your_username';
const apiKey = 'your_api_key';

const payload = {
  name: 'input_data_sample',
  objective: 'min_total_cost',
  node_num: 6,
  node_positions: [],
  vehicle_num: 2,
  vehicle_fixed_costs: [100, 120],
  vehicle_unit_distance_costs: [1.2, 1.5],
  distance_matrix: [
    [0, 98, 60, 50, 61, 39],
    [94, 0, 67, 60, 36, 91],
    [11, 51, 0, 37, 62, 30],
    [19, 44, 91, 0, 55, 51],
    [27, 69, 75, 41, 0, 36],
    [80, 44, 62, 12, 73, 0]
  ],
  start_nodes: [0, 0],
  end_nodes: [0, 0],
  node_demands: [0, 10, 10, 10, 10, 10],
  vehicles_capacity: [100, 100],
  node_time_windows: [[0, 500], [0, 500], [0, 500], [0, 500], [0, 500], [0, 500]],
  node_service_time: [0, 2, 3, 4, 5, 6],
  vehicle_speeds: [30, 30],
  max_working_hours: 8,
  base_start_time: [9, 0, 0],
  // time_limit_seconds 可省略;省略时按当前套餐默认 max_solve_time 执行
  time_limit_seconds: 120,
  // late_penalty_per_min 可选(元/分钟);>0 时启用软时间窗,允许迟到并计入惩罚成本;省略或 null 时为硬时间窗
  // late_penalty_per_min: 10,
  // callback_url 可选;提供后服务器求解完成时会同步 POST 一次结果到该地址(最多阻塞 10 秒,不重试)
  // callback_url: 'https://your-server.com/webhook/vrp-result'
};

const response = await fetch('https://yazroute.com/api/v1/solve', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-User-Name': userName,
    'X-Api-Key': apiKey
  },
  body: JSON.stringify(payload)
});

// 解析提交响应(异步任务)
const submitData = await response.json();
if (!response.ok || !submitData.success) {
  console.error('提交失败:', submitData.error || submitData.detail);
  return;
}

const requestId = submitData.request_id;
let finalData = null;
const maxPollMs = 15 * 60 * 1000; // 最多轮询 15 分钟
const pollStart = Date.now();
const backoffMs = [2000, 3000, 5000]; // 推荐轮询退避:2s -> 3s -> 5s
let pollAttempt = 0;

// 轮询最终结果
while (true) {
  if (Date.now() - pollStart > maxPollMs) {
    console.error('轮询超时,请稍后重试。request_id:', requestId);
    break;
  }
  const pollResp = await fetch(`https://yazroute.com/api/v1/solve/result/${requestId}`, {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
      'X-User-Name': userName,
      'X-Api-Key': apiKey
    }
  });
  const pollData = await pollResp.json();
  if (!pollResp.ok) {
    console.error('轮询失败:', pollData.error || pollData.detail);
    break;
  }
  if (pollData.result && pollData.result.status === 'processing') {
    const phase = pollData.result.phase || 'processing';
    if (phase === 'queued') {
      console.log('排队中... queue_depth=', pollData.result.queue_depth);
    } else if (phase === 'solving') {
      console.log('计算中...');
    } else {
      console.log('处理中... phase=', phase);
    }
    const waitMs = backoffMs[Math.min(pollAttempt, backoffMs.length - 1)];
    pollAttempt += 1;
    await new Promise(resolve => setTimeout(resolve, waitMs));
    continue;
  }
  finalData = pollData;
  break;
}

if (finalData && finalData.success) {
  const result = finalData.result;
  console.log('总成本:', result.total_cost);
  console.log('求解时间:', result.time, '秒');
  console.log('路线数量:', Object.keys(result.routes).length);
  console.log('路线详情:', result.routes);
  for (const [vehicle, path] of Object.entries(result.routes)) {
    console.log(`${vehicle}:`, path);
  }
  console.log('距离列表:', result.distances);
  console.log('载重字典:', result.loads);
  console.log('时间窗:', result.time_windows);
} else {
  console.error('请求失败:', finalData?.error);
}

4. Response Data Example

成功响应

200 OK
// 提交成功响应(POST /api/v1/solve,HTTP 200):
{
  "success": true,
  "result": {
    "status": "accepted",
    "phase": "queued",
    "message": "Task accepted. Poll /api/v1/solve/result/{request_id} for completion."
  },
  "error": null,
  "request_id": "api_153ca66c55de4162"
}

// 轮询中响应(GET /api/v1/solve/result/{request_id},HTTP 200):
{
  "success": true,
  "result": {
    "status": "processing",
    "phase": "queued",
    "queue_depth": 3
  },
  "error": null,
  "request_id": "api_153ca66c55de4162"
}

// 轮询成功响应(GET /api/v1/solve/result/{request_id},HTTP 200):
{
  "success": true,
  "result": {
    "success": true,
    "error": null,
    "total_cost": 273,
    "routes": {
      "Vehicle 0": [1, 3, 0, 2],
      "Vehicle 1": [1, 4, 5, 2]
    },
    "distances": [139, 134],
    "loads": {
      "Vehicle 0": [0, 10, 20, 30, 40],
      "Vehicle 1": [0, 10, 20, 30, 40]
    },
    "time_windows": {
      "Vehicle 0": [
        ["09:00:00", "09:02:00"],
        ["11:02:00", "11:06:00"],
        ["11:44:00", "11:45:00"],
        ["13:45:00", "13:48:00"]
      ],
      "Vehicle 1": [
        ["09:00:00", "09:02:00"],
        ["10:14:00", "10:19:00"],
        ["11:31:00", "11:37:00"],
        ["13:41:00", "13:44:00"]
      ]
    },
    "time": 3.04,
    "request_id": "api_153ca66c55de4162"
  },
  "error": null,
  "request_id": "api_153ca66c55de4162"
}

错误响应

401/400/422/403/404/429

API 返回的错误信息均为英文,下方示例为实际返回格式。

// Authentication failed (401) - missing headers:
{
  "success": false,
  "error": "Missing X-User-Name or X-Api-Key header"
}

// Authentication failed (401) - invalid key:
{
  "success": false,
  "error": "Invalid username or API Key (or expired/revoked)"
}

// Authentication failed (401) - invalid RapidAPI proxy secret:
{
  "success": false,
  "error": "Invalid RapidAPI proxy secret"
}

// Exceeds plan limit (400):
{
  "success": false,
  "error": "Node count (20) exceeds plan limit (15). Please upgrade your plan"
}

// Validation failed (422):
{
  "success": false,
  "error": "Validation failed",
  "detail": [
    {
      "loc": ["body", "time_limit_seconds"],
      "msg": "time_limit_seconds must be a positive integer",
      "type": "value_error"
    }
  ]
}

// Validation failed (422) - depot demand must be 0:
{
  "success": false,
  "error": "Validation failed",
  "detail": [
    {
      "loc": ["body"],
      "msg": "Depot/start/end node 1 demand must be 0 (got 10)",
      "type": "value_error"
    }
  ]
}

// Forbidden (403) - plan does not support API access:
{
  "success": false,
  "error": "Your current plan does not support API access. Please upgrade your plan"
}

// Forbidden (403) - polling with a different account (request_id ownership mismatch):
{
  "success": false,
  "error": "No permission to access this request result"
}

// Too many requests (429) - rate limit:
{
  "success": false,
  "error": "Too many requests. Please try again later",
  "code": "rate_limit_exceeded",
  "retry_after_seconds": 60
}

// Too many requests (429) - service busy:
{
  "success": false,
  "error": "Service is busy. Current queue depth is 3. Please try again later",
  "code": "service_busy",
  "retry_after_seconds": 10
}

// Too many requests (429) - monthly quota:
{
  "success": false,
  "error": "Monthly API quota exceeded (500 requests). Please try again next month or upgrade your plan",
  "code": "monthly_quota_exceeded"
}

// Solve failed (HTTP 200, success: false):
{
  "success": false,
  "result": null,
  "error": "No feasible solution found. Please review your constraints",
  "request_id": "api_153ca66c55de4162"
}

// Result polling failed (404) - request id not found or expired:
{
  "success": false,
  "error": "Request id not found or expired"
}