Client Extensions API Documentation

This documentation provides comprehensive guidance for reading ClientDTO.Extensions.Field.Answer data from the AlayaCare Residential API. The Extensions property contains dynamic form field data with various answer formats based on field types and subtypes.

Data Structure

Extension Object Structure
Extensions are returned as an array of FormDataExtensionDto objects.

"extensions": [
{
  "formFieldLinkID": 288,
  "fieldName": "Boolean-FF",
  "recordState": 1,
  "field": {
    "type": 300,
    "subType": 600,
    "hasAnswer": true,
    "answer": true,
    "answerAsString": "Yes"
  }
},
{
    "formFieldLinkID": 305,
    "fieldName": "StringWithExpiry-FF",
    "recordState": 1,
    "field": {
      "type": 101,
      "subType": 100,
      "hasAnswer": true,
      "answer": {
        "value": "License123",
        "expiryYear": 2025,
        "expiryMonth": 8,
        "summary": "License123. Expiry: 8/2025"
      },
      "answerAsString": "License123. Expiry: 8/2025"
    }
  }...
]

Scenario 1: By Field Name

Use this approach when you know the specific field name you're looking for.

  1. Filter the extension fields from the ClientDTO
  2. Filter the required extension field by field name
  3. Get the answer property of the field
// Step 1: Get extensions
const extensions = client.extensions;
// Step 2: Find by field name
const extension = extensions.find(ext => ext.fieldName === "Boolean-FF");
// Step 3: Extract answer
if (extension && extension.field && extension.field.hasAnswer) {
    const answer = extension.field.answer;
    const displayText = extension.field.answerAsString;
}
Complete Example:
function getAnswerByFieldName(client, fieldName) {
    // Step 1: Get extensions
    const extensions = client.extensions;
    // Step 2: Find by field name
    const extension = extensions.find(ext => ext.fieldName === fieldName);
    // Step 3: Extract answer
    if (extension && extension.field && extension.field.hasAnswer) {
        return {
            answer: extension.field.answer,
            displayText: extension.field.answerAsString
        };
    }
    return null;
}
// Usage
const result = getAnswerByFieldName(client, "String-FF");
console.log(result.answer); // "Sample text value"

Scenario 2: By Type and SubType

Use this approach when you need to process all extensions without knowing specific field names.

  1. Filter the extension fields from the ClientDTO
  2. Check the type and subType of each form field
  3. Get the answer as per the answer format of different types and subtypes
// Step 1: Access client extensions
const extensions = client.extensions;
// Step 2 & 3: Process by type and subtype
extensions.forEach(extension => {
    if (extension.field && extension.field.hasAnswer) {
        const fieldType = extension.field.type;
        const fieldSubType = extension.field.subType;
        const answer = getAnswerByType(extension.field);
    }
});

Form Field Types and Answer Formats

Type SubType Field Type Answer Property Data Type
100100Text Boxanswerstring
100101Text Areaanswerstring
101100String with Expiryanswerobject
200200Numericanswernumber
201200Numeric Rangeanswerobject
300600Booleananswerboolean
400400Dateanswerstring
400402DateTimeanswerstring
400403Timeanswerstring
401400Date Rangeanswerobject
401402DateTime Rangeanswerobject
401403Time Rangeanswerobject
500500Choice Dropdownanswerobject
500501Radio Buttonanswerobject
600500Multiple Dropdownanswersarray
600600Checkboxesanswersarray
String Fields (Type: 100)
Text Box (Type: 100, SubType: 100)

Answer Format: Direct string value

{
  "type": 100,
  "subType": 100,
  "answer": "Kevin Kumar",
  "answerAsString": "Kevin Kumar"
}
Access Pattern: field.answer returns string
Text Area (Type: 100, SubType: 101)

Answer Format: Direct string value

{
  "type": 100,
  "subType": 101,
  "answer": "this is a text area demo",
  "answerAsString": "this is a text area demo"
}
Access Pattern: field.answer returns string
String with Expiry (Type: 101, SubType: 100)

Answer Format: Object with value, expiry month, and year

{
  "type": 101,
  "subType": 100,
  "answer": {
    "value": "License123",
    "expiryYear": 2025,
    "expiryMonth": 8,
    "summary": "License123. Expiry: 8/2025"
  },
  "answerAsString": "License123. Expiry: 8/2025"
}
Access Pattern: field.answer.value, field.answer.expiryMonth, field.answer.expiryYear, field.answer.summary
Numeric Fields
Numeric Input (Type: 200, SubType: 200)

Answer Format: Numeric value

{
  "type": 200,
  "subType": 200,
  "answer": 5,
  "answerAsString": "5"
}
Access Pattern: field.answer returns number
Numeric Range (Type: 201, SubType: 200)

Answer Format: Object with start and stop values

{
  "type": 201,
  "subType": 200,
  "answer": {
    "start": 2,
    "stop": 3
  },
  "answerAsString": "2 - 3"
}
Access Pattern: field.answer.start, field.answer.stop
Boolean Fields (Type: 300, SubType: 600)

Answer Format: Boolean value

{
  "type": 300,
  "subType": 600,
  "answer": true,
  "answerAsString": "Yes",
  "checkedValue": "Yes",
  "uncheckedValue": "No"
}
Access Pattern: field.answer returns boolean
Date/Time Fields (Type: 400)
Date (Type: 400, SubType: 400)

Answer Format: ISO date string

{
  "type": 400,
  "subType": 400,
  "answer": "2025-07-25T00:00:00",
  "answerAsString": "2025-07-25"
}
Access Pattern: field.answer returns ISO date string
DateTime (Type: 400, SubType: 402)

Answer Format: ISO datetime string

{
  "type": 400,
  "subType": 402,
  "answer": "2025-07-22T18:00:00",
  "answerAsString": "2025-07-22T18:00:00"
}
Time (Type: 400, SubType: 403)

Answer Format: ISO time string

{
  "type": 400,
  "subType": 403,
  "answer": "0001-01-01T13:30:00",
  "answerAsString": "13:30:00"
}
Access Pattern: field.answer returns ISO time string
Date/Time Range Fields (Type: 401)
Date Range (Type: 401, SubType: 400)

Answer Format: Object with start and stop date strings

{
  "type": 401,
  "subType": 400,
  "answer": {
    "start": "2025-07-20T00:00:00",
    "stop": "2025-07-25T00:00:00"
  },
  "answerAsString": "20/07/2025 12:00:00 AM - 25/07/2025 12:00:00 AM"
}
Access Pattern: field.answer.start, field.answer.stop
DateTime Range (Type: 401, SubType: 402)
{
  "type": 401,
  "subType": 402,
  "answer": {
    "start": "2025-07-15T16:00:00",
    "stop": "2025-07-17T18:00:00"
  },
  "answerAsString": "15/07/2025 4:00:00 PM - 17/07/2025 6:00:00 PM"
}
Time Range (Type: 401, SubType: 403)
{
  "type": 401,
  "subType": 403,
  "answer": {
    "start": "2025-07-21T09:00:00",
    "stop": "2025-07-21T09:30:00"
  },
  "answerAsString": "21/07/2025 9:00:00 AM - 21/07/2025 9:30:00 AM"
}
Single Choice Fields (Type: 500)
Choice Dropdown (Type: 500, SubType: 500)

Answer Format: Object with key (k) and value (v)

{
  "type": 500,
  "subType": 500,
  "answer": {
    "k": 564,
    "v": "Business"
  },
  "answerAsString": "Business"
}
Access Pattern: field.answer.k, field.answer.v
Radio Button (Type: 500, SubType: 501)
{
  "type": 500,
  "subType": 501,
  "answer": {
    "k": 455,
    "v": "choice 1"
  },
  "answerAsString": "choice 1"
}
Multiple Choice Fields (Type: 600)
⚠️ Important: Multiple choice fields use the answers property instead of answer
Multiple Dropdown (Type: 600, SubType: 500)

Answer Format: Array of objects with key (k) and value (v)

{
  "type": 600,
  "subType": 500,
  "answers": [
    {"k": 461, "v": "choice 1"},
    {"k": 462, "v": "Is Vegan"}
  ],
  "answerAsString": "choice 1, Is Vegan"
}
Access Pattern: field.answers (array of objects)
Checkboxes (Type: 600, SubType: 600)
{
  "type": 600,
  "subType": 600,
  "answers": [
    {"k": 458, "v": "choice 11"},
    {"k": 459, "v": "choice 111"}
  ],
  "answerAsString": "choice 11, choice 111"
}

Complete Implementation Recipe

Process All Extensions by Type
function processExtensionsByType(client) {
    // Step 1: Get extensions
    const extensions = client.extensions;
    const results = {};
    extensions.forEach(extension => {
        if (extension.field && extension.field.hasAnswer) {
            // Step 2: Check type and subtype
            const type = extension.field.type;
            const subType = extension.field.subType;
            // Step 3: Get answer based on type
            let answer;
            switch (type) {
                case 100: // String
                case 200: // Numeric
                case 300: // Boolean
                case 400: // Date/Time
                    answer = extension.field.answer;
                    break;
                case 101: // String with Expiry
                case 201: // Numeric Range
                case 401: // Date/Time Range
                case 500: // Single Choice
                    answer = extension.field.answer; // Object
                    break;
                case 600: // Multiple Choice
                    answer = extension.field.answers; // Array
                    break;
                default:
                    answer = extension.field.answer;
            }
            results[extension.fieldName] = {
                answer: answer,
                displayText: extension.field.answerAsString,
                type: type,
                subType: subType
            };
        }
    });
    return results;
}

Important Guidelines

🔍 Key Validation Steps
  1. Always check hasAnswer before accessing values
  2. Multiple choice fields (Type 600) use answers array, not answer
  3. Use answerAsString for user-friendly display text
  4. Handle null values gracefully in your implementation
  5. Type/SubType combinations determine the data structure format

Best Practices

✅ Recommended Approach
  • Use Scenario 1 when you have specific field names
  • Use Scenario 2 when processing dynamic form data
  • Always validate hasAnswer before accessing answer values
  • Prefer answerAsString for display purposes
  • Implement proper error handling for missing or malformed data
  • Cache processed extension data when working with large datasets