Skip to content

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/graphqlnot /graphql, which is the public school API. Authenticate with an sk_live_… API key in the X-Teachify-API-Key header. See the API Overview for details.

All three mutations require:

  • courses:write

Each mutation returns a payload with two fields:

  • consultingService — the affected AdminConsultingService, or null when the operation failed on a recoverable validation error.
  • errors — a list of validation messages when the record failed to save, otherwise null.

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.


Creates a new consulting service under a course. The service is created with serviceType: consulting and attached to the course as its target.

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!]
}
  • name (required) — Display name of the service.
  • courseId (required) — Parent course ID. The course must belong to the current school, otherwise CONSULTING-002.
  • slug — URL slug. Must match ^[a-z0-9-]+$ when provided, otherwise CONSULTING-003. When blank, a slug is derived from the name by friendly_id.
  • lecturerId — Assigned lecturer. Must belong to the same school, otherwise CONSULTING-005.
  • published — When true, the service is marked published and publishedAt is 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, otherwise CONSULTING-006.
  • backgroundColor — UI background color, hex.
CodeMeaning
CONSULTING-002Parent course not found in this school.
CONSULTING-003slug is not a valid URL slug (lowercase letters, numbers, hyphens).
CONSULTING-005lecturerId does not reference a lecturer in this school.
CONSULTING-006ratingFormId does not reference a form in this school.
GENERAL-001Unexpected internal error.
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
}
}
}

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.

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!]
}
CodeMeaning
CONSULTING-001Consulting service not found in this school.
CONSULTING-003slug is not a valid URL slug.
CONSULTING-005lecturerId does not reference a lecturer in this school.
CONSULTING-006ratingFormId does not reference a form in this school.
GENERAL-001Unexpected internal error.
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
}
}
}

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.

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!]
}
CodeMeaning
CONSULTING-001Consulting service not found in this school.
CONSULTING-004The service still has undiscarded, non-canceled future meetings and cannot be deleted.
GENERAL-001Unexpected internal error.
mutation {
deleteConsultingService(id: "svc-100") {
consultingService {
id
discardedAt
}
errors
}
}
{
"data": {
"deleteConsultingService": {
"consultingService": {
"id": "svc-100",
"discardedAt": 1768521600
},
"errors": null
}
}
}

For more information about the Teachify Admin API, please refer to the API Overview.