Consulting Service Mutations
A consulting service is a bookable offering attached to a course — it groups together the consulting meetings (time slots) that students enroll in. These three mutations manage the service record itself; use the Consulting Meeting Mutations to manage the slots underneath it.
Endpoint and authentication. All admin mutations are sent to
POST /admin/graphql— not/graphql, which is the public school API. Authenticate with ansk_live_…API key in theX-Teachify-API-Keyheader. See the API Overview for details.
Required scope
Section titled “Required scope”All three mutations require:
courses:write
Shared payload
Section titled “Shared payload”Each mutation returns a payload with two fields:
consultingService— the affectedAdminConsultingService, ornullwhen the operation failed on a recoverable validation error.errors— a list of validation messages when the record failed to save, otherwisenull.
Recoverable model-validation failures return { consultingService: null, errors: [...] }. The coded errors documented below are raised into the top-level GraphQL errors array (with the code in extensions.error.code). Any unexpected internal failure is surfaced as GENERAL-001.
The AdminConsultingService type exposes: id, name, slug, description, published, publishedAt, tags, backgroundColor, ratingFormId, ratingForm, courseId, lecturerId, lecturer, effectiveTimezone, meetingCount(state:), discardedAt, createdAt, and updatedAt.
createConsultingService
Section titled “createConsultingService”Creates a new consulting service under a course. The service is created with serviceType: consulting and attached to the course as its target.
Signature
Section titled “Signature”createConsultingService( input: AdminConsultingServiceInput!): AdminConsultingServiceCreatePayload!
input AdminConsultingServiceInput { name: String! # Required. Display name of the service. courseId: String! # Required. Parent course ID; must belong to the same school. slug: String # URL slug (lowercase letters, numbers, hyphens). Derived from name if blank. description: String lecturerId: String # Assigned lecturer ID; must belong to the same school. published: Boolean # When true, stamps publishedAt to the current time. tags: [String!] # Tag list; replaces the entire list. ratingFormId: String # Linked feedback form ID. backgroundColor: String # UI background color (hex).}
type AdminConsultingServiceCreatePayload { consultingService: AdminConsultingService errors: [String!]}Arguments
Section titled “Arguments”name(required) — Display name of the service.courseId(required) — Parent course ID. The course must belong to the current school, otherwiseCONSULTING-002.slug— URL slug. Must match^[a-z0-9-]+$when provided, otherwiseCONSULTING-003. When blank, a slug is derived from the name by friendly_id.lecturerId— Assigned lecturer. Must belong to the same school, otherwiseCONSULTING-005.published— Whentrue, the service is marked published andpublishedAtis stamped to the current time.tags— Replaces the entire tag list (stored in the service settings JSON), so pass every tag each time.ratingFormId— Linked feedback form. Must belong to the same school, otherwiseCONSULTING-006.backgroundColor— UI background color, hex.
Error codes
Section titled “Error codes”| Code | Meaning |
|---|---|
CONSULTING-002 | Parent course not found in this school. |
CONSULTING-003 | slug is not a valid URL slug (lowercase letters, numbers, hyphens). |
CONSULTING-005 | lecturerId does not reference a lecturer in this school. |
CONSULTING-006 | ratingFormId does not reference a form in this school. |
GENERAL-001 | Unexpected internal error. |
Example
Section titled “Example”mutation { createConsultingService( input: { name: "1-on-1 Coaching" courseId: "course-42" slug: "one-on-one-coaching" lecturerId: "lecturer-7" published: true } ) { consultingService { id name slug published publishedAt } errors }}{ "data": { "createConsultingService": { "consultingService": { "id": "svc-100", "name": "1-on-1 Coaching", "slug": "one-on-one-coaching", "published": true, "publishedAt": 1768435200 }, "errors": null } }}updateConsultingService
Section titled “updateConsultingService”Partially updates a single consulting service. Only the input keys you provide are applied; explicit null clears the nullable fields (lecturerId, ratingFormId, backgroundColor).
courseId is intentionally not updatable — a service cannot be reparented across courses, because that would orphan its meetings and enrollments. Create a new service instead.
Setting published: false does not clear publishedAt — the historical first-publish timestamp is preserved across unpublish/republish cycles. Reassigning lecturerId updates the service-level lecturer only; existing meetings retain the lecturer they were created with.
Signature
Section titled “Signature”updateConsultingService( id: String! # Required. ID of the consulting service to update. input: AdminConsultingServiceUpdateInput!): AdminConsultingServiceUpdatePayload!
input AdminConsultingServiceUpdateInput { name: String slug: String # URL slug (lowercase letters, numbers, hyphens). description: String lecturerId: String # Pass null to remove the lecturer. published: Boolean # true publishes (stamps publishedAt on first publish); false does not clear publishedAt. tags: [String!] # Replaces the entire list. ratingFormId: String # Pass null to remove. backgroundColor: String # Pass null to remove.}
type AdminConsultingServiceUpdatePayload { consultingService: AdminConsultingService errors: [String!]}Error codes
Section titled “Error codes”| Code | Meaning |
|---|---|
CONSULTING-001 | Consulting service not found in this school. |
CONSULTING-003 | slug is not a valid URL slug. |
CONSULTING-005 | lecturerId does not reference a lecturer in this school. |
CONSULTING-006 | ratingFormId does not reference a form in this school. |
GENERAL-001 | Unexpected internal error. |
Example
Section titled “Example”mutation { updateConsultingService( id: "svc-100" input: { description: "Updated blurb", lecturerId: null } ) { consultingService { id description lecturerId } errors }}{ "data": { "updateConsultingService": { "consultingService": { "id": "svc-100", "description": "Updated blurb", "lecturerId": null }, "errors": null } }}deleteConsultingService
Section titled “deleteConsultingService”Soft-deletes (discards) a consulting service. The mutation refuses to delete a service that still has undiscarded, non-canceled future meetings — cancel those first via bulkCancelConsultingMeetings (or wait for them to end). A canceled future meeting is treated as retired and does not block deletion.
Signature
Section titled “Signature”deleteConsultingService( id: String! # Required. ID of the consulting service to delete.): AdminConsultingServiceDeletePayload!
type AdminConsultingServiceDeletePayload { consultingService: AdminConsultingService # The discarded service; discardedAt is now set. errors: [String!]}Error codes
Section titled “Error codes”| Code | Meaning |
|---|---|
CONSULTING-001 | Consulting service not found in this school. |
CONSULTING-004 | The service still has undiscarded, non-canceled future meetings and cannot be deleted. |
GENERAL-001 | Unexpected internal error. |
Example
Section titled “Example”mutation { deleteConsultingService(id: "svc-100") { consultingService { id discardedAt } errors }}{ "data": { "deleteConsultingService": { "consultingService": { "id": "svc-100", "discardedAt": 1768521600 }, "errors": null } }}Related Resources
Section titled “Related Resources”For more information about the Teachify Admin API, please refer to the API Overview.