Files
mdm-ordinis/docs/integration/api-cheatsheet.md
T
Zimin A.N. ae05e17f96 docs(api): cheatsheet + quickstart sync с реальным API после Postman audit
Audit Postman collection выявил расхождения docs ↔ runtime — фикс:

Topology clarification:
- Records (consumer) — БЕЗ /dictionaries/ префикса: /api/v1/{name}/records
- History/cascade-preview/changelog/drafts — С /dictionaries/ (writer audit)
- export-selected.csv — POST, не GET

Query params (records list, /{name}/records):
-  as_scope (required, CSV) — было документировано как ?scope= (неверно)
-  at (ISO timestamp) — было ?asOf= (неверно)
-  locale + Accept-Language header
-  bbox / polygon (geo)
-  убраны: ?limit, ?offset (pagination отсутствует),
            ?status/?country (нет ad-hoc filtering по schema полям)

Snapshots params:
-  from / to / granularity (hour/day/week) — было ?asOf= (неверно)

Base URLs:
- prod: ordinis.nstart.cloud (public LE-cert)
- staging: ordinis.k8s.265.nstart.cloud (Swagger UI здесь)
- было: ordinis.k8s.264.nstart.cloud (устаревший internal, prod переехал)

Version: v2.36 → v2.37.x.

Refs MR !242 (snapshots backend fix), Postman collection в
~/Desktop/Ordinis-Postman/.
2026-05-19 23:15:40 +03:00

10 KiB
Raw Blame History

Ordinis API · Cheat Sheet

Одностраничный референс. Полный гайд — api-quickstart.md.

Base prod: https://ordinis.nstart.cloud/api/v1 (public LE-cert) Base staging: https://ordinis.k8s.265.nstart.cloud/api/v1 (Swagger UI здесь) Version: v2.37.x · OpenAPI: /v3/api-docs (только staging — на prod Swagger выключен)

Auth

TOKEN=$(curl -s -X POST https://auth.nstart.space/realms/nstart/protocol/openid-connect/token \
  -d client_id=ordinis -d grant_type=password -d scope=openid \
  -d username=$USER -d password=$PASS | jq -r .access_token)

curl -H "Authorization: Bearer $TOKEN" $ORDINIS/api/v1/me/notifications/settings

Scopes: PUBLIC (anon ok) · INTERNAL (auth) · RESTRICTED (admin).

Read (no auth для PUBLIC)

Verb Path Что
GET /version Версия + commit + builtAt
GET /dictionaries Список всех справочников
GET /dictionaries/{name} Детали + JSON Schema
GET /dictionaries/templates 6 шаблонов схем
GET /dictionaries/templates/{id} Один шаблон со schemaJson
GET /dictionaries/graph/outgoing FK-граф между справочниками
GET /dictionaries/{name}/dependents Кто ссылается на этот dict
GET /dictionaries/{name}/changelog Список изменений схемы
GET /dictionaries/{name}/changelog/{id}/diff Diff между версиями
GET /dictionaries/{name}/snapshots?from=&to=&granularity= Bucket'ы изменений для TimeTravel slider (granularity: hour/day/week)
GET /{name}/records?as_scope=PUBLIC Список записей (⚠️ БЕЗ /dictionaries/ префикса)
GET /{name}/records/{businessKey}?as_scope=PUBLIC Одна запись
GET /dictionaries/{name}/records/{businessKey}/history?as_scope=PUBLIC История версий записи (Envers) — с /dictionaries/
GET /dictionaries/{name}/records/{businessKey}/cascade-preview?as_scope=PUBLIC Preview каскада — с /dictionaries/
GET /{name}/records/scheduled-summary?as_scope=PUBLIC Будущие версии (count + nearestValidFrom)
GET /search?q= Поиск по справочникам (records не индексируются)
GET /ai/info {enabled: bool} AI feature flag

⚠️ Корень частой путаницы: consumer endpoints (/records/...) идут БЕЗ /dictionaries/ префикса. Admin-style audit endpoints (history, cascade-preview, changelog, drafts, snapshots) — С /dictionaries/. См. api-quickstart.md § Topology.

Query params (records)

?as_scope=PUBLIC,INTERNAL    (required) CSV scope filter
?at=2026-03-15T00:00:00Z     bitemporal: запись на конкретный момент (validFrom <= at < validTo)
?locale=en-US                локаль (или Accept-Language header)
?bbox=lon1,lat1,lon2,lat2    geo: bounding box (для geo-dicts)
?polygon=<GeoJSON>           geo: polygon-фильтр

Что НЕ работает (на read-api endpoint):

  • ?limit=, ?offset= — pagination отсутствует, возвращается весь массив
  • ?status=ACTIVE&country=RU — нет ad-hoc filtering по schema полям; фильтруй на клиенте

Write (требует auth)

⚠️ Все write-endpoints — на writer сервисе, с /dictionaries/ префиксом.

Verb Path Что
POST /dictionaries/{name}/records Создать запись (если approval не нужен)
PUT /dictionaries/{name}/records/{businessKey} Обновить
DELETE /dictionaries/{name}/records/{businessKey} Soft-delete (tombstone)
POST /dictionaries/{name}/records/bulk-close Массовое закрытие
POST /dictionaries/{name}/records/{businessKey}/cascade-close Закрыть с зависимыми
POST /dictionaries/{name}/records/export-selected.csv Bulk export (выборка по ids в body)
PATCH /dictionaries/{name}/schema Изменить схему inline (non-breaking)
PUT /dictionaries/{name} Полностью пересоздать (breaking)

Workflow (drafts + approvals)

Verb Path Что
POST /dictionaries/{name}/records/drafts Создать record draft
POST /dictionaries/{name}/drafts Создать schema draft
GET /dictionaries/{name}/drafts Список schema drafts по dict
GET /dictionaries/{name}/drafts/active Активный draft (200+null если нет)
GET /dictionaries/{name}/drafts/{id} Один draft
DELETE /dictionaries/{name}/drafts/{id} Withdraw
POST /dictionaries/{name}/drafts/{id}/review Назначить ревью
POST /dictionaries/{name}/drafts/{id}/decision Approve/reject schema draft
POST /dictionaries/{name}/drafts/{id}/publish Опубликовать после approve
GET /drafts/me Мои record-drafts (status filter)
GET /drafts/{id} Один record draft
DELETE /drafts/{id} Withdraw record draft
POST /drafts/{id}/approve Одобрить (body: {comment})
POST /drafts/{id}/reject Отклонить (body: {comment})
GET /admin/reviews/pending Очередь ревьюера (records)
GET /admin/schema-reviews/pending Очередь ревьюера (schemas)
GET /admin/schema-drafts/me Мои schema drafts

AI

curl -X POST -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  $ORDINIS/api/v1/ai/suggest-field \
  -d '{"prompt":"контактный email оператора"}'

Limits: 30 req/min на IP, circuit breaker 10 fails / 60s → open 5min (503 circuit_open).

Notifications (per-user, auth)

Verb Path Что
GET /me/notifications Bell-bar feed
POST /me/notifications/{id}/read Mark as read
POST /me/notifications/read-all Mark all as read
GET /me/notifications/preferences Per-event matrix
PUT /me/notifications/preferences Сохранить матрицу
GET /me/notifications/settings Quiet hours config
PUT /me/notifications/settings Сохранить quiet hours

Webhooks (admin)

Verb Path Что
GET /admin/webhooks/subscriptions Список подписок
POST /admin/webhooks/subscriptions Создать (secret в ответе, один раз)
GET /admin/webhooks/subscriptions/{id} Детали
PUT /admin/webhooks/subscriptions/{id} Обновить
DELETE /admin/webhooks/subscriptions/{id} Удалить
POST /admin/webhooks/subscriptions/{id}/rotate-secret Перевыпуск ключа
POST /admin/webhooks/subscriptions/{id}/test Test delivery
GET /admin/webhooks/subscriptions/{id}/stats Histogram (24h/7d)
GET /admin/webhooks/subscriptions/{id}/deliveries Recent deliveries
GET /admin/webhooks/deliveries/dlq DLQ list
POST /admin/webhooks/deliveries/{id}/retry Manual retry

Headers delivered

X-Ordinis-Event: RecordCreated
X-Ordinis-Signature: sha256=<hex>     HMAC-SHA256(body, secret)
X-Ordinis-Delivery: del_01HXY...
User-Agent: ordinis-alerts

Event types

RecordCreated · RecordUpdated · RecordClosed · RecordRestored · BulkClosed · SchemaDraftSubmitted · SchemaDraftApproved · SchemaDraftRejected · SchemaDraftPublished · RecordDraftSubmitted · RecordDraftApproved

Audit (admin)

Verb Path Что
GET /admin/audit?dictionary=&action=&user=&dateFrom=&dateTo= Фильтрованный аудит
GET /admin/audit/export.csv Полный экспорт
GET /admin/audit/export-selected.csv Selected ids экспорт

Action types (13): DICTIONARY_CREATED · SCHEMA_UPDATED · SCHEMA_PUBLISHED · RECORD_CREATED · RECORD_UPDATED · RECORD_CLOSED · RECORD_RESTORED · DRAFT_CREATED · DRAFT_SUBMITTED · DRAFT_APPROVED · DRAFT_REJECTED · DRAFT_WITHDRAWN · REVIEWER_ASSIGNED

Outbox (admin)

Verb Path Что
GET /admin/outbox/stats Pending/DLQ counters
GET /admin/outbox/dlq DLQ events list

Errors — единая форма

{ "status": 422, "code": "validation_failed", "message": "...",
  "details": {}, "traceId": "...", "timestamp": "..." }
HTTP code
400 bad_request Невалидный body
401 unauthorized Нет/просрочен токен
403 forbidden Scope/role не пускает
404 not_found Нет такого ресурса
409 conflict Concurrent update / unique violation
422 validation_failed Schema validation fail
429 rate_limited Лимит запросов
500 internal_error См. traceId
502 llm_error AI: LLM upstream
503 circuit_open AI: circuit breaker

60-second smoke

ORDINIS=https://ordinis.nstart.cloud   # prod (public LE)
# или: ORDINIS=https://ordinis.k8s.265.nstart.cloud   # staging

curl -s $ORDINIS/api/v1/version | jq                                          # alive
curl -s $ORDINIS/api/v1/dictionaries | jq 'length'                            # 37 на prod / 39 на staging
curl -s $ORDINIS/api/v1/dictionaries/spacecraft | jq '.scope'                 # "PUBLIC"
curl -s "$ORDINIS/api/v1/spacecraft/records?as_scope=PUBLIC" | jq '.[0].businessKey'
curl -s "$ORDINIS/api/v1/search?q=spacecraft" | jq '.total'                   # >0
curl -s $ORDINIS/api/v1/ai/info | jq '.enabled'                               # true / false

Postman collection

Готовая collection с реальными запросами (28 запросов, demo-flow): см. docs/integration/postman/ или ~/Desktop/Ordinis-Postman/ (если генерировал локально).

Связанные доки

api-quickstart.md · bundle-format-spec.md · docs/changelog.md · Swagger UI /swagger-ui/index.html