مرجع API

توثيق Naseem EIAQI API

أرسل بيانات المستشعرات وحلّل جودة الهواء واسترجع التقارير برمجياً.

نظرة عامة

يتيح Naseem EIAQI API لأنظمة إدارة المباني (BMS) وأجهزة الاستشعار وتطبيقات الطرف الثالث إرسال بيانات جودة الهواء الداخلي مباشرةً، وحساب مؤشر EIAQI تلقائياً، وتخزين البيانات بحيث تلتزم بمتطلبات DM-HSD-GU141-IAQI2 لبلدية دبي.

عنوان الـ Base URLhttps://naseem-eiaqi.com/api/v1
المصادقةAuthorization: Bearer nsm-...
حد المعدل100 طلب / دقيقة لكل مفتاح
التوقيتجميع الطوابع الزمنية بصيغة ISO 8601 UTC
الترميزJSON (Content-Type: application/json)

نقاط النهاية المتاحة

POST
/api/v1/readings

إرسال قراءة مستشعر واحدة أو دفعة

GET
/api/v1/readings

استعلام القراءات المخزنة

POST
/api/v1/upload

رفع ملف CSV أو Excel بالجملة

GET
/api/v1/export

تصدير ZIP كامل (مسؤول المؤسسة فقط)

المصادقة

تستخدم جميع نقاط النهاية مصادقة API key بصيغة Bearer token. أنشئ مفتاحك في لوحة التحكم: الإعدادات → مفاتيح API.

الخاصيةالتفاصيل
اسم الترويسةAuthorization
صيغة القيمةBearer nsm-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
بادئة المفتاحnsm-
الصلاحياتreadings:write · readings:read
نطاق المبنىاختياري - يمكن تقييد المفتاح بمبنى واحد
الانتهاءلا ينتهي أو بعد 30 / 90 / 365 يوماً

تحذير: يُعرض المفتاح مرة واحدة فقط عند الإنشاء. خزّنه في متغيرات البيئة ولا تُدرجه في كود المصدر.

مثال على الطلب

HTTP Header
Authorization: Bearer nsm-your-api-key-here

استجابات الخطأ

الحالةالسبب
401المفتاح مفقود أو غير صالح أو ملغى
403المفتاح موجود لكن لا يملك الصلاحية المطلوبة

إرسال القراءات

POST/api/v1/readingsيتطلب: readings:write

أرسل قراءة واحدة أو دفعة (حتى 100 قراءة) لمستشعر واحد أو أكثر. يُحسب EIAQI فوراً لكل قراءة ويُخزّن في قاعدة البيانات.

قراءة واحدة - جميع المعاملات

JSON body
{
  "device_id": "SENSOR-001",
  "recorded_at": "2026-06-01T10:00:00Z",
  "readings": {
    "pm25": 12.4,
    "pm10": 28.0,
    "co2": 650,
    "co": 0.5,
    "vocs": 0.18,
    "hcho": 30,
    "no2": 25,
    "o3": 18,
    "temperature": 23.5,
    "humidity": 52
  }
}

قراءة جزئية - لا تحتاج كل المعاملات

يمكنك إرسال المعاملات التي يقيسها مستشعرك فقط. يحتسب EIAQI من المعاملات المتوفرة.

JSON body (partial)
{
  "device_id": "SENSOR-001",
  "recorded_at": "2026-06-01T10:00:00Z",
  "readings": {
    "pm25": 12.4,
    "co2": 650,
    "temperature": 23.5,
    "humidity": 52
  }
}

دفعة من القراءات

أرسل مصفوفة JSON بدلاً من كائن واحد. الحد الأقصى 100 قراءة في الطلب الواحد.

JSON body (batch)
[
  {
    "device_id": "SENSOR-001",
    "recorded_at": "2026-06-01T10:00:00Z",
    "readings": { "pm25": 12.4, "co2": 650, "temperature": 23.5 }
  },
  {
    "device_id": "SENSOR-002",
    "recorded_at": "2026-06-01T10:00:00Z",
    "readings": { "pm25": 18.2, "co2": 720, "temperature": 24.1 }
  }
]

استجابة - قراءة واحدة

200 OK
{
  "success": true,
  "eiaqi": {
    "score": 72,
    "category": "good",
    "dominant_pollutant": "pm25"
  }
}

استجابة - دفعة

200 OK
{
  "success": true,
  "results": [
    {
      "device_id": "SENSOR-001",
      "success": true,
      "eiaqi": { "score": 72, "category": "good", "dominant_pollutant": "pm25" }
    },
    {
      "device_id": "SENSOR-002",
      "success": true,
      "eiaqi": { "score": 68, "category": "good", "dominant_pollutant": "co2" }
    }
  ]
}

مرجع المعاملات داخل readings{}

المعاملالمفتاحالوحدةالنطاقالوصف
PM₂.₅pm25μg/m³0-1,000Fine particulate matter (≤ 2.5 μm aerodynamic diameter)
PM₁₀pm10μg/m³0-1,000Coarse particulate matter (≤ 10 μm)
CO₂co2ppm400-5,000Carbon dioxide
COcoppm0-50Carbon monoxide
VOCsvocsmg/m³0-25Total volatile organic compounds (TVOC)
Formaldehydehchoμg/m³0-1,000Formaldehyde (HCHO / CH₂O)
NO₂no2μg/m³0-2,000Nitrogen dioxide
O₃o3μg/m³0-800Ozone
Temperaturetemperature°C−10 to 60Indoor air temperature
Humidityhumidity%0-100Relative humidity

* جميع حقول readings اختيارية. يجب أن يحتوي الكائن على حقل واحد على الأقل.

رفع CSV / Excel

POST/api/v1/uploadيتطلب: readings:write

ارفع ملف CSV أو TSV أو Excel يحتوي على بيانات تاريخية أو دفعات كبيرة. يكتشف النظام أسماء الأعمدة تلقائياً ويحوّل الوحدات.

الخاصيةالتفاصيل
نوع المحتوىmultipart/form-data
اسم الحقلfile
الصيغ المقبولة.csv · .tsv · .xlsx
الحد الأقصى للصفوف100,000
الحد الأقصى للحجم50 MB

مثال curl

bash
curl #86efac">"color:#fbbf24">-X POST https://naseem-eiaqi.com/api/v1/upload \
  #86efac">"color:#fbbf24">-H "Authorization: Bearer nsm-your-api-key" \
  #86efac">"color:#fbbf24">-F "file=@readings.csv"

الاستجابة

200 OK
{
  "batch_id": "7f8a91c2-d3b4-4e5f-a6c7-8d9e0f1a2b3c",
  "total_rows": 480,
  "accepted": 478,
  "rejected": 2,
  "rejected_rows": [
    { "row": 47, "reason": "pm25 value 1800 exceeds maximum" },
    { "row": 312, "reason": "recorded_at is in the future" }
  ]
}
ملاحظة: استخدم نقطة نهاية /api/v1/upload/analyze لمعاينة خريطة الأعمدة قبل الرفع الفعلي.

استعلام القراءات

GET/api/v1/readingsيتطلب: readings:read

استرجع القراءات المخزنة. يجب توفير واحد على الأقل من: building_id أو zone_id أو sensor_id.

المعاملالنوعإلزاميالوصف
building_iduuidمشروطBuilding to query (required unless zone_id or sensor_id supplied)
zone_iduuidاختياريNarrow results to a specific zone
sensor_iduuidاختياريNarrow results to a specific sensor
fromISO 8601اختياريStart of time range (inclusive)
toISO 8601اختياريEnd of time range (inclusive)
limitintegerاختياريMax results - default 100, max 500

مثال curl

bash
curl #86efac">"https://naseem-eiaqi.com/api/v1/readings?building_id=BUILD-UUID&from=2026-06-01T00:00:00Z&limit=100" \
  #86efac">"color:#fbbf24">-H "Authorization: Bearer nsm-your-api-key"

الاستجابة

200 OK
{
  "success": true,
  "count": 2,
  "data": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "sensor_id": "uuid",
      "zone_id": "uuid",
      "building_id": "uuid",
      "recorded_at": "2026-06-01T10:00:00Z",
      "pm25": 12.4,
      "co2": 650,
      "temperature": 23.5,
      "humidity": 52
    }
  ]
}

استعلام النتائج

GET/api/v1/scoresيتطلب: readings:readقريباً

استرجع نتائج EIAQI المجمّعة حسب الفترة الزمنية. النتائج متاحة حالياً عبر لوحة التحكم وتقارير التصدير.

المعاملالنوعإلزاميالوصف
building_iduuidاختياريFilter by building
zone_iduuidاختياريFilter by zone
period_typeenumاختياريhourly | eight_hour | daily | weekly | monthly
fromISO 8601اختياريStart of time range
toISO 8601اختياريEnd of time range

مثال على الاستجابة

200 OK
{
  "data": [
    {
      "id": "abc12345",
      "building_id": "uuid",
      "zone_id": "uuid",
      "period_type": "hourly",
      "period_start": "2026-06-01T10:00:00Z",
      "period_end": "2026-06-01T11:00:00Z",
      "eiaqi_score": 72,
      "eiaqi_category": "good",
      "dominant_pollutant": "pm25",
      "sub_indices": {
        "pm25": 68,
        "co2": 45,
        "vocs": 30
      }
    }
  ]
}

أسماء الحقول المدعومة

عند رفع ملفات CSV أو Excel، يعترف النظام تلقائياً بعشرات الأسماء الشائعة لكل معامل. القائمة أدناه هي المرجع الكامل لمورّدي BMS.

المعاملالمفتاح القانونيالأسماء المقبولة
PM₂.₅pm25
pm25pm2.5PM2.5pm2_5fine_particlesPM25pm2p5pm25_ugm3PM 2.5
PM₁₀pm10
pm10PM10pm1_0coarse_particlespm10_ugm3
CO₂co2
co2CO2carbon_dioxideco2_ppmco2ppmco2_levelcarbondioxide
COco
coCOcarbon_monoxideco_ppmcoppmco_mgm3
VOCsvocs
vocsvocVOCVOCstvocTVOCtotal_vocvolatile_organictvoc_ppbtvoc_mgm3
Formaldehydehcho
hchoHCHOformaldehydeFormaldehydech2oCH2Ohcho_ugm3
NO₂no2
no2NO2nitrogen_dioxideno2_ugm3no2_ppbnitrogendioxide
O₃o3
o3O3ozoneOzoneo3_ugm3o3_ppb
Temperaturetemperature
temperaturetempTempTEMPtemp_cair_tempindoor_temptemperature_ctemperature_ftemp_ftempf
Humidityhumidity
humidityrhRHrelative_humidityhumhumidity_pctrh_pctrel_humidity
يُطبَّق تطبيع شامل على أسماء الأعمدة قبل المطابقة: حروف صغيرة، وإزالة المسافات والشرطات والنقاط. مثال: "PM 2.5 (µg/m³)" تُطابق pm25.

أسماء الطابع الزمني المقبولة (recorded_at)

recorded_attimestampTimestamptimedatetimeDateTimetsmeasured_atdateDateDate/Timerecording_timemeasurement_time

الوحدات والتحويل

تُطبَّق الوحدات القانونية وفقاً لـ DM-HSD-GU141-IAQI2. عند رفع الملفات، يكتشف النظام الوحدة من اسم العمود ويُحوّلها تلقائياً.

المعاملالمفتاحالوحدة القانونيةيُحوَّل تلقائياً من
PM₂.₅pm25μg/m³mg/m³ (×1,000)
PM₁₀pm10μg/m³mg/m³ (×1,000)
CO₂co2ppmppb (÷1,000)
COcoppmmg/m³ (×0.873 at 25 °C, 1 atm)
VOCsvocsmg/m³ppb (toluene MW 92.14), ppm, μg/m³
Formaldehydehchoμg/m³mg/m³ (×1,000), ppb
NO₂no2μg/m³mg/m³ (×1,000), ppb
O₃o3μg/m³mg/m³ (×1,000), ppb
Temperaturetemperature°C°F → (F − 32) × 5/9; auto-detected from column name
Humidityhumidity%0-1 fraction auto-scaled to 0-100

كيف يعمل الاكتشاف التلقائي

  • اسم عمود يحتوي على "mg" (بدون "ug") → يُعامل على أنه mg/m³
  • اسم عمود يحتوي على "ppb" → يُحوَّل لـ ppm أو μg/m³ حسب المعامل
  • درجة حرارة باسم يحتوي "fahrenheit" أو "_f" أو "°f" → تحويل فهرنهايت → سيلزيوس
  • رطوبة بقيمة ≤ 1.0 → تُضرب في 100 تلقائياً

رموز الأخطاء

جميع الأخطاء تُعاد بصيغة JSON مع حقل error وحقل details اختياري للتفاصيل الميدانية.

الكودالاسمالوصف
400Bad RequestValidation failed. Response includes a `details` array with per-field messages.
401UnauthorizedAPI key is missing, invalid, or revoked.
403ForbiddenKey exists but lacks the required scope (e.g. `readings:write`).
404Not FoundThe requested resource does not exist.
422Unprocessable EntitySchema validation passed but business rules failed (e.g. sensor not found, value out of range).
429Too Many RequestsRate limit exceeded (100 req/min per key). Check `Retry-After` header.
500Internal Server ErrorTransient server error. Retry with exponential backoff.

400 - مثال

400 Bad Request
{
  "success": false,
  "error": "Validation failed",
  "details": [
    {
      "field": "readings.pm25",
      "message": "Value 1500 exceeds maximum 1000 μg/m³"
    }
  ]
}

401 - مثال

401 Unauthorized
{
  "success": false,
  "error": "Invalid or expired API key"
}

429 - مثال

429 Too Many Requests
{
  "success": false,
  "error": "Rate limit exceeded: 100 requests per minute"
}

أمثلة برمجية

curl

إرسال قراءة مستشعر واحدة

bash
curl #86efac">"color:#fbbf24">-X POST https://naseem-eiaqi.com/api/v1/readings \
  #86efac">"color:#fbbf24">-H "Authorization: Bearer nsm-your-api-key" \
  #86efac">"color:#fbbf24">-H "Content-Type: application/json" \
  #86efac">"color:#fbbf24">-d @reading.json

Python

مكتبة requests - pip install requests

python
import requests

API_KEY = "nsm-your-api-key"
BASE_URL = "https://naseem-eiaqi.com/api/v1"

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

reading = {
    "device_id": "SENSOR-001",
    "recorded_at": "2026-06-01T10:00:00Z",
    "readings": {
        "pm25": 12.4,
        "pm10": 28.0,
        "co2": 650,
        "temperature": 23.5,
        "humidity": 52,
    },
}

response = requests.post(
    f"{BASE_URL}/readings",
    json=reading,
    headers=headers
)
print(response.json())

Node.js

مدمج في Node.js 18+ (fetch native)

javascript
const API_KEY = 'nsm-your-api-key'
const BASE_URL = 'https:"color:#6b7280">//naseem-eiaqi.com/api/v1'

async function sendReading(data) {
  const res = await fetch(BASE_URL + '/readings', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer ' + API_KEY,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(data),
  })
  if (!res.ok) throw new Error('HTTP ' + res.status)
  return res.json()
}

"color:#6b7280">// Send a single reading
const result = await sendReading({
  device_id: 'SENSOR-001',
  recorded_at: new Date().toISOString(),
  readings: { pm25: 12.4, co2: 650, temperature: 23.5 },
})
console.log(result)

n8n

استخدم عقدة "HTTP Request" مع الإعدادات التالية. عيّن البيانات من الحقول السابقة في سير العمل باستخدام تعبيرات n8n.

n8n HTTP Request node
"color:#6b7280">// HTTP Request node - configure as follows:

Method:   POST
URL:      https:"color:#6b7280">//naseem-eiaqi.com/api/v1/readings

"color:#6b7280">// Headers tab
Authorization:  Bearer nsm-your-api-key
Content-Type:   application/json

"color:#6b7280">// Body tab - select "JSON (Raw)"
{
  "device_id":   "{{ $json.device_id }}",
  "recorded_at": "{{ $now.toISO() }}",
  "readings": {
    "pm25":        {{ $json.pm25 }},
    "co2":         {{ $json.co2 }},
    "temperature": {{ $json.temperature }},
    "humidity":    {{ $json.humidity }}
  }
}

هل تحتاج مساعدة؟

أنشئ مفتاح API من الإعدادات وجرّب أول طلب خلال دقيقتين. للدعم الفني، تواصل معنا عبر hello@naseem-eiaqi.com.