

# **AUTEURLABB**

**FRONTEND GUIDE FOR AI CODING AGENTS - PART 7 - ProjectPortfolio Service**

This document is a part of a REST API guide for the auteurlabb project.
It is designed for AI agents that will generate frontend code to consume the project’s backend.

This document provides extensive instruction for the usage of projectPortfolio

## Service Access

ProjectPortfolio service management is handled through service specific base urls.

ProjectPortfolio  service may be deployed to the preview server, staging server, or production server. Therefore,it has 3 access URLs.
The frontend application must support all deployment environments during development, and the user should be able to select the target API server on the login page (already handled in first part.).

For the projectPortfolio service, the base URLs are:

* **Preview:** `https://auteurlabb.prw.mindbricks.com/projectportfolio-api`
* **Staging:** `https://auteurlabb-stage.mindbricks.co/projectportfolio-api`
* **Production:** `https://auteurlabb.mindbricks.co/projectportfolio-api`


## Scope

**ProjectPortfolio Service Description**

Handles the lifecycle of film projects and access management, allowing filmmakers &amp; studios to submit, update, publish (public/private), withdraw projects, and manage project access for investors/bookmarks. Enforces admin approval &amp; efficient searching/filtering. Connects projects to user (and optionally studio) ownership.

ProjectPortfolio service provides apis and business logic for following data objects in auteurlabb application. 
Each data object may be either a central domain of the application data structure or a related helper data object for a central concept.
Note that data object concept is equal to table concept in the database, in the service database each data object is represented as a db table scheme and the object instances as table rows.  


**`filmProject` Data Object**: A film project submitted by a filmmaker or studio with all required metadata, visibility, and lifecycle status.

**`accessGrant` Data Object**: Access grants to private projects, allowing selected users to view restricted projects (requested/granted/revoked/denied).

**`projectBookmark` Data Object**: User bookmarks/follows for projects. Each bookmark is per user+project.

**`investmentOffer` Data Object**: Tracks investment offers from investors to film projects. Each offer has an amount, optional message, and status workflow (pending/accepted/rejected/withdrawn).

**`userFollow` Data Object**: Tracks user-to-user follow relationships. A follower follows a target user (filmmaker, studio, investor).


## ProjectPortfolio Service Frontend Description By The Backend Architect

# ProjectPortfolio Service
Use this service to browse, submit, access, and manage film projects. Project listings, details, bookmarks, and access requests are all managed here. Filmmakers/studios can control project visibility. Investors can search, request access, and bookmark. Admins can moderate, approve, and oversee lifecycle transitions. All project API responses may include owner/studio data via selectJoin when needed.

## API Structure

### Object Structure of a Successful Response

When the service processes requests successfully, it wraps the requested resource(s) within a JSON envelope. This envelope includes the data and essential metadata such as configuration details and pagination information, providing context to the client.

**HTTP Status Codes:**

* **200 OK**: Returned for successful GET, LIST, UPDATE, or DELETE operations, indicating that the request was processed successfully.
* **201 Created**: Returned for CREATE operations, indicating that the resource was created successfully.

**Success Response Format:**

For successful operations, the response includes a `"status": "OK"` property, signaling that the request executed successfully. The structure of a successful response is outlined below:

```json
{
  "status":"OK",
  "statusCode": 200,   
  "elapsedMs":126,
  "ssoTime":120,
  "source": "db",
  "cacheKey": "hexCode",
  "userId": "ID",
  "sessionId": "ID",
  "requestId": "ID",
  "dataName":"products",
  "method":"GET",
  "action":"list",
  "appVersion":"Version",
  "rowCount":3,
  "products":[{},{},{}],
  "paging": {
    "pageNumber":1, 
    "pageRowCount":25, 
    "totalRowCount":3,
    "pageCount":1
  },
  "filters": [],
  "uiPermissions": []
}
```
* **`products`**: In this example, this key contains the actual response content, which may be a single object or an array of objects depending on the operation.

### Additional Data

Each API may include additional data besides the main data object, depending on the business logic of the API. These will be provided in each API’s response signature.

### Error Response

If a request encounters an issue—whether due to a logical fault or a technical problem—the service responds with a standardized JSON error structure. The HTTP status code indicates the nature of the error, using commonly recognized codes for clarity:

* **400 Bad Request**: The request was improperly formatted or contained invalid parameters.
* **401 Unauthorized**: The request lacked a valid authentication token; login is required.
* **403 Forbidden**: The current token does not grant access to the requested resource.
* **404 Not Found**: The requested resource was not found on the server.
* **500 Internal Server Error**: The server encountered an unexpected condition.

Each error response is structured to provide meaningful insight into the problem, assisting in efficient diagnosis and resolution.

```js
{
  "result": "ERR",
  "status": 400,
  "message": "errMsg_organizationIdisNotAValidID",
  "errCode": 400,
  "date": "2024-03-19T12:13:54.124Z",
  "detail": "String"
}
```


## FilmProject Data Object

A film project submitted by a filmmaker or studio with all required metadata, visibility, and lifecycle status.

### FilmProject  Data Object Frontend Description By The Backend Architect

- Owners (filmmaker/studio) can submit, edit, withdraw projects.
- Admins approve/reject projects. Only approved & public projects are visible to all; private = access grants required.
- Investors can request/bookmark. Normal users can only view public, approved projects.
- UI should show current approver, access policy, and owner(s) on detail.


### FilmProject Data Object Properties

FilmProject data object has got following properties that are represented as table fields in the database scheme. 
These properties don't stand just for data storage, but each may have different settings to manage the business logic. 

| Property | Type | IsArray | Required | Secret | Description |
|----------|------|---------|----------|--------|-------------|
| `title` | String | false | Yes | No | Project title, unique per owner |
| `description` | Text | false | Yes | No | Project description (for details page/fulltext search) |
| `synopsis` | Text | false | No | No | Short synopsis or tagline |
| `budget` | Double | false | Yes | No | Estimated budget (USD) |
| `cast` | String | true | No | No | List of major cast members (names) |
| `genre` | String | true | No | No | Project genres/tags |
| `projectType` | Enum | false | Yes | No | Origin: filmmaker or studio |
| `ownerUserId` | ID | false | Yes | No | User ID of project owner (filmmaker/studio admin) |
| `studioId` | ID | false | No | No | (Optional) User ID of the studio (for studio projects) |
| `isPublic` | Boolean | false | Yes | No | Project public visibility flag |
| `approvalStatus` | Enum | false | Yes | No | Project approval/publication workflow status |
| `mediaUrls` | String | true | No | No | Project demo reel/trailer/cover media URLs |
| `featured` | Boolean | false | No | No | Platform feature flag (for promoted projects) |
| `publishedAt` | Date | false | No | No | Publication date |
| `accessPolicy` | Enum | false | Yes | No | Access policy (open: any authorized user, restricted: need grant) |
| `director` | String | false | No | No | Director of the film project |
| `fundingGoal` | Double | false | No | No | Funding goal amount (USD) |
* Required properties are mandatory for creating objects and must be provided in the request body if no default value, formula or session bind is set.


### Array Properties 

`cast` `genre` `mediaUrls`

Array properties can hold multiple values. 
Array properties should be respected according to their multiple structure in the frontend in any user input for them.
Please use multiple input components for the array proeprties when needed.


### Enum Properties
Enum properties are defined with a set of allowed values, ensuring that only valid options can be assigned to them. 
The enum options value will be stored as strings in the database, 
but when a data object is created an additional property with the same name plus an idx suffix will be created, which will hold the index of the selected enum option.
You can use the {fieldName_idx} property to sort by the enum value or when your enum options represent a hiyerarchy of values.
In the frontend input components, enum type properties should only accept values from an option component that lists the enum options.

- **projectType**: [filmmaker, studio]

- **approvalStatus**: [pending, approved, rejected, withdrawn]

- **accessPolicy**: [open, restricted]


### Relation Properties

`ownerUserId` `studioId`

Mindbricks supports relations between data objects, allowing you to define how objects are linked together.
The relations may reference to a data object either in this service or in another service. Id the reference is remote, backend handles the relations through service communication or elastic search.
These relations should be respected in the frontend so that instaead of showing the related objects id, the frontend should list human readable values from other data objects.
If the relation points to another service, frontend should use the referenced service api in case it needs related data.
The relation logic is montly handled in backend so the api responses feeds the frontend about the relational data. 
In mmost cases the api response will provide the relational data as well as the main one.

In frontend, please ensure that, 

1- instaead of these relational ids you show the main human readable field of the related target data (like name),
2- if this data object needs a user input of these relational ids, you should provide a combobox with the list of possible records or (a searchbox) to select with the realted target data object main human readable field.


- **ownerUserId**: ID
Relation to `user`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes

- **studioId**: ID
Relation to `user`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: No


### Filter Properties

`title` `description` `synopsis` `budget` `genre` `projectType` `isPublic` `approvalStatus` `featured` `accessPolicy` `director` `fundingGoal`

Filter properties are used to define parameters that can be used in query filters, allowing for dynamic data retrieval based on user input or predefined criteria.
These properties are automatically mapped as API parameters in the listing API's.

- **title**: String  has a filter named `title`

- **description**: Text  has a filter named `description`

- **synopsis**: Text  has a filter named `synopsis`

- **budget**: Double  has a filter named `budget`

- **genre**: String  has a filter named `genre`

- **projectType**: Enum  has a filter named `projectType`

- **isPublic**: Boolean  has a filter named `isPublic`

- **approvalStatus**: Enum  has a filter named `approvalStatus`

- **featured**: Boolean  has a filter named `featured`

- **accessPolicy**: Enum  has a filter named `accessPolicy`

- **director**: String  has a filter named `director`

- **fundingGoal**: Double  has a filter named `fundingGoal`


## AccessGrant Data Object

Access grants to private projects, allowing selected users to view restricted projects (requested/granted/revoked/denied).

### AccessGrant  Data Object Frontend Description By The Backend Architect

- For private (restricted) projects, this governs who can view the project in detail.
- Only owner/admin can grant/revoke directly; others can request (status=requested).
- Each grant/deny/revoke/change tracks who, when, and why; direct mapping to UI access control modals.


### AccessGrant Data Object Properties

AccessGrant data object has got following properties that are represented as table fields in the database scheme. 
These properties don't stand just for data storage, but each may have different settings to manage the business logic. 

| Property | Type | IsArray | Required | Secret | Description |
|----------|------|---------|----------|--------|-------------|
| `projectId` | ID | false | Yes | No | Film project ID for which access is granted/requested |
| `granteeUserId` | ID | false | Yes | No | ID of user being granted/requesting access |
| `grantedByUserId` | ID | false | No | No | Who granted/revoked the access (or null for self-request) |
| `status` | Enum | false | Yes | No | requested (pending); granted (success); revoked; denied |
| `requestMessage` | Text | false | No | No | Message from requester (for context) |
| `dateGranted` | Date | false | No | No | Timestamp when access status last updated |
* Required properties are mandatory for creating objects and must be provided in the request body if no default value, formula or session bind is set.



### Enum Properties
Enum properties are defined with a set of allowed values, ensuring that only valid options can be assigned to them. 
The enum options value will be stored as strings in the database, 
but when a data object is created an additional property with the same name plus an idx suffix will be created, which will hold the index of the selected enum option.
You can use the {fieldName_idx} property to sort by the enum value or when your enum options represent a hiyerarchy of values.
In the frontend input components, enum type properties should only accept values from an option component that lists the enum options.

- **status**: [requested, granted, revoked, denied]


### Relation Properties

`projectId` `granteeUserId` `grantedByUserId`

Mindbricks supports relations between data objects, allowing you to define how objects are linked together.
The relations may reference to a data object either in this service or in another service. Id the reference is remote, backend handles the relations through service communication or elastic search.
These relations should be respected in the frontend so that instaead of showing the related objects id, the frontend should list human readable values from other data objects.
If the relation points to another service, frontend should use the referenced service api in case it needs related data.
The relation logic is montly handled in backend so the api responses feeds the frontend about the relational data. 
In mmost cases the api response will provide the relational data as well as the main one.

In frontend, please ensure that, 

1- instaead of these relational ids you show the main human readable field of the related target data (like name),
2- if this data object needs a user input of these relational ids, you should provide a combobox with the list of possible records or (a searchbox) to select with the realted target data object main human readable field.


- **projectId**: ID
Relation to `filmProject`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes

- **granteeUserId**: ID
Relation to `user`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes

- **grantedByUserId**: ID
Relation to `user`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: No


### Filter Properties

`projectId` `granteeUserId` `status`

Filter properties are used to define parameters that can be used in query filters, allowing for dynamic data retrieval based on user input or predefined criteria.
These properties are automatically mapped as API parameters in the listing API's.

- **projectId**: ID  has a filter named `projectId`

- **granteeUserId**: ID  has a filter named `granteeUserId`

- **status**: Enum  has a filter named `status`


## ProjectBookmark Data Object

User bookmarks/follows for projects. Each bookmark is per user+project.

### ProjectBookmark  Data Object Frontend Description By The Backend Architect

- Users can bookmark projects for easy quick access.
- Bookmark is per-user & per-project. User can view, add, and remove their own bookmarks only.


### ProjectBookmark Data Object Properties

ProjectBookmark data object has got following properties that are represented as table fields in the database scheme. 
These properties don't stand just for data storage, but each may have different settings to manage the business logic. 

| Property | Type | IsArray | Required | Secret | Description |
|----------|------|---------|----------|--------|-------------|
| `projectId` | ID | false | Yes | No | The project being bookmarked |
| `userId` | ID | false | Yes | No | The user who bookmarked this project |
| `createdAtBookmark` | Date | false | No | No | When bookmark was made |
* Required properties are mandatory for creating objects and must be provided in the request body if no default value, formula or session bind is set.




### Relation Properties

`projectId` `userId`

Mindbricks supports relations between data objects, allowing you to define how objects are linked together.
The relations may reference to a data object either in this service or in another service. Id the reference is remote, backend handles the relations through service communication or elastic search.
These relations should be respected in the frontend so that instaead of showing the related objects id, the frontend should list human readable values from other data objects.
If the relation points to another service, frontend should use the referenced service api in case it needs related data.
The relation logic is montly handled in backend so the api responses feeds the frontend about the relational data. 
In mmost cases the api response will provide the relational data as well as the main one.

In frontend, please ensure that, 

1- instaead of these relational ids you show the main human readable field of the related target data (like name),
2- if this data object needs a user input of these relational ids, you should provide a combobox with the list of possible records or (a searchbox) to select with the realted target data object main human readable field.


- **projectId**: ID
Relation to `filmProject`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes

- **userId**: ID
Relation to `user`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes


### Filter Properties

`projectId` `userId`

Filter properties are used to define parameters that can be used in query filters, allowing for dynamic data retrieval based on user input or predefined criteria.
These properties are automatically mapped as API parameters in the listing API's.

- **projectId**: ID  has a filter named `projectId`

- **userId**: ID  has a filter named `userId`


## InvestmentOffer Data Object

Tracks investment offers from investors to film projects. Each offer has an amount, optional message, and status workflow (pending/accepted/rejected/withdrawn).



### InvestmentOffer Data Object Properties

InvestmentOffer data object has got following properties that are represented as table fields in the database scheme. 
These properties don't stand just for data storage, but each may have different settings to manage the business logic. 

| Property | Type | IsArray | Required | Secret | Description |
|----------|------|---------|----------|--------|-------------|
| `projectId` | ID | false | Yes | No | Film project receiving the investment offer |
| `investorUserId` | ID | false | Yes | No | Investor who made the offer |
| `offerAmount` | Double | false | Yes | No | Investment amount in USD |
| `message` | Text | false | No | No | Cover letter or terms from the investor |
| `status` | Enum | false | No | No | Offer lifecycle status |
| `respondedAt` | Date | false | No | No | When the project owner responded |
| `responseNote` | Text | false | No | No | Project owner note on accept/reject |
* Required properties are mandatory for creating objects and must be provided in the request body if no default value, formula or session bind is set.



### Enum Properties
Enum properties are defined with a set of allowed values, ensuring that only valid options can be assigned to them. 
The enum options value will be stored as strings in the database, 
but when a data object is created an additional property with the same name plus an idx suffix will be created, which will hold the index of the selected enum option.
You can use the {fieldName_idx} property to sort by the enum value or when your enum options represent a hiyerarchy of values.
In the frontend input components, enum type properties should only accept values from an option component that lists the enum options.

- **status**: [pending, accepted, rejected, withdrawn]


### Relation Properties

`projectId` `investorUserId`

Mindbricks supports relations between data objects, allowing you to define how objects are linked together.
The relations may reference to a data object either in this service or in another service. Id the reference is remote, backend handles the relations through service communication or elastic search.
These relations should be respected in the frontend so that instaead of showing the related objects id, the frontend should list human readable values from other data objects.
If the relation points to another service, frontend should use the referenced service api in case it needs related data.
The relation logic is montly handled in backend so the api responses feeds the frontend about the relational data. 
In mmost cases the api response will provide the relational data as well as the main one.

In frontend, please ensure that, 

1- instaead of these relational ids you show the main human readable field of the related target data (like name),
2- if this data object needs a user input of these relational ids, you should provide a combobox with the list of possible records or (a searchbox) to select with the realted target data object main human readable field.


- **projectId**: ID
Relation to `filmProject`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes

- **investorUserId**: ID
Relation to `user`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes


### Filter Properties

`projectId` `investorUserId` `offerAmount` `status`

Filter properties are used to define parameters that can be used in query filters, allowing for dynamic data retrieval based on user input or predefined criteria.
These properties are automatically mapped as API parameters in the listing API's.

- **projectId**: ID  has a filter named `projectId`

- **investorUserId**: ID  has a filter named `investorUserId`

- **offerAmount**: Double  has a filter named `offerAmount`

- **status**: Enum  has a filter named `status`


## UserFollow Data Object

Tracks user-to-user follow relationships. A follower follows a target user (filmmaker, studio, investor).



### UserFollow Data Object Properties

UserFollow data object has got following properties that are represented as table fields in the database scheme. 
These properties don't stand just for data storage, but each may have different settings to manage the business logic. 

| Property | Type | IsArray | Required | Secret | Description |
|----------|------|---------|----------|--------|-------------|
| `followerUserId` | ID | false | Yes | No | The user who is following |
| `followingUserId` | ID | false | Yes | No | The user being followed |
| `followedAt` | Date | false | No | No | When the follow relationship was created |
* Required properties are mandatory for creating objects and must be provided in the request body if no default value, formula or session bind is set.




### Relation Properties

`followerUserId` `followingUserId`

Mindbricks supports relations between data objects, allowing you to define how objects are linked together.
The relations may reference to a data object either in this service or in another service. Id the reference is remote, backend handles the relations through service communication or elastic search.
These relations should be respected in the frontend so that instaead of showing the related objects id, the frontend should list human readable values from other data objects.
If the relation points to another service, frontend should use the referenced service api in case it needs related data.
The relation logic is montly handled in backend so the api responses feeds the frontend about the relational data. 
In mmost cases the api response will provide the relational data as well as the main one.

In frontend, please ensure that, 

1- instaead of these relational ids you show the main human readable field of the related target data (like name),
2- if this data object needs a user input of these relational ids, you should provide a combobox with the list of possible records or (a searchbox) to select with the realted target data object main human readable field.


- **followerUserId**: ID
Relation to `user`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes

- **followingUserId**: ID
Relation to `user`.id

The target object is a parent object, meaning that the relation is a one-to-many relationship from target to this object.

Required: Yes


### Filter Properties

`followerUserId` `followingUserId`

Filter properties are used to define parameters that can be used in query filters, allowing for dynamic data retrieval based on user input or predefined criteria.
These properties are automatically mapped as API parameters in the listing API's.

- **followerUserId**: ID  has a filter named `followerUserId`

- **followingUserId**: ID  has a filter named `followingUserId`



## Default CRUD APIs

For each data object, the backend architect may designate **default APIs** for standard operations (create, update, delete, get, list). These are the APIs that frontend CRUD forms and AI agents should use for basic record management. If no default is explicitly set (`isDefaultApi`), the frontend generator auto-discovers the most general API for each operation.

### FilmProject Default APIs

**Display Label Property:** `title` — Use this property as the human-readable label when displaying records of this data object (e.g., in dropdowns, references).
| Operation | API Name | Route | Explicitly Set |
|-----------|----------|-------|----------------|
| Create | `createFilmProject` | `/v1/filmprojects` | Yes |
| Update | `updateFilmProject` | `/v1/filmprojects/:filmProjectId` | Yes |
| Delete | _none_ | - | Auto |
| Get | `getFilmProject` | `/v1/filmprojects/:filmProjectId` | Yes |
| List | `listFilmProjects` | `/v1/filmprojects` | Yes |
### AccessGrant Default APIs

| Operation | API Name | Route | Explicitly Set |
|-----------|----------|-------|----------------|
| Create | `createAccessGrant` | `/v1/accessgrants` | Yes |
| Update | `updateAccessGrant` | `/v1/accessgrants/:accessGrantId` | Yes |
| Delete | _none_ | - | Auto |
| Get | `getAccessGrant` | `/v1/accessgrants/:accessGrantId` | Yes |
| List | `listAccessGrants` | `/v1/accessgrants` | Yes |
### ProjectBookmark Default APIs

| Operation | API Name | Route | Explicitly Set |
|-----------|----------|-------|----------------|
| Create | `createBookmark` | `/v1/bookmark` | Yes |
| Update | _none_ | - | Auto |
| Delete | `deleteBookmark` | `/v1/bookmark/:projectBookmarkId` | Yes |
| Get | _none_ | - | Auto |
| List | `listBookmarks` | `/v1/bookmarks` | Yes |
### InvestmentOffer Default APIs

| Operation | API Name | Route | Explicitly Set |
|-----------|----------|-------|----------------|
| Create | `createInvestmentOffer` | `/v1/investmentoffers` | Yes |
| Update | `respondToInvestmentOffer` | `/v1/respondtoinvestmentoffer/:investmentOfferId` | Yes |
| Delete | _none_ | - | Auto |
| Get | _none_ | - | Auto |
| List | `listInvestmentOffers` | `/v1/investmentoffers` | Yes |
### UserFollow Default APIs

| Operation | API Name | Route | Explicitly Set |
|-----------|----------|-------|----------------|
| Create | `followUser` | `/v1/followuser` | Yes |
| Update | _none_ | - | Auto |
| Delete | `unfollowUser` | `/v1/unfollowuser/:userFollowId` | Yes |
| Get | _none_ | - | Auto |
| List | `listUserFollows` | `/v1/userfollows` | Yes |

When building CRUD forms for a data object, use the default create/update APIs listed above. The form fields should correspond to the API's body parameters. For relation fields, render a dropdown loaded from the related object's list API using the display label property.





## API Reference

### `Create Filmproject` API
**[Default create API]** — This is the designated default `create` API for the `filmProject` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Submit a new film project (by filmmaker/studio). Sets approvalStatus=pending and assigns ownerUserId from session. Studio projects require studioId.

**API Frontend Description By The Backend Architect**

Used by filmmakers/studios to submit a new project. Standard create form. Approval workflow starts automatically. Owner assigned from session.

**Rest Route**

The `createFilmProject` API REST controller can be triggered via the following route:

`/v1/filmprojects`


**Rest Request Parameters**


The `createFilmProject` api has got 15 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| title  | String  | true | request.body?.["title"] |
| description  | Text  | true | request.body?.["description"] |
| synopsis  | Text  | false | request.body?.["synopsis"] |
| budget  | Double  | true | request.body?.["budget"] |
| cast  | String  | false | request.body?.["cast"] |
| genre  | String  | false | request.body?.["genre"] |
| projectType  | Enum  | true | request.body?.["projectType"] |
| studioId  | ID  | false | request.body?.["studioId"] |
| isPublic  | Boolean  | true | request.body?.["isPublic"] |
| mediaUrls  | String  | false | request.body?.["mediaUrls"] |
| featured  | Boolean  | false | request.body?.["featured"] |
| publishedAt  | Date  | false | request.body?.["publishedAt"] |
| accessPolicy  | Enum  | true | request.body?.["accessPolicy"] |
| director  | String  | false | request.body?.["director"] |
| fundingGoal  | Double  | false | request.body?.["fundingGoal"] |
**title** : Project title, unique per owner
**description** : Project description (for details page/fulltext search)
**synopsis** : Short synopsis or tagline
**budget** : Estimated budget (USD)
**cast** : List of major cast members (names)
**genre** : Project genres/tags
**projectType** : Origin: filmmaker or studio
**studioId** : (Optional) User ID of the studio (for studio projects)
**isPublic** : Project public visibility flag
**mediaUrls** : Project demo reel/trailer/cover media URLs
**featured** : Platform feature flag (for promoted projects)
**publishedAt** : Publication date
**accessPolicy** : Access policy (open: any authorized user, restricted: need grant)
**director** : Director of the film project
**fundingGoal** : Funding goal amount (USD)



**REST Request**
To access the api you can use the **REST** controller with the path **POST  /v1/filmprojects**
```js
  axios({
    method: 'POST',
    url: '/v1/filmprojects',
    data: {
            title:"String",  
            description:"Text",  
            synopsis:"Text",  
            budget:"Double",  
            cast:"String",  
            genre:"String",  
            projectType:"Enum",  
            studioId:"ID",  
            isPublic:"Boolean",  
            mediaUrls:"String",  
            featured:"Boolean",  
            publishedAt:"Date",  
            accessPolicy:"Enum",  
            director:"String",  
            fundingGoal:"Double",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "filmProject",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"filmProject": {
		"id": "ID",
		"title": "String",
		"description": "Text",
		"synopsis": "Text",
		"budget": "Double",
		"cast": "String",
		"genre": "String",
		"projectType": "Enum",
		"projectType_idx": "Integer",
		"ownerUserId": "ID",
		"studioId": "ID",
		"isPublic": "Boolean",
		"approvalStatus": "Enum",
		"approvalStatus_idx": "Integer",
		"mediaUrls": "String",
		"featured": "Boolean",
		"publishedAt": "Date",
		"accessPolicy": "Enum",
		"accessPolicy_idx": "Integer",
		"director": "String",
		"fundingGoal": "Double",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `Update Filmproject` API
**[Default update API]** — This is the designated default `update` API for the `filmProject` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Update a film project. Only the owner or admin can update. Only admin can set approvalStatus=approved/rejected. Owner can withdraw (approvalStatus=withdrawn).

**API Frontend Description By The Backend Architect**

For editing project details (including withdrawal). ApprovalStatus can only be changed by admin (other than withdrawn by owner). Owner cannot submit direct publish/approve requests; always wait admin.

**Rest Route**

The `updateFilmProject` API REST controller can be triggered via the following route:

`/v1/filmprojects/:filmProjectId`


**Rest Request Parameters**


The `updateFilmProject` api has got 15 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| filmProjectId  | ID  | true | request.params?.["filmProjectId"] |
| title  | String  | false | request.body?.["title"] |
| description  | Text  | false | request.body?.["description"] |
| synopsis  | Text  | false | request.body?.["synopsis"] |
| budget  | Double  | false | request.body?.["budget"] |
| cast  | String  | false | request.body?.["cast"] |
| genre  | String  | false | request.body?.["genre"] |
| isPublic  | Boolean  | false | request.body?.["isPublic"] |
| approvalStatus  | Enum  | true | request.body?.["approvalStatus"] |
| mediaUrls  | String  | false | request.body?.["mediaUrls"] |
| featured  | Boolean  | false | request.body?.["featured"] |
| publishedAt  | Date  | false | request.body?.["publishedAt"] |
| accessPolicy  | Enum  | false | request.body?.["accessPolicy"] |
| director  | String  | false | request.body?.["director"] |
| fundingGoal  | Double  | false | request.body?.["fundingGoal"] |
**filmProjectId** : This id paremeter is used to select the required data object that will be updated
**title** : Project title, unique per owner
**description** : Project description (for details page/fulltext search)
**synopsis** : Short synopsis or tagline
**budget** : Estimated budget (USD)
**cast** : List of major cast members (names)
**genre** : Project genres/tags
**isPublic** : Project public visibility flag
**approvalStatus** : Project approval/publication workflow status
**mediaUrls** : Project demo reel/trailer/cover media URLs
**featured** : Platform feature flag (for promoted projects)
**publishedAt** : Publication date
**accessPolicy** : Access policy (open: any authorized user, restricted: need grant)
**director** : Director of the film project
**fundingGoal** : Funding goal amount (USD)



**REST Request**
To access the api you can use the **REST** controller with the path **PATCH  /v1/filmprojects/:filmProjectId**
```js
  axios({
    method: 'PATCH',
    url: `/v1/filmprojects/${filmProjectId}`,
    data: {
            title:"String",  
            description:"Text",  
            synopsis:"Text",  
            budget:"Double",  
            cast:"String",  
            genre:"String",  
            isPublic:"Boolean",  
            approvalStatus:"Enum",  
            mediaUrls:"String",  
            featured:"Boolean",  
            publishedAt:"Date",  
            accessPolicy:"Enum",  
            director:"String",  
            fundingGoal:"Double",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "filmProject",
	"method": "PATCH",
	"action": "update",
	"appVersion": "Version",
	"rowCount": 1,
	"filmProject": {
		"id": "ID",
		"title": "String",
		"description": "Text",
		"synopsis": "Text",
		"budget": "Double",
		"cast": "String",
		"genre": "String",
		"projectType": "Enum",
		"projectType_idx": "Integer",
		"ownerUserId": "ID",
		"studioId": "ID",
		"isPublic": "Boolean",
		"approvalStatus": "Enum",
		"approvalStatus_idx": "Integer",
		"mediaUrls": "String",
		"featured": "Boolean",
		"publishedAt": "Date",
		"accessPolicy": "Enum",
		"accessPolicy_idx": "Integer",
		"director": "String",
		"fundingGoal": "Double",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	},
	"ownerUser": {}
}
```


### `Get Filmproject` API
**[Default get API]** — This is the designated default `get` API for the `filmProject` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Fetch project details. Accessible by owner, admin, or for public + approved projects. Also for granted investors/users (accessGrant).

**API Frontend Description By The Backend Architect**

Used to display project details page. Applies access and visibility policy -- if project is private, only owner/admin/granted users can see; if public+approved, visible to everyone logged in. User denied access gets 404.

**Rest Route**

The `getFilmProject` API REST controller can be triggered via the following route:

`/v1/filmprojects/:filmProjectId`


**Rest Request Parameters**


The `getFilmProject` api has got 1 regular request parameter  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| filmProjectId  | ID  | true | request.params?.["filmProjectId"] |
**filmProjectId** : This id paremeter is used to query the required data object.



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/filmprojects/:filmProjectId**
```js
  axios({
    method: 'GET',
    url: `/v1/filmprojects/${filmProjectId}`,
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**

This route's response is constrained to a select list of properties, and therefore does not encompass all attributes of the resource.

```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "filmProject",
	"method": "GET",
	"action": "get",
	"appVersion": "Version",
	"rowCount": 1,
	"filmProject": {
		"ownerUser": {
			"fullname": "String",
			"avatar": "String",
			"roleId": "String"
		},
		"studio": {
			"fullname": "String",
			"avatar": "String",
			"roleId": "String"
		},
		"isActive": true
	}
}
```


### `List Filmprojects` API
**[Default list API]** — This is the designated default `list` API for the `filmProject` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
List projects (public+approved, owned, or where granted). With filters for search. Results by role: owner/all their projects; normal users see only public+approved; investors/studios see owned or accessible, or public+approved. Filters: genre, budget, approvalStatus, isPublic, featured, projectType, title, description (text search).

**API Frontend Description By The Backend Architect**

Allows all users to search/browse projects. Only public/approved projects are visible to normal users; owners/investors get private projects to which they're granted. Search by genre, budget, etc. Use for the main project directory.

**Rest Route**

The `listFilmProjects` API REST controller can be triggered via the following route:

`/v1/filmprojects`


**Rest Request Parameters**
The `listFilmProjects` api has got no request parameters.    




**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/filmprojects**
```js
  axios({
    method: 'GET',
    url: '/v1/filmprojects',
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**

This route's response is constrained to a select list of properties, and therefore does not encompass all attributes of the resource.

```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "filmProjects",
	"method": "GET",
	"action": "list",
	"appVersion": "Version",
	"rowCount": "\"Number\"",
	"filmProjects": [
		{
			"ownerUser": [
				{
					"fullname": "String",
					"avatar": "String",
					"roleId": "String"
				},
				{},
				{}
			],
			"isActive": true
		},
		{},
		{}
	],
	"paging": {
		"pageNumber": "Number",
		"pageRowCount": "NUmber",
		"totalRowCount": "Number",
		"pageCount": "Number"
	},
	"filters": [],
	"uiPermissions": []
}
```


### `Create Accessgrant` API
**[Default create API]** — This is the designated default `create` API for the `accessGrant` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Create a new accessGrant. Used for access requests (user) or direct grant (owner/admin).

**API Frontend Description By The Backend Architect**

Investors request access to private/restricted projects; project owners or admins grant/revoke access to users. Status flows: requested→granted/denied/revoked. Owner can only grant/revoke their own; admins can manage all.

**Rest Route**

The `createAccessGrant` API REST controller can be triggered via the following route:

`/v1/accessgrants`


**Rest Request Parameters**


The `createAccessGrant` api has got 6 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| projectId  | ID  | true | request.body?.["projectId"] |
| granteeUserId  | ID  | true | request.body?.["granteeUserId"] |
| grantedByUserId  | ID  | false | request.body?.["grantedByUserId"] |
| status  | Enum  | true | request.body?.["status"] |
| requestMessage  | Text  | false | request.body?.["requestMessage"] |
| dateGranted  | Date  | false | request.body?.["dateGranted"] |
**projectId** : Film project ID for which access is granted/requested
**granteeUserId** : ID of user being granted/requesting access
**grantedByUserId** : Who granted/revoked the access (or null for self-request)
**status** : requested (pending); granted (success); revoked; denied
**requestMessage** : Message from requester (for context)
**dateGranted** : Timestamp when access status last updated



**REST Request**
To access the api you can use the **REST** controller with the path **POST  /v1/accessgrants**
```js
  axios({
    method: 'POST',
    url: '/v1/accessgrants',
    data: {
            projectId:"ID",  
            granteeUserId:"ID",  
            grantedByUserId:"ID",  
            status:"Enum",  
            requestMessage:"Text",  
            dateGranted:"Date",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "accessGrant",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"accessGrant": {
		"id": "ID",
		"projectId": "ID",
		"granteeUserId": "ID",
		"grantedByUserId": "ID",
		"status": "Enum",
		"status_idx": "Integer",
		"requestMessage": "Text",
		"dateGranted": "Date",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `Update Accessgrant` API
**[Default update API]** — This is the designated default `update` API for the `accessGrant` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Update status of an access grant. Only admin or project owner can grant, revoke, or deny. User can cancel (delete) their own pending request or see status.

**API Frontend Description By The Backend Architect**

Used for access management UI. Owners/admins can grant/revoke/deny access grants; requesters can cancel. For status transitions, always log who did it and when. Only valid transitions possible (ex: can't grant if not owner/admin).

**Rest Route**

The `updateAccessGrant` API REST controller can be triggered via the following route:

`/v1/accessgrants/:accessGrantId`


**Rest Request Parameters**


The `updateAccessGrant` api has got 4 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| accessGrantId  | ID  | true | request.params?.["accessGrantId"] |
| status  | Enum  | true | request.body?.["status"] |
| requestMessage  | Text  | false | request.body?.["requestMessage"] |
| dateGranted  | Date  | false | request.body?.["dateGranted"] |
**accessGrantId** : This id paremeter is used to select the required data object that will be updated
**status** : requested (pending); granted (success); revoked; denied
**requestMessage** : Message from requester (for context)
**dateGranted** : Timestamp when access status last updated



**REST Request**
To access the api you can use the **REST** controller with the path **PATCH  /v1/accessgrants/:accessGrantId**
```js
  axios({
    method: 'PATCH',
    url: `/v1/accessgrants/${accessGrantId}`,
    data: {
            status:"Enum",  
            requestMessage:"Text",  
            dateGranted:"Date",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "accessGrant",
	"method": "PATCH",
	"action": "update",
	"appVersion": "Version",
	"rowCount": 1,
	"accessGrant": {
		"id": "ID",
		"projectId": "ID",
		"granteeUserId": "ID",
		"grantedByUserId": "ID",
		"status": "Enum",
		"status_idx": "Integer",
		"requestMessage": "Text",
		"dateGranted": "Date",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `Get Accessgrant` API
**[Default get API]** — This is the designated default `get` API for the `accessGrant` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Get a single accessGrant record by id. Used for grant management UI.

**API Frontend Description By The Backend Architect**

Shows a single access grant: who, for what project, current status, request message.

**Rest Route**

The `getAccessGrant` API REST controller can be triggered via the following route:

`/v1/accessgrants/:accessGrantId`


**Rest Request Parameters**


The `getAccessGrant` api has got 1 regular request parameter  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| accessGrantId  | ID  | true | request.params?.["accessGrantId"] |
**accessGrantId** : This id paremeter is used to query the required data object.



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/accessgrants/:accessGrantId**
```js
  axios({
    method: 'GET',
    url: `/v1/accessgrants/${accessGrantId}`,
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "accessGrant",
	"method": "GET",
	"action": "get",
	"appVersion": "Version",
	"rowCount": 1,
	"accessGrant": {
		"id": "ID",
		"projectId": "ID",
		"granteeUserId": "ID",
		"grantedByUserId": "ID",
		"status": "Enum",
		"status_idx": "Integer",
		"requestMessage": "Text",
		"dateGranted": "Date",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `List Accessgrants` API
**[Default list API]** — This is the designated default `list` API for the `accessGrant` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
List all accessGrants for a project (owner/admin) or for a user (user's own requests).

**API Frontend Description By The Backend Architect**

Used by project owners/admins to see all access requests; by users to see their own requests & statuses. Investors check their granted projects for dashboard; owners manage through this list.

**Rest Route**

The `listAccessGrants` API REST controller can be triggered via the following route:

`/v1/accessgrants`


**Rest Request Parameters**



**Filter Parameters**

The `listAccessGrants` api supports 3 optional filter parameters for filtering list results:

**projectId** (`ID`): Film project ID for which access is granted/requested

- Single: `?projectId=<value>`
- Multiple: `?projectId=<value1>&projectId=<value2>`
- Null: `?projectId=null`


**granteeUserId** (`ID`): ID of user being granted/requesting access

- Single: `?granteeUserId=<value>`
- Multiple: `?granteeUserId=<value1>&granteeUserId=<value2>`
- Null: `?granteeUserId=null`


**status** (`Enum`): requested (pending); granted (success); revoked; denied

- Single: `?status=<value>` (case-insensitive)
- Multiple: `?status=<value1>&status=<value2>`
- Null: `?status=null`



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/accessgrants**
```js
  axios({
    method: 'GET',
    url: '/v1/accessgrants',
    data: {
    
    },
    params: {
    
        // Filter parameters (see Filter Parameters section above)
        // projectId: '<value>' // Filter by projectId
        // granteeUserId: '<value>' // Filter by granteeUserId
        // status: '<value>' // Filter by status
            }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "accessGrants",
	"method": "GET",
	"action": "list",
	"appVersion": "Version",
	"rowCount": "\"Number\"",
	"accessGrants": [
		{
			"id": "ID",
			"projectId": "ID",
			"granteeUserId": "ID",
			"grantedByUserId": "ID",
			"status": "Enum",
			"status_idx": "Integer",
			"requestMessage": "Text",
			"dateGranted": "Date",
			"isActive": true,
			"recordVersion": "Integer",
			"createdAt": "Date",
			"updatedAt": "Date",
			"_owner": "ID"
		},
		{},
		{}
	],
	"paging": {
		"pageNumber": "Number",
		"pageRowCount": "NUmber",
		"totalRowCount": "Number",
		"pageCount": "Number"
	},
	"filters": [],
	"uiPermissions": []
}
```


### `Create Bookmark` API
**[Default create API]** — This is the designated default `create` API for the `projectBookmark` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Add a project bookmark (user/project pair, unique).

**API Frontend Description By The Backend Architect**

Users bookmark projects for easy retrieval. Only one bookmark per (user, project).

**Rest Route**

The `createBookmark` API REST controller can be triggered via the following route:

`/v1/bookmark`


**Rest Request Parameters**


The `createBookmark` api has got 1 regular request parameter  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| projectId  | ID  | true | request.body?.["projectId"] |
**projectId** : The project being bookmarked



**REST Request**
To access the api you can use the **REST** controller with the path **POST  /v1/bookmark**
```js
  axios({
    method: 'POST',
    url: '/v1/bookmark',
    data: {
            projectId:"ID",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "projectBookmark",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"projectBookmark": {
		"id": "ID",
		"projectId": "ID",
		"userId": "ID",
		"createdAtBookmark": "Date",
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID",
		"isActive": true
	}
}
```


### `Delete Bookmark` API
**[Default delete API]** — This is the designated default `delete` API for the `projectBookmark` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Remove a project bookmark (user can only delete their own bookmarks).

**API Frontend Description By The Backend Architect**

Bookmarks are always per-user: can only remove bookmark if you're the owner.

**Rest Route**

The `deleteBookmark` API REST controller can be triggered via the following route:

`/v1/bookmark/:projectBookmarkId`


**Rest Request Parameters**


The `deleteBookmark` api has got 1 regular request parameter  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| projectBookmarkId  | ID  | true | request.params?.["projectBookmarkId"] |
**projectBookmarkId** : This id paremeter is used to select the required data object that will be deleted



**REST Request**
To access the api you can use the **REST** controller with the path **DELETE  /v1/bookmark/:projectBookmarkId**
```js
  axios({
    method: 'DELETE',
    url: `/v1/bookmark/${projectBookmarkId}`,
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "projectBookmark",
	"method": "DELETE",
	"action": "delete",
	"appVersion": "Version",
	"rowCount": 1,
	"projectBookmark": {
		"id": "ID",
		"projectId": "ID",
		"userId": "ID",
		"createdAtBookmark": "Date",
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID",
		"isActive": false
	}
}
```


### `List Bookmarks` API
**[Default list API]** — This is the designated default `list` API for the `projectBookmark` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
List a user's own bookmarks. Only accessible for current user. Used for profile/bookmarks view.

**API Frontend Description By The Backend Architect**

Used for the user's My Bookmarks page. Always lists only YOUR bookmarks, never others'.

**Rest Route**

The `listBookmarks` API REST controller can be triggered via the following route:

`/v1/bookmarks`


**Rest Request Parameters**



**Filter Parameters**

The `listBookmarks` api supports 2 optional filter parameters for filtering list results:

**projectId** (`ID`): The project being bookmarked

- Single: `?projectId=<value>`
- Multiple: `?projectId=<value1>&projectId=<value2>`
- Null: `?projectId=null`


**userId** (`ID`): The user who bookmarked this project

- Single: `?userId=<value>`
- Multiple: `?userId=<value1>&userId=<value2>`
- Null: `?userId=null`



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/bookmarks**
```js
  axios({
    method: 'GET',
    url: '/v1/bookmarks',
    data: {
    
    },
    params: {
    
        // Filter parameters (see Filter Parameters section above)
        // projectId: '<value>' // Filter by projectId
        // userId: '<value>' // Filter by userId
            }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "projectBookmarks",
	"method": "GET",
	"action": "list",
	"appVersion": "Version",
	"rowCount": "\"Number\"",
	"projectBookmarks": [
		{
			"id": "ID",
			"projectId": "ID",
			"userId": "ID",
			"createdAtBookmark": "Date",
			"recordVersion": "Integer",
			"createdAt": "Date",
			"updatedAt": "Date",
			"_owner": "ID",
			"isActive": true
		},
		{},
		{}
	],
	"paging": {
		"pageNumber": "Number",
		"pageRowCount": "NUmber",
		"totalRowCount": "Number",
		"pageCount": "Number"
	},
	"filters": [],
	"uiPermissions": []
}
```


### `Create Investmentoffer` API
**[Default create API]** — This is the designated default `create` API for the `investmentOffer` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Investor sends an investment offer to a film project. Status defaults to pending. Only investors can create offers.


**Rest Route**

The `createInvestmentOffer` API REST controller can be triggered via the following route:

`/v1/investmentoffers`


**Rest Request Parameters**


The `createInvestmentOffer` api has got 5 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| projectId  | ID  | true | request.body?.["projectId"] |
| offerAmount  | Double  | true | request.body?.["offerAmount"] |
| message  | Text  | false | request.body?.["message"] |
| respondedAt  | Date  | false | request.body?.["respondedAt"] |
| responseNote  | Text  | false | request.body?.["responseNote"] |
**projectId** : Film project receiving the investment offer
**offerAmount** : Investment amount in USD
**message** : Cover letter or terms from the investor
**respondedAt** : When the project owner responded
**responseNote** : Project owner note on accept/reject



**REST Request**
To access the api you can use the **REST** controller with the path **POST  /v1/investmentoffers**
```js
  axios({
    method: 'POST',
    url: '/v1/investmentoffers',
    data: {
            projectId:"ID",  
            offerAmount:"Double",  
            message:"Text",  
            respondedAt:"Date",  
            responseNote:"Text",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "investmentOffer",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"investmentOffer": {
		"id": "ID",
		"projectId": "ID",
		"investorUserId": "ID",
		"offerAmount": "Double",
		"message": "Text",
		"status": "Enum",
		"status_idx": "Integer",
		"respondedAt": "Date",
		"responseNote": "Text",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `Respond Toinvestmentoffer` API
**[Default update API]** — This is the designated default `update` API for the `investmentOffer` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Project owner accepts or rejects an investment offer. Only the project owner or admin can respond.


**Rest Route**

The `respondToInvestmentOffer` API REST controller can be triggered via the following route:

`/v1/respondtoinvestmentoffer/:investmentOfferId`


**Rest Request Parameters**


The `respondToInvestmentOffer` api has got 6 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| investmentOfferId  | ID  | true | request.params?.["investmentOfferId"] |
| offerAmount  | Double  | false | request.body?.["offerAmount"] |
| message  | Text  | false | request.body?.["message"] |
| status  | Enum  | false | request.body?.["status"] |
| respondedAt  | Date  | false | request.body?.["respondedAt"] |
| responseNote  | Text  | false | request.body?.["responseNote"] |
**investmentOfferId** : This id paremeter is used to select the required data object that will be updated
**offerAmount** : Investment amount in USD
**message** : Cover letter or terms from the investor
**status** : Offer lifecycle status
**respondedAt** : When the project owner responded
**responseNote** : Project owner note on accept/reject



**REST Request**
To access the api you can use the **REST** controller with the path **PATCH  /v1/respondtoinvestmentoffer/:investmentOfferId**
```js
  axios({
    method: 'PATCH',
    url: `/v1/respondtoinvestmentoffer/${investmentOfferId}`,
    data: {
            offerAmount:"Double",  
            message:"Text",  
            status:"Enum",  
            respondedAt:"Date",  
            responseNote:"Text",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "investmentOffer",
	"method": "PATCH",
	"action": "update",
	"appVersion": "Version",
	"rowCount": 1,
	"investmentOffer": {
		"id": "ID",
		"projectId": "ID",
		"investorUserId": "ID",
		"offerAmount": "Double",
		"message": "Text",
		"status": "Enum",
		"status_idx": "Integer",
		"respondedAt": "Date",
		"responseNote": "Text",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `List Investmentoffers` API
**[Default list API]** — This is the designated default `list` API for the `investmentOffer` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
List investment offers. Admins see all, investors see their own, filmmakers/studios see offers on their projects.


**Rest Route**

The `listInvestmentOffers` API REST controller can be triggered via the following route:

`/v1/investmentoffers`


**Rest Request Parameters**



**Filter Parameters**

The `listInvestmentOffers` api supports 4 optional filter parameters for filtering list results:

**projectId** (`ID`): Film project receiving the investment offer

- Single: `?projectId=<value>`
- Multiple: `?projectId=<value1>&projectId=<value2>`
- Null: `?projectId=null`


**investorUserId** (`ID`): Investor who made the offer

- Single: `?investorUserId=<value>`
- Multiple: `?investorUserId=<value1>&investorUserId=<value2>`
- Null: `?investorUserId=null`


**offerAmount** (`Double`): Investment amount in USD

- Single: `?offerAmount=<value>`
- Multiple: `?offerAmount=<value1>&offerAmount=<value2>`
- Range: `?offerAmount=$lt-<value>`, `$lte-`, `$gt-`, `$gte-`, `$btw-<min>-<max>`
- Null: `?offerAmount=null`


**status** (`Enum`): Offer lifecycle status

- Single: `?status=<value>` (case-insensitive)
- Multiple: `?status=<value1>&status=<value2>`
- Null: `?status=null`



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/investmentoffers**
```js
  axios({
    method: 'GET',
    url: '/v1/investmentoffers',
    data: {
    
    },
    params: {
    
        // Filter parameters (see Filter Parameters section above)
        // projectId: '<value>' // Filter by projectId
        // investorUserId: '<value>' // Filter by investorUserId
        // offerAmount: '<value>' // Filter by offerAmount
        // status: '<value>' // Filter by status
            }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "investmentOffers",
	"method": "GET",
	"action": "list",
	"appVersion": "Version",
	"rowCount": "\"Number\"",
	"investmentOffers": [
		{
			"id": "ID",
			"projectId": "ID",
			"investorUserId": "ID",
			"offerAmount": "Double",
			"message": "Text",
			"status": "Enum",
			"status_idx": "Integer",
			"respondedAt": "Date",
			"responseNote": "Text",
			"isActive": true,
			"recordVersion": "Integer",
			"createdAt": "Date",
			"updatedAt": "Date",
			"_owner": "ID"
		},
		{},
		{}
	],
	"paging": {
		"pageNumber": "Number",
		"pageRowCount": "NUmber",
		"totalRowCount": "Number",
		"pageCount": "Number"
	},
	"filters": [],
	"uiPermissions": []
}
```


### `Withdraw Investmentoffer` API
Investor withdraws their own pending offer. Sets status to withdrawn.


**Rest Route**

The `withdrawInvestmentOffer` API REST controller can be triggered via the following route:

`/v1/withdrawinvestmentoffer/:investmentOfferId`


**Rest Request Parameters**


The `withdrawInvestmentOffer` api has got 6 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| investmentOfferId  | ID  | true | request.params?.["investmentOfferId"] |
| offerAmount  | Double  | false | request.body?.["offerAmount"] |
| message  | Text  | false | request.body?.["message"] |
| status  | Enum  | false | request.body?.["status"] |
| respondedAt  | Date  | false | request.body?.["respondedAt"] |
| responseNote  | Text  | false | request.body?.["responseNote"] |
**investmentOfferId** : This id paremeter is used to select the required data object that will be updated
**offerAmount** : Investment amount in USD
**message** : Cover letter or terms from the investor
**status** : Offer lifecycle status
**respondedAt** : When the project owner responded
**responseNote** : Project owner note on accept/reject



**REST Request**
To access the api you can use the **REST** controller with the path **PATCH  /v1/withdrawinvestmentoffer/:investmentOfferId**
```js
  axios({
    method: 'PATCH',
    url: `/v1/withdrawinvestmentoffer/${investmentOfferId}`,
    data: {
            offerAmount:"Double",  
            message:"Text",  
            status:"Enum",  
            respondedAt:"Date",  
            responseNote:"Text",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "investmentOffer",
	"method": "PATCH",
	"action": "update",
	"appVersion": "Version",
	"rowCount": 1,
	"investmentOffer": {
		"id": "ID",
		"projectId": "ID",
		"investorUserId": "ID",
		"offerAmount": "Double",
		"message": "Text",
		"status": "Enum",
		"status_idx": "Integer",
		"respondedAt": "Date",
		"responseNote": "Text",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `Follow User` API
**[Default create API]** — This is the designated default `create` API for the `userFollow` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Follow a user. Creates a follow relationship between the session user and the target user. Duplicate follows are prevented by composite index.


**Rest Route**

The `followUser` API REST controller can be triggered via the following route:

`/v1/followuser`


**Rest Request Parameters**


The `followUser` api has got 2 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| followingUserId  | ID  | true | request.body?.["followingUserId"] |
| followedAt  | Date  | false | request.body?.["followedAt"] |
**followingUserId** : The user being followed
**followedAt** : When the follow relationship was created



**REST Request**
To access the api you can use the **REST** controller with the path **POST  /v1/followuser**
```js
  axios({
    method: 'POST',
    url: '/v1/followuser',
    data: {
            followingUserId:"ID",  
            followedAt:"Date",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "userFollow",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"userFollow": {
		"id": "ID",
		"followerUserId": "ID",
		"followingUserId": "ID",
		"followedAt": "Date",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `Unfollow User` API
**[Default delete API]** — This is the designated default `delete` API for the `userFollow` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
Unfollow a user. Removes the follow relationship. Only the follower (owner) can unfollow.


**Rest Route**

The `unfollowUser` API REST controller can be triggered via the following route:

`/v1/unfollowuser/:userFollowId`


**Rest Request Parameters**


The `unfollowUser` api has got 1 regular request parameter  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| userFollowId  | ID  | true | request.params?.["userFollowId"] |
**userFollowId** : This id paremeter is used to select the required data object that will be deleted



**REST Request**
To access the api you can use the **REST** controller with the path **DELETE  /v1/unfollowuser/:userFollowId**
```js
  axios({
    method: 'DELETE',
    url: `/v1/unfollowuser/${userFollowId}`,
    data: {
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "userFollow",
	"method": "DELETE",
	"action": "delete",
	"appVersion": "Version",
	"rowCount": 1,
	"userFollow": {
		"id": "ID",
		"followerUserId": "ID",
		"followingUserId": "ID",
		"followedAt": "Date",
		"isActive": false,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```


### `List Userfollows` API
**[Default list API]** — This is the designated default `list` API for the `userFollow` data object. Frontend generators and AI agents should use this API for standard CRUD operations.
List follow relationships. Filter by followerUserId to get who a user follows, or by followingUserId to get a user's followers.


**Rest Route**

The `listUserFollows` API REST controller can be triggered via the following route:

`/v1/userfollows`


**Rest Request Parameters**



**Filter Parameters**

The `listUserFollows` api supports 2 optional filter parameters for filtering list results:

**followerUserId** (`ID`): The user who is following

- Single: `?followerUserId=<value>`
- Multiple: `?followerUserId=<value1>&followerUserId=<value2>`
- Null: `?followerUserId=null`


**followingUserId** (`ID`): The user being followed

- Single: `?followingUserId=<value>`
- Multiple: `?followingUserId=<value1>&followingUserId=<value2>`
- Null: `?followingUserId=null`



**REST Request**
To access the api you can use the **REST** controller with the path **GET  /v1/userfollows**
```js
  axios({
    method: 'GET',
    url: '/v1/userfollows',
    data: {
    
    },
    params: {
    
        // Filter parameters (see Filter Parameters section above)
        // followerUserId: '<value>' // Filter by followerUserId
        // followingUserId: '<value>' // Filter by followingUserId
            }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "200",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "userFollows",
	"method": "GET",
	"action": "list",
	"appVersion": "Version",
	"rowCount": "\"Number\"",
	"userFollows": [
		{
			"id": "ID",
			"followerUserId": "ID",
			"followingUserId": "ID",
			"followedAt": "Date",
			"isActive": true,
			"recordVersion": "Integer",
			"createdAt": "Date",
			"updatedAt": "Date",
			"_owner": "ID"
		},
		{},
		{}
	],
	"paging": {
		"pageNumber": "Number",
		"pageRowCount": "NUmber",
		"totalRowCount": "Number",
		"pageCount": "Number"
	},
	"filters": [],
	"uiPermissions": []
}
```



**After this prompt, the user may give you new instructions to update the output of this prompt or provide subsequent prompts about the project.**


