Skip to main content
Version: 2026-09-21 (current)

Errors

note

Building a hosted tool? The Voshi API client turns every one of these into a thrown error with a name that says what happened — see Errors in the API section. This page is the HTTP contract behind it, for self-hosted tools calling the REST APIs directly.

All Voshi API errors share one JSON envelope:

{
"id": "Ie4rR0r1d",
"api": "api",
"time": "2026-07-27T18:10:00+00:00",
"error": "ValidationError",
"message": "score must be between 0 and 1",
"details": {}
}
idstring

A unique ID for this error occurrence. Include it when contacting support — it lets the Voshi team find the corresponding server-side report.

errorstring

The error class, matching the status code below.

messagestring

A human-readable description of what went wrong.

detailsobject

Structured extras, when the error has them.

note

The response format is content-negotiated on the Accept header: API clients sending Accept: application/json (or no preference) get the JSON envelope; a browser gets an HTML error page carrying the same report ID.

Status codes​

StatusErrorWhen
401AuthenticationErrorMissing, malformed, invalid, or expired credentials — a bad or rotated API key, a suspended tool, an API key on a route that only takes a user's own token, or a stale api.token.
403NotAuthorizedAuthenticated, but not allowed — e.g. an storage token used on another user's row, or an API key used for another tool or for a course your tool isn't placed in.
404Http404The resource doesn't exist — or belongs to another tool. Voshi deliberately doesn't distinguish these, so other tools' data can't be probed.
422ValidationErrorThe request was understood but a value is invalid. The message says which — see the per-endpoint error tables. Also how an unprovisioned course or location row answers.
500ApiExceptionSomething failed on Voshi's side. Retry, and report the error id if it persists.
warning

Validation failures return 422, not 400. If your HTTP client only treats 400 as a validation error, widen the check.

Provisioning errors​

Two 422s come from the provisioning flow:

MessageCause
App … has not been provisioned for Context …A GET/PUT/PATCH on a context or location storage row whose level isn't provisioned yet.
App … must be provisioned before its locations are provisionedA PUT to a provision.location URL while that course's provision.context is still unfinished. Call the course URL first.

Errors that don't reach your code​

Launch-time failures (draft tool, broken callback URL, a course that isn't provisioned yet) happen before your endpoint is called: the user sees a Voshi page with a report ID, and your tool never hears about the launch. See errors on Voshi's side.

Deep-link failures work the same way, in the other direction: if your locations endpoint times out, refuses the request, or returns something Voshi can't read, the instructor sees the error and your tool is told nothing.

A rejected grade is not an HTTP error​

A score the LMS refuses still returns 200: the call was valid and was made, and the refusal is reported in the attempt itself as status: "failed", with the reason in data.error. Check status on every submission — a tool that only checks the HTTP code will think a rejected score reached the gradebook. To retry, post again; each submission is its own attempt. See failed attempts vs. errors.