Zurück zur Dokumentation

Sutram REST API v1

Version: 0.89.0 Datum: 2026-02-19 Status: In Produktion


Übersicht

Die Sutram REST API stellt JSON-Endpunkte für den externen Zugriff auf Projektinhalte (Ordner, Dateien, Links) bereit. Sie verwendet die gleiche Dual-Key-Authentifizierung wie der MCP-Server (x-project-key + x-user-key), sodass jedes Projekt mit aktiviertem Fernzugriff automatisch über die REST API erreichbar ist.

Anwendungsfälle

  • APM-Plattform-Integration — Sutram-Inhalte (Events, Nachrichten, Podcasts, Webinare) als zentrales Repository (SSOT) nutzen
  • Benutzerdefinierte Dashboards — Inhaltslistenseiten außerhalb von Sutram erstellen
  • Mobile Apps — Dateien und Links mit vorsignierten Download-URLs abrufen
  • Automatisierung — Programmatische Inhaltsermittlung und -abruf über Skripte oder CI/CD

Basis-URL

https://sutram.io/api/v1

Entwicklung:

http://localhost:4001/api/v1

Funktionsweise

External Client (app, script, dashboard)
        |
        | HTTPS + JSON
        v
  Sutram REST API
    /api/v1/*
        |
        | Dual Key Authentication
        v
  Project Content (folders, files, links, tags)

Authentifizierung

Jede Anfrage muss zwei Header enthalten:

Header Wert Beschreibung
x-project-key sk_proj_... Identifiziert das Projekt
x-user-key sk_user_... Identifiziert den Benutzer

Beide Schlüssel werden über die Sutram-Weboberfläche erstellt. Siehe die MCP-Server-Benutzeranleitung für eine Schritt-für-Schritt-Anleitung.

Beispiel

curl -H "x-project-key: sk_proj_ej8NWMisd2rJgMwAJ22T..." \
     -H "x-user-key: sk_user_zQD0BjH56nQhOgX3uxni..." \
     https://sutram.io/api/v1/project

Fehlerantworten

Wenn die Authentifizierung fehlschlägt, gibt die API HTTP 401 zurück:

{ "error": "Missing x-project-key header" }
{ "error": "Invalid project key" }
{ "error": "Invalid user key" }
{ "error": "Viewers cannot access this API" }
{ "error": "Not a member of this project" }

Berechtigungen

Rolle Zugriff
Owner Voller Lesezugriff
Admin Voller Lesezugriff
Member Voller Lesezugriff
Viewer Kein Zugriff (401)

Die REST API v1 ist schreibgeschützt. Schreiboperationen (Hochladen, Löschen, Umbenennen, Verschieben) sind über den MCP-Server verfügbar.


Endpunkte

GET /api/v1/project

Gibt Informationen über das authentifizierte Projekt zurück.

Beispielanfrage:

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     https://sutram.io/api/v1/project

Antwort:

{
  "project": {
    "id": "a1b2c3d4-...",
    "name": "Construction Site Alpha",
    "description": "Main project documentation",
    "your_role": "owner",
    "created_at": "2026-01-15T10:00:00Z",
    "updated_at": "2026-02-19T14:30:00Z"
  }
}

GET /api/v1/folders

Listet die Ordner auf der Stammebene des Projekts auf.

Beispielanfrage:

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     https://sutram.io/api/v1/folders

Antwort:

{
  "folders": [
    {
      "id": "f1a2b3c4-...",
      "name": "Reports",
      "parent_id": null,
      "tags": {"category": "monthly"},
      "created_at": "2026-01-20T10:00:00Z"
    },
    {
      "id": "f5e6d7c8-...",
      "name": "Photos",
      "parent_id": null,
      "tags": {},
      "created_at": "2026-01-22T08:00:00Z"
    }
  ],
  "meta": {
    "total_count": 2
  }
}

GET /api/v1/folders/:id

Gibt die Details eines Ordners, seine Unterordner und seine Inhaltselemente zurück.

Pfadparameter:

Parameter Typ Beschreibung
id UUID Ordner-ID

Beispielanfrage:

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     https://sutram.io/api/v1/folders/f1a2b3c4-...

Antwort:

{
  "folder": {
    "id": "f1a2b3c4-...",
    "name": "Reports",
    "parent_id": null,
    "path": "/Reports",
    "tags": {"category": "monthly"},
    "created_at": "2026-01-20T10:00:00Z"
  },
  "subfolders": [
    {
      "id": "a1b2c3d4-...",
      "name": "2024",
      "parent_id": "f1a2b3c4-...",
      "tags": {"year": "2024"},
      "created_at": "2026-01-25T12:00:00Z"
    }
  ],
  "items": [
    {
      "id": "d5e6f7a8-...",
      "type": "file",
      "name": "summary",
      "description": null,
      "tags": {"status": "final"},
      "folder_id": "f1a2b3c4-...",
      "created_at": "2026-02-01T10:00:00Z",
      "file": {
        "filename": "summary.pdf",
        "content_type": "application/pdf",
        "file_size": 245000
      }
    }
  ],
  "meta": {
    "subfolder_count": 1,
    "item_count": 1
  }
}

Fehlerantworten:

Status Body Wann
404 {"error": "Folder not found"} Ordner existiert nicht oder gehört zu einem anderen Projekt

GET /api/v1/content

Listet Inhaltselemente mit Filterung, Tag-Suche, Textsuche und Paginierung auf.

Abfrageparameter:

Parameter Typ Standard Beschreibung
folder_id UUID Nach Ordner filtern. Ohne diesen werden nur Elemente auf der Stammebene zurückgegeben.
all_folders boolean false Wenn true, wird über alle Ordner gesucht (nicht nur Stammebene). Erforderlich für Tag-/Suchabfragen über das gesamte Projekt.
type string Nach Inhaltstyp filtern: "file", "web_link", "video_link", "audio_link"
tag string Einzelner Tag-Schlüssel zum Filtern (z.B. tag=category)
tag_value string Zu vergleichender Tag-Wert (zusammen mit tag). Groß-/Kleinschreibung-unabhängige Teilstringsuche.
tags JSON Mehrere UND-Bedingungen als JSON-Array (z.B. tags=[{"key":"topic","value":"neuro"}])
search string Nach Elementname suchen (Groß-/Kleinschreibung-unabhängige Teilstringsuche)
page integer 1 Seitennummer
per_page integer 50 Elemente pro Seite (max: 100)

Tag-Suchverhalten:

  • Schlüsselabgleich: Groß-/Kleinschreibung-unabhängiger exakter Abgleich ("Category" stimmt mit "category" überein)
  • Wertabgleich: Groß-/Kleinschreibung-unabhängige Teilstringsuche ("neuro" stimmt mit "Neurologia Avançada" überein)
  • Mehrere Bedingungen (tags-Parameter): Alle Bedingungen müssen zutreffen (UND-Logik)
  • Ohne Wert: Wenn tag_value weggelassen wird, wird jedes Element mit dem Tag-Schlüssel gefunden, unabhängig vom Wert

Beispiel — Stammelemente auflisten

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content"

Beispiel — Elemente in einem Ordner auflisten

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content?folder_id=f1a2b3c4-..."

Beispiel — nach Typ filtern

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content?type=video_link&all_folders=true"

Beispiel — einzelne Tag-Suche

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content?tag=category&tag_value=cientifico&all_folders=true"

Beispiel — Multi-Tag-UND-Suche

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content?tags=%5B%7B%22key%22%3A%22patient%22%2C%22value%22%3A%22jo%C3%A3o%22%7D%2C%7B%22key%22%3A%22year%22%2C%22value%22%3A%222024%22%7D%5D&all_folders=true"

Der tags-Parameter oben ist die URL-kodierte Version von:

[{"key": "patient", "value": "joão"}, {"key": "year", "value": "2024"}]

Beispiel — nach Name suchen

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content?search=report&all_folders=true"

Beispiel — paginierte Auflistung

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content?page=2&per_page=20"

Antwort:

{
  "items": [
    {
      "id": "d5e6f7a8-...",
      "type": "file",
      "name": "site-plan",
      "description": null,
      "tags": {"category": "planta", "year": "2024"},
      "folder_id": "f1a2b3c4-...",
      "created_at": "2026-02-19T10:00:00Z",
      "file": {
        "filename": "site-plan.pdf",
        "content_type": "application/pdf",
        "file_size": 2450000
      }
    },
    {
      "id": "e5f6a7b8-...",
      "type": "video_link",
      "name": "Site walkthrough",
      "description": null,
      "tags": {"topic": "neurologia"},
      "folder_id": null,
      "created_at": "2026-02-18T14:00:00Z",
      "video_link": {
        "url": "https://youtube.com/watch?v=abc",
        "platform": "youtube",
        "video_id": "abc",
        "thumbnail_url": "https://img.youtube.com/vi/abc/hqdefault.jpg"
      }
    },
    {
      "id": "a1b2c3d4-...",
      "type": "web_link",
      "name": "Documentation",
      "description": "Project reference docs",
      "tags": {},
      "folder_id": null,
      "created_at": "2026-02-17T09:00:00Z",
      "web_link": {
        "url": "https://docs.example.com",
        "fetched_title": "Documentation Hub",
        "favicon_url": "https://docs.example.com/favicon.ico"
      }
    },
    {
      "id": "c9d0e1f2-...",
      "type": "audio_link",
      "name": "Weekly recap",
      "description": null,
      "tags": {"series": "weekly"},
      "folder_id": null,
      "created_at": "2026-02-16T16:00:00Z",
      "audio_link": {
        "url": "https://open.spotify.com/episode/xyz",
        "platform": "spotify",
        "artist_or_author": "Team Alpha",
        "thumbnail_url": "https://i.scdn.co/image/abc"
      }
    }
  ],
  "meta": {
    "page": 1,
    "per_page": 50,
    "total_count": 4,
    "total_pages": 1
  }
}

Inhaltliche Felder nach Typ:

Das Inhaltsobjekt wird unter einem Schlüssel serialisiert, der dem Elementtyp entspricht:

Typ Schlüssel Felder
file file filename, content_type, file_size
web_link web_link url, fetched_title, favicon_url
video_link video_link url, platform, video_id, thumbnail_url
audio_link audio_link url, platform, artist_or_author, thumbnail_url

GET /api/v1/content/:id

Gibt vollständige Details eines einzelnen Inhaltselements zurück, einschließlich vorsignierter Download-URLs für Dateien.

Pfadparameter:

Parameter Typ Beschreibung
id UUID Inhaltselement-ID

Beispielanfrage:

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     https://sutram.io/api/v1/content/d5e6f7a8-...

Antwort (Datei):

{
  "item": {
    "id": "d5e6f7a8-...",
    "type": "file",
    "name": "site-plan",
    "description": null,
    "tags": {"category": "planta", "year": "2024"},
    "folder_id": "f1a2b3c4-...",
    "folder_path": "/Reports/2024",
    "created_at": "2026-02-19T10:00:00Z",
    "file": {
      "filename": "site-plan.pdf",
      "content_type": "application/pdf",
      "file_size": 2450000,
      "version": 1,
      "download_url": "https://storage.example.com/projects/.../site-plan.pdf?X-Amz-..."
    }
  }
}

Antwort (Video-Link):

{
  "item": {
    "id": "e5f6a7b8-...",
    "type": "video_link",
    "name": "Site walkthrough",
    "description": null,
    "tags": {"topic": "neurologia"},
    "folder_id": null,
    "folder_path": "/",
    "created_at": "2026-02-18T14:00:00Z",
    "video_link": {
      "url": "https://youtube.com/watch?v=abc",
      "platform": "youtube",
      "video_id": "abc",
      "thumbnail_url": "https://img.youtube.com/vi/abc/hqdefault.jpg",
      "duration_seconds": null,
      "fetched_title": "Construction Site Alpha - Full Tour"
    }
  }
}

Antwort (Audio-Link):

{
  "item": {
    "id": "c9d0e1f2-...",
    "type": "audio_link",
    "name": "Weekly recap",
    "description": null,
    "tags": {"series": "weekly"},
    "folder_id": null,
    "folder_path": "/",
    "created_at": "2026-02-16T16:00:00Z",
    "audio_link": {
      "url": "https://open.spotify.com/episode/xyz",
      "platform": "spotify",
      "artist_or_author": "Team Alpha",
      "thumbnail_url": "https://i.scdn.co/image/abc",
      "duration_seconds": 1800,
      "fetched_title": "Weekly Standup Recap - Feb 16"
    }
  }
}

Antwort (Web-Link):

{
  "item": {
    "id": "a1b2c3d4-...",
    "type": "web_link",
    "name": "Documentation",
    "description": "Project reference docs",
    "tags": {},
    "folder_id": null,
    "folder_path": "/",
    "created_at": "2026-02-17T09:00:00Z",
    "web_link": {
      "url": "https://docs.example.com",
      "fetched_title": "Documentation Hub",
      "fetched_description": "Complete project documentation",
      "favicon_url": "https://docs.example.com/favicon.ico"
    }
  }
}

Unterschiede zwischen Detail- und Listenantwort:

Der Endpunkt /content/:id gibt im Vergleich zum Listenendpunkt zusätzliche Felder zurück:

Feld Liste (/content) Detail (/content/:id)
folder_path Nein Ja
file.version Nein Ja
file.download_url Nein Ja (vorsigniert, temporär)
web_link.fetched_description Nein Ja
video_link.duration_seconds Nein Ja
video_link.fetched_title Nein Ja
audio_link.duration_seconds Nein Ja
audio_link.fetched_title Nein Ja

Fehlerantworten:

Status Body Wann
404 {"error": "Content item not found"} Element existiert nicht oder gehört zu einem anderen Projekt

Tags für Inhaltselemente

Tags sind frei definierbare Schlüssel-Wert-Stringpaare, die an Inhaltselemente und Ordner angehängt werden. Sie ermöglichen strukturierte Metadaten und leistungsfähige Suchfunktionen.

Tag-Einschränkungen

Einschränkung Limit
Maximale Tags pro Element 50
Maximale Schlüssellänge 100 Zeichen
Maximale Wertlänge 500 Zeichen
Schlüssel- und Werttypen Nur Strings

Tags verwalten

Tags auf Inhaltselementen werden über die MCP-Server-Tools verwaltet:

MCP-Tool Beschreibung
sutram_set_item_tags Alle Tags eines Inhaltselements setzen/ersetzen
sutram_search_items Elemente nach Tag suchen (einzelne oder Multi-Bedingung UND)
sutram_get_item_tag_keys Alle unterschiedlichen Tag-Schlüssel über Elemente auflisten

Siehe die MCP-Server-Benutzeranleitung für Details zu diesen Tools.

Tags über die REST API abfragen

Verwenden Sie die Abfrageparameter tag, tag_value und tags bei GET /api/v1/content:

# Alle Elemente mit dem Tag "category" finden
curl ... "https://sutram.io/api/v1/content?tag=category&all_folders=true"

# Elemente finden, bei denen category "report" enthält
curl ... "https://sutram.io/api/v1/content?tag=category&tag_value=report&all_folders=true"

# Elemente finden, die mehrere Bedingungen erfüllen (UND)
curl ... "https://sutram.io/api/v1/content?tags=[{\"key\":\"patient\",\"value\":\"joão\"},{\"key\":\"year\",\"value\":\"2024\"}]&all_folders=true"

Vergleich: REST API vs. MCP-Server

Fähigkeit REST API (/api/v1) MCP-Server (/mcp)
Protokoll HTTP/JSON JSON-RPC 2.0 (MCP)
Inhalte lesen Ja Ja
Nach Tags suchen Ja Ja
Download-URLs Ja (vorsigniert) Ja (vorsigniert)
Dateien hochladen Nein Ja
Links erstellen Nein Ja
Ordner erstellen Nein Ja
Tags setzen Nein Ja
Verschieben/Umbenennen/Löschen Nein Ja
Authentifizierung Gleicher Dual-Key Gleicher Dual-Key
Am besten geeignet für Externe Apps, Dashboards, Skripte KI-Assistenten, Automatisierung

Ratenlimits

Derzeit gibt es keine Ratenlimits für die REST API. Dies kann sich in zukünftigen Versionen ändern. Bitte gehen Sie vernünftig mit der Anfragehäufigkeit um.


Versionierung

Die API wird über den URL-Pfad versioniert (/api/v1). Breaking Changes werden in neuen Versionen eingeführt (/api/v2). Nicht-breaking Ergänzungen (neue Felder, neue optionale Parameter) können der aktuellen Version ohne Vorankündigung hinzugefügt werden.


Beispiele

Alle Video-Links in einem Projekt abrufen

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content?type=video_link&all_folders=true"

Inhalte abrufen, die für ein bestimmtes Thema getaggt sind

curl -H "x-project-key: $PROJECT_KEY" \
     -H "x-user-key: $USER_KEY" \
     "https://sutram.io/api/v1/content?tag=topic&tag_value=neurologia&all_folders=true"

Eine Ordnerhierarchie durchsuchen

# 1. Stammordner auflisten
curl ... "https://sutram.io/api/v1/folders"

# 2. Einen bestimmten Ordner öffnen
curl ... "https://sutram.io/api/v1/folders/f1a2b3c4-..."

# 3. Download-URL für eine Datei abrufen
curl ... "https://sutram.io/api/v1/content/d5e6f7a8-..."

Durch alle Inhalte paginieren

# Seite 1
curl ... "https://sutram.io/api/v1/content?page=1&per_page=20&all_folders=true"

# Seite 2
curl ... "https://sutram.io/api/v1/content?page=2&per_page=20&all_folders=true"

# Fortsetzen bis page >= total_pages aus meta

Integration mit JavaScript (fetch)

const PROJECT_KEY = "sk_proj_...";
const USER_KEY = "sk_user_...";
const BASE_URL = "https://sutram.io/api/v1";

async function fetchContent(params = {}) {
  const query = new URLSearchParams(params).toString();
  const url = `${BASE_URL}/content${query ? "?" + query : ""}`;

  const response = await fetch(url, {
    headers: {
      "x-project-key": PROJECT_KEY,
      "x-user-key": USER_KEY,
    },
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(error.error);
  }

  return response.json();
}

// List all video links
const videos = await fetchContent({ type: "video_link", all_folders: "true" });
console.log(`Found ${videos.meta.total_count} videos`);

// Search by tag
const tagged = await fetchContent({
  tag: "topic",
  tag_value: "neurologia",
  all_folders: "true",
});

Integration mit Python (requests)

import requests

PROJECT_KEY = "sk_proj_..."
USER_KEY = "sk_user_..."
BASE_URL = "https://sutram.io/api/v1"

headers = {
    "x-project-key": PROJECT_KEY,
    "x-user-key": USER_KEY,
}

# List root folders
folders = requests.get(f"{BASE_URL}/folders", headers=headers).json()

# Get content in a folder
folder_id = folders["folders"][0]["id"]
content = requests.get(
    f"{BASE_URL}/content",
    headers=headers,
    params={"folder_id": folder_id},
).json()

# Search by multiple tags
import json
tags = json.dumps([
    {"key": "patient", "value": "joão"},
    {"key": "year", "value": "2024"},
])
results = requests.get(
    f"{BASE_URL}/content",
    headers=headers,
    params={"tags": tags, "all_folders": "true"},
).json()

print(f"Found {results['meta']['total_count']} items")

Fehlerbehebung

401 Unauthorized

  • Überprüfen Sie, ob beide Header x-project-key und x-user-key vorhanden sind
  • Prüfen Sie, ob die Schlüssel nicht widerrufen wurden
  • Stellen Sie sicher, dass Sie ein aktives Mitglied (kein Viewer) des Projekts sind

404 Not Found

  • Überprüfen Sie, ob die Ordner-/Inhalts-ID zum authentifizierten Projekt gehört
  • Prüfen Sie, ob das Element nicht gelöscht wurde

Leere Ergebnisse bei der Tag-Suche

  • Fügen Sie all_folders=true hinzu, um über alle Ordner zu suchen (ohne diesen werden nur Stammelemente zurückgegeben)
  • Die Tag-Suche ist Groß-/Kleinschreibung-unabhängig — überprüfen Sie auf Tippfehler in Schlüsselnamen
  • Verwenden Sie GET /api/v1/content?tag=YOUR_KEY&all_folders=true ohne Wert zuerst, um zu überprüfen, ob der Tag-Schlüssel existiert

tags-Parameter gibt einen Fehler zurück

  • Der tags-Parameter muss ein gültiges JSON-Array sein: [{"key": "...", "value": "..."}]
  • URL-kodieren Sie den JSON-String, wenn Sie ihn als Abfrageparameter übergeben
  • Jede Bedingung muss ein key-Feld haben; value ist optional