Student Mutations
Create students and update their profile and admin tags in your Loopwise school
The student mutations allow you to create students and update an existing student's profile fields and admin-managed tags.
Student entity mutations:
createStudent— Creates a new student, or returns the existing user if the email already matches oneupdateStudent— Updates a student's name, phone number, and/or admin tags
Both mutations require a token with the students:write scope.
Note: Admin tags can gate access to tag-restricted consulting services, so tag writes are an access-granting operation — grant
students:writeaccordingly.
Create a Student
The createStudent mutation creates a new student in your school, or returns the existing user if the email already matches one. It is idempotent — safe to retry — and does NOT send any email.
Input Parameters
| Field | Type | Required | Description |
|---|---|---|---|
email | String! | Yes | Email of the student. Used as the idempotency key within the school. |
name | String | No | Display name of the student. When omitted or blank, the email is used as the display name. For existing users, an incoming name is ignored unless the existing name is blank or the placeholder "Student". |
phoneNumber | String | No | Phone number. Ignored if the user already exists. |
Return Type
type AdminCreateStudentPayload {
# The created or existing student
student: AdminUser!
# True if a new user was created, false if the email matched an existing user
created: Boolean!
}Example
mutation CreateStudent {
createStudent(
email: "jane@example.com"
name: "Jane Doe"
phoneNumber: "0912345678"
) {
student {
id
email
name
phoneNumber
}
created
}
}Sample Response
{
"data": {
"createStudent": {
"student": {
"id": "user_12345",
"email": "jane@example.com",
"name": "Jane Doe",
"phoneNumber": "+886912345678"
},
"created": true
}
}
}Common Errors
| Code | Description |
|---|---|
STUDENT-002 | Invalid email format |
STUDENT-004 | Failed to create new user |
Update a Student
The updateStudent mutation performs a partial update on an existing student in your school. Only the input keys you provide are applied — omitted keys leave the corresponding field unchanged. All writes are absolute sets, so the mutation is idempotent — safe to retry.
Note:
createStudentand is never changed through the Admin API.
Who is updatable: any user holding the student role in the school. Teaching assistants without the student role and unknown or out-of-school IDs return a not-found error.
Input Parameters
| Field | Type | Description |
|---|---|---|
id | String! | ID of the student to update |
input | AdminStudentUpdateInput! | Partial-update fields (see below) |
AdminStudentUpdateInput Fields
| Field | Type | Required | Description |
|---|---|---|---|
name | String | No | Display name. Omit to leave unchanged. Explicit null or a blank string is rejected — students must keep a display name. |
phoneNumber | String | No | Phone number. Omit to leave unchanged; pass null to clear it. Numbers are normalized with a TW default country code and echoed back normalized (e.g. 0912345678 → +886912345678). |
tags | [String!] | No | Admin tags. Replaces the entire list — pass all tags every time. An empty array ([]) clears all admin tags; explicit null is a no-op, same as omitting the key. Tags containing commas are rejected. Tag names match case-insensitively but preserve the casing of first use. System-managed tags are never touched. |
To modify tags safely, read the current list first from the tags field on AdminUser (see Users Query), modify it, and write the full list back.
Return Type
type AdminUpdateStudentPayload {
# The updated student, null if the update failed
student: AdminUser
# Validation errors, if any occurred during the update
errors: [String!]
}Example
mutation UpdateStudent {
updateStudent(
id: "user_12345"
input: {
name: "Jane Doe"
phoneNumber: "0912345678"
tags: ["vip", "beta-tester"]
}
) {
student {
id
name
phoneNumber
tags
}
errors
}
}Sample Response
{
"data": {
"updateStudent": {
"student": {
"id": "user_12345",
"name": "Jane Doe",
"phoneNumber": "+886912345678",
"tags": ["beta-tester", "vip"]
},
"errors": null
}
}
}Partial Update Example
Omitted keys (including tags) are left untouched:
mutation UpdateStudentNameOnly {
updateStudent(id: "user_12345", input: { name: "Jane Smith" }) {
student {
id
name
phoneNumber # unchanged
tags # unchanged
}
errors
}
}Clearing All Tags
Pass an empty array to remove all admin tags from a student (tags: null would be a no-op):
mutation ClearStudentTags {
updateStudent(id: "user_12345", input: { tags: [] }) {
student {
id
tags
}
errors
}
}Common Errors
| Code | Description |
|---|---|
STUDENT-005 | User not found — the id does not resolve to a user with the student role in the current school (unknown ID, out-of-school user, or a teaching assistant without the student role) |
STUDENT-003 | Name cannot be blank — explicit null or blank name is rejected |
STUDENT-007 | Invalid tag value — tags must be non-blank and must not contain commas |
STUDENT-006 | Failed to update user |
Model validation failures (e.g. an invalid phone number) are returned in the errors field of the payload rather than as GraphQL errors.