| Location | Name | Required | Meaning |
|---|---|---|---|
| query | status | Conditional / optional | {"type":"string","enum":["active","suspended"],"default":"active"} |
| query | cursor | Conditional / optional | {"type":"string","maxLength":2000} |
| query | limit | Conditional / optional | {"type":"integer","minimum":1,"maximum":100,"default":50} |
{error:{code,message}} for CloudError failures, attaches Request-Id, and disables caching. Handle 401 by signing in; show role refusal for 403 forbidden, reauthenticate only for step_up_required, and collect a reason for 400 reason_required. A CSRF failure needs a current page/session token, not blind retries. Operation-specific 404/409/413/422/502/503 errors retain their status. Honor Retry-After on 429./** GET /api/admin/schools?status=active|suspended&cursor&limit (schools.read): approved schools, newest first (§16). */
export const GET = adminRoute("schools.read", async (request, ctx) => {
const params = new URL(request.url).searchParams;
const parsed = query.safeParse({ status: params.get("status") ?? undefined, cursor: params.get("cursor") ?? undefined, limit: params.get("limit") ?? undefined });
if (!parsed.success) throw invalid("status must be active or suspended; limit 1–100.");
return adminJson(await listSchools(ctx, parsed.data));
});