# API Reference

All REST endpoints follow the base path `api/app/{resource}` and are defined in `src/OtisEd.Nimble.HttpApi/Controllers/`. Each controller inherits `NimbleController` (except `PageController`, `CardController`, `CardDataController`, which inherit `AbpController` directly — a known inconsistency), implements its corresponding `IXxxAppService` interface, and delegates every action to the injected application service with no additional logic.

## Table of Contents

* [Conventions](#conventions)
* [Authentication and Authorization](#authentication-and-authorization)
* [Endpoint Inventory](#endpoint-inventory)
  * [About](#about)
  * [AI Chatbot](#ai-chatbot)
  * [Alerts](#alerts)
  * [App Terms](#app-terms)
  * [Approval Statuses](#approval-statuses)
  * [Cards](#cards)
  * [Card Data](#card-data)
  * [Containers](#containers)
  * [Container Cards](#container-cards)
  * [Container Card Data](#container-card-data)
  * [Container Viewer](#container-viewer)
  * [Data Collection — Agencies](#data-collection--agencies)
  * [Data Collection — Agency Types](#data-collection--agency-types)
  * [Data Collection — File Requests](#data-collection--file-requests)
  * [Data Collection — File Type Categories](#data-collection--file-type-categories)
  * [Data Collection — File Type Groups](#data-collection--file-type-groups)
  * [Data Collection — File Types](#data-collection--file-types)
  * [Data Collection — Forms](#data-collection--forms)
  * [Data Request](#data-request)
  * [Dictionaries](#dictionaries)
  * [Glossaries](#glossaries)
  * [Menus](#menus)
  * [Migrate Config](#migrate-config)
  * [Modules](#modules)
  * [Page Cards](#page-cards)
  * [Pages](#pages)
  * [Power BI](#power-bi)
  * [Publish Config](#publish-config)
  * [Reference Items](#reference-items)
  * [Report Access Logs](#report-access-logs)
  * [Report Group Containers](#report-group-containers)
  * [Routes](#routes)
  * [Security Users](#security-users)
  * [Site Reports](#site-reports)
  * [Site Settings](#site-settings)
  * [Store Messages and Message Types](#store-messages-and-message-types)
  * [User Report Page Filters](#user-report-page-filters)
  * [Module APIs — File Management](#module-apis--file-management)
  * [Module APIs — Forms](#module-apis--forms)

***

## Conventions

### Route Pattern

```
GET|POST|PUT|DELETE  /api/app/{resource}
GET|POST|PUT|DELETE  /api/app/{resource}/{id}
```

Resources use kebab-case: `dc-file-requests`, `report-access-logs`, `container-card-data`.

### Controller Attributes

Every controller carries:

* `[RemoteService]` — exposes the controller to ABP dynamic proxying
* `[Area("app")]` — groups it under the app API area
* `[Route("api/app/{resource}")]` — sets the base route

### Standard CRUD Pattern

Most resources follow an identical CRUD surface:

| Method   | Path                       | Description                       |
| -------- | -------------------------- | --------------------------------- |
| `GET`    | `/api/app/{resource}`      | Paged list (ABP `PagedResultDto`) |
| `GET`    | `/api/app/{resource}/{id}` | Single item                       |
| `POST`   | `/api/app/{resource}`      | Create                            |
| `PUT`    | `/api/app/{resource}/{id}` | Update                            |
| `DELETE` | `/api/app/{resource}/{id}` | Delete                            |

Resources that deviate from this pattern are documented individually below.

### Paged Requests

List endpoints accept ABP `PagedAndSortedResultRequestDto` query parameters:

| Parameter        | Type   | Description                                   |
| ---------------- | ------ | --------------------------------------------- |
| `skipCount`      | int    | Records to skip                               |
| `maxResultCount` | int    | Max records to return                         |
| `sorting`        | string | Sort field and direction (e.g., `"Name ASC"`) |

### Navigation Properties Variant

Several resources expose an additional endpoint for eager-loaded joins:

```
GET /api/app/{resource}/with-navigation-properties/{id}
```

Returns a `*WithNavigationPropertiesDto` containing the entity plus related lookup objects.

***

## Authentication and Authorization

### API Authentication

The React SPA authenticates via the ASP.NET Core antiforgery system:

* The server sets an `XSRF-TOKEN` cookie on page load
* Every Axios request reads the cookie and sets it as the `RequestVerificationToken` request header
* All requests use `withCredentials: true` (cookies are included cross-origin)

### Permission Checks

Application services enforce permissions using ABP's `[Authorize]` attribute and `IAuthorizationService`. Permission names follow the pattern `Nimble.{Resource}.{Operation}` (e.g., `Nimble.Reports.Edit`). Controllers themselves do not duplicate these checks — permission enforcement lives exclusively in the application layer.

### Anti-Forgery Exception

`SiteReportsController.GetFiltersAsync` disables anti-forgery validation (`[IgnoreAntiforgeryToken]`) to support external MicroStrategy filter POST requests.

***

## Endpoint Inventory

### About

**Controller:** `AboutController`

| Method | Path                     | Description                      |
| ------ | ------------------------ | -------------------------------- |
| `GET`  | `/api/app/about/version` | Returns application version info |

***

### AI Chatbot

**Controllers:** `AiChatbotController`, `AiChatbotJobController`

| Method  | Path                          | Description                  |
| ------- | ----------------------------- | ---------------------------- |
| `GET`   | `/api/app/ai-chatbot/options` | Get AI chatbot configuration |
| Various | `/api/app/ai-chatbot-job`     | AI chatbot job management    |

***

### Alerts

**Controller:** `AlertMessagesController`

| Method | Path                                   | Description                            |
| ------ | -------------------------------------- | -------------------------------------- |
| `GET`  | `/api/app/alert-messages-user/history` | Get alert history for the current user |

***

### App Terms

**Controller:** `AppTermsController`

| Method   | Path                      | Description             |
| -------- | ------------------------- | ----------------------- |
| `GET`    | `/api/app/app-terms`      | Paged list of app terms |
| `GET`    | `/api/app/app-terms/{id}` | Get single term         |
| `POST`   | `/api/app/app-terms`      | Create term             |
| `PUT`    | `/api/app/app-terms/{id}` | Update term             |
| `DELETE` | `/api/app/app-terms/{id}` | Delete term             |

***

### Approval Statuses

**Controller:** `ApprovalStatusesController`

| Method   | Path                              | Description            |
| -------- | --------------------------------- | ---------------------- |
| `GET`    | `/api/app/approval-statuses`      | List approval statuses |
| `POST`   | `/api/app/approval-statuses`      | Create approval status |
| `PUT`    | `/api/app/approval-statuses/{id}` | Update approval status |
| `DELETE` | `/api/app/approval-statuses/{id}` | Delete approval status |

***

### Cards

**Controller:** `CardController` (inherits `AbpController`, not `NimbleController`)

| Method   | Path                  | Description         |
| -------- | --------------------- | ------------------- |
| `GET`    | `/api/app/cards`      | Paged list of cards |
| `GET`    | `/api/app/cards/{id}` | Get card            |
| `POST`   | `/api/app/cards`      | Create card         |
| `PUT`    | `/api/app/cards/{id}` | Update card         |
| `DELETE` | `/api/app/cards/{id}` | Delete card         |

***

### Card Data

**Controller:** `CardDataController` (inherits `AbpController`, not `NimbleController`)

| Method   | Path                       | Description             |
| -------- | -------------------------- | ----------------------- |
| `GET`    | `/api/app/card-datas`      | Paged list of card data |
| `GET`    | `/api/app/card-datas/{id}` | Get card data           |
| `POST`   | `/api/app/card-datas`      | Create card data        |
| `PUT`    | `/api/app/card-datas/{id}` | Update card data        |
| `DELETE` | `/api/app/card-datas/{id}` | Delete card data        |

***

### Containers

**Controller:** `ContainersController`

| Method   | Path                                                  | Description                              |
| -------- | ----------------------------------------------------- | ---------------------------------------- |
| `GET`    | `/api/app/containers`                                 | Paged list of containers                 |
| `GET`    | `/api/app/containers/{id}`                            | Get container                            |
| `GET`    | `/api/app/containers/with-navigation-properties/{id}` | Get container with navigation properties |
| `POST`   | `/api/app/containers`                                 | Create container                         |
| `PUT`    | `/api/app/containers/{id}`                            | Update container                         |
| `DELETE` | `/api/app/containers/{id}`                            | Delete container                         |

***

### Container Cards

**Controller:** `ContainerCardController`

| Method        | Path                           | Description            |
| ------------- | ------------------------------ | ---------------------- |
| `GET`         | `/api/app/container-card`      | List container cards   |
| Standard CRUD | `/api/app/container-card/{id}` | Create, update, delete |

***

### Container Card Data

**Controller:** `ContainerCardDataController`

| Method        | Path                                | Description              |
| ------------- | ----------------------------------- | ------------------------ |
| `GET`         | `/api/app/container-card-data`      | List container card data |
| Standard CRUD | `/api/app/container-card-data/{id}` | Create, update, delete   |

***

### Container Viewer

**Controller:** `ContainerViewerController`

Read-only container rendering endpoints. Used by the `ContainerViewer` React component (query parameter: `containerId`).

***

### Data Collection — Agencies

**Controller:** `DcAgenciesController`

| Method        | Path                        | Description            |
| ------------- | --------------------------- | ---------------------- |
| `GET`         | `/api/app/dc-agencies`      | List agencies          |
| Standard CRUD | `/api/app/dc-agencies/{id}` | Create, update, delete |

***

### Data Collection — Agency Types

**Controller:** `DcAgencyTypesController`

| Method        | Path                              | Description        |
| ------------- | --------------------------------- | ------------------ |
| `POST`        | `/api/app/dc-agency-types/create` | Create agency type |
| Standard CRUD | `/api/app/dc-agency-types/{id}`   | Update, delete     |

***

### Data Collection — File Requests

**Controller:** `DcFileRequestsController`

| Method        | Path                             | Description                  |
| ------------- | -------------------------------- | ---------------------------- |
| `GET`         | `/api/app/dc-file-requests`      | List file requests           |
| `POST`        | `/api/app/dc-file-requests`      | Create / upload file request |
| Standard CRUD | `/api/app/dc-file-requests/{id}` | Update, delete               |

***

### Data Collection — File Type Categories

**Controller:** `DcFileTypeCategoriesController`

| Method        | Path                                      | Description     |
| ------------- | ----------------------------------------- | --------------- |
| `POST`        | `/api/app/dc-file-type-categories/create` | Create category |
| Standard CRUD | `/api/app/dc-file-type-categories/{id}`   | Update, delete  |

***

### Data Collection — File Type Groups

**Controller:** `DcFileTypeGroupsController`

| Method        | Path                                  | Description    |
| ------------- | ------------------------------------- | -------------- |
| `POST`        | `/api/app/dc-file-type-groups/create` | Create group   |
| Standard CRUD | `/api/app/dc-file-type-groups/{id}`   | Update, delete |

***

### Data Collection — File Types

**Controller:** `DcFileTypesController`

| Method        | Path                          | Description      |
| ------------- | ----------------------------- | ---------------- |
| `GET`         | `/api/app/dc-file-types`      | List file types  |
| `POST`        | `/api/app/dc-file-types`      | Create file type |
| Standard CRUD | `/api/app/dc-file-types/{id}` | Update, delete   |

***

### Data Collection — Forms

**Controller:** `DcFormsController`

| Method     | Path                                                | Description                              |
| ---------- | --------------------------------------------------- | ---------------------------------------- |
| `GET`      | `/api/app/dc-forms/current-user-organization-units` | Get org units accessible to current user |
| Additional | `/api/app/dc-forms/...`                             | Form CRUD and listing operations         |

***

### Data Request

**Controller:** `DataRequestController`

| Method | Path                   | Description                  |
| ------ | ---------------------- | ---------------------------- |
| `GET`  | `/api/app/datarequest` | Get data request settings    |
| `PUT`  | `/api/app/datarequest` | Update data request settings |

***

### Dictionaries

**Controller:** `DictionaryController`

| Method | Path                    | Description                |
| ------ | ----------------------- | -------------------------- |
| `GET`  | `/api/app/dictionaries` | Get dictionary settings    |
| `PUT`  | `/api/app/dictionaries` | Update dictionary settings |

***

### Glossaries

**Controller:** `GlossariesController`

| Method        | Path                       | Description                    |
| ------------- | -------------------------- | ------------------------------ |
| `GET`         | `/api/app/glossaries`      | Paged list of glossary entries |
| Standard CRUD | `/api/app/glossaries/{id}` | Create, update, delete         |

***

### Menus

**Controller:** `MenusController`

| Method   | Path                                             | Description                         |
| -------- | ------------------------------------------------ | ----------------------------------- |
| `GET`    | `/api/app/menus`                                 | Paged list of menus                 |
| `GET`    | `/api/app/menus/{id}`                            | Get menu                            |
| `GET`    | `/api/app/menus/with-navigation-properties/{id}` | Get menu with navigation properties |
| `GET`    | `/api/app/menus/route-lookup`                    | Lookup routes for menu assignment   |
| `GET`    | `/api/app/menus/usermenus`                       | Get current user's visible menus    |
| `POST`   | `/api/app/menus`                                 | Create menu                         |
| `PUT`    | `/api/app/menus/{id}`                            | Update menu                         |
| `PUT`    | `/api/app/menus/{id}/permissions`                | Update menu permissions             |
| `DELETE` | `/api/app/menus/{id}`                            | Delete menu                         |

***

### Migrate Config

**Controller:** `MigrateConfigController`

| Method | Path                      | Description                                          |
| ------ | ------------------------- | ---------------------------------------------------- |
| `POST` | `/api/app/migrate-config` | Trigger configuration migration between environments |

***

### Modules

**Controller:** `ModulesController`

| Method        | Path                    | Description            |
| ------------- | ----------------------- | ---------------------- |
| `GET`         | `/api/app/modules`      | List modules           |
| Standard CRUD | `/api/app/modules/{id}` | Create, update, delete |

***

### Page Cards

**Controller:** `PageCardController`

| Method        | Path                       | Description            |
| ------------- | -------------------------- | ---------------------- |
| `GET`         | `/api/app/page-cards`      | List page cards        |
| Standard CRUD | `/api/app/page-cards/{id}` | Create, update, delete |

***

### Pages

**Controller:** `PageController` (inherits `AbpController`, not `NimbleController`)

| Method   | Path                                                  | Description                    |
| -------- | ----------------------------------------------------- | ------------------------------ |
| `GET`    | `/api/app/pages`                                      | Paged list of pages            |
| `GET`    | `/api/app/pages/{id}`                                 | Get page                       |
| `GET`    | `/api/app/pages/get-page-json-data?orgcode={orgcode}` | Get page JSON data by org code |
| `POST`   | `/api/app/pages`                                      | Create page                    |
| `PUT`    | `/api/app/pages/{id}`                                 | Update page                    |
| `DELETE` | `/api/app/pages/{id}`                                 | Delete page                    |

***

### Power BI

**Controller:** `PowerBIController`

| Method | Path               | Description                                       |
| ------ | ------------------ | ------------------------------------------------- |
| `GET`  | `/api/app/powerbi` | Get Power BI embed token and report configuration |

***

### Publish Config

**Controller:** `PublishConfigController`

| Method     | Path                                      | Description                   |
| ---------- | ----------------------------------------- | ----------------------------- |
| `POST`     | `/api/app/publish-config/publish-reports` | Publish report configuration  |
| Additional | `/api/app/publish-config/...`             | Additional publish operations |

***

### Reference Items

**Controller:** `ReferenceItemsController`

| Method        | Path                            | Description                   |
| ------------- | ------------------------------- | ----------------------------- |
| `GET`         | `/api/app/reference-items`      | Paged list of reference items |
| Standard CRUD | `/api/app/reference-items/{id}` | Create, update, delete        |

***

### Report Access Logs

**Controller:** `ReportAccessLogController`

| Method | Path                          | Description                                                    |
| ------ | ----------------------------- | -------------------------------------------------------------- |
| `POST` | `/api/app/report-access-logs` | Create a report access log entry (called on every report view) |

***

### Report Group Containers

**Controller:** `ReportGroupContainersController`

| Method        | Path                                    | Description                  |
| ------------- | --------------------------------------- | ---------------------------- |
| `GET`         | `/api/app/report-group-containers`      | List report group containers |
| Standard CRUD | `/api/app/report-group-containers/{id}` | Create, update, delete       |

***

### Routes

**Controller:** `RoutesController`

| Method        | Path                   | Description                                    |
| ------------- | ---------------------- | ---------------------------------------------- |
| `GET`         | `/api/app/routes`      | List active routes for the current user/tenant |
| Standard CRUD | `/api/app/routes/{id}` | Create, update, delete                         |

***

### Security Users

**Controller:** `SecurityUsersController`

| Method   | Path                                                     | Description                  |
| -------- | -------------------------------------------------------- | ---------------------------- |
| `GET`    | `/api/app/security-users`                                | Paged list of security users |
| `GET`    | `/api/app/security-users/{id}`                           | Get security user            |
| `GET`    | `/api/app/security-users/organization-unit-ids/{userId}` | Get org unit IDs for a user  |
| `POST`   | `/api/app/security-users`                                | Create security user         |
| `PUT`    | `/api/app/security-users/{id}`                           | Update security user         |
| `DELETE` | `/api/app/security-users/{id}`                           | Delete security user         |

***

### Site Reports

**Controller:** `SiteReportsController`

This controller deviates from the thin-delegation pattern: `CreateSessionAsync` reads MicroStrategy configuration directly from `IConfiguration` (`App:MicroStrategySessionServer`, `App:MicroStrategyPassword`).

| Method | Path                                   | Description                                |
| ------ | -------------------------------------- | ------------------------------------------ |
| `GET`  | `/api/app/site-reports`                | List site reports                          |
| `GET`  | `/api/app/site-reports/{id}`           | Get site report                            |
| `POST` | `/api/app/site-reports/create-session` | Create a MicroStrategy session             |
| `POST` | `/api/app/site-reports/view-report`    | View report data                           |
| `POST` | `/api/app/site-reports/filters`        | Get report filters (anti-forgery disabled) |
| `POST` | `/api/app/site-reports/form-filters`   | Get form filters                           |
| `POST` | `/api/app/site-reports/file-filters`   | Get file filters                           |

***

### Site Settings

**Controller:** `SiteSettingsController`

| Method | Path                     | Description                 |
| ------ | ------------------------ | --------------------------- |
| `GET`  | `/api/app/site-settings` | Get tenant site settings    |
| `PUT`  | `/api/app/site-settings` | Update tenant site settings |

***

### Store Messages and Message Types

**Controllers:** `StoreMessageController`, `MessageTypeController`

| Method        | Path                           | Description            |
| ------------- | ------------------------------ | ---------------------- |
| `GET`         | `/api/app/store-messages`      | List store messages    |
| Standard CRUD | `/api/app/store-messages/{id}` | Create, update, delete |
| `GET`         | `/api/app/message-types`       | List message types     |
| Standard CRUD | `/api/app/message-types/{id}`  | Create, update, delete |

***

### User Report Page Filters

**Controller:** `UserReportPageFiltersController`

| Method     | Path                                    | Description                                |
| ---------- | --------------------------------------- | ------------------------------------------ |
| `GET`      | `/api/app/user-report-page-filters`     | Get the current user's report page filters |
| Additional | `/api/app/user-report-page-filters/...` | Filter save and rebuild operations         |

***

## Module APIs — File Management

Provided by the forked `Volo.FileManagement` module.

| Controller                      | Endpoints                           |
| ------------------------------- | ----------------------------------- |
| `FileDescriptorController`      | File upload, download, rename, move |
| `DirectoryDescriptorController` | Directory CRUD, rename, move        |

***

## Module APIs — Forms

Provided by the forked `Volo.Forms` module.

| Controller           | Endpoints           |
| -------------------- | ------------------- |
| `FormController`     | Form CRUD           |
| `QuestionController` | Question management |
| `ResponseController` | Response handling   |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://nimble.docs.otised.com/technical/api-reference.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
