# Form Builder API Reference
## SignalR Hub (Websocket)
The Form builder SignalR Hub URL is
```txt
{backend-url}/FormBuilderHub
```
Events (`Message Names for subscription`):
- Session Events
- `AllSessionsFormBuilderClosedEvent`
- `UserJoinedFormBuilderEvent`
- `UserLeftFormBuilderEvent`
- Form Events
- `ControlAddedEvent`
- `ControlMovedEvent`
- `ControlRemovedEvent`
- `FormHistoryRevertedEvent`
- `PropertyValueChangedEvent`
Requests (`Methods to be invoked`):
- Session Requests
- `JoinFormBuilder`
- `Authorize`
- Form Requests
- `AddControl`
- `ChangePropertyValue`
- `MoveControl`
- `RemoveControl`
- `RevertFormHistory`
### Authorize User
This method should be called after connecting with the signalR Hub, It should also be called if the current token has been expired to send a new valid token.
> Note: This method is a mock and accepts any string and create a random userid for the session.
```cs
Result<bool> Authorize(string accessToken);
```
Response:
```json
{
"hasErrors": false,
"data": false,
"errors": [
{
"code": "...",
"description": "..."
}
]
}
```
Errors:
| Code | # | Notes |
| -------------------------- | --- | ------------- |
| `InternalServerError` | | Unknown Error |
### Join for Specific Form
This method should be called once the user is authorized before getting any data or sending any form related requests.
```cs
Result<bool> JoinFormBuilder(Guid formId)
```
Response:
```json
{
"hasErrors": false,
"data": false,
"errors": [
{
"code": "...",
"description": "..."
}
]
}
```
Event Published to the others:
`UserJoinedFormBuilderEvent`
```json
{
"id": "Guid",
"formId": "Guid",
"userId": "Guid",
"dateOccurred": "2021-11-22T17:48:48.626Z"
}
```
Errors:
| Code | # | Notes |
| -------------------------- | --- | ------------------------ |
| `Hub:UnAuthorized` | | |
| `Hub:ChangeFormNotAllowed` | | User resend join request |
| `InternalServerError` | | Unknown Error |
### Add Control
```cs
Result<AddControlResponse> AddControl(AddControlHubRequest request);
```
Request:
```json
{
"controlId": "Guid",
"controlType": "Page",
"parentId": "Guid or null",
"order": "1"
}
```
Response:
```json
{
"hasErrors": false,
"data": {
"control": { } // one of `BasicControl` driven types
},
"errors": [
{
"code": "...",
"description": "..."
}
]
}
```
Event Published to the others:
`ControlAddedEvent`
```json
{
"id": "Guid",
"formId": "Guid",
"userId": "Guid",
"dateOccurred": "2021-11-22T17:48:48.626Z",
"control": { } // one of `BasicControl` driven types
}
```
Errors:
| Code | # | Notes |
| -------------------------- | --- | --------------------------- |
| `Hub:UnAuthorized` | | |
| `Hub:UnKnownSessionForm` | | User didn't join a form |
| `InternalServerError` | | Unknown Error |
| `InputValidationError` | (1) | formId is default Guid ⚠️ |
| `InputValidationError` | (2) | controlId is default Guid |
| `InputValidationError` | (3) | Page with not null parentId |
| `InputValidationError` | (4) | Not Page with null parentId |
| `Form:FormNotFound` | | ⚠️ |
| `Form:ParentNotFound` | | |
| `Form:InvalidControlId` | | |
| `Form:InvalidControlOrder` | | |
### Move Control
```cs
Result<MoveControlResponse> MoveControl(MoveControlHubRequest request);
```
Request:
```json
{
"controlId": "Guid",
"parentId": "Guid or null", // NewParent
"order": "1"
}
```
Response:
```json
{
"hasErrors": false,
"data": {
"controlId": "Guid",
"parentId": "Guid or null",
"order": "1"
},
"errors": [
{
"code": "...",
"description": "..."
}
]
}
```
Event Published to the others:
`ControlMovedEvent`
```json
{
"id": "Guid",
"formId": "Guid",
"userId": "Guid",
"dateOccurred": "2021-11-22T17:48:48.626Z",
"controlId": "Guid",
"parentId": "Guid or null",
"order": "1"
}
```
Errors:
| Code | # | Notes |
| -------------------------- | --- | --------------------------- |
| `Hub:UnAuthorized` | | |
| `Hub:UnKnownSessionForm` | | User didn't join a form |
| `InternalServerError` | | Unknown Error |
| `InputValidationError` | (1) | formId is default Guid ⚠️ |
| `InputValidationError` | (2) | controlId is default Guid |
| `InputValidationError` | (3) | Page with not null parentId |
| `InputValidationError` | (4) | Not Page with null parentId |
| `Form:FormNotFound` | | ⚠️ |
| `Form:ControlNotFound` | | |
| `Form:ParentNotFound` | | |
| `Form:InvalidControlOrder` | | |
### Remove Control
```cs
Result<RemoveControlResponse> RemoveControl(RemoveControlHubRequest request);
```
Request:
```json
{
"controlId": "Guid",
"controlType": "Page"
}
```
Response:
```json
{
"hasErrors": false,
"data": {
"controlId": "Guid",
"controlType": "Page",
"deletedIds": [
"Guid"
]
},
"errors": [
{
"code": "...",
"description": "..."
}
]
}
```
Event Published to the others:
`ControlRemovedEvent`
```json
{
"id": "Guid",
"formId": "Guid",
"userId": "Guid",
"dateOccurred": "2021-11-22T17:48:48.626Z",
"controlId": "Guid",
"controlType": "Page",
"deletedIds": [
"Guid"
]
}
```
Errors:
| Code | # | Notes |
| -------------------------- | --- | --------------------------- |
| `Hub:UnAuthorized` | | |
| `Hub:UnKnownSessionForm` | | User didn't join a form |
| `InternalServerError` | | Unknown Error |
| `InputValidationError` | (1) | formId is default Guid ⚠️ |
| `InputValidationError` | (2) | controlId is default Guid |
| `InputValidationError` | (3) | Page with not null parentId |
| `InputValidationError` | (4) | Not Page with null parentId |
| `Form:FormNotFound` | | ⚠️ |
| `Form:ControlNotFound` | | |
### Change Property Value
```cs
Result<ChangePropertyValueResponse> ChangePropertyValue(ChangePropertyValueHubRequest request);
```
Request:
```json
{
"controlId": "Guid",
"entityType": "Control", // Form, Control
"property": {
"path": ".style.color",
"value": "\"red\"", // the value should be a valid serialzied json string
}
}
```
Response:
```json
{
"hasErrors": false,
"data": {
"controlId": "Guid",
"property": {
"path": ".style.color",
"value": "\"red\"", // the value should be a valid serialzied json string
}
},
"errors": [
{
"code": "...",
"description": "..."
}
]
}
```
Event Published to the others:
`PropertyValueChangedEvent`
```json
{
"id": "Guid",
"formId": "Guid",
"userId": "Guid",
"dateOccurred": "2021-11-22T17:48:48.626Z",
"controlId": "Guid",
"property": {
"path": ".style.color",
"value": "\"red\"", // the value should be a valid serialzied json string
}
}
```
Errors:
| Code | # | Notes |
| -------------------------- | --- | --------------------------- |
| `Hub:UnAuthorized` | | |
| `Hub:UnKnownSessionForm` | | User didn't join a form |
| `InternalServerError` | | Unknown Error |
| `InputValidationError` | (1) | formId is default Guid ⚠️ |
| `InputValidationError` | (2) | controlId is default Guid |
| `InputValidationError` | (3) | Page with not null parentId |
| `InputValidationError` | (4) | Not Page with null parentId |
| `Form:FormNotFound` | | ⚠️ |
| `Form:ControlNotFound` | | |
| `Form:InvalidProprtyPath` | | |
### Revert History
> TODO: Not Implemented yet
## Rest APIs (HTTP)
### Create New Form
```txt
POST {backend-url}/api/Forms/Create
{
"name": "..."
}
```
Response:
```json
{
"isDeleted": true,
"createdAt": "2021-12-01T01:10:06.055Z",
"createdBy": "string",
"updatedAt": "2021-12-01T01:10:06.055Z",
"updatedBy": "string",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"lastPublishedVersionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"draftedSchema": {
"isDeleted": true,
"createdAt": "2021-12-01T01:10:06.055Z",
"createdBy": "string",
"updatedAt": "2021-12-01T01:10:06.055Z",
"updatedBy": "string",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"lastAppliedEventId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"schema": {},
"status": 0,
"concurrencyStamp": "string"
},
"draftEvents": [
{
"isDeleted": true,
"createdAt": "2021-12-01T01:10:06.055Z",
"createdBy": "string",
"updatedAt": "2021-12-01T01:10:06.055Z",
"updatedBy": "string",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"eventData": {}
}
],
"schemaVersions": [
{
"isDeleted": true,
"createdAt": "2021-12-01T01:10:06.055Z",
"createdBy": "string",
"updatedAt": "2021-12-01T01:10:06.055Z",
"updatedBy": "string",
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"schema": {}
}
]
}
```
### List All Forms
```txt
GET {backend-url}/api/Forms/GetAll
```
Response:
```json
[
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "string",
"lastPublishedVersionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"createdAt": "2021-11-22T17:50:31.036Z",
"createdBy": "string",
"updatedAt": "2021-11-22T17:50:31.036Z",
"updatedBy": "string"
}
]
```
### Get Form Json Schema
```txt
GET {backend-url}/api/Forms/GetSchema/{formId: GUID}
```
Response:
```json
{
"schema": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"templateId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"lastAppliedEventId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"themeId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": 0,
"settings": {
"format": 0,
"enableScoreCalculation": true,
"expirationDate": "2021-12-13T17:39:13.105Z",
"defaultLanguage": 0,
"availableLanguages": [
0
]
},
"properties": {
"navigation": {
"submit": "string",
"next": "string",
"back": "string",
"backVisibility": true,
"localization": {
"additionalProp1": {
"submit": "string",
"next": "string",
"back": "string"
},
"additionalProp2": {
"submit": "string",
"next": "string",
"back": "string"
},
"additionalProp3": {
"submit": "string",
"next": "string",
"back": "string"
}
}
},
"campaign": {
"header": {
"logo": "string",
"title": "string",
"description": "string",
"showQuestionsCount": true,
"localization": {
"additionalProp1": {
"title": "string",
"description": "string"
},
"additionalProp2": {
"title": "string",
"description": "string"
},
"additionalProp3": {
"title": "string",
"description": "string"
}
}
},
"footer": {
"logo": "string",
"title": "string",
"description": "string",
"showQuestionsCount": true,
"localization": {
"additionalProp1": {
"title": "string",
"description": "string"
},
"additionalProp2": {
"title": "string",
"description": "string"
},
"additionalProp3": {
"title": "string",
"description": "string"
}
}
},
"welcome": {
"logo": "string",
"title": "string",
"description": "string",
"showQuestionsCount": true,
"localization": {
"additionalProp1": {
"title": "string",
"description": "string"
},
"additionalProp2": {
"title": "string",
"description": "string"
},
"additionalProp3": {
"title": "string",
"description": "string"
}
}
},
"submissionMessage": {
"logo": "string",
"title": "string",
"description": "string",
"showQuestionsCount": true,
"localization": {
"additionalProp1": {
"title": "string",
"description": "string"
},
"additionalProp2": {
"title": "string",
"description": "string"
},
"additionalProp3": {
"title": "string",
"description": "string"
}
}
}
}
},
"warningMsgs": {
"required": {
"fieldRequired": "string",
"oneFieldPerFormRequired": "string"
},
"textBox": {
"minimumCharacterLength": "string",
"maximumCharacterLength": "string",
"minimumWordLength": "string",
"maximumWordLength": "string",
"email": "string",
"url": "string",
"alphapetic": "string",
"alphaNumeric": "string",
"numeric": "string",
"custom": "string"
},
"textArea": {
"minimumCharacterLength": "string",
"maximumCharacterLength": "string",
"minimumWordLength": "string",
"maximumWordLength": "string"
},
"number": {
"minimumValue": "string",
"maximumValue": "string",
"minimumDigits": "string",
"maximumDigits": "string"
},
"email": {
"validEmail": "string",
"notMatchEmail": "string"
}
},
"fields": [
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"templateQuestionId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"type": 0,
"parentId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"order": "string",
"properties": {
"labelPosition": 0,
"hidden": true,
"label": "string",
"sublabel": "string",
"tooltip": "string",
"localization": {
"additionalProp1": {
"label": "string",
"sublabel": "string",
"tooltip": "string"
},
"additionalProp2": {
"label": "string",
"sublabel": "string",
"tooltip": "string"
},
"additionalProp3": {
"label": "string",
"sublabel": "string",
"tooltip": "string"
}
}
},
"styles": {
"labelStyle": {
"color": "string",
"backgroundColor": "string",
"fontSize": 0,
"weight": 0
}
}
}
]
}
}
```
Errors:
| Code | # | Notes |
| -------------------------- | -- | ------------- |
| `InternalServerError` | | Unknown Error |
| `Form:FormNotFound` | | |
| `Form:LoadingTimeout` | | |