Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/vruizz22/innova-backend-serverless/llms.txt

Use this file to discover all available pages before exploring further.

The Admin API allows ADMIN-role users to manage the error tag catalog — the taxonomy of 2,600+ procedural error codes aligned to the Chilean curriculum. This is the backend source of truth synced from the innova-ai-engine taxonomy. Admins can browse the live catalog with fast keyset pagination, filter by domain or status, and promote or deprecate individual tags to control which codes the AI classifier can assign.
All endpoints in this section require an ADMIN role JWT. TEACHER and PARENT tokens are rejected with 403 Forbidden.

Endpoints

GET /admin/error-tags

Browse the live error-tag catalog with keyset pagination. The catalog is ordered by the unique code index, which ensures stable pagination even as new tags are inserted. In addition to the current page of items, the response includes total counts, per-status counts, and a domain facet list — useful for building a catalog browser UI. Authentication: JWT (ADMIN role required)
status
string
Filter by tag status. One of ACTIVE, DRAFT, or DEPRECATED.
domainCode
string
Filter to a specific domain using its short code (e.g. ARITH, FRACT, GEOM, TRIG). Pick from the domains facet in the response.
source
string
Filter by tag source (e.g. LLM_GENERATED, CURATED). Matches the ErrorSource enum from Prisma.
q
string
Case-insensitive substring search over code, name, and description.
cursor
string
Keyset cursor — the code value of the last item on the previous page. Omit for the first page.
limit
number
Page size. Defaults to 50. Maximum 100.
# First page — ACTIVE tags in the ARITH domain
curl "https://api.example.com/admin/error-tags?status=ACTIVE&domainCode=ARITH&limit=50" \
  -H "Authorization: Bearer <admin-token>"

# Next page — pass the nextCursor from the previous response
curl "https://api.example.com/admin/error-tags?status=ACTIVE&domainCode=ARITH&limit=50&cursor=ARITH_ADD_ZERO_COLUMN_CARRY_SKIPPED_G4" \
  -H "Authorization: Bearer <admin-token>"
Example response:
{
  "items": [
    {
      "code": "ARITH_ADD_CARRY_OMITTED_G3",
      "name": "Carry omitted",
      "domainCode": "ARITH",
      "domainName": "Arithmetic",
      "subdomainCode": "addition",
      "source": "CURATED",
      "status": "ACTIVE",
      "severity": "MED",
      "applicableGrades": [3, 4],
      "diagnosticHint": "Student adds column sums without propagating the carry digit."
    }
  ],
  "nextCursor": "ARITH_ADD_CARRY_OMITTED_G3",
  "total": 312,
  "statusCounts": {
    "active": 2624,
    "draft": 18,
    "deprecated": 45
  },
  "domains": [
    { "code": "ARITH", "name": "Arithmetic", "count": 312 },
    { "code": "FRACT", "name": "Fractions", "count": 198 }
  ]
}
items
array
Current page of error tags. Each tag contains:
  • code (string): unique tag code (e.g. ARITH_ADD_CARRY_OMITTED_G3)
  • name (string): human-readable error name
  • domainCode (string | null): parent domain code
  • domainName (string | null): parent domain display name
  • subdomainCode (string | null): subdomain code if set
  • source (string): tag origin (CURATED, LLM_GENERATED, etc.)
  • status (string): ACTIVE, DRAFT, or DEPRECATED
  • severity (string | null): error severity level
  • applicableGrades (array): grade levels this error is relevant for
  • diagnosticHint (string | null): teacher-facing hint about the error
nextCursor
string | null
Pass this as cursor to retrieve the next page. null means this is the last page.
total
number
Total count of tags matching the current filters (across all pages).
statusCounts
object
Aggregate counts by status: { active, draft, deprecated }. Always reflects the unfiltered catalog totals.
domains
array
All domains with their tag counts — useful for populating a domain filter facet. Each entry: { code, name, count }.

PATCH /admin/error-tags/:code/status

Promote an error tag to ACTIVE or deprecate it to DEPRECATED. Use this to control which tags the AI classifier can assign in new classifications. Authentication: JWT (ADMIN role required)
code
string
required
The unique error tag code (e.g. ARITH_SUB_BORROW_OMITTED_TENS_G3). Case-sensitive — must exactly match the code column.
status
string
required
New status. One of ACTIVE, DRAFT, or DEPRECATED. Validated against the ErrorStatus Prisma enum.
# Deprecate a tag
curl -X PATCH https://api.example.com/admin/error-tags/ARITH_SUB_BORROW_OMITTED_TENS_G3/status \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{ "status": "DEPRECATED" }'

# Re-activate a tag
curl -X PATCH https://api.example.com/admin/error-tags/ARITH_SUB_BORROW_OMITTED_TENS_G3/status \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{ "status": "ACTIVE" }'
Response: 200 OK — the updated error tag object (same shape as the items in GET /admin/error-tags). Returns 404 Not Found if the tag code does not exist in the catalog.
Deprecating an error tag does not remove or alter historical classification data. All past Attempt records that were classified with this tag retain their classification. Deprecation only prevents the tag from being assigned in new classifications by the AI classifier and from appearing in the teacher typeahead (GET /skills/error-tags).

Admin status endpoint

GET /admin/status provides a real-time health snapshot of the entire Innova pipeline. It is implemented in AdminStatusController and backed by AdminStatusService. Authentication: JWT (ADMIN role required)
curl https://api.example.com/admin/status \
  -H "Authorization: Bearer <admin-token>"
The response includes:
queues
object
SQS queue depths for each pipeline queue: guide-ingest, attempt-reprocess, llm-classify, and hourly-alerts. Each entry: { depth, dlqDepth, processedLastHour }.
pipeline
object
Activity counts for the last hour: { attemptsLastHour, submissionsLastHour, classifiedLastHour, pendingGuides }.
cost
object
LLM cost breakdown: { todayUsd, monthUsd, byModel: [{ model, calls, inputTokens, outputTokens, costUsd }] }.
killswitches
object
Current state of pipeline killswitches. true = worker running, false = worker paused:
  • graderEnabled — controls the guide grader Lambda
  • classifierEnabled — controls the LLM error classifier
  • solutionGeneratorEnabled — controls the solution generator
  • hourlyAlertsEnabled — always true (no SSM parameter to pause)

Pipeline killswitches

Individual workers can be paused via PATCH /admin/status/killswitches/:key. Valid keys are graderEnabled, classifierEnabled, and solutionGeneratorEnabled. The enabled field maps to an SSM parameter: enabled: true sets the SSM “paused” parameter to false, and vice versa.
# Pause the LLM classifier
curl -X PATCH https://api.example.com/admin/status/killswitches/classifierEnabled \
  -H "Authorization: Bearer <admin-token>" \
  -H "Content-Type: application/json" \
  -d '{ "enabled": false }'

Error tag sync

The error catalog is seeded and kept in sync from the innova-ai-engine taxonomy using a two-step script:
  1. import-error-catalog.ts — fetches the canonical tag list from the AI engine and upserts records into the ErrorTag table.
  2. codegen-error-tags.ts — generates the src/shared/domain/error-tags.generated.ts TypeScript enum (ErrorTagCode) from the live database state.
Run both steps with:
pnpm seed:full
The generated enum currently contains 2,624 ACTIVE tags (as of the last codegen run on 2026-06-20). After running seed:full, redeploy the backend so the updated enum is bundled into the Lambda package.
After a sync, check GET /admin/error-tags?status=DRAFT for any newly imported tags that have not yet been reviewed. New tags arrive as DRAFT and must be promoted to ACTIVE (via PATCH /admin/error-tags/:code/status) before the classifier will use them.

Build docs developers (and LLMs) love