Skip to content

Öffentliche API ​

Mit der öffentlichen API (/api/v1) verbindest du eigene Systeme mit PollYou: Umfragen anlegen und veröffentlichen, Antworten in ein CRM oder Data Warehouse übernehmen, Kennzahlen in ein BI-Tool laden oder Antworten auf Löschanfragen hin entfernen.

Die vollständige Liste der Endpunkte mit Parametern und Feldern steht in der Referenz v1. Für KI-Assistenten gibt es außerdem den MCP-Server, der dieselben Fähigkeiten als MCP-Tools bereitstellt.

API-Schlüssel ​

Die API authentifiziert sich mit API-Schlüsseln deiner Organisation. Admins und Inhaber legen sie im Dashboard unter Einstellungen → API-Schlüssel an:

  1. Name vergeben, z. B. „CRM-Synchronisation“ – gib jedem System einen eigenen Schlüssel.
  2. Scopes wählen: nur die Rechte, die das System braucht (siehe unten).
  3. Optional ein Ablaufdatum setzen. Ohne Datum gilt der Schlüssel, bis er widerrufen wird.

Nach dem Anlegen zeigt das Dashboard den vollständigen Schlüssel genau einmal an. Kopiere ihn sofort in deinen Passwort-Manager oder Secret-Store: PollYou speichert nur einen Hash und kann den Schlüssel später nicht mehr anzeigen. In der Liste siehst du danach nur noch das Präfix (z. B. py_live_k3x9a2bq…), die Scopes und wann der Schlüssel zuletzt benutzt wurde.

Ein Schlüssel sieht so aus:

py_live_k3x9a2bq_Q8yS0d…   (py_live_ + 8 Zeichen Präfix + _ + 40 Zeichen Geheimnis)

Widerrufen wirkt sofort: Anfragen mit dem Schlüssel werden danach mit 401 abgelehnt. Anlegen und Widerrufen stehen im Audit-Log der Organisation.

Schlüssel geheim halten

Ein API-Schlüssel gehört nur auf Server, nie in Browser-Code, Apps oder Repositories. Ist ein Schlüssel nach außen gelangt, widerrufe ihn und lege einen neuen an.

Authentifizierung ​

Sende den Schlüssel als Bearer-Token:

bash
curl https://api.pollyou.example/api/v1/surveys \
  -H "Authorization: Bearer $POLLYOU_API_KEY"

Ein Schlüssel gehört zu genau einer Organisation, deshalb ist der Header X-Organization-Id nicht nötig. Sendest du ihn trotzdem, muss er die Organisation des Schlüssels nennen – sonst antwortet die API mit 403.

StatusBedeutung
401Schlüssel fehlt, ist ungültig, abgelaufen oder widerrufen (detail sagt, was)
403Dem Schlüssel fehlt der nötige Scope, oder X-Organization-Id passt nicht
404Die Ressource existiert nicht – oder gehört einer anderen Organisation
422Ungültige Eingabe; violations nennt Feld (propertyPath) und Grund (message)
429Rate-Limit überschritten, siehe unten

Fehler kommen als Problem-JSON (application/problem+json) mit title, status und detail.

Die Anmeldung des Dashboards (Zugangstokens von Personen) funktioniert für /api/v1 nicht, und API-Schlüssel funktionieren nicht für die interne API des Dashboards.

Scopes ​

Jeder Endpunkt verlangt einen Scope. Ein …:write-Scope enthält den passenden …:read-Scope.

ScopeErlaubt
surveys:readUmfragen auflisten und mit Struktur abrufen
surveys:writeUmfragen anlegen, Titel/Beschreibung ändern, veröffentlichen, beenden (enthält surveys:read)
responses:readAntworten einer Umfrage auflisten und einzeln mit allen Angaben abrufen
responses:writeAntworten endgültig löschen (enthält responses:read)
analytics:readKennzahlen und Ergebnisse pro Frage abrufen

Fehlt der Scope, antwortet die API mit 403 und "detail": "The API key lacks the scope \"responses:read\".".

Datenschutz

responses:read gibt Zugriff auf einzelne Antworten inklusive Kontextdaten (Land, Gerät, UTM-Parameter, Metadaten der Einbettung). Vergib den Scope nur an Systeme, die diese Daten wirklich verarbeiten dürfen; für Dashboards reicht meist analytics:read.

Rate-Limits ​

Pro Schlüssel sind 600 Anfragen pro Minute erlaubt. Jede Antwort enthält:

HeaderInhalt
X-RateLimit-LimitAnfragen pro Minute
X-RateLimit-RemainingVerbleibende Anfragen im aktuellen Fenster
X-RateLimit-ResetUnix-Zeit, ab der die nächste Anfrage frühestens wieder angenommen wird

Ist das Limit erreicht, antwortet die API mit 429 Too Many Requests und Retry-After (Sekunden). Warte mindestens so lange, bevor du es erneut versuchst. Brauchst du mehr Durchsatz für einen Import, verteile die Arbeit nicht auf mehrere Schlüssel, sondern sprich uns an.

Versionierung ​

Die Version steht im Pfad: /api/v1. Für v1 gilt:

  • Felder, Parameter und Endpunkte kommen nur hinzu. Nichts wird umbenannt, entfernt oder ändert seine Bedeutung.
  • Dein Client muss unbekannte Felder ignorieren – neue Felder sind keine Breaking Changes.
  • Neue Fragetypen können in pages einer Umfrage und in questions der Auswertung auftauchen; behandle unbekannte type-Werte tolerant.
  • Breaking Changes erscheinen als neue Version (/api/v2), die eine Übergangszeit lang parallel zu v1 läuft.

Die API spricht reines JSON (application/json); Änderungen per PATCH erwarten application/merge-patch+json.

Beispiele ​

Umfragen auflisten ​

bash
curl "https://api.pollyou.example/api/v1/surveys?status=live" \
  -H "Authorization: Bearer $POLLYOU_API_KEY"
json
{
  "items": [
    {
      "id": "01a12b79-3855-7453-b69a-a847cfe69ce1",
      "publicId": "Abc123XyZ0",
      "type": "survey",
      "title": "Kundenzufriedenheit",
      "status": "live",
      "questionCount": 5,
      "publishedVersion": 2,
      "publishedAt": "2026-10-01T08:00:00+00:00",
      "hasUnpublishedChanges": false,
      "createdAt": "2026-09-20T10:00:00+00:00",
      "updatedAt": "2026-10-01T08:00:00+00:00"
    }
  ],
  "page": 1,
  "itemsPerPage": 25,
  "totalItems": 1
}

Weitere Seiten mit ?page=2.

Umfrage anlegen und veröffentlichen ​

bash
# Entwurf anlegen (scope surveys:write) – eine Abstimmung startet mit einer Frage und zwei Optionen
curl https://api.pollyou.example/api/v1/surveys \
  -H "Authorization: Bearer $POLLYOU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"type": "poll", "title": "Welches Feature zuerst?"}'

# Titel ändern
curl -X PATCH https://api.pollyou.example/api/v1/surveys/$SURVEY_ID \
  -H "Authorization: Bearer $POLLYOU_API_KEY" \
  -H "Content-Type: application/merge-patch+json" \
  -d '{"title": "Welches Feature bauen wir zuerst?"}'

# Veröffentlichen und später beenden
curl -X POST https://api.pollyou.example/api/v1/surveys/$SURVEY_ID/publish \
  -H "Authorization: Bearer $POLLYOU_API_KEY"
curl -X POST https://api.pollyou.example/api/v1/surveys/$SURVEY_ID/close \
  -H "Authorization: Bearer $POLLYOU_API_KEY"

Fragen und Optionen bearbeitest du im Dashboard. Im Audit-Log erscheint als handelnde Stelle der API-Schlüssel (Name und Präfix).

Antworten abholen (inkrementell) ​

bash
curl "https://api.pollyou.example/api/v1/surveys/$SURVEY_ID/responses?from=2026-10-01&timezone=Europe/Berlin&limit=100" \
  -H "Authorization: Bearer $POLLYOU_API_KEY"
json
{
  "items": [
    {
      "id": "01a12b7a-cd25-7eb6-90e5-64dd7baa2772",
      "status": "completed",
      "startedAt": "2026-10-11T09:12:03+00:00",
      "completedAt": "2026-10-11T09:13:10+00:00",
      "durationMs": 67000,
      "channel": "script",
      "country": "DE",
      "versionNumber": 2,
      "excluded": false,
      "answers": { "nps": 9, "plan": "Pro" }
    }
  ],
  "totalItems": 1342,
  "nextCursor": "eyJ2IjoiMjAyNi0xMC0xMVQwOToxMzoxMC4wMDBaIiwiaWQiOiIwMWExMmI3YS0uLi4ifQ"
}

Die Liste ist nach Abschlusszeit sortiert (neueste zuerst). Für die nächste Seite übergibst du nextCursor als cursor; der Cursor bleibt stabil, auch wenn währenddessen neue Antworten eintreffen. nextCursor: null heißt: letzte Seite. Ausgeschlossene Antworten (Spam, Tests) kommen nur mit includeExcluded=true, laufende Antworten mit status=started oder status=all.

Alle Angaben einer Antwort, inklusive Rohwerten, Anzeige-Texten und Zeitpunkten pro Frage:

bash
curl https://api.pollyou.example/api/v1/responses/$RESPONSE_ID \
  -H "Authorization: Bearer $POLLYOU_API_KEY"

Antwort löschen ​

bash
curl -X DELETE https://api.pollyou.example/api/v1/responses/$RESPONSE_ID \
  -H "Authorization: Bearer $POLLYOU_API_KEY"   # 204, scope responses:write

Die Antwort wird endgültig gelöscht, die Auswertungen werden neu berechnet. Die Löschung steht im Audit-Log.

Kennzahlen abrufen ​

bash
curl "https://api.pollyou.example/api/v1/surveys/$SURVEY_ID/analytics?from=2026-10-01&to=2026-10-31&timezone=Europe/Berlin" \
  -H "Authorization: Bearer $POLLYOU_API_KEY"
json
{
  "surveyId": "01a12b79-3855-7453-b69a-a847cfe69ce1",
  "meta": {
    "source": "rollup",
    "timezone": "Europe/Berlin",
    "from": "2026-10-01T00:00:00+02:00",
    "to": "2026-11-01T00:00:00+01:00"
  },
  "overview": {
    "impressions": 5120,
    "starts": 1830,
    "completions": 1342,
    "startRate": 0.357,
    "completionRate": 0.733,
    "averageDurationMs": 71000,
    "medianDurationMs": 58000
  },
  "totalResponses": 1342,
  "questions": [
    {
      "key": "nps",
      "type": "nps",
      "title": "Wie wahrscheinlich …?",
      "totalAnswers": 1342,
      "nps": { "score": 41.2, "promoters": 702, "passives": 410, "detractors": 230 }
    }
  ]
}

Ohne from/to gelten die letzten 30 Tage inklusive heute. Es zählen dieselben Antworten wie im Dashboard: abgeschlossen und nicht ausgeschlossen.

OpenAPI ​

Das OpenAPI-Dokument der öffentlichen API liefert die API selbst unter GET /api/v1/openapi.json (ohne Schlüssel). Du kannst es in Postman oder Insomnia importieren oder daraus einen Client generieren, z. B. mit openapi-typescript. Eine Kopie liegt in der Doku: Referenz v1.