Skip to content
  • There are no suggestions because the search field is empty.

Handling k12panel API errors

Every error response uses the same shape, so your program can handle them consistently.

Every error response uses the same shape, so your program can handle them consistently:

{ "error": "not_found", "message": "No person matches email 'nobody@school.org'." } 

Check the HTTP status code and the error field.

Common responses

Status error Meaning What to do
401 authentication_failed Missing, invalid, revoked, or expired key Check the Authorization header; rotate the key if needed
403 insufficient_scope The key lacks the required permission Grant the permission (or use a key that has it)
404 The record doesn't exist in your organization Check the id; you can only access your own org's data
409 already_checked_out The asset is already checked out to someone Check it in first, or leave it as-is
409 ambiguous_reference A lookup matched more than one record Retry with an exact id (see below)
409 serial_conflict A create/edit would reuse a serial already in your org Use the existing device returned in candidates
409 email_conflict A person create/edit would reuse an email already in your org Use the existing person returned in candidates
409 person_sync_blocked Can't delete a person synced from a cloud service Remove them in that service first
409 person_has_checkouts Can't delete a person with assets still checked out Check their devices in first
422 group_is_dynamic Can't hand-edit membership of a rule-managed group Change the attribute the group's rule matches on
413 batch_too_large A bulk request exceeded the 1,000-item limit Split it into smaller batches
422 not_found A referenced record (person/site) wasn't found Check the email/name you sent
400 unknown_include An unrecognised block name in include= Use health, security, or inventory
400 invalid_datetime A date filter couldn't be read Send 2026-07-18 or 2026-07-18T14:30:00Z
400 invalid_buckets buckets= wasn't ascending, positive day thresholds Send e.g. buckets=1,7,30
400 expand_requires_name expand=assets on the software catalog without name Add name= to pick a title first
422 invalid The request body failed validation See the details field
429 Too many requests Wait a moment and retry


The "more than one match" case

Because emails, serials, and names aren't always unique, a lookup used in an action (like checkout) can match more than one record. Instead of guessing, the API returns the list of candidates so you can pick the right one and retry with its id:

{
  "error": "ambiguous_reference",
  "message": "3 people match email 'jsmith@school.org'. Retry with an id.",
  "candidates": [
    { "id": 3087, "first_name": "John",  "last_name": "Smith", "org_unit": "HS / Staff",    "groups": ["Teachers"] },
    { "id": 4192, "first_name": "Jane",  "last_name": "Smith", "org_unit": "MS / Staff",    "groups": ["Teachers"] },
    { "id": 5310, "first_name": "Jamie", "last_name": "Smith", "org_unit": "HS / Students", "groups": ["Grade 11"] }
  ]
}

The easy case (a unique email) is a single call. The ambiguous case gives you everything you need to resolve it — including enough detail to show a technician a "which one?" prompt. Retry the action with the exact id:

{ "person": { "id": 3087 } } 

Rate limits

Each key can make a reasonable number of requests per minute. If you exceed it you'll get a 429 response — pace your requests and retry after a moment. Well-behaved tools won't hit this in normal use.