Skip to main content

API Introspection

FlowOn API provides introspection endpoints that allow UI developers to discover the API schema automatically. This enables:

  • Auto-generation of API clients
  • Dynamic form building based on schemas
  • Validation rule discovery
  • Documentation generation

Introspection Endpoints

EndpointDescription
/api/schemaComplete API schema
/api/schema/entitiesAll exposed entities and their operations
/api/schema/queriesAll available queries
/api/schema/processesAll exposed process actions
/api/schema/optionsetsAll exposed option sets

Example Schema Response

Request:

GET /api/schema/entities/account

Response:

{
"entityName": "account",
"displayName": "Account",
"endpoint": "/api/sales/accounts",
"operations": {
"create": {
"enabled": true,
"fields": [
{ "name": "name", "type": "string", "required": true, "maxLength": 160 },
{ "name": "telephone1", "type": "string", "required": false, "maxLength": 50 },
{ "name": "accountcategorycode", "type": "optionset", "optionSetName": "accountcategorycode" }
]
},
"update": {
"enabled": true,
"fields": [...]
},
"delete": {
"enabled": true
}
}
}

Use Cases

Dynamic Form Generation

UI applications can use the schema to automatically generate forms:

// Fetch entity schema
const schema = await fetch('/api/schema/entities/account');
const { operations } = await schema.json();

// Build form fields from create operation
operations.create.fields.forEach(field => {
createFormField({
name: field.name,
type: field.type,
required: field.required,
maxLength: field.maxLength
});
});

Client SDK Generation

The schema can be used to generate typed API clients:

// Generated from schema
interface Account {
accountId: string;
name: string;
telephone1?: string;
emailAddress1?: string;
accountCategoryCode?: number;
}

class AccountsApi {
async create(account: Omit<Account, 'accountId'>): Promise<{ id: string }> {
// ...
}

async update(id: string, account: Partial<Account>): Promise<void> {
// ...
}
}

Validation

Client applications can validate inputs before submitting:

function validateAccount(data, schema) {
const errors = [];

schema.fields.forEach(field => {
if (field.required && !data[field.name]) {
errors.push(`${field.name} is required`);
}
if (field.maxLength && data[field.name]?.length > field.maxLength) {
errors.push(`${field.name} exceeds maximum length of ${field.maxLength}`);
}
});

return errors;
}