# 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 ```bash 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](api-quickstart.md). ### Query params (records) ``` ?as_scope=PUBLIC,INTERNAL (required) CSV scope filter ?at=2026-03-15T00:00:00Z bitemporal: запись на конкретный момент (validFrom <= at < validTo) Accept-Language: en-US (header) локаль — единственный рабочий путь ⚠️ ?locale= query param backend сейчас игнорирует ?bbox=lon1,lat1,lon2,lat2 geo: bounding box (для geo-dicts) ?polygon= 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 ```bash 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= 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 — единая форма ```json { "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 ```bash 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/](postman/) или `~/Desktop/Ordinis-Postman/` (если генерировал локально). ## Связанные доки `api-quickstart.md` · `bundle-format-spec.md` · `docs/changelog.md` · Swagger UI `/swagger-ui/index.html`