Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DavidCevallos15/inforario-IA-null/llms.txt

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

The extract-schedule function is a Deno Edge Function deployed on Supabase. It receives raw text extracted from a UTM schedule PDF, forwards it to Groq’s llama-3.3-70b-versatile model with a strict system prompt, and returns a validated array of structured class sessions. The function handles all session normalisation and virtual-class detection internally — the caller only needs to supply the plain PDF text.
This function does not require user authentication. Any request bearing a valid Supabase anon key can invoke it. If the endpoint should be restricted to authenticated users, protect it at the infrastructure level (e.g., RLS policies, API gateway rules) rather than relying on this function alone.

Endpoint

POST https://{project}.supabase.co/functions/v1/extract-schedule
The function accepts POST requests only. An OPTIONS preflight request returns the shared CORS headers and a 200 ok response without executing any LLM logic.

CORS headers

All responses (including OPTIONS preflight) include the following headers defined in _shared/cors.ts:
HeaderValue
Access-Control-Allow-Origin*
Access-Control-Allow-Headersauthorization, x-client-info, apikey, content-type
Access-Control-Allow-MethodsPOST, GET, OPTIONS, PUT, DELETE

Authentication

Pass the Supabase anon key as a Bearer token in the Authorization header. This is the public client key found in your Supabase project settings — no user session is needed.
Authorization: Bearer <supabase-anon-key>

Request

Headers

HeaderRequiredValue
AuthorizationBearer <supabase-anon-key>
Content-Typeapplication/json

Body

pdfText
string
required
The raw plain-text content extracted from a UTM schedule PDF. The string must be non-empty after trimming whitespace. The function sends this verbatim to Groq inside a user-role message: "Extrae el horario del siguiente texto:\n{pdfText}".

Example request

curl -X POST \
  https://{project}.supabase.co/functions/v1/extract-schedule \
  -H "Authorization: Bearer <supabase-anon-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "pdfText": "SISTEMAS DISTRIBUIDOS\nDocente: PÉREZ JUAN\nLunes 07:00 - 09:00 Aula 301 Piso 3\nBASES DE DATOS AVANZADAS\nDocente: GÓMEZ ANA\nMiércoles 09:00 - 11:00 Aula 205 Piso 2\nMATERIA VIRTUAL\nDocente: TORRES LUIS"
  }'

Response

200 — Success

Returns a JSON object with a single sessions key containing an array of validated, normalised class sessions. Sessions that fail validation (missing subject, invalid day, or malformed time on a non-virtual class) are silently dropped before the response is sent.
sessions
Session[]
Array of validated class session objects. May be empty if none of the model’s output passes validation.

Example response

{
  "sessions": [
    {
      "subject": "SISTEMAS DISTRIBUIDOS",
      "teacher": "PÉREZ JUAN",
      "day": "Lunes",
      "startTime": "07:00",
      "endTime": "09:00",
      "location": "Aula 301",
      "floor": "Piso 3",
      "isVirtual": false
    },
    {
      "subject": "BASES DE DATOS AVANZADAS",
      "teacher": "GÓMEZ ANA",
      "day": "Miércoles",
      "startTime": "09:00",
      "endTime": "11:00",
      "location": "Aula 205",
      "floor": "Piso 2",
      "isVirtual": false
    },
    {
      "subject": "MATERIA VIRTUAL",
      "teacher": "TORRES LUIS",
      "location": "Virtual",
      "floor": "N/A",
      "isVirtual": true
    }
  ]
}
Virtual sessions omit day, startTime, and endTime entirely from the JSON output because those fields are set to undefined in the TypeScript response object and are therefore not serialised by JSON.stringify.

Error responses

StatusConditionBody
400pdfText is missing or blank{ "error": "pdfText es obligatorio." }
405Request method is not POST{ "error": "Método no permitido." }
500GROQ_API_KEY environment variable is not set{ "error": "Falta GROQ_API_KEY" }
500Unexpected runtime error{ "error": "<error message>" }
502Groq API returned a non-OK status{ "error": "<groq error message>" }
502Groq response body was empty or not valid JSON (no content){ "error": "Groq respondió sin contenido parseable." }
502Groq response content was not valid JSON{ "error": "Groq devolvió contenido no JSON." }

Environment variables

GROQ_API_KEY
string
required
Secret API key for the Groq platform. Set this in your Supabase project’s Edge Function secrets (supabase secrets set GROQ_API_KEY=...). The function returns 500 immediately if this variable is absent.
GROQ_MODEL
string
Groq model identifier to use for extraction. Defaults to llama-3.3-70b-versatile when not set. Override this to switch models without redeploying.

Session validation rules

The function runs a multi-step validation pipeline on every object returned by the model before including it in the response.
Sessions that fail validation are silently filtered out. The caller should check the length of the returned sessions array and prompt the user to retry if it is unexpectedly low.
  1. Type coercion — Every field is cast to a string and trimmed. Non-string values fall back to sensible defaults ("N/A" for teacher/floor, "" for day/times, "Virtual" for location).
  2. Virtual detection — A session is marked isVirtual = true if isVirtual is already true, OR the location string contains "VIRTUAL" (case-insensitive), OR day, startTime, and endTime are all empty strings after coercion.
  3. Virtual field clearing — On virtual sessions, day, startTime, and endTime are set to undefined and location is overwritten with "Virtual".
  4. Filter pass — A session is kept only if subject is non-empty AND either isVirtual is true OR all three of day (must be one of the five allowed days), startTime, and endTime (both matching HH:MM) are valid.

Allowed days

The ALLOWED_DAYS set contains exactly: 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes'. Any other value (including 'Sábado', 'Domingo', or misspellings) causes the session to be dropped.

Time format

Times are validated against the regex /^([01]\d|2[0-3]):[0-5]\d$/. Values such as "7:00" (missing leading zero) or "24:00" will fail validation and cause the session to be dropped.

LLM system prompt rules

The system prompt sent to Groq instructs the model to:
  • Return only a valid JSON object with a root key "sessions" containing an array — no markdown fences or prose.
  • Include every class session found, including virtual ones (isVirtual: true).
  • Set temperature: 0.1 and response_format: { type: "json_object" } to maximise determinism.
Each session object must follow this structure:
{
  subject:   string;            // real subject name only
  teacher:   string;            // "N/A" if absent
  day?:      string;            // "Lunes" | "Martes" | "Miércoles" | "Jueves" | "Viernes" — omit for virtual
  startTime?: string;           // "HH:MM" 24-hour — omit for virtual
  endTime?:  string;            // "HH:MM" 24-hour — omit for virtual
  location:  string;            // classroom or "Virtual"
  floor:     string;            // floor label or "N/A"
  isVirtual: boolean;           // true if text says "MATERIA VIRTUAL" or no schedule
}
Subject name rules enforced by the system prompt:
  • Extract only the real subject name — no career or programme name prefix.
  • Forbidden prefixes: "TECNOLOGÍAS DE LA ", degree programme name.
  • Forbidden suffixes: parenthetical mesh/curriculum codes such as "(A19)", "(ITINERARIO)", "(VIRTUAL)".
  • Correct: "SISTEMAS DISTRIBUIDOS" — Incorrect: "TECNOLOGÍAS DE LA SISTEMAS DISTRIBUIDOS (A19)".
The frontend client (parseScheduleFileWithEdge) performs an additional sanitisation pass on subject values after receiving the response, removing any residual prefixes or parenthetical suffixes the model may have missed. Both layers together ensure clean subject names reach the UI.

Build docs developers (and LLMs) love