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
| Endpoint | Description |
|---|---|
/api/schema | Complete API schema |
/api/schema/entities | All exposed entities and their operations |
/api/schema/queries | All available queries |
/api/schema/processes | All exposed process actions |
/api/schema/optionsets | All 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;
}