1

Open Source

Documentación API (GraphQL) – Historia del Internet

Una guía para acceder a los datos del proyecto “Historia del Internet” usando GraphQL

Introducción

Este proyecto almacena información sobre la historia del internet en Colombia en una base de datos de WordPress con capacidades GraphQL. Si deseas usar nuestros datos para tus propias investigaciones, esta guía te mostrará cómo hacerlo de forma sencilla.

¿Qué es GraphQL?

GraphQL es un lenguaje para pedir datos de una API. A diferencia de las APIs tradicionales que devuelven datos fijos, con GraphQL tú eliges exactamente qué datos necesitas.

¿Cómo acceder?

URL base: https://historiasinternetpre.uniandes.edu.co/graphql

Método: POST (envías datos al servidor)

Formato: JSON

Primeros pasos

Ejemplo básico con curl (terminal)

curl -X POST https://historiasinternetpre.uniandes.edu.co/graphql \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ pages { nodes { title slug } } }"
  }'

Con JavaScript/Node.js

async function obtenerDatos(query) {
  const respuesta = await fetch(
    'https://historiasinternetpre.uniandes.edu.co/graphql',
    {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query })
    }
  );

  const data = await respuesta.json();
  return data;
}

// Usar la función
const query = `{
  pages {
    nodes {
      title
      slug
    }
  }
}`;

obtenerDatos(query).then(resultado => console.log(resultado));

Con Python

import requests
import json

API_URL = "https://historiasinternetpre.uniandes.edu.co/graphql"

def obtener_datos(query):
    respuesta = requests.post(
        API_URL,
        json={"query": query}
    )
    return respuesta.json()

# Usar la función
query = """
{
  pages {
    nodes {
      title
      slug
    }
  }
}
"""

resultado = obtener_datos(query)
print(json.dumps(resultado, indent=2))

Tipos de datos principales

El proyecto tiene varios tipos de contenido que puedes consultar:

TipoDescripciónEjemplo
pagesPáginas estáticas del sitioInicio, Acerca de, Investigación
eventosEventos históricos del internetNacimiento de ARPANET, primer .co
documentosDocumentos, artículos, referenciasPDFs, textos académicos
personajesPersonas importantes en la historiaFundadores, investigadores
entrevistasEntrevistas a personajesTranscripciones de entrevistas
terminosTérminos del glosarioDefiniciones técnicas

Consultas por tipo de datos

1. PÁGINAS (Pages)

Las páginas son contenido estático del sitio web.

Campos disponibles:
Consulta para obtener todas las páginas:
{
  pages {
    nodes {
      title
      slug
      content
      descripcion
      menuOrder
    }
  }
}
Consulta para obtener una página específica:
{
  page(id: "inicio", idType: URI) {
    title
    slug
    content
    descripcion
  }
}

Nota: Algunos slugs útiles: inicio, acerca-de, documentos, glosario

2. EVENTOS (Eventos)

Los eventos son momentos importantes en la historia del internet.

Campos disponibles:
Consulta para obtener eventos:
{
  eventos(first: 100) {
    pageInfo {
      hasNextPage
      endCursor
    }
    nodes {
      title
      slug
      fecha
      tipo
      content
      categories {
        nodes {
          name
          slug
        }
      }
    }
  }
}
Consulta con paginación (obtener siguientes 100):
{
  eventos(first: 100, after: "CURSOR_ANTERIOR") {
    pageInfo {
      hasNextPage
      endCursor
    }
    nodes {
      title
      fecha
      tipo
    }
  }
}

Tipos de eventos:

3. DOCUMENTOS (Documentos)

Documentos, artículos y referencias del proyecto.

Campos disponibles:
Consulta para obtener documentos:
{
  documentos(first: 50) {
    pageInfo {
      hasNextPage
      endCursor
    }
    nodes {
      title
      slug
      tituloCorto
      descripcion
      fecha
      autores
      fuente
      tiposDeDocumentos {
        nodes {
          name
          slug
        }
      }
      categories {
        edges {
          node {
            name
            slug
          }
        }
      }
      archivos {
        nodes {
          filePath
        }
      }
    }
  }
}
Obtener documentos de un tipo específico:
{
  documentosTipo(slug: "articulo", first: 50) {
    nodes {
      title
      descripcion
      autores
      fecha
    }
  }
}

4. PERSONAJES (Personajes)

Personas importantes en la historia del internet en Colombia.

Campos disponibles:
Consulta para obtener personajes:
{
  personajes(first: 50) {
    pageInfo {
      hasNextPage
      endCursor
    }
    nodes {
      title
      slug
      content
      featuredImage {
        node {
          sourceUrl
          altText
        }
      }
    }
  }
}
Obtener un personaje específico con sus entrevistas:
{
  personajeBy(slug: "nombre-del-personaje") {
    title
    content
    featuredImage {
      node {
        sourceUrl
      }
    }
    entrevistas {
      nodes {
        fecha
        content
      }
    }
  }
}

5. ENTREVISTAS (Entrevistas)

Entrevistas a personajes clave del proyecto.

Campos disponibles:
Consulta para obtener entrevistas:
{
  entrevistas(first: 50) {
    pageInfo {
      hasNextPage
      endCursor
    }
    nodes {
      title
      slug
      fecha
      personajes {
        nodes {
          title
          slug
        }
      }
      transcripciones {
        nodes {
          title
          transcripcion
        }
      }
    }
  }
}

6. TÉRMINOS (Glosario)

Términos técnicos definidos en el glosario.

Campos disponibles:
Consulta para obtener términos:
{
  terminos(first: 100) {
    pageInfo {
      hasNextPage
      endCursor
    }
    nodes {
      title
      slug
      content
    }
  }
}
Obtener un término específico:
{
  terminoBy(slug: "arpanet") {
    title
    content
  }
}

7. CATEGORÍAS (Categories)

Temas y categorías para clasificar contenido.

Campos disponibles:
Consulta para obtener el árbol de categorías:
{
  categories(first: 100) {
    pageInfo {
      hasNextPage
      endCursor
    }
    nodes {
      name
      slug
      count
      description
      children {
        nodes {
          name
          slug
          count
        }
      }
      parent {
        node {
          name
          slug
        }
      }
    }
  }
}

Paginación

Como habrás notado, muchas consultas devuelven pageInfo y usan first. Esto es para paginación: obtener los datos en pequeños lotes en lugar de todo a la vez.

Conceptos clave:

Ejemplo de paginación completa:
async function obtenerTodos(tipoContenido) {
  const API_URL = 'https://historiasinternetpre.uniandes.edu.co/graphql';
  const todos = [];
  let tieneMas = true;
  let cursor = null;

  while (tieneMas) {
    const query = `{
      ${tipoContenido}(first: 100${cursor ? `, after: "${cursor}"` : ''}) {
        pageInfo {
          hasNextPage
          endCursor
        }
        nodes {
          title
          slug
          fecha
        }
      }
    }`;

    const respuesta = await fetch(API_URL, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ query }),
    });

    const { data } = await respuesta.json();
    const contenido = data[tipoContenido];

    todos.push(...contenido.nodes);
    tieneMas = contenido.pageInfo.hasNextPage;
    cursor = contenido.pageInfo.endCursor;

    console.log(`Obtenidos ${todos.length} items...`);
  }

  return todos;
}

// Usar:
obtenerTodos('eventos').then((eventos) => {
  console.log(`Total eventos: ${eventos.length}`);
  console.log(eventos);
});

Filtros y búsquedas

Filtrar por estado de publicación:
{
  eventos(first: 50, where: { status: PUBLISH }) {
    nodes {
      title
      status
    }
  }
}
Obtener solo documentos con archivos:
{
  documentos(first: 50) {
    nodes {
      title
      archivos {
        nodes {
          filePath
        }
      }
    }
  }
}
Filtrar por categoría:
{
  eventos(first: 50, where: { categoryName: "tecnologia" }) {
    nodes {
      title
      categories {
        nodes {
          name
        }
      }
    }
  }
}

Casos de uso prácticos

Caso 1: Crear una línea de tiempo de eventos

const query = `{
  eventos(first: 1000) {
    nodes {
      title
      fecha
      tipo
      content
    }
  }
}`;

const response = await fetch('https://historiasinternetpre.uniandes.edu.co/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query }),
});

const { data } = await response.json();

// Ordenar por fecha
const eventos = data.eventos.nodes.sort((a, b) => new Date(a.fecha) - new Date(b.fecha));

console.log('Línea de tiempo:');
eventos.forEach((e) => {
  console.log(`${e.fecha} - ${e.title}`);
});

Caso 2: Analizar categorías más usadas

const query = `{
  categories(first: 100) {
    nodes {
      name
      count
    }
  }
}`;

const response = await fetch('https://historiasinternetpre.uniandes.edu.co/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query }),
});

const { data } = await response.json();

// Ordenar por cantidad de contenido
const categorias = data.categories.nodes.sort((a, b) => b.count - a.count).slice(0, 10);

console.log('Top 10 categorías:');
categorias.forEach((c) => {
  console.log(`${c.name}: ${c.count} items`);
});

Caso 3: Obtener todas las transcripciones de entrevistas

const query = `{
  entrevistas(first: 1000) {
    nodes {
      title
      fecha
      personajes {
        nodes {
          title
        }
      }
      transcripciones {
        nodes {
          title
          transcripcion
        }
      }
    }
  }
}`;

const response = await fetch('https://historiasinternetpre.uniandes.edu.co/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ query }),
});

const { data } = await response.json();
const entrevistas = data.entrevistas.nodes;

// Imprimir como JSON
console.log(JSON.stringify(entrevistas, null, 2));