Skip to content

Справочник HTTP API

Полная спецификация REST API без использования SDK. Для интерактивной проверки см. API Playground.

Эндпоинт

https://meters-api-prod.nyc-1.optimatica.pro/api/meters/analyze

В SDK этот URL зашит на этапе сборки (переменная OPTIMATICA_API_URL).

Аутентификация

Каждый запрос к /api/* должен содержать заголовок:

http
Authorization: Bearer ВАШ_JWT
ПараметрОписание
Формат ключаJWT (header.payload.signature), без префикса
Срок действияДо явного отзыва в личном кабинете
ПередачаТолько заголовок Authorization, не query-параметр

Ошибки авторизации

HTTPТелоПричина
401{ "error": "Unauthorized" }Ключ отсутствует, неверный или отозван
403{ "error": "Client blocked" }Аккаунт заблокирован
402{ "error": "Payment required" }Исчерпана квота запросов

Эндпоинты

МетодПутьОписание
POST/api/meters/analyzeРаспознавание счётчика по фото

POST /api/meters/analyze

Анализирует фотографию счётчика и возвращает тип, серийный номер и показания.

Запрос

http
POST /api/meters/analyze
Authorization: Bearer ВАШ_JWT
Content-Type: multipart/form-data
ПолеТипОбязательноеОписание
imagefileдаJPEG или PNG, фото счётчика (до 20 MB)

WARNING

Имя поля формы должно быть image. Другие имена вернут 400.

cURL

bash
curl -X POST https://meters-api-prod.nyc-1.optimatica.pro/api/meters/analyze \
  -H "Authorization: Bearer ВАШ_JWT" \
  -F "image=@/path/to/meter.jpg"

fetch (браузер / Node 18+)

js
const form = new FormData()
form.append('image', file)

const res = await fetch('https://meters-api-prod.nyc-1.optimatica.pro/api/meters/analyze', {
  method: 'POST',
  headers: { Authorization: 'Bearer ВАШ_JWT' },
  body: form,
})

const data = await res.json()

Python (requests)

python
import requests

with open('meter.jpg', 'rb') as f:
    res = requests.post(
        'https://meters-api-prod.nyc-1.optimatica.pro/api/meters/analyze',
        headers={'Authorization': 'Bearer ВАШ_JWT'},
        files={'image': f},
    )

data = res.json()

Ответы

Успешное распознавание — HTTP 200

json
{
  "success": true,
  "meter": {
    "type": "water_cold",
    "serialNumber": "12345678",
    "currentReading": 123.456,
    "tariffCount": null,
    "waterTypeUnknown": false
  }
}
ПолеТипОписание
successbooleanВсегда true
meter.typestringТип счётчика — см. типы
meter.serialNumberstringЗаводской номер с шильдика
meter.currentReadingnumber | nullПоказания; null если не читаются
meter.tariffCountnumber | nullЧисло тарифных зон (электросчётчики)
meter.waterTypeUnknownboolean?true если тип воды не определился

Не удалось распознать — HTTP 200

API возвращает 200, но success: false — это не HTTP-ошибка:

json
{
  "success": false,
  "error": "Could not detect meter in the photo"
}
ПолеТипОписание
successbooleanВсегда false
errorstringЧеловекочитаемая причина

HTTP-ошибки

HTTPПример телаКогда
400{ "error": "No file uploaded" }Нет поля image или неверный формат
401{ "error": "Unauthorized" }Проблема с API-ключом
402{ "error": "Payment required" }Квота исчерпана
403{ "error": "Client blocked" }Клиент заблокирован
500{ "error": "..." }Внутренняя ошибка сервера

Типы счётчиков (meter.type)

ЗначениеОписание
water_coldХолодная вода
water_hotГорячая вода
electricityЭлектричество
gasГаз
heatТеплоснабжение

Ограничения

ПараметрЗначение
Форматы изображенияJPEG, PNG
Максимальный размер20 MB
Content-Type запросаmultipart/form-data
Поле файлаimage

SDK

HTTP-вызовы можно не писать вручную — используйте пакет optimatica-meters:

ts
import { analyzeMeterPhoto, ZhkhApiError } from 'optimatica-meters'

try {
  const result = await analyzeMeterPhoto(file, { apiKey: 'eyJhbGci...' })
  if (result.success) {
    console.log(result.meter.serialNumber)
  }
} catch (err) {
  if (err instanceof ZhkhApiError) {
    console.log(err.status, err.message)
  }
}

UI-компоненты с камерой и drag-and-drop: Vue Playground, React Playground.

MIT License