Setting Up
Authentication
How requests are authenticated, what the errors mean, and how request ids help support.
Send the key as a bearer token on every request:
GET /v1/students HTTP/1.1
Host: serverless.grout.app
Authorization: Bearer grt_live_k3JdP8x…There is no session, cookie or refresh token. The key identifies the institution; nothing else in the request does.
Response envelope#
{ "success": true, "data": { … } }{ "success": false, "error": "insufficient_scope", "message": "This endpoint requires scope(s): students:write",
"required": ["students:write"], "missing": ["students:write"] }Validation failures use 422 validation_error with an issues array of { path, message }.
Errors#
| Status | error | Meaning |
|---|---|---|
| 401 | unauthorized | No bearer token, or the token is not a grt_ key |
| 401 | invalid_api_key | Unknown, revoked, expired, or institution not approved — deliberately indistinguishable |
| 403 | insufficient_scope | See required / missing |
| 404 | not_found | Resource does not exist in your institution |
| 409 | conflict and friends | State conflict (already added, already verified, insufficient allowance…) |
| 422 | validation_error and friends | Body or query invalid |
| 429 | rate_limited | Honour Retry-After |
| 500 | internal_error | Quote X-Request-Id to support |
| 503 | rate_limiter_unavailable | Transient; retry after 5 s |
Request ids#
Every response carries X-Request-Id: req_…. Log it next to your own correlation id. Support can trace a request end to end from it.
CORS#
Browser calls from *.grout.app origins are allowed, but a key must never be embedded in client-side code. Call the API from your server and expose only what your users need.
Checking a key#
GET /v1/me returns the key's name, scopes, rate limit and institution. Use it as a health check in your deploy pipeline:
curl -fsS https://serverless.grout.app/v1/me -H "Authorization: Bearer $GROUT_API_KEY" > /dev/null \
&& echo "key ok"