Form
FormBase
Section titled “FormBase”A form for collecting data from a user.
From v0.5, a form’s label is title, in place of the name used through v0.4. A payload for any one version never carries both; only TypeSpec source examples do (see Authoring in TypeSpec).
The table and the example below show the v0.5 payload. To validate a payload, use the OpenAPI document for its version, such as /openapi/openapi.0.5.0.yaml, also browsable on the API docs page.
| Property | Type | Required | Description |
|---|---|---|---|
| id | uuid | Yes | The form's unique identifier. |
| title | string | Yes | The form's title. |
| description | string | No | The form's description. |
| version | string | No | |
| instructions | string or array<File> | No | The form's instructions. |
| jsonSchema | FormJsonSchema | No | The form's JSON schema used to render the form and validate responses. |
| uiSchema | FormUISchema | No | The form's UI schema used to render the form in the browser. |
| mappingToCommonGrants | MappingSchema | No | A mapping from form schema to CommonGrants schema. |
| mappingFromCommonGrants | MappingSchema | No | A mapping from CommonGrants schema to form schema. |
| customFields | record<CustomField> | No | Custom attributes about the form itself, not custom fields within the form. |
| createdAt | utcDateTime | Yes | The timestamp (in UTC) at which the record was created. |
| lastModifiedAt | utcDateTime | Yes | The timestamp (in UTC) at which the record was last modified. |
Formats
Section titled “Formats”The JSON Schema tab shows the unversioned authoring schema, not a v0.5 payload schema. It combines every version’s fields, so it requires both name and title.
A JSON example of this model.
{ "id": "b7c1e2f4-8a3d-4e2a-9c5b-1f2e3d4c5b6a", "title": "Form A", "description": "Form A description", "instructions": "Form A instructions", "jsonSchema": { "$id": "formA.json", "type": "object", "properties": { "name": { "first": { "type": "string" }, "last": { "type": "string" } }, "email": { "type": "string" }, "phone": { "type": "string" } } }, "uiSchema": { "type": "VerticalLayout", "elements": [ { "type": "Group", "label": "Name", "elements": [ { "type": "Control", "scope": "#/properties/name/first" }, { "type": "Control", "scope": "#/properties/name/last" } ] }, { "type": "Control", "scope": "#/properties/email" }, { "type": "Control", "scope": "#/properties/phone" } ] }, "mappingToCommonGrants": { "name": { "firstName": { "field": "name.first" }, "lastName": { "field": "name.last" } }, "emails": { "primary": { "field": "email" } }, "phones": { "primary": { "field": "phone" } } }, "mappingFromCommonGrants": { "name": { "first": { "field": "name.firstName" }, "last": { "field": "name.lastName" } }, "email": { "field": "emails.primary" }, "phone": { "field": "phones.primary" } }, "createdAt": "2025-01-01T17:01:01", "lastModifiedAt": "2025-01-02T17:30:00"}The JSON Schema for this model.
$schema: https://json-schema.org/draft/2020-12/schema$id: FormBase.yamltype: objectproperties: id: $ref: uuid.yaml description: The form's unique identifier. name: type: string description: The form's name. title: type: string description: The form's title. description: type: string description: The form's description. version: type: string instructions: anyOf: - type: string - type: array items: $ref: File.yaml description: The form's instructions. jsonSchema: $ref: FormJsonSchema.yaml description: The form's JSON schema used to render the form and validate responses. uiSchema: $ref: FormUISchema.yaml description: The form's UI schema used to render the form in the browser. mappingToCommonGrants: $ref: MappingSchema.yaml description: A mapping from form schema to CommonGrants schema. mappingFromCommonGrants: $ref: MappingSchema.yaml description: A mapping from CommonGrants schema to form schema. customFields: $ref: "#/$defs/RecordCustomField" description: Custom attributes about the form itself, not custom fields within the form. createdAt: type: string format: date-time description: The timestamp (in UTC) at which the record was created. lastModifiedAt: type: string format: date-time description: The timestamp (in UTC) at which the record was last modified.required: - id - name - title - createdAt - lastModifiedAtunevaluatedProperties: not: {}examples: - id: b7c1e2f4-8a3d-4e2a-9c5b-1f2e3d4c5b6a name: Form A title: Form A description: Form A description instructions: Form A instructions jsonSchema: $id: formA.json type: object properties: name: first: type: string last: type: string email: type: string phone: type: string uiSchema: type: VerticalLayout elements: - type: Group label: Name elements: - type: Control scope: "#/properties/name/first" - type: Control scope: "#/properties/name/last" - type: Control scope: "#/properties/email" - type: Control scope: "#/properties/phone" mappingToCommonGrants: name: firstName: field: name.first lastName: field: name.last emails: primary: field: email phones: primary: field: phone mappingFromCommonGrants: name: first: field: name.firstName last: field: name.lastName email: field: emails.primary phone: field: phones.primary createdAt: 2025-01-01T17:01:01 lastModifiedAt: 2025-01-02T17:30:00description: A form for collecting data from a user.$defs: RecordCustomField: type: object properties: {} unevaluatedProperties: $ref: CustomField.yamlThe TypeSpec code for this model.
/** A form for collecting data from a user. */@example(Examples.Form.form)@Versioning.added(CommonGrants.Versions.v0_2)@Versioning.renamedFrom(CommonGrants.Versions.v0_3, "Form")model FormBase { /** The form's unique identifier. */ id: Types.uuid;
/** The form's name. */ @Versioning.removed(CommonGrants.Versions.v0_5) name: string;
/** The form's title. */ @Versioning.added(CommonGrants.Versions.v0_5) title: string;
/** The form's description. */ description?: string;
@Versioning.added(CommonGrants.Versions.v0_3) version?: string;
/** The form's instructions. */ instructions?: string | Fields.File[];
/** The form's JSON schema used to render the form and validate responses. */ jsonSchema?: FormJsonSchema;
/** The form's UI schema used to render the form in the browser. */ uiSchema?: FormUISchema;
/** A mapping from form schema to CommonGrants schema. */ mappingToCommonGrants?: Models.MappingSchema;
/** A mapping from CommonGrants schema to form schema. */ mappingFromCommonGrants?: Models.MappingSchema;
/** Custom attributes about the form itself, not custom fields within the form. */ customFields?: Record<Fields.CustomField>;
/** The system metadata for the form. */ ...Fields.SystemMetadata;}Changelog
Section titled “Changelog”| Version | Changes | Schema |
|---|---|---|
| 0.5.0 |
| FormBase.yaml |
| 0.3.0 |
| FormBase.yaml |
| 0.2.0 |
| Form.yaml |
Migrating from v0.4
Section titled “Migrating from v0.4”| Version | Field | Type |
|---|---|---|
| v0.4 and earlier | name |
string, required |
| v0.5 | title |
string, required |
- Producers: send the value you sent as
nameastitleinstead. - Consumers: read a form’s label from
title. - Everywhere a form appears: forms nested in a competition’s
forms, and in any model of your own that embedsFormBase, change the same way. - Form content is unaffected:
jsonSchema,uiSchema, both mappings, andcustomFieldskeep their keys and values, includingnamekeys of their own. Form responses and answers still identify a form byformId.
v0.4 and earlier:
{ "id": "b7c1e2f4-8a3d-4e2a-9c5b-1f2e3d4c5b6a", "name": "Form A", "description": "Form A description"}v0.5:
{ "id": "b7c1e2f4-8a3d-4e2a-9c5b-1f2e3d4c5b6a", "title": "Form A", "description": "Form A description"}Both excerpts omit the other required fields.
Authoring in TypeSpec
Section titled “Authoring in TypeSpec”The TypeSpec model declares every version’s fields at once: name is removed in v0.5 and title added in v0.5, so the changelog records a removal and an addition, and the unversioned model requires both.
- Examples: an
@exampleforFormBase, or for a model that embeds a form, must set bothnameandtitle, even in a project pinned to an earlier version, and should give them the same value. The compiler checks examples against the unversioned model and does not compare the two values; each version’s OpenAPI output keeps only the field that version declares. - The unversioned JSON Schema,
/schemas/yaml/FormBase.yaml(the JSON Schema tab above), is that combined model, so it requires both fields. No single version’s payload satisfies it; validate a payload with the OpenAPI document for its version.
FormJsonSchema
Section titled “FormJsonSchema”A JSON schema used to validate form responses.
A JSON example of this model.
{ "$id": "formA.json", "type": "object", "properties": { "name": { "first": { "type": "string" }, "last": { "type": "string" } }, "email": { "type": "string" }, "phone": { "type": "string" } }}The JSON Schema for this model.
$schema: https://json-schema.org/draft/2020-12/schema$id: FormJsonSchema.yamltype: objectproperties: {}unevaluatedProperties: {}examples: - $id: formA.json type: object properties: name: first: type: string last: type: string email: type: string phone: type: stringdescription: A JSON schema used to validate form responses.The TypeSpec code for this model.
/** A JSON schema used to validate form responses. */@example(Examples.Form.formSchema)@Versioning.added(CommonGrants.Versions.v0_2)model FormJsonSchema { ...Record<unknown>;}Changelog
Section titled “Changelog”| Version | Changes | Schema |
|---|---|---|
| 0.2.0 |
| FormJsonSchema.yaml |
FormUISchema
Section titled “FormUISchema”A UI schema used to render the form in the browser.
A JSON example of this model.
{ "type": "VerticalLayout", "elements": [ { "type": "Group", "label": "Name", "elements": [ { "type": "Control", "scope": "#/properties/name/first" }, { "type": "Control", "scope": "#/properties/name/last" } ] }, { "type": "Control", "scope": "#/properties/email" }, { "type": "Control", "scope": "#/properties/phone" } ]}The JSON Schema for this model.
$schema: https://json-schema.org/draft/2020-12/schema$id: FormUISchema.yamltype: objectproperties: {}unevaluatedProperties: {}examples: - type: VerticalLayout elements: - type: Group label: Name elements: - type: Control scope: "#/properties/name/first" - type: Control scope: "#/properties/name/last" - type: Control scope: "#/properties/email" - type: Control scope: "#/properties/phone"description: A UI schema used to render the form in the browser.The TypeSpec code for this model.
/** A UI schema used to render the form in the browser. */@example(Examples.Form.uiSchema)@Versioning.added(CommonGrants.Versions.v0_2)model FormUISchema { ...Record<unknown>;}Changelog
Section titled “Changelog”| Version | Changes | Schema |
|---|---|---|
| 0.2.0 |
| FormUISchema.yaml |