Introduction to Extensibility - Quick Start

In this documentation, you'll familiarize yourself with extending the Ed-Fi data model to fill in any gaps for your specific use case.

Typically, this means that the ODS data store, data access code, API surface, documentation, and other components would all need to be changed to accommodate changes to the data model. 

The Ed-Fi Alliance provides a free tool called the MetaEd IDE that allows you to author and build extensions using a simple language. Ed-Fi Alliance also provides the extension project templates which can be used to create Ed-Fi ODS / API packages that can be used to extend the core API.

In a real-world project, you would take the preliminary step of designing your extension. For the purpose of this Quick Start, we have provided a useful extension example for the membership and special education count use cases. In these extensions, we are adding fields to existing entities.

Deep dive

Review the How To: Student Transportation Example and How To: Student Transcript Example articles for detailed, step-by-step extension instructions. 

Extensions to existing entities follow a pattern that creates a companion table in the organization's extension schema. The companion table is named the same as the resource being extended plus the suffix "Extension". For example, extensions to the StudentSchoolAssociation would be expressed in a table named StudentSchoolAssociationExtension. The following schema diagram for EdFi_Ods database shows the example extension artifacts added in 'sk' schema. 

More information

See Starter Kit GitHub repository for MetaEd source files.


This extension is brought into the Starter Kit Quick Start as an extension plugin. Source code for the C# extension project and the build that creates the extension plugin package are provided in the Starter Kit GitHub repository. 

You can see the extension artifacts in the Swagger documentation as well as notice the extension data being posted in the Postman collection provided with the Starter Kit. Notice that the extended elements of an existing entity are held in an extension JSON object (_ext) instead of being seamlessly blended into the JSON payload. 


Once you have gone through Introduction to API section, you can verify how the data you POSTed to the API landed in the extension tables in the EdFi_Ods. 

 Expand for SQL listing...
SELECT s.StudentUSI, s.FirstName, s.LastSurname, s.BirthDate, sa.EntryDate, sa.SchoolId, sa.FullTimeEquivalency,
saex.ReportingSchoolId, saex.ResidentLocalEducationAgencyId, saex.ResidentSchoolId, sa.ExitWithdrawDate, sa.ExitWithdrawTypeDescriptorId
FROM [edfi].[Student] as s
INNER JOIN [edfi].[StudentSchoolAssociation] as sa on s.StudentUSI = sa.StudentUSI
INNER JOIN [sk].[StudentSchoolAssociationExtension] as saex on saex.StudentUSI = sa.StudentUSI AND saex.SchoolId = sa.SchoolId
WHERE (FirstName = 'John' AND LastSurname = 'Smith') OR (FirstName = 'Kelly' AND LastSurname = 'Logan' )
OR (FirstName = 'Jennifer' AND LastSurname = 'Hart')

 Expand for SQL listing...
SELECT s.StudentUSI, s.FirstName, s.LastSurname, s.BirthDate, sp.BeginDate, sp.ProgramName, sle.RedesignatedEnglishFluent, spe.ToTakeAlternateAssessment
FROM [edfi].[Student] as s
INNER JOIN [edfi].[StudentSpecialEducationProgramAssociation] as sp on s.StudentUSI = sp.StudentUSI
INNER JOIN [sk].[StudentSpecialEducationProgramAssociationExtension] as spe on spe.StudentUSI = s.StudentUSI AND spe.EducationOrganizationId = sp.EducationOrganizationId AND spe.ProgramEducationOrganizationId = sp.ProgramEducationOrganizationId
INNER JOIN [sk].[StudentLanguageInstructionProgramAssociationExtension] as sle on sle.StudentUSI = s.StudentUSI AND sle.EducationOrganizationId = sp.EducationOrganizationId AND sle.ProgramEducationOrganizationId = sp.ProgramEducationOrganizationId
WHERE (FirstName = 'John' AND LastSurname = 'Smith') OR (FirstName = 'Kelly' AND LastSurname = 'Logan'  )
OR (FirstName = 'Jennifer' AND LastSurname = 'Hart' )

More information

See Starter Kit GitHub repository for C# extension project, extension plugin build for this example.