Skip to content

Discovery API

Public API for browsing learning content. Returns aggregated data optimized for UI consumption.

Base URL: {base-url}/discovery Authentication: Not required


Overview

The Discovery API provides read-only access to learning content with pre-aggregated counts and nested data. It's designed for:

  • Landing pages and content catalogs
  • Filter bars and faceted navigation
  • Mixed-content feeds (domains, trails, concepts together)

Endpoints

Endpoint Purpose
GET /domains List domains with nested trails
GET /trails List trails with nested concepts
GET /concepts List concepts with nested sparks
GET /sparks List sparks
GET /all Unified feed with mixed content types
GET /facets Filter options with counts
GET /health Health check

GET /domains

Returns domains with their trails and aggregated statistics.

When to Use

  • Homepage "Explore by Domain" section
  • Domain catalog page
  • Top-level navigation

Parameters

Parameter Type Default Description
page integer 1 Page number
per_page integer 20 Items per page
trail_limit integer 5 Max trails per domain

Response

{
  "data": [
    {
      "id": "uuid",
      "slug": "machine-learning",
      "name": "Machine Learning",
      "description": "Fundamentals of ML...",
      "icon": "brain",
      "color": "#4F46E5",
      "trail_count": 12,
      "concept_count": 45,
      "spark_count": 180,
      "estimated_mins": 2400,
      "trails": [
        {
          "id": "uuid",
          "slug": "neural-networks",
          "title": "Neural Networks",
          "estimated_mins": 180
        }
      ]
    }
  ],
  "meta": { ... }
}

Key Fields

Field Description
trail_count Total trails in this domain
concept_count Total concepts across all trails
spark_count Total sparks across all concepts
estimated_mins Total learning time in minutes
trails Preview of trails (limited by trail_limit)

GET /trails

Returns trails with their concepts and statistics.

When to Use

  • Domain detail page showing trails
  • "Learning Paths" catalog
  • Trail cards in listings

Parameters

Parameter Type Default Description
page integer 1 Page number
per_page integer 20 Items per page
domain string - Filter by domain slug
difficulty enum - Filter: beginner, intermediate, advanced, expert
concept_limit integer 5 Max concepts per trail

Response

{
  "data": [
    {
      "id": "uuid",
      "slug": "neural-networks",
      "title": "Neural Networks Fundamentals",
      "description": "Learn the building blocks...",
      "difficulty_level": "intermediate",
      "concept_count": 8,
      "spark_count": 32,
      "estimated_mins": 180,
      "concepts": [
        {
          "id": "uuid",
          "slug": "backpropagation",
          "title": "Backpropagation",
          "estimated_mins": 25
        }
      ]
    }
  ],
  "meta": { ... }
}

Key Fields

Field Description
difficulty_level Trail difficulty rating
concept_count Number of concepts in trail
spark_count Total sparks in trail
concepts Preview of concepts (limited by concept_limit)

GET /concepts

Returns concepts with their sparks and statistics.

When to Use

  • Trail detail page showing concepts
  • Concept catalog
  • "What you'll learn" sections

Parameters

Parameter Type Default Description
page integer 1 Page number
per_page integer 20 Items per page
trail string - Filter by trail slug
spark_limit integer 3 Max sparks per concept

Response

{
  "data": [
    {
      "id": "uuid",
      "slug": "backpropagation",
      "title": "Backpropagation",
      "description": "Understanding gradient flow...",
      "order_index": 3,
      "spark_count": 4,
      "estimated_mins": 25,
      "sparks": [
        {
          "id": "uuid",
          "slug": "chain-rule-basics",
          "title": "Chain Rule Basics",
          "summary": "How derivatives flow...",
          "difficulty": "intermediate",
          "estimated_mins": 7
        }
      ]
    }
  ],
  "meta": { ... }
}

Key Fields

Field Description
order_index Position within trail
spark_count Number of sparks in concept
sparks Preview of sparks (limited by spark_limit)

GET /sparks

Returns sparks (atomic learning units).

When to Use

  • "Quick Start" sections
  • Spark catalogs
  • Search result displays

Parameters

Parameter Type Default Description
page integer 1 Page number
per_page integer 20 Items per page
concept string - Filter by concept slug
difficulty enum - Filter: beginner, intermediate, advanced, expert

Response

{
  "data": [
    {
      "id": "uuid",
      "slug": "chain-rule-basics",
      "title": "Chain Rule Basics",
      "summary": "How derivatives flow through computation graphs",
      "difficulty": "intermediate",
      "estimated_mins": 7
    }
  ],
  "meta": { ... }
}

GET /all

Unified discovery endpoint returning mixed content types (domains, trails, concepts) with type discrimination.

When to Use

  • "Deep Dive" sections showing trails and concepts together
  • Mixed-content feeds
  • Unified search results display
  • Filter bar implementations

Parameters

Parameter Type Default Description
page integer 1 Page number
per_page integer 20 Items per page
types string all Comma-separated: domain,trail,concept
domain string - Filter by domain slug
track string - Filter by trail slug (alias: "track")
difficulty enum - Filter: beginner, intermediate, advanced, expert
q string - Text search query
include_facets boolean false Include filter counts
nested_limit integer 3 Nested items per entity (0-10)

Response

{
  "data": [
    {
      "type": "DOMAIN",
      "id": "uuid",
      "slug": "machine-learning",
      "name": "Machine Learning",
      "description": "...",
      "trail_count": 12,
      "concept_count": 45,
      "spark_count": 180,
      "estimated_mins": 2400
    },
    {
      "type": "TRAIL",
      "id": "uuid",
      "slug": "neural-networks",
      "title": "Neural Networks",
      "description": "...",
      "difficulty_level": "intermediate",
      "concept_count": 8,
      "spark_count": 32,
      "estimated_mins": 180,
      "concepts": [...]
    },
    {
      "type": "CONCEPT",
      "id": "uuid",
      "slug": "backpropagation",
      "title": "Backpropagation",
      "description": "...",
      "spark_count": 4,
      "estimated_mins": 25,
      "sparks": [...]
    }
  ],
  "meta": { ... },
  "facets": { ... }
}

Type Discrimination

Each item includes a type field to identify its entity type:

Type Entity Name Field
DOMAIN Domain name
TRAIL Trail title
CONCEPT Concept title

Proportional Distribution

Results are distributed proportionally across types: - Domains: ~10% of page - Trails: ~25% of page - Concepts: ~65% of page

This ensures balanced representation when browsing mixed content.

Filtering Behavior

Filter Effect
domain=ml Shows only content within that domain
track=neural-nets Shows only concepts within that trail
difficulty=beginner Filters trails only (domains/concepts excluded)
types=trail,concept Excludes domains from results

GET /facets

Returns available filter options with item counts.

When to Use

  • Filter bar dropdowns
  • Sidebar filter panels
  • "Refine results" UI

Parameters

Parameter Type Default Description
domain string - Scope facets to domain
track string - Scope facets to trail
difficulty enum - Scope facets to difficulty

Response

{
  "domains": [
    { "slug": "machine-learning", "name": "Machine Learning", "count": 45 },
    { "slug": "data-science", "name": "Data Science", "count": 32 }
  ],
  "tracks": [
    { "slug": "neural-networks", "name": "Neural Networks", "count": 28 },
    { "slug": "deep-learning", "name": "Deep Learning", "count": 35 }
  ],
  "difficulties": [
    { "level": "beginner", "count": 15 },
    { "level": "intermediate", "count": 42 },
    { "level": "advanced", "count": 23 },
    { "level": "expert", "count": 8 }
  ],
  "types": [
    { "type": "DOMAIN", "count": 5 },
    { "type": "TRAIL", "count": 18 },
    { "type": "CONCEPT", "count": 65 }
  ]
}

Facet Fields

Facet Description
domains Available domains with content count
tracks Available trails (tracks) with content count
difficulties Difficulty levels with trail count
types Entity types with total count

GET /health

Health check endpoint.

Response

{
  "status": "healthy",
  "timestamp": "2024-01-15T10:30:00Z"
}

Common Patterns

Building a Filter Bar

  1. Call GET /facets to populate dropdowns
  2. User selects filters
  3. Call GET /all with selected filters
  4. Use include_facets=true to update counts dynamically

Deep Dive Section (Trails + Concepts)

GET /all?types=trail,concept&per_page=20

Domain Landing Page

GET /domains/{slug}
GET /trails?domain={slug}

Paginating Mixed Results

The /all endpoint maintains proportional distribution across pages. Page 2 continues from where each type left off:

  • Page 1: 2 domains, 5 trails, 13 concepts
  • Page 2: 2 domains, 5 trails, 13 concepts (next batch)
  • When a type is exhausted, its slots are redistributed

Notes

  • All endpoints are public (no authentication required)
  • Results are sorted alphabetically within each type
  • Use nested_limit=0 to exclude nested items for lighter responses
  • Counts in facets reflect the total matching items, not just the current page