Skip to main content

FE Import API Error Reference

This document is a complete reference for all error responses produced by the API Import Process

FE Colleges | April 2026

Overview

Use it to look up an HTTP status code or error message, understand the cause, and find the fix.

All endpoints require OAuth 2.0 bearer-token authentication. Errors are returned as JSON regardless of the source — authentication, field validation, security checks, rate limiting, business logic, or unhandled exceptions.

Response shapes at a glance

Different error conditions return different JSON structures. The table below shows each shape.

Status code

Response body shape

400 — Field validation

{"message":"The request is invalid.","modelState":{"<field>":["<message>"]}}

400 — Security check

{"message":"Validation failed. N error(s) found: The field <X> contains invalid characters..."}

400 — Path/body mismatch

{"message":"The <Entity> <ID>: <value> does not match the path: <path>"}

400 — Wrong endpoint

{"message":"Cannot save a <Entity> Instance using the <entity> endpoint. Use the <entity>/instance endpoint."}

401

{"error":"invalid_grant","error_description":"..."}

403

{"message":"Unable to save <entity>: <detail>"}

404

{"message":"<Entity> does not exist or has been deleted"}

429

{"message":"API request limit exceeded. Please try again later."}

500 (production)

{"message":"An error has occurred."}

500 (non-production)

{"message":"An error has occurred.","exceptionMessage":"...","exceptionType":"...","stackTrace":"..."}

Import order and entity dependencies

Several resources must be imported before others that reference them. Importing a child entity before its parent produces a 403 Forbidden response.

Order

Resource

Depends on

1

Faculties

(none)

2

Sectors

(none)

3

Campuses

(none)

4

Programme Areas

Faculties, Sectors

5

Staff

(none)

6

Courses

Programme Areas

7

Programmes

Programme Areas

8

Students

Staff (tutor), Campuses

9

Applicants

(none)

10

Businesses

(none)

11

Business Contacts

Businesses

12

Business Departments

Businesses

13

Student Courses

Students, Courses

14

Student Primary Contacts

Students

15

Student Target Hours

Students, Student Courses

16

Student Target Skills

Students

Rate limiting

A per-client request limit is enforced during business hours. The client identifier is the ClientID claim in the bearer token — not the IP address.

Setting

Value

Request limit

60,000 requests

Window

60 minutes (rolling)

Enforced hours

08:00–18:00 UTC

Enforced days

Monday–Friday (weekends exempt)

Client identifier

ClientID claim in the bearer token

Global errors — all endpoints

The following errors can occur on any request, regardless of endpoint, before the action executes. They are not repeated in each resource section below.

Message

Meaning and fix

Code

Category

Field

{"error":"invalid_grant","error_description":"The user name or password is incorrect."}

The OAuth 2.0 bearer token is missing, expired, or malformed. Tokens are valid for 7 days (168 hours).

ⓘ This error uses a different response shape from all other errors — it returns error and error_description rather than message. Ensure the Authorization header is formatted as: Bearer <token>.

401

Authentication

Authorization

{"message":"The request is invalid.","modelState":{"<field>":["<error>"]}}

One or more request body fields failed validation. All validation errors are returned together in modelState.

ⓘ All validation errors are batched into a single response — fix all highlighted fields before retrying, not just the first one listed.

400

Field validation

{"message":"Validation failed. N error(s) found: The field <Name> contains invalid characters that could pose a security risk."}

One or more string values contain characters that could pose a security risk. The request is rejected before processing.

ⓘ Characters that commonly trigger this: angle brackets (< >), ampersands (&), and certain Unicode control characters. These may appear in free-text fields copied from external sources — strip or encode them before sending.

400

Security check

{"message":"API request limit exceeded. Please try again later."}

The per-client limit of 60,000 requests per 60-minute rolling window has been exceeded. Enforced Monday–Friday 08:00–18:00 UTC only. Weekends are exempt.

ⓘ The limit is per ClientID (from the bearer token), not per IP. If multiple systems share a token their requests are counted together. Schedule large bulk imports outside business hours to avoid this.

429

Rate limiting

{"message":"An error has occurred."}

An unhandled exception occurred. All exceptions are logged automatically. In production only the generic message is returned; non-production responses also include exceptionMessage, exceptionType, and stackTrace.

ⓘ A 500 on a previously working request often indicates a null or unexpected value in a field that is not explicitly validated. Contact Grofar support with the request body and timestamp.

500

Server error

Faculties — /api/v1/faculties

Message

Meaning and fix

Code

Category

Field

The Code field is required.

The Code field is missing or blank.

400

Field validation

Code

The Name field is required.

The Name field is missing or blank.

400

Field validation

Name

Maximum number of characters allowed for Name is 200.

The Name value exceeds 200 characters.

400

Field validation

Name

The faculty code: {value} does not match the path: {code}

The Code in the request body does not match the {code} URL path parameter. Both must be identical.

ⓘ Common cause: the same request body is reused for multiple PUT calls but the URL is updated without updating the body. Always keep Code in sync with the URL path parameter.

400

Path/body mismatch

Code

Faculty does not exist or has been deleted

No faculty exists with the code in the URL path, or it has been soft-deleted.

404

Not found

Sectors — /api/v1/sectors

Message

Meaning and fix

Code

Category

Field

The Code field is required.

The Code field is missing or blank.

400

Field validation

Code

The Name field is required.

The Name field is missing or blank.

400

Field validation

Name

Maximum number of characters allowed for Name is 200.

The Name value exceeds 200 characters.

400

Field validation

Name

Sector does not exist or has been deleted

No sector exists with the code in the URL path, or it has been soft-deleted.

404

Not found

Campuses — /api/v1/campuses

Message

Meaning and fix

Code

Category

Field

The ExternalCampusID field is required.

The ExternalCampusID field is missing or blank.

400

Field validation

ExternalCampusID

The Name field is required.

The Name field is missing or blank.

400

Field validation

Name

Maximum number of characters allowed for Name is 200.

The Name value exceeds 200 characters.

400

Field validation

Name

Campus does not exist or has been deleted

No campus exists with the ExternalCampusID in the URL path.

404

Not found

Programme Areas — /api/v1/programmeareas

Message

Meaning and fix

Code

Category

Field

The Code field is required.

The Code field is missing or blank.

400

Field validation

Code

The Name field is required.

The Name field is missing or blank.

400

Field validation

Name

Maximum number of characters allowed for Name is 200.

The Name value exceeds 200 characters.

400

Field validation

Name

Maximum number of characters allowed for Location is 200.

The Location value exceeds 200 characters.

400

Field validation

Location

The FacultyCode field is required.

The FacultyCode field is missing or blank.

400

Field validation

FacultyCode

Unable to save Programme Area: The Faculty {facultyCode} does not exist.

The referenced faculty has not been imported yet. Faculties must exist before programme areas.

ⓘ Import order: Faculties then Sectors then Programme Areas. Check the FacultyCode exactly matches the Code used when the faculty was imported — casing matters.

403

Business logic

FacultyCode

Unable to save Programme Area: The sector {sectorCode} does not exist.

The referenced sector has not been imported yet.

ⓘ Import order: Sectors must exist before Programme Areas. Check the SectorCode matches exactly.

403

Business logic

SectorCode

Unable to perform bulk delete for programme areas: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request body is not a valid date-time.

ⓘ Use ISO 8601 format: 2026-04-15T08:00:00Z. Common mistakes: omitting the trailing Z, or using DD/MM/YYYY format.

403

Business logic

earliestImportedUtcDateTime

Programme area does not exist or has been deleted

No programme area exists with the code in the URL path.

404

Not found

Staff — /api/v1/staff

Message

Meaning and fix

Code

Category

Field

The ExternalID field is required.

The ExternalID field is missing or blank.

400

Field validation

ExternalID

Maximum number of characters allowed for the External ID is 100.

The ExternalID value exceeds 100 characters.

400

Field validation

ExternalID

The FirstName field is required.

The FirstName field is missing or blank.

400

Field validation

FirstName

The LastName field is required.

The LastName field is missing or blank.

400

Field validation

LastName

The Email field is required.

The Email field is missing or blank.

400

Field validation

Email

The Email field is not a valid e-mail address.

The Email value is not in a valid format.

400

Field validation

Email

The value of field Gender must be one of the specified values.

The Gender value is not one of the accepted values. Refer to the API specification for the full list.

400

Field validation

Gender

Maximum number of characters allowed for the Title is 100.

The Title value exceeds 100 characters.

400

Field validation

Title

Maximum number of characters allowed for the Job Title is 200.

The JobTitle value exceeds 200 characters.

400

Field validation

JobTitle

The Telephone field is not a valid phone number.

The Telephone value is not in a valid phone number format.

ⓘ Common causes: value contains non-dialable text such as x123, Ext 4567, Extension 2, or a descriptive label. Send only the dialable number.

400

Field validation

Telephone

Unable to save staff member: The External login {externalLoginValue} is already linked to another user in the system

The Microsoft or Google login identity is already linked to a different Grofar user account.

ⓘ Each external login can only be linked to one user. If the same person exists under a different ExternalID, resolve by deleting the old record first or correcting the ExternalID.

403

Business logic

ExternalLogin

Unable to save staff member: Could not find role: {roleName}

A role specified in the request does not exist in the Grofar system configuration. This is a configuration issue, not a data issue.

ⓘ Contact Grofar support — this indicates a role name mismatch between the API caller and the system configuration.

403

Business logic

Role

Unable to perform bulk delete for staff: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid. Use ISO 8601: 2026-04-15T08:00:00Z.

403

Business logic

earliestImportedUtcDateTime

Staff Member does not exist or has been deleted

No staff member exists with the ExternalID in the URL path, or the record has been soft-deleted.

404

Not found

Students — /api/v1/students

Message

Meaning and fix

Code

Category

Field

The ExternalID field is required.

The ExternalID field is missing or blank.

400

Field validation

ExternalID

Maximum number of characters allowed for the External ID is 100.

The ExternalID value exceeds 100 characters.

400

Field validation

ExternalID

The FirstName field is required.

The FirstName field is missing or blank.

400

Field validation

FirstName

The LastName field is required.

The LastName field is missing or blank.

400

Field validation

LastName

The Email field is required.

The Email field is missing or blank.

400

Field validation

Email

The Email field is not a valid e-mail address.

The Email value is not in a valid format.

400

Field validation

Email

The value of field Gender must be one of the specified values.

The Gender value is not one of the accepted values.

400

Field validation

Gender

The value of field AgeBand must be one of the specified values.

The AgeBand value is not one of the accepted values. Accepted values: 16-18, 19+.

400

Field validation

AgeBand

The Telephone field is not a valid phone number.

The Telephone value is not valid.

ⓘ Common causes: value contains non-dialable text such as x123, Ext 4567, or labels like Mum's number or Dad's number. Send only the dialable number.

400

Field validation

Telephone

The Mobile field is not a valid phone number.

The Mobile value is not valid.

ⓘ Common causes: same as Telephone. Also check for landlines in the Mobile field, or extension notation appended to a number.

400

Field validation

Mobile

The Student ExternalID: {value} does not match the path: {path}

The ExternalID in the request body does not match the {externalid} URL path parameter. Both must be identical.

ⓘ Common cause: reusing a request body template without updating the ExternalID to match the URL.

400

Path/body mismatch

ExternalID

Unable to save student: Date of birth is incorrect date format

The DateOfBirth value is not in a recognised format. Use ISO 8601: YYYY-MM-DD.

ⓘ This error is a 403, not a 400 — it is caught by business logic rather than field validation. Common cause: sending DD/MM/YYYY or a Unix timestamp instead of YYYY-MM-DD.

403

Business logic

DateOfBirth

Unable to save student: No tutor with External ID {tutorExternalID} exists

The referenced tutor (staff member) has not been imported, or the ExternalID does not match.

ⓘ Import order: Staff must be imported before Students if a tutor is being assigned. The TutorExternalID must exactly match the ExternalID used when the staff member was imported.

403

Business logic

TutorExternalID

Unable to save student: No campus with External ID {campusExternalID} exists

The referenced campus has not been imported, or the ExternalID does not match.

ⓘ Import order: Campuses must be imported before Students. The CampusExternalID must exactly match the ExternalCampusID used when the campus was imported.

403

Business logic

CampusExternalID

Unable to save student: {value} is not a valid Learning Difficulty.

One of the ILR learning difficulty codes in the LearningDifficulties field is not recognised. Valid codes: 1–18, 93–99.

403

Business logic

LearningDifficulties

Unable to save student: Failed to parse the Learning Difficulties CSV. The values must be one of 1 2 3 ... 99 separated by ,

The LearningDifficulties field could not be parsed. Values must be comma-separated in the API.

ⓘ The API uses comma (,) as the separator for LearningDifficulties, whereas the CSV import uses pipe (|). This is a common source of confusion when migrating between import methods.

403

Business logic

LearningDifficulties

Unable to save student: The External login {externalLoginValue} is already linked to another user in the system

The Microsoft or Google login identity is already linked to a different user account.

403

Business logic

ExternalLogin

Unable to perform bulk delete for students: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid. Use ISO 8601.

403

Business logic

earliestImportedUtcDateTime

Student does not exist or has been deleted

No student exists with the ExternalID in the URL path, or the record has been soft-deleted.

404

Not found

Applicants — /api/v1/applicants

Message

Meaning and fix

Code

Category

Field

The ExternalID field is required.

The ExternalID field is missing or blank.

400

Field validation

ExternalID

The FirstName field is required.

The FirstName field is missing or blank.

400

Field validation

FirstName

The LastName field is required.

The LastName field is missing or blank.

400

Field validation

LastName

The Email field is required.

The Email field is missing or blank.

400

Field validation

Email

The Email field is not a valid e-mail address.

The Email value is not in a valid format.

400

Field validation

Email

The value of field Gender must be one of the specified values.

The Gender value is not one of the accepted values.

400

Field validation

Gender

Please enter a valid national insurance number.

The NationalInsuranceNumber does not match the expected UK format (e.g. AB 12 34 56 C).

400

Field validation

NationalInsuranceNumber

Value must be a valid ethnicity code.

The Ethnicity value is not an approved DfE ethnicity code. Refer to the API specification for the full list.

400

Field validation

Ethnicity

Value must be a valid nationality.

The Nationality value is not in the approved list. Spelling and casing must match exactly.

400

Field validation

Nationality

The Telephone field is not a valid phone number.

The Telephone value is not valid.

ⓘ Common causes: value contains non-dialable text such as x123, Ext 4567, or labels like Mum's number. Send only the dialable number.

400

Field validation

Telephone

The Mobile field is not a valid phone number.

The Mobile value is not valid.

400

Field validation

Mobile

The Applicants ExternalID: {value} does not match the path: {path}

The ExternalID in the request body does not match the URL path parameter.

400

Path/body mismatch

ExternalID

Unable to save applicant: Cannot create the applicant with internal id {grofarInternalID} and external id {externalID} because the applicant already exists with this external id

An applicant with this ExternalID already exists. Use PUT to update the existing record.

ⓘ If the ExternalID is genuinely new, a stale record may exist from a previous import. Check and delete it first if appropriate.

403

Business logic

ExternalID

Unable to save applicant: The date of birth is not recognised as a date format

The DateOfBirth value is not in a recognised format. Use ISO 8601: YYYY-MM-DD.

403

Business logic

DateOfBirth

Unable to perform bulk delete for applicants: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid.

403

Business logic

earliestImportedUtcDateTime

Applicant does not exist or has been deleted

No applicant exists with the ExternalID in the URL path.

404

Not found

Businesses — /api/v1/businesses

Message

Meaning and fix

Code

Category

Field

The ExternalBusinessID field is required.

The ExternalBusinessID field is missing or blank.

400

Field validation

ExternalBusinessID

The Name field is required.

The business Name field is missing or blank.

400

Field validation

Name

Maximum number of characters allowed for the Business Name is 200.

The business Name exceeds 200 characters.

400

Field validation

Name

The Website field is not a valid fully-qualified http, https, or ftp URL.

The Website must include a protocol: http://, https://, or ftp://.

ⓘ Common mistake: submitting www.example.com without the https:// prefix. Always include the protocol.

400

Field validation

Website

The value of field IndustrySector must be one of the specified values (A, B, C ... U).

The IndustrySector must be a single UK SIC section letter A–U. A=Agriculture, B=Mining, C=Manufacturing, D=Electricity, E=Water/sewerage, F=Construction, G=Wholesale/retail, H=Transport, I=Accommodation/food, J=Information/communication, K=Financial, L=Real estate, M=Professional/scientific, N=Administrative, O=Public administration, P=Education, Q=Health/social work, R=Arts/recreation, S=Other services, T=Household employers, U=Extraterritorial.

400

Field validation

IndustrySector

The value of field JobCategory must be one of the specified values (1 - 25).

The JobCategory must be a number from 1 to 25. Refer to the API specification for the full name mapping.

400

Field validation

JobCategory

The value of field CompanySize must be one of: 1, 2-10, 11-50, 51-200, 201-500, 501-1000, 1001-5000, 5001-10000, 10000+.

The CompanySize must exactly match one of the listed band strings, including hyphens and plus signs.

400

Field validation

CompanySize

The external business id: {value} does not match the path: {path}

The ExternalBusinessID in the request body does not match the URL path parameter.

400

Path/body mismatch

ExternalBusinessID

Unable to save business: The business owner {ownerExternalID} does not exist or has been deleted

The staff member referenced as the business owner has not been imported, or the ExternalID does not match.

ⓘ Staff must be imported before Businesses if a business owner is being assigned.

403

Business logic

BusinessOwnerExternalID

Unable to save business: Cannot update the business with internal id {grofarInternalID} because another business already exists with externalBusinessID {externalBusinessID}

Another business record already exists with this ExternalBusinessID. ExternalBusinessIDs must be unique.

ⓘ This can occur after a delete and re-import cycle leaves a stale record. Check for duplicate external IDs and resolve before retrying.

403

Business logic

ExternalBusinessID

Unable to save business: The PublicLiabilityExpiresDate is not recognised as a date format

The PublicLiabilityExpiresDate is not in a recognised format. Use YYYY-MM-DD.

403

Business logic

PublicLiabilityExpiresDate

Unable to save business: The EmployerLiabilityInsuranceExpiresDate is not recognised as a date format

Use YYYY-MM-DD format.

403

Business logic

EmployerLiabilityInsuranceExpiresDate

Unable to save business: {url} is not a well formed URL.

One of the URLs in the OtherSites list is not a valid fully-qualified URL.

ⓘ Every URL in OtherSites must include a protocol (http:// or https://). A single malformed entry rejects the whole request.

403

Business logic

OtherSites

Unable to perform bulk delete for businesses: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid.

403

Business logic

earliestImportedUtcDateTime

Business does not exist or has been deleted

No business exists with the ExternalID in the URL path.

404

Not found

Business Contacts — /api/v1/businesses/{businessid}/contacts

Message

Meaning and fix

Code

Category

Field

The Email field is not a valid e-mail address.

The contact Email value is not in a valid format.

400

Field validation

Email

The Telephone field is not a valid phone number.

The contact Telephone is not valid.

ⓘ Common causes: value contains non-dialable text such as x123, Ext 4567, or extension notation. Send only the dialable number.

400

Field validation

Telephone

The value of field Gender must be one of the specified values.

The Gender value is not one of the accepted values.

400

Field validation

Gender

Maximum number of characters allowed for the Title is 50.

The Title exceeds 50 characters.

400

Field validation

Title

The external business id: {value} does not match the path: {path}

The ExternalBusinessID in the request body does not match the {businessid} URL path parameter.

400

Path/body mismatch

ExternalBusinessID

The external contact id: {value} does not match the path: {path}

The ExternalContactID in the request body does not match the {contactid} URL path parameter.

400

Path/body mismatch

ExternalContactID

Unable to save business contact: The business {externalBusinessID} does not exist.

The parent business has not been imported, or the ExternalBusinessID does not match.

ⓘ Businesses must be imported before Business Contacts. The business must exist before any of its contacts can be saved.

403

Business logic

ExternalBusinessID

Unable to save business contact: Cannot create the business contact with id: {contactID} (business id: {businessID}) as a FirstName or a LastName is required

When creating a new contact, either FirstName or LastName (or both) must be provided.

ⓘ Both fields are optional for updates to existing contacts, but at least one is required on creation.

403

Business logic

FirstName / LastName

Unable to save business contact: Cannot update the business contact with internal id {grofarInternalID} because the business {businessID} already has a contact with external id {contactID}

Another contact for this business already uses this ExternalContactID.

403

Business logic

ExternalContactID

Unable to save business contact: {url} is not a well formed URL.

A URL in OtherSites is not a valid fully-qualified URL. Every URL must include a protocol.

403

Business logic

OtherSites

Unable to save business contact: The External login {externalLoginValue} is already linked to another user in the system

The Microsoft or Google login identity is already linked to a different user account.

403

Business logic

ExternalLogin

Unable to perform bulk delete for business contacts: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid.

403

Business logic

earliestImportedUtcDateTime

Business Contact does not exist or has been deleted

No contact exists with the contactid in the URL path, or it has been soft-deleted.

404

Not found

Business Departments — /api/v1/businesses/{businessid}/departments

Message

Meaning and fix

Code

Category

Field

The external business id: {value} does not match the path: {path}

The ExternalBusinessID in the request body does not match the {businessid} URL path parameter.

400

Path/body mismatch

ExternalBusinessID

The external department id: {value} does not match the path: {path}

The ExternalDepartmentID in the request body does not match the {deptid} URL path parameter.

400

Path/body mismatch

ExternalDepartmentID

Unable to save business department: The business {externalBusinessID} does not exist or has been deleted

The parent business has not been imported, or has been deleted.

ⓘ Businesses must be imported before Business Departments.

403

Business logic

ExternalBusinessID

Unable to save business department: Cannot update the department with internal id {grofarInternalID} because the business {businessID} already has a department with external id {departmentID}

Another department for this business already uses this ExternalDepartmentID.

403

Business logic

ExternalDepartmentID

Unable to save business department: The HealthAndSafetyCheckedDate is not recognised as a date format

Use ISO 8601: YYYY-MM-DD.

403

Business logic

HealthAndSafetyCheckedDate

Unable to save business department: The HealthAndSafetyExpiresDate is not recognised as a date format

Use ISO 8601: YYYY-MM-DD.

403

Business logic

HealthAndSafetyExpiresDate

Unable to save business department: The HigherRiskAssessmentDocumentsReviewedDate is not recognised as a date format

Use ISO 8601: YYYY-MM-DD.

403

Business logic

HigherRiskAssessmentDocumentsReviewedDate

Unable to save business department: HasEmployerLiabilityInsurance and EmployerLiabilityInsuranceNotRequired cannot both be true.

These two boolean flags are mutually exclusive. A department cannot both have ELI and be marked as not requiring ELI.

ⓘ If the employer has ELI: HasEmployerLiabilityInsurance=true, EmployerLiabilityInsuranceNotRequired=false. If ELI is not required: EmployerLiabilityInsuranceNotRequired=true, HasEmployerLiabilityInsurance=false.

403

Business logic

HasEmployerLiabilityInsurance / EmployerLiabilityInsuranceNotRequired

Cannot delete the primary department {departmentID} for business {businessID}

The primary department of a business cannot be deleted. First make another department primary, then delete this one.

ⓘ PUT another department with IsPrimaryDepartment=true first, then issue the DELETE on the old primary.

403

Business logic

Unable to perform bulk delete for business departments: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid.

403

Business logic

earliestImportedUtcDateTime

Business department does not exist or has been deleted

No department exists with the deptid in the URL path.

404

Not found

Courses — /api/v1/courses

Message

Meaning and fix

Code

Category

Field

The Code field is required.

The Code field is missing or blank.

400

Field validation

Code

The Title field is required.

The Title field is missing or blank.

400

Field validation

Title

Maximum number of characters allowed for Title is 200.

The Title exceeds 200 characters.

400

Field validation

Title

The ProgrammeAreaCode field is required.

The ProgrammeAreaCode field is missing or blank.

400

Field validation

ProgrammeAreaCode

Course Level must be a number between 0 and 6.

The Level must be an integer from 0 to 6. 0=Entry, 1=Level 1, 2=Level 2, 3=Level 3, 4=Level 4, 5=Level 5, 6=Level 6.

400

Field validation

Level

The value of field CourseYear must be one of: 1, 2, 3, 4, 5.

The CourseYear must be a number from 1 to 5.

ⓘ The API accepts CourseYear 1–5. The CSV import accepts 0–5. The value 0 is not valid via the API.

400

Field validation

CourseYear

The field TargetPlacementType must be between 1 and 14.

TargetPlacementType must be an integer from 1 to 14. Refer to the API specification for the name mapping.

ⓘ The API accepts TargetPlacementType 1–14. The CSV import accepts 0–14. The value 0 is not valid via the API.

400

Field validation

TargetPlacementType

The Course code: {value} does not match the path: {code}.

The Code in the request body does not match the {code} URL path parameter.

400

Path/body mismatch

Code

The Course instance: {value} does not match the path: {instance}.

The Instance in the request body does not match the {instance} URL path parameter.

400

Path/body mismatch

Instance

Cannot save a Course Instance using the course endpoint. Use the course/instance endpoint.

A request body containing an Instance value was sent to the course endpoint. Course instances must be saved via /api/v1/courses/course/{code}/instance/{instance}.

ⓘ A common mistake when adapting requests: if the body includes an Instance value, it must go to the /instance/ endpoint, not the base course endpoint.

400

Wrong endpoint

Unable to save course: The Programme Area {programmeAreaCode} does not exist.

The referenced programme area has not been imported, or the code does not match.

ⓘ Import order: Programme Areas must exist before Courses. The ProgrammeAreaCode must exactly match the Code used when the programme area was imported — including casing.

403

Business logic

ProgrammeAreaCode

Unable to save course: The StartDate is not recognised as a date format

The StartDate is not in a recognised format. Use YYYY-MM-DD.

403

Business logic

StartDate

Unable to save course: The EndDate is not recognised as a date format

The EndDate is not in a recognised format. Use YYYY-MM-DD.

403

Business logic

EndDate

Unable to perform bulk delete for courses: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid.

403

Business logic

earliestImportedUtcDateTime

Course does not exist or has been deleted

No course or course instance exists at the URL path given.

404

Not found

Programmes — /api/v1/programmes

Message

Meaning and fix

Code

Category

Field

The Code field is required.

The Code field is missing or blank.

400

Field validation

Code

The Instance field is required.

The Instance field is missing or blank.

400

Field validation

Instance

The Title field is required.

The Title field is missing or blank.

400

Field validation

Title

The ProgrammeAreaCode field is required.

The ProgrammeAreaCode field is missing or blank.

400

Field validation

ProgrammeAreaCode

The Programme code: {value} does not match the path: {code}

The Code in the request body does not match the URL path parameter.

400

Path/body mismatch

Code

The Programme instance: {value} does not match the path: {instance}

The Instance in the request body does not match the URL path parameter.

400

Path/body mismatch

Instance

Cannot save a Programme Instance using the programme endpoint. Use the programme/instance endpoint.

A programme instance was submitted to the programme endpoint. Use /api/v1/programmes/{code}/instance/{instance}.

400

Wrong endpoint

Unable to save programme: The Programme Area {programmeAreaCode} does not exist.

The referenced programme area has not been imported. Programme Areas must exist before Programmes.

403

Business logic

ProgrammeAreaCode

Unable to perform bulk delete for programmes: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid.

403

Business logic

earliestImportedUtcDateTime

Programme does not exist or has been deleted

No programme or programme instance exists at the URL path given.

404

Not found

Student Courses — /api/v1/studentcourses

Message

Meaning and fix

Code

Category

Field

The ExternalStudentID field is required.

The ExternalStudentID field is missing or blank.

400

Field validation

ExternalStudentID

The CourseCode field is required.

The CourseCode field is missing or blank.

400

Field validation

CourseCode

The value of field Status must be one of: Completed, Transferred, Continuing, Withdrawn, TemporarilyWithdrawn.

The Status value must exactly match one of the listed strings, including casing.

400

Field validation

Status

The External Student ID: {value} does not match the path: {path}.

The ExternalStudentID in the request body does not match the {studentid} URL path parameter.

400

Path/body mismatch

ExternalStudentID

The Course code: {value} does not match the path: {code}.

The CourseCode in the request body does not match the {code} URL path parameter.

400

Path/body mismatch

CourseCode

The courseInstance property is missing from the body - it must match the parameter value: {instance}.

The URL path includes a course instance segment but the courseInstance property is missing from the request body.

ⓘ When using the instance endpoint (/instance/{instance}), the courseInstance property in the request body is required and must match the URL parameter. A common omission when adapting from the non-instance endpoint.

400

Path/body mismatch

CourseInstance

Cannot save a Student Course instance. Use the course/instance endpoint to save a Student Course Instance.

A student course instance was submitted to the non-instance endpoint.

400

Wrong endpoint

Unable to save course instance: The student {externalStudentID} does not exist or has been deleted

The referenced student has not been imported, or the ExternalID does not match.

ⓘ Import order: Students must be imported before Student Courses. This is the most common 403 in a fresh import — check the students endpoint completed without errors first.

403

Business logic

ExternalStudentID

Unable to save course instance: The course {courseCode} {courseInstance} does not exist or has been deleted

The referenced course or course instance has not been imported, or the code/instance does not match.

ⓘ Courses must be imported before Student Courses. Check CourseCode and CourseInstance match exactly — including casing — what was used when the course was imported.

403

Business logic

CourseCode / CourseInstance

Unable to save course instance: The StartDate is not recognised as a date format

Use ISO 8601: YYYY-MM-DD.

403

Business logic

StartDate

Unable to save course instance: The EndDate is not recognised as a date format

Use ISO 8601: YYYY-MM-DD.

403

Business logic

EndDate

Unable to perform bulk delete for student courses: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid.

403

Business logic

earliestImportedUtcDateTime

Student Course does not exist or has been deleted

No student course enrolment exists at the URL path given.

404

Not found

Student Primary Contacts — /api/v1/studentprimarycontacts

Message

Meaning and fix

Code

Category

Field

The ExternalStudentID field is required.

The ExternalStudentID field is missing or blank.

400

Field validation

ExternalStudentID

The FirstName field is required.

The FirstName field is missing or blank.

400

Field validation

FirstName

The LastName field is required.

The LastName field is missing or blank.

400

Field validation

LastName

The Email field is not a valid e-mail address.

The Email value is not in a valid format.

400

Field validation

Email

The HomePhoneNumber field is not a valid phone number.

The HomePhoneNumber value is not valid.

ⓘ Common causes: value contains non-dialable text such as Mum's number, Dad's number, x123, or Ext 4567. Send only the dialable number.

400

Field validation

HomePhoneNumber

The MobilePhoneNumber field is not a valid phone number.

The MobilePhoneNumber value is not valid.

ⓘ Common causes: same as HomePhoneNumber. Also check for landlines placed in the mobile field.

400

Field validation

MobilePhoneNumber

Unable to save student primary contact: The student {externalStudentID} does not exist or has been deleted

The referenced student has not been imported, or the ExternalID does not match.

ⓘ Students must be imported before Student Primary Contacts.

403

Business logic

ExternalStudentID

Unable to perform bulk delete for student primary contacts: The {dateValue} is not a valid date

The earliestImportedUtcDateTime in the bulk delete request is not valid.

403

Business logic

earliestImportedUtcDateTime

Student primary contact does not exist or has been deleted

No student primary contact exists at the URL path given.

404

Not found

Student Target Hours — /api/v1/studenttargethours

Message

Meaning and fix

Code

Category

Field

The ExternalStudentID field is required.

The ExternalStudentID field is missing or blank.

400

Field validation

ExternalStudentID

Unable to save student target hours: The student {externalStudentID} does not exist or has been deleted

The referenced student has not been imported.

ⓘ Students must be imported before Student Target Hours.

403

Business logic

ExternalStudentID

Unable to save student target hours: Cannot import Target Hours for Student {externalStudentID} for course {courseCode}/{courseInstance} as this Student Course enrolment has not been imported for the student.

The student course enrolment must exist before target hours can be set for it.

ⓘ Import order: Students then Student Courses then Student Target Hours. The student must be enrolled on the specific course before target hours can be saved for that enrolment.

403

Business logic

CourseCode / CourseInstance

Unable to save student target hours: Cannot Import Target Hours for Student {externalStudentID} the ToAcademicYear: {toYear} is not greater than the FromAcademicYear: {fromYear}

The ToAcademicYear must be strictly greater than FromAcademicYear. Both values are the start year of the academic year (e.g. 2024 for 2024/25).

ⓘ The two values cannot be equal — ToAcademicYear must always be later than FromAcademicYear.

403

Business logic

ToAcademicYear / FromAcademicYear

The Student does not exist or has been deleted

No student exists with the ExternalID in the URL path.

404

Not found

Student Target Skills — /api/v1/studentTargetSkills

Message

Meaning and fix

Code

Category

Field

The ExternalStudentID field is required.

The ExternalStudentID field is missing or blank.

400

Field validation

ExternalStudentID

The External Student ID: {value} does not match the path: {externalStudentID}.

The ExternalStudentID in the request body does not match the URL path parameter.

400

Path/body mismatch

ExternalStudentID

Unable to save student target skill: The student {externalStudentID} does not exist or has been deleted

The referenced student has not been imported.

ⓘ Students must be imported before Student Target Skills.

403

Business logic

ExternalStudentID

Unable to save student target skill: No skill with id {skillID} exists

The skill ID referenced in the request does not exist in the Grofar system.

ⓘ Retrieve the list of valid skill IDs from GET /api/v1/studentTargetSkills/Skills before submitting. Skill IDs are system-defined and cannot be created via the import API.

403

Business logic

SkillID

Student does not exist or has been deleted

No student exists with the ExternalID in the URL path.

404

Not found

Quick-reference: common causes

Most API errors fall into one of these categories:

  • 401 on every request — the bearer token is missing, expired, or malformed. Tokens are valid for 7 days.

  • 403 with "does not exist" — a referenced entity (student, course, campus, faculty, etc.) has not been imported yet, or the ID does not match exactly. Check import order and ID casing.

  • 400 path/body mismatch — the ID in the request body does not match the ID in the URL. Always keep them in sync, especially when reusing request templates.

  • 400 wrong endpoint — a resource instance (e.g. course instance) was submitted to the base endpoint rather than the /instance/ endpoint.

  • 400 invalid phone number — the value contains non-dialable text such as x123, Ext 4567, or labels like Mum's number. Send only the dialable number.

  • 400 security check — a field contains angle brackets, ampersands, or other characters flagged as a potential security risk. Strip or encode them.

  • 403 date format — a date field is not in ISO 8601 format (YYYY-MM-DD). This is a 403 business logic error, not a 400 validation error, for several resources.

  • 429 rate limit — 60,000 requests per 60-minute window during business hours. Schedule large imports outside 08:00–18:00 UTC on weekdays.

  • 500 server error — often caused by a null or unexpected value in a field that passes validation but causes a server-side exception. Contact Grofar support with the request body and timestamp.

Did this answer your question?