Für wen ist die API? Die API steht aktiven Vertragskunden zur Verfügung. Testzugänge können sie nicht nutzen und keinen API-Schlüssel erstellen. Diese Dokumentation ist öffentlich, damit Sie vorab prüfen können, wie sich PortraitFlow in Ihren HR-/IT-Ablauf einbinden lässt. Fragen dazu beantworten wir gerne: studio@portraitflow.ch.
1. Überblick
Die API ist eine JSON-Schnittstelle (REST). Damit kann Ihr System:
- Ihre Projekte abfragen,
- Mitarbeitende anlegen – einzeln oder bis zu 200 auf einmal,
- Mitarbeitende abfragen, ändern und löschen, inklusive Status,
- fertige, vom Mitarbeitenden freigegebene Porträts herunterladen (JPEG mit Hintergrund oder freigestelltes PNG, auf Wunsch in Ihren hinterlegten Bildgrössen).
Der Ablauf im Hintergrund bleibt wie im Portal: PortraitFlow lädt die Mitarbeitenden ein, ein Fotograf bearbeitet die Bilder, die Mitarbeitenden geben ihr Bild frei. Die API übernimmt das Übertragen der Daten und das Abholen der Ergebnisse.
2. Typischer Ablauf
- Ihre IT erstellt im Portal einen API-Schlüssel (nur aktive Vertragskunden).
- Ihr System fragt die Projekte ab und merkt sich die Projekt-ID.
- Ihr System überträgt die Mitarbeitenden. Ihre Personalnummer geben Sie als „mitarbeiternummer“ mit – sie ist später der Schlüssel, um jedes Bild dem richtigen Datensatz zuzuordnen.
- PortraitFlow lädt die Mitarbeitenden ein und bearbeitet die Fotos. Die Einladung wird bewusst von PortraitFlow ausgelöst, nicht über die API.
- Ein regelmässiger Job (z. B. stündlich oder nachts) fragt die Mitarbeitenden mit fertigem Bild ab und lädt die Bilder herunter.
- Ihr System legt das Bild beim passenden Mitarbeitenden ab (Zuordnung über die Personalnummer).
Hinweis: Jeder Mitarbeitende braucht eine E-Mail-Adresse, weil die Einladung per E-Mail erfolgt. E-Mail-Adresse und Personalnummer sind pro Projekt eindeutig.
3. Zugang und Authentifizierung
- Die API steht aktiven Vertragskunden zur Verfügung. Testzugänge können sie nicht nutzen.
- API-Schlüssel erstellen und widerrufen Sie im Portal unter Konto → API-Zugang. Pro Konto sind bis zu 5 aktive Schlüssel möglich (z. B. für einen Schlüsselwechsel).
- Ein Schlüssel wird nur einmal bei der Erstellung angezeigt. Bewahren Sie ihn wie ein Passwort auf. Geht er verloren oder in falsche Hände, widerrufen Sie ihn und erstellen einen neuen.
Senden Sie den Schlüssel bei jeder Anfrage im Header „Authorization“. Basis-URL: https://portraitflow.ch/api/v1
curl https://portraitflow.ch/api/v1/projects \
-H "Authorization: Bearer pf_IhrSchluessel"
4. Endpunkte im Überblick
| Endpunkt | Zweck |
|---|---|
GET /projects | Ihre Projekte auflisten |
GET /projects/{projectId}/employees | Mitarbeitende eines Projekts auflisten (Filter, Seiten) |
POST /projects/{projectId}/employees | Einen oder mehrere Mitarbeitende anlegen |
GET /employees/{employeeId} | Einen Mitarbeitenden abrufen |
PATCH /employees/{employeeId} | Einen Mitarbeitenden ändern |
DELETE /employees/{employeeId} | Einen Mitarbeitenden samt Fotos löschen |
GET /employees/{employeeId}/photo | Das fertige Bild herunterladen |
GET /image-sizes | Ihre hinterlegten Bildgrössen auflisten |
5. Endpunkte im Detail
Projekte abfragen
GET https://portraitflow.ch/api/v1/projects
{
"data": [
{ "id": 11, "projektnummer": "P-2026-014", "name": "Porträts 2026", "status": "active",
"start_date": "2026-10-01", "deadline": "2026-11-30", "employees_count": 700 }
]
}
Mitarbeitende anlegen
Entweder einen Mitarbeitenden direkt im Body senden oder mehrere als Liste „employees“ (maximal 200 pro Aufruf). Der Aufruf gilt ganz oder gar nicht: ist ein Eintrag ungültig, wird keiner angelegt, und die Fehlermeldung nennt den betroffenen Eintrag (z. B. „employees.1.email“). „mitarbeiternummer“ und „locale“ (de/en) sind optional; ohne Nummer vergibt PortraitFlow automatisch eine. Die Antwort enthält die angelegten Mitarbeitenden in derselben Reihenfolge.
curl -X POST https://portraitflow.ch/api/v1/projects/11/employees \
-H "Authorization: Bearer pf_IhrSchluessel" \
-H "Content-Type: application/json" \
-d '{"employees":[
{"first_name":"Anna","last_name":"Muster","email":"anna.muster@example.com","mitarbeiternummer":"PERS-1042"},
{"first_name":"Ben","last_name":"Beispiel","email":"ben.beispiel@example.com"}]}'
Tipp: Übertragen Sie bei einer erneuten Synchronisation nur neue Mitarbeitende. Schon vorhandene E-Mail-Adressen lehnt der Aufruf ab (und damit den ganzen Aufruf). Fragen Sie vorher die vorhandenen Mitarbeitenden ab.
Mitarbeitende abfragen
Optionale Filter (als Query-Parameter):
status | pending, uploaded, edited, retake |
mitarbeiternummer | Genaue Personalnummer |
photo_ready=1 | Nur Mitarbeitende mit fertigem, freigegebenem Bild |
per_page, page | Seitengrösse (1–200, Standard 50) und Seitennummer |
GET https://portraitflow.ch/api/v1/projects/11/employees?photo_ready=1&per_page=200&page=1
{
"data": [
{ "id": 23, "project_id": 11, "mitarbeiternummer": "PERS-1042",
"first_name": "Anna", "last_name": "Muster", "email": "anna.muster@example.com",
"locale": null, "status": "edited",
"invited_at": "2026-10-20T08:00:00+02:00", "uploaded_at": "2026-10-21T10:15:00+02:00",
"photo": {
"approved": true,
"edited_at": "2026-10-22T14:00:00+02:00",
"standard_url": "https://portraitflow.ch/api/v1/employees/23/photo",
"transparent_url": null
} }
],
"links": { "next": null },
"meta": { "current_page": 1, "last_page": 1, "per_page": 200, "total": 1 }
}
| Feld | Bedeutung |
|---|---|
status | pending = noch kein Foto · uploaded = Foto eingegangen · edited = bearbeitetes Foto vorhanden · retake = Neuaufnahme angefragt |
photo.approved | Der Mitarbeitende hat das bearbeitete Bild freigegeben |
photo.edited_at | Zeitpunkt der letzten Bearbeitung. Ändert sich bei einer Neuaufnahme – daran erkennen Sie ein aktualisiertes Bild. |
photo.standard_url | Download-Adresse des JPEG mit Hintergrund – nur gesetzt, wenn fertig und freigegeben |
photo.transparent_url | Download-Adresse des freigestellten PNG – nur gesetzt, wenn vorhanden und freigegeben |
Einen einzelnen Mitarbeitenden liefert GET /employees/{employeeId} im selben Format.
Mitarbeitende ändern und löschen
Bei „PATCH“ senden Sie nur die Felder, die sich ändern (first_name, last_name, email, mitarbeiternummer, locale). Ändert sich die E-Mail-Adresse eines bereits eingeladenen Mitarbeitenden, der noch kein Foto hochgeladen hat, wird automatisch eine neue Einladung an die korrigierte Adresse gesendet (Antwort: meta.invitation_resent). „DELETE“ entfernt den Mitarbeitenden samt seinen Fotos dauerhaft und antwortet mit 204.
curl -X PATCH https://portraitflow.ch/api/v1/employees/23 \
-H "Authorization: Bearer pf_IhrSchluessel" \
-H "Content-Type: application/json" \
-d '{"email":"anna.muster@neuefirma.example"}'
6. Fertige Bilder abrufen
Ein Bild kann erst abgerufen werden, wenn das bearbeitete Foto vorhanden ist und der Mitarbeitende es freigegeben hat. Mit „photo_ready=1“ (siehe oben) fragen Sie genau diese Mitarbeitenden ab. Für den Download senden Sie ebenfalls Ihren API-Schlüssel mit:
| Parameter | Wirkung |
|---|---|
variant=standard | JPEG mit Hintergrund (Standard). Immer ein echtes JPEG; transparente Bereiche werden weiss. |
variant=transparent | Freigestelltes PNG mit transparentem Hintergrund. Immer ein echtes PNG. |
size=0, size=1 … | Eine Ihrer hinterlegten Bildgrössen (Index aus „GET /image-sizes“). Ohne „size“ erhalten Sie das Bild in voller Grösse. Beide Varianten werden identisch zugeschnitten (gleicher Ausschnitt, ausgerichtet an den Augen wie im Portal); das PNG behält dabei seine Transparenz. |
curl -o anna.jpg "https://portraitflow.ch/api/v1/employees/23/photo?size=0" \
-H "Authorization: Bearer pf_IhrSchluessel"
GET https://portraitflow.ch/api/v1/image-sizes
{ "data": [ { "index": 0, "label": "Quadrat", "width": 500, "height": 500 } ] }
Die Bildgrössen (bis zu 4) legt PortraitFlow in Ihrem Konto fest. Wünschen Sie andere Grössen, schreiben Sie uns.
7. Fehler und Limits
| Code | Bedeutung |
|---|---|
| 401 | API-Schlüssel fehlt, ist ungültig oder wurde widerrufen |
| 403 | Für dieses Konto ist kein API-Zugang freigeschaltet |
| 404 | Unbekannte ID oder gehört zu einem anderen Kunden. Beim Bild: noch kein bearbeitetes Foto („not_available“) oder unbekannte Grösse („unknown_size“). |
| 409 | Der Mitarbeitende hat das Bild noch nicht freigegeben („not_approved“) – später erneut versuchen. Beim Anlegen: kurzer Konflikt bei der Nummernvergabe, erneut senden. |
| 422 | Ungültige Eingabe. Die Antwort nennt je Feld den Grund („errors“). |
| 429 | Zu viele Anfragen. Warten Sie die Zeit im Header „Retry-After“ (Sekunden) ab. |
- Limit: 120 Anfragen pro Minute und Schlüssel. 700 Bilder herunterladen dauert damit rund 6 Minuten.
- Maximal 200 Mitarbeitende pro Anlegen-Aufruf.
- Alle Antworten sind JSON (ausser dem Bild-Download). Daten sind strikt auf Ihr Konto beschränkt.
8. Beispiele aus der Praxis
Beispiel 1: 700 Mitarbeitende aus dem HR-System
- Ihr Job liest die 700 Mitarbeitenden aus dem HR-System und sendet sie in 4 Aufrufen (200, 200, 200, 100) an „POST /projects/{projectId}/employees“, jeweils mit der Personalnummer als „mitarbeiternummer“.
- PortraitFlow lädt ein und bearbeitet, die Mitarbeitenden geben ihr Bild frei.
- Ein regelmässiger Job holt alle Mitarbeitenden mit „photo_ready=1“, lädt die neuen Bilder herunter und legt sie im HR-System bei der passenden Personalnummer ab.
Beispielskript (Python), das Bilder abholt und die bereits übernommenen merkt:
import requests
H = {"Authorization": "Bearer pf_IhrSchluessel"}
BASE = "https://portraitflow.ch/api/v1"
PROJECT, SIZE = 11, 0 # Projekt-ID, Index Ihrer Bildgrösse
def ready_employees():
page = 1
while True:
r = requests.get(f"{BASE}/projects/{PROJECT}/employees", headers=H,
params={"photo_ready": 1, "per_page": 200, "page": page}).json()
yield from r["data"]
if page >= r["meta"]["last_page"]:
break
page += 1
for e in ready_employees():
key = (e["mitarbeiternummer"], e["photo"]["edited_at"]) # edited_at ändert sich bei Neuaufnahme
if key in already_imported: # Ihre eigene Merkliste
continue
img = requests.get(e["photo"]["standard_url"], headers=H, params={"size": SIZE})
img.raise_for_status()
hr_system.set_photo(personnel_no=e["mitarbeiternummer"], jpeg=img.content)
already_imported.add(key)
Beispiel 2: Laufender Betrieb mit Zutrittsbadge und Intranet
Sobald Ihr HR-System eine neue Person erfasst, sendet es diese einzeln an „POST /projects/{projectId}/employees“. Jede Nacht holt ein Job alle neu fertigen Bilder: für das Intranet die kleine Bildgrösse („size=1“), für den Badge das freigestellte PNG („variant=transparent“), das auf die Badge-Vorlage gesetzt wird. Bei einem Austritt ruft das HR-System „DELETE /employees/{employeeId}“ auf – das entfernt auch die Fotos bei PortraitFlow.
9. OpenAPI-Datei
Für Ihre Entwickler gibt es die maschinenlesbare Beschreibung der Schnittstelle (OpenAPI 3). Damit lassen sich Clients und Testwerkzeuge (z. B. Postman) automatisch einrichten: portraitflow-api-v1.yaml
Weitere Anleitungen: So funktioniert PortraitFlow, Mitarbeitende einladen und importieren, Bildformate und Download.
Häufige Fragen
Wer kann die API nutzen?
Aktive Vertragskunden. Testzugänge können die API nicht nutzen und keine API-Schlüssel erstellen, die Dokumentation steht aber allen offen.
Wie erhält mein System die fertigen Bilder?
Ein regelmässiger Job fragt Mitarbeitende mit fertigem, freigegebenem Bild ab (photo_ready=1) und lädt die Bilder über die mitgelieferte Adresse herunter.
Wie viele Mitarbeitende kann ich pro Aufruf übertragen?
Bis zu 200. Bei 700 Mitarbeitenden genügen vier Aufrufe.
Gibt es ein Limit für Anfragen?
Ja: 120 Anfragen pro Minute und API-Schlüssel. Bei Überschreitung antwortet die API mit 429 und der Wartezeit im Header Retry-After.
Löst die API auch die Einladungen aus?
Nein. Mitarbeitende werden über die API angelegt, die Einladung löst PortraitFlow bewusst selbst aus.
PortraitFlow unverbindlich ausprobieren
Kostenloser Testzugang, ohne Kreditkarte, in wenigen Minuten eingerichtet.