Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/davidmpizarro/QuipuEco-Hackaton/llms.txt

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

POST /clasificar is the core intelligence endpoint of QuipuEco. It receives a photo of any solid waste item — snapped by the phone camera or selected from the gallery — and returns a complete recycling decision in under two seconds. The backend encodes the image, sends it to Google Gemini gemini-3.1-flash-lite with a structured classification prompt, and parses the response into a deterministic JSON object that the frontend renders directly in ClassificationResult.jsx.

Request

Endpoint: POST http://localhost:8000/clasificar Content-Type: multipart/form-data

Parameters

file
file
required
The waste image to classify. Accepted formats: JPEG, PNG, WEBP. Maximum recommended file size: 10 MB. Images captured with ImageCapture.jsx’s camera mode are encoded as image/jpeg at 0.85 quality before upload.

Code Examples

const formData = new FormData();
formData.append("file", file);

const { data } = await axios.post(`${API_URL}/clasificar`, formData, {
  headers: { "Content-Type": "multipart/form-data" },
});

Response

Content-Type: application/json A successful classification returns HTTP 200 with the following JSON object:

Response Fields

nombre
string
required
Human-readable name of the identified object, capitalised by the frontend before display. Examples: "Botella de plástico PET", "Caja de cartón", "Pila AA".
tipo
string
required
Material category used throughout the app for routing, map filtering, and stats aggregation. One of eight canonical values:
co2_evitado_kg
number
required
Estimated kilograms of CO₂ emissions avoided by recycling this item instead of landfilling it. Rendered in the result card and accumulated in the useHistorial hook for the Impact Dashboard. Example: 0.18.
peso_estimado_kg
number
required
Estimated weight of the item in kilograms, used for dashboard statistics. Example: 0.03.
instrucciones
string
required
Step-by-step preparation instructions specific to Lima’s recycling network. Displayed in the “Cómo descartarlo en Lima” section of ClassificationResult.jsx. Example: "Retira la etiqueta y enjuaga con agua fría.".
punto_acopio
string
required
Recommended collection point type for this material. The frontend normalises this value — strings containing "tambo" display as “Tiendas Tambo” and strings containing "centro verde" display as “Centro Verde Municipal”. Example: "Tiendas Tambo".
consejo
string
required
An ecological tip related to the specific material, shown in the green “Consejo Ecológico” card. Example: "El plástico PET puede reciclarse hasta 10 veces.".
respuesta_voz
string
required
A TTS-optimised sentence read aloud by the voice agent when the user first opens the chat after classification. Written to be natural and concise when spoken. Example: "He clasificado una botella de plástico PET.".

Example Response

{
  "nombre": "Botella de plástico PET",
  "tipo": "plastico",
  "co2_evitado_kg": 0.18,
  "peso_estimado_kg": 0.03,
  "instrucciones": "Retira la etiqueta y enjuaga con agua fría.",
  "punto_acopio": "Tiendas Tambo",
  "consejo": "El plástico PET puede reciclarse hasta 10 veces.",
  "respuesta_voz": "He clasificado una botella de plástico PET."
}

Error Responses

422 Unprocessable Entity
object
Returned when the file field is missing or the uploaded content is not a valid image. The detail array follows FastAPI’s standard validation error format.
{
  "detail": [
    {
      "type": "missing",
      "loc": ["body", "file"],
      "msg": "Field required"
    }
  ]
}
500 Internal Server Error
object
Returned when the Gemini API call fails (network timeout, quota exceeded, invalid API key, or an unparseable model response). The detail field contains a plain-text description of the failure.
{
  "detail": "Error al procesar la imagen con Gemini."
}
Sending a non-image file (e.g., a PDF or a plain text document) may return either a 422 or a 500 depending on whether the error is caught at the FastAPI validation layer or inside the Gemini call. Always validate file.type.startsWith("image/") on the client before submitting.

How the Response Is Used

Once ImageCapture.jsx receives the classification JSON, it calls onResult(data, preview) which triggers a cascade through the app: ClassificationResult.jsx renders every field in the response:
  • tipo is looked up in TIPO_CONFIG to determine the card colour scheme, material emoji, and bin colour.
  • co2_evitado_kg and peso_estimado_kg are displayed in the three-stat grid and formatted with .toFixed(2).
  • instrucciones, consejo, and punto_acopio populate their respective labelled sections.
  • The nombre field is capitalised and shown as the main heading.
AgenteVoz.jsx uses respuesta_voz as the agent’s opening sentence when the voice panel is launched immediately after classification:
const texto = resultado
  ? (resultado.respuesta_voz || `He clasificado ${resultado.nombre}.`)
  : "¡Hola! Soy QuipuEco...";
useHistorial hook accumulates tipo, co2_evitado_kg, and peso_estimado_kg across sessions to power the Impact Dashboard’s cumulative CO₂ savings and recycling-by-category breakdown.
During development you can test the endpoint quickly with Swagger UI at http://localhost:8000/docs. The /clasificar form accepts a file upload directly in the browser without writing any code.

Build docs developers (and LLMs) love