Direkt zum Hauptinhalt

Inhalte API

Die Content API ermöglicht den Zugriff auf redaktionelle Inhalte des Kulturpools. Sie liefert strukturierte Content-Seiten mit verschiedenen Block-Typen, SEO-Metadaten und mehrsprachigen Übersetzungen für die Website-Darstellung.

Endpunkte

Alle Inhalte abrufen

GET /content

Ruft alle verfügbaren redaktionellen Inhalte vom CMS ab.

Antwort
{
  "data": [
    {
      "id": 1,
      "status": "published",
      "sort": 1,
      "date_published": "2024-01-15T09:00:00Z",
      "color_text": "#333333",
      "color_background": "#ffffff",
      "seo": {
        "id": 1,
        "title": "Willkommen im Kulturpool - Digitale Kunst entdecken",
        "meta_description": "Entdecken Sie die Vielfalt österreichischer Kultur im digitalen Raum",
        "canonical_url": "https://kulturpool.at/willkommen"
      },
      "category": {
        "id": 1,
        "sort": 1,
        "translations": []
      },
      "translations": [
        {
          "id": 1,
          "languages_code": "de",
          "title": "Willkommen im Kulturpool",
          "slug": "willkommen",
          "summary": "Entdecken Sie die Vielfalt österreichischer Kultur",
          "items": [
            {
              "id": 1,
              "collection": "block_text",
              "item": {
                "id": 1,
                "type": "hero",
                "heading": "Willkommen im Kulturpool",
                "body": "<p>Hier finden Sie digitalisierte Kunst und Kultur aus österreichischen Institutionen.</p>",
                "heading_tag": "h1",
                "is_enabled": true
              }
            }
          ]
        }
      ]
    }
  ]
}

Einzelnen Content-Eintrag abrufen

GET /content/{content_id}

Ruft einen spezifischen Content-Eintrag anhand seiner ID ab.

Parameter
Parameter Typ Beschreibung
content_id integer Die eindeutige ID des Content-Eintrags (Pfad-Parameter)
Beispiel
curl -X GET "https://api.kulturpool.at/content/1"
Antwort
{
  "data": {
    "id": 1,
    "status": "published",
    "sort": 1,
    "date_published": "2024-01-15T09:00:00Z",
    "color_text": "#333333",
    "color_background": "#ffffff",
    "seo": {
      "id": 1,
      "title": "Willkommen im Kulturpool - Digitale Kunst entdecken",
      "meta_description": "Entdecken Sie die Vielfalt österreichischer Kultur im digitalen Raum",
      "canonical_url": "https://kulturpool.at/willkommen"
    },
    "category": {
      "id": 1,
      "sort": 1,
      "translations": []
    },
    "translations": [
      {
        "id": 1,
        "languages_code": "de",
        "title": "Willkommen im Kulturpool",
        "slug": "willkommen",
        "summary": "Entdecken Sie die Vielfalt österreichischer Kultur",
        "items": [
          {
            "id": 1,
            "collection": "block_text",
            "item": {
              "id": 1,
              "type": "hero",
              "heading": "Willkommen im Kulturpool",
              "body": "<p>Hier finden Sie digitalisierte Kunst und Kultur aus österreichischen Institutionen.</p>",
              "heading_tag": "h1",
              "is_enabled": true
            }
          }
        ]
      }
    ]
  }
}

Datenstruktur

Content

Feld Typ Beschreibung
id integer Eindeutige ID des Content-Eintrags
status string Veröffentlichungsstatus ("published", "draft")
sort integer Sortierreihenfolge
date_published string Veröffentlichungsdatum (ISO 8601)
color_text string Textfarbe (Hex-Code)
color_background string Hintergrundfarbe (Hex-Code)
seo SEO SEO-Metadaten
category ContentCategory Zugeordnete Kategorie
translations ContentTranslation[] Mehrsprachige Versionen

SEO

Feld Typ Beschreibung
id integer SEO-Eintrag ID
title string Meta-Titel für Suchmaschinen
meta_description string Meta-Beschreibung
canonical_url string Kanonische URL
no_index boolean Suchmaschinenindexierung verhindern
no_follow boolean Link-Verfolgung verhindern
og_image File Open Graph Bild

ContentTranslation

Feld Typ Beschreibung
id integer Übersetzungs-ID
languages_code string Sprachcode (ISO 639-1)
title string Seitentitel
slug string URL-Slug
summary string Kurzzusammenfassung
items ContentTranslationsItem[] Content-Blöcke

ContentTranslationsItem

Feld Typ Beschreibung
id integer Item-ID
collection string Block-Typ ("block_text", "block_slider", etc.)
item ContentItem Der eigentliche Content-Block
sort integer Sortierreihenfolge

Content-Block-Typen

BlockText

Textblöcke für Überschriften, Fließtext und Hero-Bereiche.

Feld Typ Beschreibung
id integer Block-ID
type string Block-Untertyp ("hero", "text", "quote")
heading string Überschrift
body string Haupttext (HTML)
summary string Zusammenfassung
heading_tag string HTML-Tag für Überschrift ("h1", "h2", etc.)
heading_size string Überschriftsgröße
is_enabled boolean Block ist aktiv

BlockSlider

Bildergalerien und Slider-Komponenten.

Feld Typ Beschreibung
id integer Block-ID
type string Slider-Typ
aspect_ratio string Seitenverhältnis (z.B. "16:9")
row_mode boolean Reihen-Modus aktiviert
pick_items integer Anzahl anzuzeigender Items
randomize boolean Zufällige Reihenfolge
items object Slider-Inhalte

Linksammlungen und Navigationsblöcke.

Feld Typ Beschreibung
id integer Block-ID
heading string Block-Überschrift
type string Link-Block-Typ
summary string Beschreibung
item object Link-Daten

BlockEmbed

Eingebettete Inhalte wie Videos oder externe Widgets.

Feld Typ Beschreibung
id integer Block-ID
type string Embed-Typ
link string URL des eingebetteten Inhalts
code string Embed-Code
aspect_ratio string Seitenverhältnis
max_width integer Maximale Breite in Pixeln
file File Eingebettete Datei

BlockList

Listen-Darstellungen für Sammlungen und Aufzählungen.

Feld Typ Beschreibung
id integer Block-ID
type string Listen-Typ
heading string Listen-Überschrift
summary string Listen-Beschreibung
collection string Quell-Collection
mode string Darstellungsmodus
pick_items integer Anzahl Items
show_filter boolean Filter anzeigen
row_mode boolean Reihen-Layout
randomize boolean Zufällige Sortierung
items object[] Listen-Items

Beispiel-Code

JavaScript/Fetch

// Alle Inhalte abrufen
const response = await fetch('https://api.kulturpool.at/content');
const { data: contentPages } = await response.json();

// Einzelne Seite abrufen
const pageResponse = await fetch('https://api.kulturpool.at/content/1');
const { data: page } = await pageResponse.json();

// Deutsche Übersetzung extrahieren
const germanTranslation = page.translations.find(t => t.languages_code === 'de');
console.log(`Titel: ${germanTranslation.title}`);
console.log(`Slug: ${germanTranslation.slug}`);

Python/requests

import requests

# Alle Inhalte abrufen
response = requests.get('https://api.kulturpool.at/content')
content_pages = response.json()['data']

# Einzelne Seite abrufen
page_response = requests.get('https://api.kulturpool.at/content/1')
page = page_response.json()['data']

# Deutsche Übersetzung finden
german_translation = next(
    (t for t in page['translations'] if t['languages_code'] == 'de'),
    None
)

if german_translation:
    print(f"Titel: {german_translation['title']}")
    print(f"Slug: {german_translation['slug']}")

Content-Blöcke verarbeiten

function processContentBlocks(translation) {
  return translation.items.map(item => {
    const { collection, item: block } = item;

    switch (collection) {
      case 'block_text':
        return {
          type: 'text',
          heading: block.heading,
          body: block.body,
          tag: block.heading_tag || 'h2'
        };

      case 'block_slider':
        return {
          type: 'slider',
          aspectRatio: block.aspect_ratio,
          items: block.items || []
        };

      case 'block_embed':
        return {
          type: 'embed',
          url: block.link,
          code: block.code,
          maxWidth: block.max_width
        };

      default:
        return { type: 'unknown', data: block };
    }
  });
}

Anwendungsfälle

Dynamische Website-Seiten

async function renderContentPage(slug) {
  // Alle Seiten abrufen und nach Slug filtern
  const response = await fetch('https://api.kulturpool.at/content');
  const { data: pages } = await response.json();

  const page = pages.find(page =>
    page.translations.some(t => t.slug === slug)
  );

  if (!page) {
    throw new Error(`Seite mit Slug "${slug}" nicht gefunden`);
  }

  const translation = page.translations.find(t => t.languages_code === 'de');

  return {
    title: translation.title,
    seoTitle: page.seo?.title || translation.title,
    metaDescription: page.seo?.meta_description || translation.summary,
    canonicalUrl: page.seo?.canonical_url,
    blocks: processContentBlocks(translation),
    theme: {
      textColor: page.color_text,
      backgroundColor: page.color_background
    }
  };
}

SEO-Metadaten extrahieren

function extractSEOMetadata(page, language = 'de') {
  const translation = page.translations.find(t => t.languages_code === language);

  return {
    title: page.seo?.title || translation?.title,
    description: page.seo?.meta_description || translation?.summary,
    canonical: page.seo?.canonical_url,
    noIndex: page.seo?.no_index || false,
    noFollow: page.seo?.no_follow || false,
    ogImage: page.seo?.og_image?.id ?
      `https://api.kulturpool.at/assets/${page.seo.og_image.id}?format=jpg&width=1200&height=630&fit=cover` : null
  };
}

Content-Management für Headless CMS

class ContentManager {
  constructor(baseUrl = 'https://api.kulturpool.at') {
    this.baseUrl = baseUrl;
    this.cache = new Map();
  }

  async getPage(id) {
    if (this.cache.has(id)) {
      return this.cache.get(id);
    }

    const response = await fetch(`${this.baseUrl}/content/${id}`);
    const { data: page } = await response.json();

    this.cache.set(id, page);
    return page;
  }

  async getPageBySlug(slug, language = 'de') {
    const response = await fetch(`${this.baseUrl}/content`);
    const { data: pages } = await response.json();

    return pages.find(page =>
      page.translations.some(t =>
        t.slug === slug && t.languages_code === language
      )
    );
  }

  getBlocks(page, language = 'de') {
    const translation = page.translations.find(t => t.languages_code === language);
    return translation?.items || [];
  }

  getActiveBlocks(page, language = 'de') {
    return this.getBlocks(page, language)
      .filter(item => item.item.is_enabled !== false)
      .sort((a, b) => (a.sort || 0) - (b.sort || 0));
  }
}

Mehrsprachige Navigation

async function buildNavigation() {
  const response = await fetch('https://api.kulturpool.at/content');
  const { data: pages } = await response.json();

  const navigation = {};

  pages.forEach(page => {
    page.translations.forEach(translation => {
      const { languages_code, title, slug } = translation;

      if (!navigation[languages_code]) {
        navigation[languages_code] = [];
      }

      navigation[languages_code].push({
        title,
        slug,
        url: `/${languages_code}/${slug}`,
        sort: page.sort || 999
      });
    });
  });

  // Sortieren nach sort-Wert
  Object.keys(navigation).forEach(lang => {
    navigation[lang].sort((a, b) => a.sort - b.sort);
  });

  return navigation;
}

Fehlerbehandlung

404 - Content nicht gefunden

{
  "detail": "Content not found"
}

500 - Validierungsfehler

{
  "detail": "Response validation error for content 1: ..."
}