راه‌یارمستندات توسعه‌دهندگان
نسخه ۱ · v1

API نقشه راه‌یار

با این API می‌توانید نقشه ایران، جست‌وجوی بیش از ۴۰ هزار مکان، ژئوکد معکوس و کاشی‌های برداری را در برنامه خودتان استفاده کنید؛ بدون وابستگی به هیچ سرویس خارجی. همه داده‌ها از همین میزبان خوانده می‌شوند.

خودمیزبان

هیچ درخواستی به سرویس نقشه یا جست‌وجوی بیرونی ارسال نمی‌شود؛ داده از OpenStreetMap روی همین سرور است.

فارسی و راست‌به‌چپ

جست‌وجو با حروف فارسی و عربی، اعداد فارسی و نیم‌فاصله یکسان رفتار می‌کند و نام‌ها را فارسی برمی‌گرداند.

مناسب فلاتر

خروجی JSON ساده و CORS باز؛ کافی است با http درخواست بزنید و مکان تراکنش را ثبت کنید.

آدرس پایهآدرس پایه API همین میزبان است و به صورت /api/v1 در دسترس قرار دارد. نمونه‌های این صفحه به‌صورت خودکار با دامنه فعلی شما پر می‌شوند.

شروع در سه قدم

۱) آدرس پایه را بگیرید

GET/api/v1

این نشانی فهرست سرویس‌ها را برمی‌گرداند و بهترین راه برای بررسی درستی نصب است.

۲) یک جست‌وجوی نمونه اجرا کنید

curl "/api/v1/search?q=مشهد&limit=3"

۳) پاسخ را بخوانید

{
  "query": "مشهد",
  "count": 3,
  "results": [
    {
      "id": "iran-26038568",
      "name": "مشهد",
      "nameEn": "Mashhad",
      "kind": "city",
      "province": "خراسان رضوی",
      "coordinates": [59.60592, 36.29749],
      "distanceMeters": 0
    }
  ],
  "attribution": "© OpenStreetMap contributors, ODbL 1.0"
}
امتحان زنده

کلید API

استفاده عمومی از API بدون کلید هم ممکن است، اما ثبت کلید برای برنامه شما چند مزیت دارد: شناسایی مصرف، سقف روزانه قابل تنظیم و امکان مدیریت دسترسی در آینده.

روش ارسالنمونه
پارامتر آدرس?api_key=rahyar_...
هدر X-API-KeyX-API-Key: rahyar_...
هدر BearerAuthorization: Bearer rahyar_...

کلیدها با پیشوند rahyar_ شروع می‌شوند. کلید واقعی فقط یک‌بار، هنگام تأیید درخواست، نشان داده می‌شود و روی سرور فقط درهم‌سازی SHA-256 آن نگه داشته می‌شود.

درخواست کلید API
حالت اجباریمدیر میزبان می‌تواند با مقدار RAHYAR_REQUIRE_API_KEY=true کلید را برای همه فراخوانی‌های داده اجباری کند. در آن حالت درخواست بدون کلید با خطای ۴۰۱ پاسخ داده می‌شود.

دریافت یک مکان

GET/api/v1/places/{id}

شناسه‌ای که از جست‌وجو یا ژئوکد معکوس گرفته‌اید را جای {id} بگذارید.

curl "/api/v1/places/iran-26038568"

شناسه نامعتبر با 404 و بدنه place_not_found پاسخ داده می‌شود.

ژئوکد معکوس

GET/api/v1/reverse?lat=35.700&lon=51.390

مختصات را به نزدیک‌ترین مکان‌های نام‌دار تبدیل می‌کند. این سرویس برای برچسب‌گذاری مکان تراکنش یا هر رویداد مکانی مناسب است.

پارامترالزامیتوضیح
lat, lonبلهعرض و طول جغرافیایی.
radiusخیرشعاع جست‌وجو بر حسب متر؛ پیش‌فرض ۱۵۰، حداکثر ۵۰۰۰۰.
limitخیرتعداد نتایج ۱ تا ۵۰، پیش‌فرض ۵.
curl "/api/v1/reverse?lat=35.700&lon=51.390&radius=500"

نتایج بر اساس فاصله مرتب‌اند و هر مورد distanceMeters دارد. اگر در شعاع چیزی نباشد، results خالی است.

مکان‌های اطراف

GET/api/v1/nearby?lat=35.7&lon=51.39&radius=1000

فهرست مکان‌ها درون یک شعاع، قابل فیلتر با kind و مرتب‌شده بر اساس فاصله.

# دانشگاه‌های نزدیک در شعاع ۵ کیلومتر
curl "/api/v1/nearby?lat=35.7&lon=51.39&radius=5000&kind=university"

پوشش نقشه

GET/api/v1/coverage

محدوده جغرافیایی، سقف زوم و تعداد مکان‌ها را می‌دهد تا برنامه شما بداند کجا جزئیات خیابان وجود دارد.

فیلدمعنی
boundsمحدوده کشور به شکل [west,south,east,north].
maxZoomعمیق‌ترین زوم کاشی‌های برداری (۱۵).
plainMaxZoomزوم مجاز بیرون از مناطق دارای جزئیات (۱۳).
detailMaxZoomزوم مجاز داخل مناطق دارای جزئیات (۱۸).
detailAreasفهرست مستطیل‌هایی که داده خیابان و ساختمان دارند.
countsتعداد مکان‌های محلی، ملی و مجموع.

کاشی‌های برداری

GET/api/v1/tiles/{z}/{x}/{y}.mvt

کاشی‌های استاندارد Mapbox Vector Tile با کدگذاری gzip، از زوم ۰ تا ۱۵. لایه‌ها: roads, buildings, landuse, earth, water, places, pois.

این آدرس مستقیماً در MapLibre، OpenLayers و QGIS (با XYZ) قابل استفاده است و به کلاینت PMTiles نیاز ندارد. کاشی‌های خالی با 204 پاسخ داده می‌شوند.

const map = new maplibregl.Map({
  container: 'map',
  style: {
    version: 8,
    glyphs: '/fonts/{fontstack}/{range}.pbf',
    sprite: '/sprites/light',
    sources: {
      rahyar: {
        type: 'vector',
        tiles: ['/api/v1/tiles/{z}/{x}/{y}.mvt'],
        maxzoom: 15
      }
    },
    layers: []
  }
});

استایل آماده MapLibre

GET/api/v1/style.json

برای نمایش همان ظاهر نقشه راه‌یار، کافی است این نشانی را به‌جای آبجکت استایل بدهید:

const map = new maplibregl.Map({
  container: 'map',
  style: '/api/v1/style.json',
  center: [53.7, 32.4],
  zoom: 5
});

مسیریابی

GET/api/v1/route

مسیریابی در مرورگر و روی دستگاه کاربر انجام می‌شود، نه روی سرور. شبکه جاده تهران به تنهایی نزدیک به ۴۷۰ مگابایت حافظه PHP در هر درخواست نیاز دارد که میزبان اشتراکی نمی‌تواند تأمین کند.

این نشانی، مدل محاسبه و نشانی فایل‌های شبکه جاده را برمی‌گرداند. اگر مسیریابی سمت سرور لازم دارید، باید یک سرویس Node جدا راه‌اندازی کنید.

فایلکاربرد
/data/tehran-roads.json.gzشبکه کامل خیابان‌های تهران.
/data/iran-roads.json.gzشبکه بین‌شهری جاده‌های اصلی.

استفاده در فلاتر

برای ثبت مکان تراکنش‌ها، مختصات را ذخیره کنید و با ژئوکد معکوس نام مکان را بگیرید:

import 'dart:convert';
import 'package:http/http.dart' as http;

class RahyarApi {
  RahyarApi(this.baseUrl, {this.apiKey});
  final String baseUrl;      // مثلاً https://maps.example.com
  final String? apiKey;

  Future<Map<String, dynamic>> _get(String path) async {
    final uri = Uri.parse('$baseUrl/api/v1$path');
    final response = await http.get(uri, headers: {
      if (apiKey != null) 'X-API-Key': apiKey!,
    });
    if (response.statusCode != 200) {
      throw Exception('Rahyar API ${response.statusCode}: ${response.body}');
    }
    return jsonDecode(utf8.decode(response.bodyBytes)) as Map<String, dynamic>;
  }

  Future<List<dynamic>> search(String query) async {
    final body = await _get('/search?q=${Uri.encodeQueryComponent(query)}');
    return body['results'] as List<dynamic>;
  }

  // نام نزدیک‌ترین مکان به مختصات تراکنش
  Future<String?> labelFor(double lat, double lon) async {
    final body = await _get('/reverse?lat=$lat&lon=$lon&radius=500');
    final results = body['results'] as List<dynamic>;
    if (results.isEmpty) return null;
    return results.first['name'] as String?;
  }
}

برای نمایش نقشه در فلاتر می‌توانید از WebView با نشانی /?place={id} یا از style.json همین میزبان در maplibre_gl استفاده کنید.

خطاها

بدنه خطا همیشه JSON است و شامل کد ماشین‌خوان و توضیح فارسی:

{ "error": "invalid_api_key", "message": "کلید API معتبر نیست.", "api": "v1" }
کد HTTPمعنی
401کلید لازم است یا معتبر نیست (api_key_required, invalid_api_key).
403کلید غیرفعال شده (api_key_revoked).
404مسیر یا مکان پیدا نشد.
405متد مجاز نیست؛ فقط GET/HEAD/OPTIONS.
422پارامتر لازم نیست یا نامعتبر است.
429سقف روزانه کلید تمام شده (quota_exceeded).
503داده یا پیکربندی سرویس آماده نیست.

محدودیت‌ها و مجوز

  • داده مکان‌ها و کاشی‌ها از OpenStreetMap است و تحت مجوز ODbL 1.0 عرضه می‌شود. نمایش عبارت © OpenStreetMap contributors و پیوند به /data/NOTICE.txt الزامی است.
  • پاسخ‌ها ETag و Cache-Control دارند؛ برای کاهش بار، نتایج تکراری را کش کنید و درخواست شرطی با If-None-Match بفرستید.
  • CORS برای همه مبدأها باز است؛ در فلاتر وب و مرورگر نیازی به پروکسی نیست.
  • مسیرهای /coverage, /style.json و /route اطلاعاتی هستند و به کلید نیاز ندارند.
  • محدودیت روزانه پیش‌فرض هر کلید ۲۰ هزار درخواست است و مدیر می‌تواند آن را تغییر دهد.

پرسش‌های متداول

آیا برای استفاده باید کلید بگیرم؟

خیر، در حالت پیش‌فرض نه. کلید برای شناسایی مصرف و مدیریت بهتر است. مدیر میزبان می‌تواند آن را اجباری کند.

چرا مسیریابی به‌صورت HTTP نیست؟

چون شبکه جاده روی میزبان اشتراکی PHP در حافظه جا نمی‌شود. مسیریابی فعلی روی دستگاه کاربر و با همان داده محلی انجام می‌شود.

چطور مکان دقیق تراکنش را ذخیره کنم؟

مختصات lat/lon را همراه تراکنش نگه دارید و برای نمایش نام، /reverse را بزنید. شناسه مکان برگشتی را هم ذخیره کنید تا بعداً با /places/{id} جزئیات بگیرید.

آیا جست‌وجوی فارسی و عربی فرق می‌کند؟

نه؛ ی و ک عربی، اعداد فارسی و نیم‌فاصله در زمان جست‌وجو یکسان‌سازی می‌شوند.