@extends('web.layouts.web-master') @section('title', 'API-Dokumentation') @section('meta_description', 'REST-API v1: Pressemitteilungen programmatisch erstellen, mit Bildern versehen und zur Prüfung einreichen — Token-basiert, JSON, versioniert.') @php // Die API läuft zentral über den Publisher-Hub (pressekonto). $apiBase = rtrim((string) config('domains.domain_portal_url', config('app.url')), '/').'/api/v1'; $host = request()->getHost(); $apiBrandKey = str_contains($host, 'pressekonto') ? 'pressekonto' : (str_contains($host, 'presseecho') ? 'presseecho' : 'businessportal24'); $apiContactEmail = config('domains.domains.'.$apiBrandKey.'.brand.contact_email') ?? 'info@businessportal24.com'; $endpoints = [ [ 'group' => 'Pressemitteilungen', 'items' => [ ['method' => 'GET', 'path' => '/press-releases', 'desc' => 'Eigene Mitteilungen auflisten (paginiert, filterbar über ?status= und ?per_page=, max. 100).', 'ability' => 'press-releases:read'], ['method' => 'POST', 'path' => '/press-releases', 'desc' => 'Neue Mitteilung anlegen — immer als Entwurf (Status draft).', 'ability' => 'press-releases:write'], ['method' => 'GET', 'path' => '/press-releases/{id}', 'desc' => 'Eine Mitteilung inkl. Firma, Rubrik und Bildern abrufen.', 'ability' => 'press-releases:read'], ['method' => 'PATCH', 'path' => '/press-releases/{id}', 'desc' => 'Mitteilung ändern — nur im Status draft oder rejected.', 'ability' => 'press-releases:write'], ['method' => 'POST', 'path' => '/press-releases/{id}/submit', 'desc' => 'Zur Inhaltsprüfung einreichen — der einzige Weg Richtung Veröffentlichung.', 'ability' => 'press-releases:write'], ['method' => 'DELETE', 'path' => '/press-releases/{id}', 'desc' => 'Mitteilung löschen — veröffentlichte Mitteilungen sind ausgenommen.', 'ability' => 'press-releases:write'], ], ], [ 'group' => 'Bilder', 'items' => [ ['method' => 'GET', 'path' => '/press-releases/{id}/images', 'desc' => 'Bilder einer Mitteilung auflisten.', 'ability' => 'press-releases:read'], ['method' => 'POST', 'path' => '/press-releases/{id}/images', 'desc' => 'Bild hochladen (multipart/form-data) — nur bei draft/rejected.', 'ability' => 'press-release-images:write'], ['method' => 'DELETE', 'path' => '/press-release-images/{imageId}', 'desc' => 'Bild entfernen — nur bei draft/rejected.', 'ability' => 'press-release-images:write'], ], ], [ 'group' => 'Stammdaten', 'items' => [ ['method' => 'GET', 'path' => '/companies', 'desc' => 'Eigene Firmenprofile (Newsrooms) auflisten.', 'ability' => 'companies:read'], ['method' => 'GET', 'path' => '/companies/{id}', 'desc' => 'Ein Firmenprofil abrufen.', 'ability' => 'companies:read'], ['method' => 'GET', 'path' => '/categories', 'desc' => 'Aktive Rubriken inkl. Übersetzungen — liefert die category_id für neue Mitteilungen.', 'ability' => 'press-releases:read'], ], ], ]; $pressReleaseFields = [ ['name' => 'company_id', 'type' => 'integer', 'required' => true, 'desc' => 'ID eines eigenen Firmenprofils — bestimmt Newsroom und Portal.'], ['name' => 'category_id', 'type' => 'integer', 'required' => true, 'desc' => 'Rubrik (siehe GET /categories).'], ['name' => 'language', 'type' => 'string', 'required' => true, 'desc' => 'Sprachcode, zwei Zeichen: de oder en.'], ['name' => 'title', 'type' => 'string', 'required' => true, 'desc' => 'Überschrift, max. 255 Zeichen.'], ['name' => 'text', 'type' => 'string', 'required' => true, 'desc' => 'Inhalt. Erlaubtes HTML: p, br, h2, h3, strong, em, ul, ol, li, blockquote, a — alles andere wird entfernt.'], ['name' => 'backlink_url', 'type' => 'string', 'required' => false, 'desc' => 'Link zur Quelle/Website, max. 255 Zeichen.'], ['name' => 'keywords', 'type' => 'string', 'required' => false, 'desc' => 'Schlagworte, kommagetrennt, max. 255 Zeichen.'], ['name' => 'teaser_begin / teaser_end', 'type' => 'integer', 'required' => false, 'desc' => 'Zeichen-Offsets für den Teaser-Ausschnitt.'], ['name' => 'no_export', 'type' => 'boolean', 'required' => false, 'desc' => 'Mitteilung von Feeds/Exporten ausnehmen.'], ]; $imageFields = [ ['name' => 'image', 'type' => 'file', 'required' => true, 'desc' => 'JPG, PNG oder WebP, max. 8 MB.'], ['name' => 'title', 'type' => 'string', 'required' => false, 'desc' => 'Bildtitel, max. 120 Zeichen.'], ['name' => 'description', 'type' => 'string', 'required' => false, 'desc' => 'Beschreibung, max. 500 Zeichen.'], ['name' => 'copyright', 'type' => 'string', 'required' => false, 'desc' => 'Urheberangabe, max. 255 Zeichen.'], ['name' => 'is_preview', 'type' => 'boolean', 'required' => false, 'desc' => 'Als Vorschaubild setzen (ersetzt ein vorhandenes).'], ]; $statusCodes = [ ['code' => '200 / 201 / 204', 'desc' => 'Erfolg — Abruf, Ressource erstellt bzw. gelöscht.'], ['code' => '401', 'desc' => 'Kein oder ungültiger API-Token.'], ['code' => '402', 'desc' => 'Einreichen erfordert eine aktive Buchung (Tarif oder Einzel-PM).'], ['code' => '403', 'desc' => 'Token-Berechtigung fehlt oder die Ressource gehört nicht zu Ihrem Konto.'], ['code' => '409', 'desc' => 'Statuskonflikt — z. B. Bearbeiten einer bereits veröffentlichten Mitteilung.'], ['code' => '422', 'desc' => 'Validierungsfehler oder Kontingent-/Richtlinienverstoß (Details im Body).'], ['code' => '429', 'desc' => 'Rate-Limit erreicht: 60 Anfragen pro Minute je Token (Header X-RateLimit-*).'], ]; $methodColors = [ 'GET' => 'text-[#1F6B3F] bg-[#E7F2EA]', 'POST' => 'text-[#8A4B12] bg-[#F7EBDD]', 'PATCH' => 'text-[#6B4FA1] bg-[#EEE9F7]', 'DELETE' => 'text-[#A13030] bg-[#F7E5E5]', ]; @endphp @section('content') {{-- Überblick + Authentifizierung --}}

Grundlagen

Die API v1 ist ein RESTful Web Service mit JSON-Responses. Basis-URL: {{ $apiBase }}. Eine über die API angelegte Mitteilung ist immer ein Entwurf; veröffentlicht wird sie erst nach dem Einreichen über die Submit-Route und der anschließenden Inhaltsprüfung — sie erscheint dann wie jede andere Mitteilung auf beiden Portalen.

Authentifizierung

Alle Anfragen benötigen einen persönlichen API-Token als Bearer-Header: Authorization: Bearer <token>. Jeder Token trägt Berechtigungen (z. B. press-releases:write), die den Zugriff auf die jeweiligen Endpunkte steuern. Tokens erstellen und widerrufen Sie selbst in Ihrem Publisher-Konto unter „API-Tokens" — Voraussetzung ist eine aktive Buchung (Tarif oder Einzel-Pressemitteilung). Bestandskunden der Altportale: Ihre bisherigen API-Schlüssel wurden übernommen und funktionieren weiter — sowohl als Bearer-Token als auch in der alten Form (X-ApiKey-Header) und auf den dokumentierten /service/…-Pfaden. Für neue Integrationen empfehlen wir die aktuellen /api/v1/…-Endpunkte mit Bearer-Token.

{{-- Endpunkte --}}

Endpunkte

@foreach ($endpoints as $group)

{{ $group['group'] }}

@foreach ($group['items'] as $endpoint)
{{ $endpoint['method'] }}
{{ $endpoint['path'] }}

{{ $endpoint['desc'] }} · Berechtigung: {{ $endpoint['ability'] }}

@endforeach
@endforeach
{{-- Felder --}}

Felder einer Pressemitteilung

@foreach ($pressReleaseFields as $field) @endforeach
Feld Typ Pflicht Beschreibung
{{ $field['name'] }} {{ $field['type'] }} {{ $field['required'] ? 'ja' : '—' }} {{ $field['desc'] }}

Felder eines Bild-Uploads

@foreach ($imageFields as $field) @endforeach
Feld Typ Pflicht Beschreibung
{{ $field['name'] }} {{ $field['type'] }} {{ $field['required'] ? 'ja' : '—' }} {{ $field['desc'] }}
{{-- Workflow-Beispiel --}}

Schneller Einstieg

Der typische Ablauf: Entwurf anlegen, Bild hochladen, zur Prüfung einreichen.

# 1. Entwurf anlegen
curl -X POST {{ $apiBase }}/press-releases \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "company_id": 1,
    "category_id": 2,
    "language": "de",
    "title": "Neue Produktankündigung",
    "text": "<p>Unser neues Produkt …</p>"
  }'

# 2. Bild hochladen (multipart)
curl -X POST {{ $apiBase }}/press-releases/123/images \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -F "image=@pressefoto.jpg" \
  -F "copyright=Mustermann GmbH" \
  -F "is_preview=1"

# 3. Zur Inhaltsprüfung einreichen
curl -X POST {{ $apiBase }}/press-releases/123/submit \
  -H "Authorization: Bearer YOUR_API_TOKEN"

Maschinenlesbare Referenz: OpenAPI-Spezifikation (YAML).

{{-- Statuscodes --}}

HTTP-Statuscodes

@foreach ($statusCodes as $status) @endforeach
Code Bedeutung
{{ $status['code'] }} {{ $status['desc'] }}
{{-- CTA --}}

API-Token erstellen

Tokens verwalten Sie selbst im Publisher-Konto. Bei Fragen zur Anbindung hilft der Support: {{ $apiContactEmail }}

@endsection