Planifica API Error Codes

API reference

Error Codes

The full error-code catalog for the optimizer and the partner API gateway, split out from the main reference so it stays easy to scan.

Optimizer Error Codes

Domain-level scheduling errors returned inside the response body by the optimize, allocation, and validate endpoints — not as HTTP error statuses.

Request Data Integrity

DUPLICATE_SESSION_IDData Integrity

The same session id is used by more than one session in the request. Session IDs must be unique.

PARENT_ID_DURATION_CONFLICTData Integrity

Two or more sessions share the same parentId but have different duration values. All sessions in a group must have the same length.

SESSION_INSTRUCTOR_CONFLICTData Integrity

Two locked sessions are pinned to overlapping times and would require the same instructor at once.

NO_VALID_SESSIONSData Integrity

After processing the request, no sessions remained to schedule — check your schemas/sessions data.

INVALID_WORKING_DAYData Integrity

Something in the request (an instructor's available_days, a grade's working_hours, or a capacity/affinity/cardinality config day) references a day that isn't one of the school's configured working_days.

Setup & Prerequisites

NO_CLASSROOMSSetup

The request contains no classrooms at all. At least one is required.

NO_INSTRUCTORSSetup

The request contains no instructors at all. At least one is required.

SUBJECT_NO_INSTRUCTORSSetup

A subject is used by one or more sessions, but no instructor lists that subject as something they can teach.

INSTRUCTOR_NO_GRADESWarning only

An instructor isn't assigned to any grade, so they can never be matched to a session.

NO_AVAILABLE_ROOMSWarning only

A session has no classroom that matches its subject's room requirements. The session can still be scheduled without a fixed room, but you should add a suitable classroom.

Availability & Feasibility

NO_AVAILABLE_INSTRUCTORSAvailability

A session's grade/subject combination has zero instructors that can teach it (after matching availability and grade assignment).

NO_AVAILABLE_TIMESLOTSAvailability

A session has matching instructors, but no time slot fits its duration alongside grade hours and other constraints.

UNSCHEDULABLE_SESSIONAvailability

Catch-all: a session cannot be placed anywhere that satisfies all of its requirements simultaneously (instructor, room, time, ordering, etc.).

INSUFFICIENT_CONTINUOUS_SLOTSAvailability

A grade has a session whose duration exceeds the longest continuous block of available time in that grade's working hours. Lengthening or rearranging working hours is required.

SPECIALIZED_ROOM_CAPACITY_EXCEEDEDAvailability

The total hours of sessions that require a specific specialized room exceed the total time slots available for that room across the whole week.

Instructor & Grade Capacity

INSTRUCTOR_OVERALLOCATIONCapacity

A locked session assigns more hours to an instructor than they have available — either overall, or specifically within one grade.

INSUFFICIENT_INSTRUCTOR_CAPACITYCapacity

The hours required for a (grade, subject) pair exceed the combined available capacity of instructors who can teach it.

INSUFFICIENT_TOTAL_INSTRUCTOR_CAPACITYCapacity

The hours a set of sessions needs exceed what their eligible instructors can share across them. Two checks raise it:

  • Per subject — the hours for one subject, summed across all grades, exceed the total capacity of every instructor who can teach it. subject is set; details carries required_hours and available_hours.
  • Shared instructors — instructors who teach several subjects or grades cannot split their available slots and weekly budgets to cover every eligible session, even though each subject fits on its own. details.constraint_type is shared_instructor_capacity; session_ids lists the affected sessions, and details adds deficit_hours, instructor_ids, instructor_names, grades, and subjects. grade and subject are set only when a single grade or subject is affected — otherwise read details.grades and details.subjects.

Add availability or capacity to the listed instructors, assign more instructors to the listed subjects, or reduce the sessions' hours.

INSUFFICIENT_GRADE_CAPACITYCapacity

A grade/group's total scheduled hours exceed the maximum hours available in that grade's school week.

INSUFFICIENT_TOTAL_CAPACITYWarning only

The total teaching time needed across the whole request exceeds what all instructors combined can provide.

CAPACITY_WINDOW_INFEASIBLECapacity

The sessions of one grade, subject, and group cannot fit the capacity_configs hour limits or cardinality_configs session-count limits of their time windows, given the times those sessions are allowed to start (including locked sessions). grade, subject, group, and session_ids are set. Three checks raise it:

  • One window overflows — the hours or sessions that unavoidably overlap a single window exceed its limit. details carries forced_sessions, required_hours, capacity_hours, cardinality_limit, window_start_slot, and window_end_slot.
  • Combined hour limits — no placement fits all sessions across the windows' hour budgets. details.constraint_type is combined_window_capacity; details adds required_hours, available_hours, deficit_hours, and a windows array of start_slot, end_slot, and capacity_hours.
  • Combined session limits — no placement fits all sessions across the windows' session-count budgets. details carries total_sessions, windows, capacity_outside_windows, and total_available.

Raise the window limits, widen the windows, or free up allowed start times outside them.

Locked Sessions (Incremental Optimization)

A session becomes "locked" once both day and start are set — see Understanding Constraints on the API concepts page.

LOCKED_SESSION_INSTRUCTOR_UNAVAILABLELocked Session

A locked session (with day, start, and institutor all set) falls outside that instructor's declared availability.

LOCKED_SESSION_OUTSIDE_GRADE_HOURSLocked Session

A locked session's start time — or its full duration — falls outside the grade's configured working_hours.

FIXED_SESSION_CLASS_CONFLICTLocked Session

Two locked sessions belonging to the same grade/group can't both be scheduled without overlapping — their fixed times are mutually incompatible.

FIXED_SESSION_ROOM_CONFLICTLocked Session

Two or more locked sessions require the same specialized classroom at the same time slot.

Session Ordering & Spacing

These relate to ordering_configs rules — see Understanding Constraints on the API concepts page.

SESSION_ORDERING_CYCLEOrdering

The follows constraints for a grade form a circular dependency (A follows B, B follows A, directly or transitively). Remove or rework one of the constraints.

INVALID_DISTANCE_BETWEEN_CONFIGOrdering

A distance_between entry is malformed — missing both gap bounds, a negative gap, min_gap_slots > max_gap_slots, or its subject/session targets don't resolve to any session. (A small subset of these same checks are instead caught earlier as 422 schema errors.)

DISTANCE_BETWEEN_INFEASIBLEOrdering

A distance_between constraint can't be satisfied given the other constraints in the request — e.g. no placement keeps the required minimum/maximum gap between the referenced sessions.

Cardinality Configuration

INVALID_CARDINALITY_CONFIGCardinality

A cardinality_configs entry is malformed. Covers many distinct sub-cases: missing/invalid subject, cardinality <= 0, missing/invalid day or time window fields, a window that doesn't align to any timetable slot, or a duplicate window for the same subject. The message field always spells out which sub-case applies.

Reserved — Not Currently Emitted

These codes exist in the API's ErrorCodeenum for forward compatibility but aren't currently produced by any endpoint. You may see them in generated client SDKs or OpenAPI schemas — there's no need to handle them today, and their absence from a response is expected, not a sign your integration is missing something.

NO_AVAILABLE_CAPACITYEXCESSIVE_INSTRUCTOR_CAPACITYINSTRUCTOR_TIME_CONFLICTROOM_TIME_CONFLICTGRADE_GROUP_TIME_CONFLICTCARDINALITY_FEASIBILITY_WARNING

Error Response Example

Every entry has code and message. grade, group, subject, session_ids, instructor, room, and day are present when they apply. details is a code-specific object of machine-readable context, such as the hours involved or the instructors concerned; its keys are listed on each card above.

{
  "id": "validation_123",
  "valid": false,
  "errors": [
    {
      "message": "Session scheduled outside valid working days",
      "code": "INVALID_WORKING_DAY",
      "grade": "CP",
      "group": "A",
      "subject": "MATH"
    },
    {
      "message": "No instructors are available for the session",
      "code": "NO_AVAILABLE_INSTRUCTORS",
      "grade": "CM1",
      "subject": "SCIENCE"
    },
    {
      "message": "Shared teachers cannot cover all MATH, PHYSICS sessions in grades CM1, CM2: need 6.0 hours, but their eligible time and shared weekly budgets can cover at most 4.0 hours. Add eligible teacher time or reduce demand.",
      "code": "INSUFFICIENT_TOTAL_INSTRUCTOR_CAPACITY",
      "session_ids": ["CM1-MATH-1", "CM1-PHYSICS-1", "CM2-MATH-1"],
      "details": {
        "constraint_type": "shared_instructor_capacity",
        "required_hours": 6.0,
        "available_hours": 4.0,
        "deficit_hours": 2.0,
        "instructor_ids": [12, 15],
        "instructor_names": ["A. Benali", "S. Idrissi"],
        "grades": ["CM1", "CM2"],
        "subjects": ["MATH", "PHYSICS"]
      }
    }
  ],
  "warnings": []
}

Partner API Error Codes

Errors specific to the partner gateway: API key issues, rate limiting, and request validation — including the unit and slot-multiple rules, which the optimizer reports inside a 2xx body rather than as an HTTP status.

HTTP
Response indicator
400
Missing school metadata
code: SCHOOL_REQUIRED
Explanation: The request does not include both schoolExternalId and schoolName as top-level fields, or one of them is empty or longer than 255 characters.
Recommended action: Send a stable partner-side school identifier and a readable school name on every validate, allocate, and optimize request.
400
Invalid duration or capacity in minutes
code: INVALID_DURATION_MINUTES
Explanation: A session or capacity entry sends duration_minutes or capacity_minutes together with its hour equivalent (duration or capacity), or sends a value that is not a positive whole number of minutes. details[] names the offending entry with its dotted path, such as schemas.0.sessions.3.
Recommended action: Send exactly one spelling per entry. Prefer the minutes fields with whole positive integers; keep the hour fields only for legacy integrations.
200 / 202
Session length is not a whole number of slots
errors[].code: DURATION_NOT_SLOT_MULTIPLE
Explanation: A session length is not an exact multiple of timetable.time_granularity, so it cannot be placed on the timetable grid. The optimizer reports every offending session in one 2xx body rather than silently rounding up, which used to consume an extra slot of grade and teacher time. Each entry carries errors[].session_ids, and an errors[].details object whose keys are duration_minutes, time_granularity, nearest_upper, and nearest_lower when a shorter valid length exists — nearest_lower is absent for a session shorter than one slot.
Recommended action: Set each session length to one of the nearest valid values, or change timetable.time_granularity so the lengths you need are exact multiples of it. Capacities are budgets and are never rejected this way; a non-multiple capacity only produces a CAPACITY_NOT_SLOT_MULTIPLE warning naming the effective value.
401
API key missing
message: API key required
Explanation: The request did not include an API key header.
Recommended action: Include X-API-Key, or use Authorization with the ApiKey scheme.
401
Malformed API key
message: Invalid API key format
Explanation: The key does not match the expected Planifica API-key format.
Recommended action: Copy the full key from the partner portal. If the key was lost, rotate it and use the newly generated value.
401
Unknown or invalid API key
message: Invalid API key
Explanation: The key could not be matched or is no longer valid.
Recommended action: Verify the environment variable, remove whitespace, and rotate the key if the value may have been exposed.
401
Disabled API key
message: API key is disabled
Explanation: The key exists but is not active.
Recommended action: Create or activate a key in the partner portal, then deploy the active key to the integration.
401
Expired API key
message: API key has expired
Explanation: The key is past its expiration date.
Recommended action: Rotate the key in the partner portal and update the integration configuration.
401 or 429
Rate limit exceeded
message: Rate limit exceeded
Explanation: The key or subscription has exceeded an operational usage limit.
Recommended action: Reduce request concurrency, retry with backoff, and review usage limits in the partner portal.
401
IP address not allowed
message: IP address not whitelisted
Explanation: The key is restricted to specific IP addresses and the caller IP is not on the list.
Recommended action: Call from an allowed server IP or update the key restrictions in the portal.
401
Origin not allowed
message: Origin not allowed
Explanation: The key is restricted to specific origins and the request origin is not allowed.
Recommended action: Use the integration from an allowed origin or update allowed origins in the portal.
401
Endpoint not allowed
message: Endpoint not allowed
Explanation: The key is restricted to a set of paths and this request does not match those restrictions.
Recommended action: Use the documented Planifica optimization endpoints or update the key endpoint restrictions.
403
Key scoped to another application
message: API key is not scoped to application 'planifica'
Explanation: The key exists but is not scoped to Planifica.
Recommended action: Create a Planifica API key in the partner portal and use that key for optimizer requests.
403
Missing Planifica permission
message: Service account has no permission for application
Explanation: The service account behind the key does not have access to the Planifica API feature.
Recommended action: Ask an organization administrator to grant the Planifica API permission or use a key created for a permitted account.
503
Optimizer unavailable
code: OPTIMIZER_UNREACHABLE
Explanation: Planifica could not reach the optimizer service.
Recommended action: Retry with backoff. If the issue persists, share the requestId with Planifica support.
504
Optimizer timeout
code: OPTIMIZER_TIMEOUT
Explanation: The optimizer did not answer before the request timeout.
Recommended action: Retry later, reduce payload complexity if possible, and keep the requestId for support.
400
Optimizer rejected the payload
code: OPTIMIZER_ERROR_400
Explanation: The optimizer reported that the request payload is invalid.
Recommended action: Call validate first, fix reported data issues, then resubmit the optimization request.
403
Optimizer authorization failure
code: OPTIMIZER_ERROR_401 or OPTIMIZER_ERROR_403
Explanation: Planifica could not authorize the downstream optimizer request.
Recommended action: Retry later and contact support with the requestId if it repeats.
404
Optimizer resource not found
code: OPTIMIZER_ERROR_404
Explanation: The optimizer could not find the downstream task or resource.
Recommended action: Confirm the taskId and retry status polling only for taskIds returned by Planifica.
429
Optimizer busy
code: OPTIMIZER_ERROR_429
Explanation: The optimizer rejected the request because of downstream throttling.
Recommended action: Retry with exponential backoff and avoid submitting duplicate optimization jobs.
502
Optimizer service error
code: OPTIMIZER_ERROR_500, OPTIMIZER_ERROR_502, or OPTIMIZER_ERROR_503
Explanation: The optimizer returned a server-side error.
Recommended action: Retry with backoff. If the error persists, send the requestId and timestamp to support.
500
Unexpected API error
code: UNKNOWN_ERROR
Explanation: Planifica encountered an unexpected error while processing the request.
Recommended action: Retry once. If the error repeats, contact support with the requestId.
400
Task not found
message: Task {taskId} not found
Explanation: The task does not exist for the organization attached to the API key.
Recommended action: Check that the taskId came from the same API key organization and was not mistyped.
400
Task can no longer be cancelled
message: Task {taskId} is already completed or failed
Explanation: The task is already completed or failed, so cancellation is no longer possible.
Recommended action: Read the final task status and submit a new optimization request if needed.
503
Task status temporarily unavailable
message: Failed to get task status
Explanation: Planifica could not retrieve the task status at this moment.
Recommended action: Retry polling with backoff. Keep the taskId for later status checks.
Retry only transient errors such as optimizer unavailability, timeout, throttling, and temporary task-status failures. Fix request and credential errors before retrying.