feat: initial openapi content (v0.1.0)
- Vollständige OpenAPI 3.1 Spezifikation - Alle Endpoints, Schemas, Webhooks, Error-Responses - Beispiel-Requests für minimal/async/webhook-Modi - Initiale CHANGELOG.md
This commit is contained in:
parent
2db26ced18
commit
b13fba1d75
5 changed files with 720 additions and 49 deletions
18
CHANGELOG.md
Normal file
18
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
# Changelog
|
||||
|
||||
Alle nennenswerten Änderungen an der OpenAPI-Spec werden hier dokumentiert.
|
||||
Format orientiert sich an [Keep a Changelog](https://keepachangelog.com/de/1.1.0/).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.0.0] — 2026-04-25
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
- Initiale Veröffentlichung der OpenAPI 3.1 Spezifikation
|
||||
- Endpoints: `POST /captures`, `GET /captures`, `GET /captures/{id}`,
|
||||
`GET /captures/{id}/pdf`, `POST /verify`, `GET /usage`
|
||||
- Drei Aufruf-Modi: `sync`, `async`, `webhook`
|
||||
- Webhook-Events: `capture.ready`, `capture.failed`
|
||||
- Komplette Schema-Definitionen für `Capture`, `VerifyResult`, `Usage`, `Error`
|
||||
- Beispiel-Requests für minimal, async-mit-Referenz, und webhook-mit-Co-Branding
|
||||
20
LICENSE
20
LICENSE
|
|
@ -1,9 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2026 hightrusted
|
||||
Copyright (c) 2026 hightrusted GmbH
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
|
|
|||
79
README.md
79
README.md
|
|
@ -1,6 +1,6 @@
|
|||
# hightrusted CAPTURE — OpenAPI Specification
|
||||
|
||||
> **Status:** v0.1 Preview — API stabil, Spec ist Single Source of Truth für alle SDKs
|
||||
> **Status:** v1.0.0 — Single Source of Truth für alle SDKs
|
||||
|
||||
OpenAPI 3.1 Spezifikation der [hightrusted CAPTURE API](https://capture.hightrusted.net) —
|
||||
forensische Web-Captures mit qualifiziertem Zeitstempel nach RFC 3161 / eIDAS Art. 41.
|
||||
|
|
@ -8,16 +8,14 @@ forensische Web-Captures mit qualifiziertem Zeitstempel nach RFC 3161 / eIDAS Ar
|
|||
Diese Spec ist die **maschinenlesbare Referenz**, aus der wir alle anderen Artefakte
|
||||
ableiten: SDKs, Client-Bibliotheken, Postman-Collection, gerenderte Doku.
|
||||
|
||||
**Made in Germany.** Server in Deutschland. DSGVO-nativ. Kein US-Cloud-Anbieter
|
||||
in der Verarbeitungskette.
|
||||
**Made in Germany.** Server in Deutschland. DSGVO-nativ.
|
||||
|
||||
## Inhalt
|
||||
|
||||
- `openapi.yaml` — die OpenAPI 3.1 Spec
|
||||
- `examples/` — Beispiel-Requests und -Responses für jeden Endpoint
|
||||
- `CHANGELOG.md` — Versions-History der Spec
|
||||
- `CHANGELOG.md` — Versions-History
|
||||
|
||||
## Validierung
|
||||
## Validieren
|
||||
|
||||
```bash
|
||||
# Mit redocly cli
|
||||
|
|
@ -32,25 +30,47 @@ npx @stoplight/spectral-cli lint openapi.yaml
|
|||
```bash
|
||||
# HTML-Doku mit Redoc bauen
|
||||
npx @redocly/cli build-docs openapi.yaml -o ./docs/index.html
|
||||
```
|
||||
|
||||
Ergebnis: statische HTML-Datei mit kompletter API-Doku, die du auf jedem Webserver
|
||||
ablegen kannst.
|
||||
# Mit Swagger UI lokal anzeigen
|
||||
npx swagger-ui-watcher openapi.yaml
|
||||
```
|
||||
|
||||
## Client-Generierung
|
||||
|
||||
Aus dieser Spec lassen sich automatisch Clients für 50+ Sprachen erzeugen
|
||||
(siehe https://openapi-generator.tech). Wir pflegen offizielle Clients für
|
||||
Python, Node.js und PHP — siehe [Verwandte Repositorys](#verwandte-repositorys).
|
||||
Aus dieser Spec lassen sich automatisch Clients für 50+ Sprachen erzeugen:
|
||||
|
||||
```bash
|
||||
# Beispiel: Go-Client erzeugen
|
||||
openapi-generator-cli generate \
|
||||
npx @openapitools/openapi-generator-cli generate \
|
||||
-i openapi.yaml \
|
||||
-g go \
|
||||
-o ./clients/go
|
||||
```
|
||||
|
||||
Wir pflegen offizielle Clients **handgeschrieben** für Python, Node.js und PHP
|
||||
— sie sind idiomatischer als generierte Clients und haben getestete
|
||||
Webhook-Verifikation, typisierte Exceptions und ergonomische APIs.
|
||||
|
||||
## Endpoints (Übersicht)
|
||||
|
||||
| Endpoint | Beschreibung | Auth |
|
||||
|--------------------------------|--------------------------------------------|--------|
|
||||
| `POST /captures` | Capture erstellen (sync/async/webhook) | Bearer |
|
||||
| `GET /captures` | Captures auflisten (paginiert) | Bearer |
|
||||
| `GET /captures/{id}` | Status & Metadaten abrufen | Bearer |
|
||||
| `GET /captures/{id}/pdf` | PDF herunterladen | Bearer |
|
||||
| `POST /verify` | Verifizieren (per ID, URL, oder PDF) | — |
|
||||
| `GET /usage` | eigenen Verbrauch abrufen | Bearer |
|
||||
|
||||
## Webhook-Events
|
||||
|
||||
| Event | Wann |
|
||||
|-------------------|-----------------------------------------|
|
||||
| `capture.ready` | PDF und Zeitstempel fertig |
|
||||
| `capture.failed` | Fehler beim Rendern oder TSA |
|
||||
|
||||
Webhook-Retry: 3 Versuche mit exponentiellem Backoff (1 min, 5 min, 30 min).
|
||||
Signaturverifikation per HMAC-SHA-256 (`X-Hightrusted-Signature: sha256=...`).
|
||||
|
||||
## Versionierung
|
||||
|
||||
API-Versionen sind im Pfad: `/api/v1/...`
|
||||
|
|
@ -61,25 +81,6 @@ API-Versionen sind im Pfad: `/api/v1/...`
|
|||
Diese OpenAPI-Spec verfolgt die API 1:1. Änderungen sind in `CHANGELOG.md`
|
||||
nachvollziehbar.
|
||||
|
||||
## Endpoints (Übersicht)
|
||||
|
||||
| Endpoint | Beschreibung | Auth |
|
||||
|--------------------------------|---------------------------------------|--------|
|
||||
| `POST /captures` | Capture erstellen (sync/async/webhook)| Bearer |
|
||||
| `GET /captures/{id}` | Status & Metadaten abrufen | Bearer |
|
||||
| `GET /captures/{id}/pdf` | PDF herunterladen | Bearer |
|
||||
| `GET /captures/{id}/verify` | Capture verifizieren | — |
|
||||
| `GET /usage` | eigenen Verbrauch abrufen | Bearer |
|
||||
|
||||
## Webhook-Events
|
||||
|
||||
| Event | Wann |
|
||||
|-------------------|-----------------------------------------|
|
||||
| `capture.ready` | PDF und Zeitstempel fertig |
|
||||
| `capture.failed` | Fehler beim Rendern oder TSA |
|
||||
|
||||
Webhook-Retry: 3 Versuche mit exponentiellem Backoff (1 min, 5 min, 30 min).
|
||||
|
||||
## Verwandte Repositorys
|
||||
|
||||
**Im selben Produkt** ([`hightrusted-capture`](https://git.hightrusted.net/hightrusted-capture)):
|
||||
|
|
@ -92,20 +93,20 @@ Webhook-Retry: 3 Versuche mit exponentiellem Backoff (1 min, 5 min, 30 min).
|
|||
|
||||
**Plattform-übergreifend** ([`hightrusted`](https://git.hightrusted.net/hightrusted)):
|
||||
|
||||
- [`platform`](https://git.hightrusted.net/hightrusted/platform) — Plattform-Übersicht, Architektur, Produkt-Liste
|
||||
- [`developer-portal`](https://git.hightrusted.net/hightrusted/developer-portal) — gemeinsame Konventionen, Auth, Errors, Rate-Limits
|
||||
- [`compliance`](https://git.hightrusted.net/hightrusted/compliance) — DSGVO, AGB-Templates, Whitepaper
|
||||
- [`platform`](https://git.hightrusted.net/hightrusted/platform)
|
||||
- [`developer-portal`](https://git.hightrusted.net/hightrusted/developer-portal)
|
||||
- [`compliance`](https://git.hightrusted.net/hightrusted/compliance)
|
||||
|
||||
## Support
|
||||
|
||||
- **Doku:** https://capture.hightrusted.net/api/docs
|
||||
- **Status-Page:** https://status.hightrusted.net
|
||||
- **Status:** https://status.hightrusted.net
|
||||
- **Developer Support:** developers@hightrusted.net
|
||||
- **Sicherheitslücken:** siehe [SECURITY.md](./SECURITY.md)
|
||||
|
||||
## Lizenz
|
||||
|
||||
MIT — siehe [LICENSE](./LICENSE).
|
||||
MIT — siehe [LICENSE](./LICENSE). Spec und Beispiele dürfen frei für eigene
|
||||
Implementierungen genutzt werden.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,3 @@ Während der `v0.x`-Phase werden nur die jeweils aktuellste Minor-Version und
|
|||
deren letzte zwei Patch-Versionen aktiv mit Sicherheits-Updates versorgt.
|
||||
|
||||
Ab `v1.0` gilt: aktuelle Major + vorherige Major (12 Monate Übergangsfrist).
|
||||
|
||||
## Out of Scope
|
||||
|
||||
Diese Policy gilt für die SDKs in diesem Repository und die zugehörige
|
||||
hightrusted CAPTURE API. Für Schwachstellen in anderen hightrusted-Produkten
|
||||
(SIGN, ID, MEET, PAY, …) gilt jeweils die dortige `SECURITY.md`.
|
||||
|
|
|
|||
646
openapi.yaml
Normal file
646
openapi.yaml
Normal file
|
|
@ -0,0 +1,646 @@
|
|||
openapi: 3.1.0
|
||||
info:
|
||||
title: hightrusted CAPTURE API
|
||||
version: "1.0.0"
|
||||
summary: Forensische Web-Captures mit qualifiziertem EU-Zeitstempel
|
||||
description: |
|
||||
Forensische Web-Captures mit qualifiziertem EU-Zeitstempel nach
|
||||
RFC 3161 / eIDAS Art. 41.
|
||||
|
||||
Die API nimmt eine URL entgegen, rendert die Seite vollständig (inkl.
|
||||
JavaScript), liefert sie als PDF/A-3 zurück und versieht das Ergebnis mit
|
||||
einem qualifizierten Zeitstempel. Das Ergebnis ist gerichtsverwertbar und
|
||||
Jahre später noch verifizierbar — auch nachdem die Original-Seite längst
|
||||
offline ist.
|
||||
|
||||
**Drei Aufruf-Modi:**
|
||||
- `sync` (Default) — Server wartet bis zu 30 s und liefert das fertige Capture
|
||||
- `async` — Server liefert sofort `id`, Client pollt `GET /captures/{id}`
|
||||
- `webhook` — Server liefert das fertige Capture per HTTP-POST an `webhook_url`
|
||||
|
||||
**Authentifizierung:** Bearer-Token mit API-Key. Erzeugung im Dashboard:
|
||||
https://capture.hightrusted.net/dashboard/api-keys
|
||||
|
||||
**Made in Germany.** Server in Deutschland. DSGVO-nativ. eIDAS-konform.
|
||||
Kein US-Cloud-Anbieter in der Verarbeitungskette.
|
||||
contact:
|
||||
name: hightrusted Developer Support
|
||||
email: developers@hightrusted.net
|
||||
url: https://capture.hightrusted.net/api
|
||||
license:
|
||||
name: hightrusted API Terms
|
||||
url: https://hightrusted.net/legal/api-terms
|
||||
termsOfService: https://hightrusted.net/legal/terms
|
||||
|
||||
servers:
|
||||
- url: https://capture.hightrusted.net/api/v1
|
||||
description: Production
|
||||
|
||||
security:
|
||||
- bearerAuth: []
|
||||
|
||||
tags:
|
||||
- name: Captures
|
||||
description: Capture-Erstellung, -Status, -Download
|
||||
- name: Verify
|
||||
description: Verifikation gespeicherter Captures (kostenlos, ohne Quota)
|
||||
- name: Account
|
||||
description: Verbrauch und Quota-Status
|
||||
|
||||
paths:
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
/captures:
|
||||
post:
|
||||
tags: [Captures]
|
||||
summary: Capture erstellen
|
||||
operationId: createCapture
|
||||
description: |
|
||||
Erstellt eine forensische Web-Capture in einem von drei Modi:
|
||||
|
||||
- **sync** (Default): wartet bis zu 30 s und liefert das fertige PDF
|
||||
- **async**: liefert sofort `id`, Client pollt `GET /captures/{id}`
|
||||
- **webhook**: Server liefert das fertige Capture per HTTP-POST
|
||||
|
||||
**Shortlink-Auflösung:** `maps.app.goo.gl`-Links und ähnliche Shortlinks
|
||||
werden automatisch aufgelöst. Das Originalfeld `url` bleibt für die
|
||||
Nachweisbarkeit erhalten.
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CaptureRequest"
|
||||
examples:
|
||||
minimal:
|
||||
summary: Minimal — synchron
|
||||
value:
|
||||
url: https://example.com/article/123
|
||||
async_with_reference:
|
||||
summary: Asynchron mit Referenz
|
||||
value:
|
||||
url: https://example.com/page
|
||||
mode: async
|
||||
reference: case-2026-001
|
||||
webhook_full:
|
||||
summary: Webhook mit Co-Branding
|
||||
value:
|
||||
url: https://example.com/page
|
||||
mode: webhook
|
||||
webhook_url: https://api.deinedomain.de/capture-callback
|
||||
reference: case-2026-001
|
||||
viewport:
|
||||
width: 1920
|
||||
height: 1080
|
||||
co_branding:
|
||||
logo_url: https://kanzlei-mueller.de/logo.png
|
||||
footer_text: Kanzlei Müller — Beweissicherung
|
||||
responses:
|
||||
"200":
|
||||
description: Synchron — fertiges Capture
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Capture"
|
||||
"202":
|
||||
description: Asynchron / Webhook — Capture in Bearbeitung
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/CaptureQueued"
|
||||
"400":
|
||||
$ref: "#/components/responses/BadRequest"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"402":
|
||||
$ref: "#/components/responses/QuotaExceeded"
|
||||
"422":
|
||||
$ref: "#/components/responses/UnreachableUrl"
|
||||
"429":
|
||||
$ref: "#/components/responses/RateLimited"
|
||||
"503":
|
||||
$ref: "#/components/responses/TsaUnavailable"
|
||||
|
||||
get:
|
||||
tags: [Captures]
|
||||
summary: Eigene Captures auflisten
|
||||
operationId: listCaptures
|
||||
description: |
|
||||
Listet die Captures des Accounts, paginiert per Cursor.
|
||||
parameters:
|
||||
- in: query
|
||||
name: status
|
||||
schema:
|
||||
type: string
|
||||
enum: [queued, rendering, ready, failed]
|
||||
description: Nur Captures mit diesem Status
|
||||
- in: query
|
||||
name: reference
|
||||
schema:
|
||||
type: string
|
||||
description: Filter auf Custom-Reference (z.B. Mandanten-ID)
|
||||
- in: query
|
||||
name: limit
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
maximum: 100
|
||||
default: 25
|
||||
- in: query
|
||||
name: cursor
|
||||
schema:
|
||||
type: string
|
||||
description: Cursor aus vorheriger Response
|
||||
responses:
|
||||
"200":
|
||||
description: Paginierte Liste
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Capture"
|
||||
next_cursor:
|
||||
type: string
|
||||
nullable: true
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
/captures/{id}:
|
||||
get:
|
||||
tags: [Captures]
|
||||
summary: Capture-Status / Detail
|
||||
operationId: getCapture
|
||||
description: |
|
||||
Liefert das Capture-Objekt mit aktuellem `status`. Solange `queued` oder
|
||||
`rendering`, fehlen `pdf_url` und `timestamp`.
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/CaptureId"
|
||||
responses:
|
||||
"200":
|
||||
description: Capture-Detail
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Capture"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"404":
|
||||
$ref: "#/components/responses/CaptureNotFound"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
/captures/{id}/pdf:
|
||||
get:
|
||||
tags: [Captures]
|
||||
summary: PDF herunterladen
|
||||
operationId: downloadCapturePdf
|
||||
description: |
|
||||
Liefert PDF/A-3 mit eingebettetem RFC-3161-Zeitstempel.
|
||||
Verfügbar erst, wenn `status: ready`.
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/CaptureId"
|
||||
responses:
|
||||
"200":
|
||||
description: PDF-Datei
|
||||
headers:
|
||||
Content-Disposition:
|
||||
schema:
|
||||
type: string
|
||||
example: attachment; filename="capture_550e....pdf"
|
||||
content:
|
||||
application/pdf:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
"404":
|
||||
$ref: "#/components/responses/CaptureNotFound"
|
||||
"409":
|
||||
description: Capture noch nicht fertig
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
/verify:
|
||||
post:
|
||||
tags: [Verify]
|
||||
summary: Capture / PDF verifizieren
|
||||
operationId: verifyCapture
|
||||
description: |
|
||||
Prüft, ob ein Capture / PDF noch gültig ist (Hash, Zeitstempel,
|
||||
Audit-Chain).
|
||||
|
||||
**Kostenlos für alle Tarife. Keine Quota-Belastung.**
|
||||
|
||||
Drei Eingabe-Modi:
|
||||
- Per Capture-ID (`source: "550e..."`)
|
||||
- Per Verify-URL (`source: "https://verify.hightrusted.net/c/..."`)
|
||||
- Per PDF-Upload (multipart/form-data, Feld `pdf`)
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [source]
|
||||
properties:
|
||||
source:
|
||||
type: string
|
||||
description: Capture-ID oder Verify-URL
|
||||
examples:
|
||||
by_id:
|
||||
summary: Per Capture-ID
|
||||
value:
|
||||
source: 550e8400-e29b-41d4-a716-446655440000
|
||||
by_url:
|
||||
summary: Per Verify-URL
|
||||
value:
|
||||
source: https://verify.hightrusted.net/c/550e...
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
pdf:
|
||||
type: string
|
||||
format: binary
|
||||
description: PDF-Datei zur lokalen Verifikation
|
||||
responses:
|
||||
"200":
|
||||
description: Verifikations-Ergebnis
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/VerifyResult"
|
||||
"404":
|
||||
description: Quelle nicht auffindbar
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
/usage:
|
||||
get:
|
||||
tags: [Account]
|
||||
summary: Eigener Verbrauch
|
||||
operationId: getUsage
|
||||
description: Aktueller Verbrauch und Restkontingent für die laufende Periode.
|
||||
responses:
|
||||
"200":
|
||||
description: Verbrauchs-Status
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Usage"
|
||||
"401":
|
||||
$ref: "#/components/responses/Unauthorized"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════════
|
||||
components:
|
||||
securitySchemes:
|
||||
bearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: ht_live_xxx | ht_test_xxx
|
||||
|
||||
parameters:
|
||||
CaptureId:
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 550e8400-e29b-41d4-a716-446655440000
|
||||
description: ID des Captures
|
||||
|
||||
schemas:
|
||||
# ─────────────────────────────────────────────────────────
|
||||
CaptureRequest:
|
||||
type: object
|
||||
required: [url]
|
||||
properties:
|
||||
url:
|
||||
type: string
|
||||
format: uri
|
||||
description: Zu erfassende URL. Pflicht.
|
||||
example: https://example.com/article/123
|
||||
mode:
|
||||
type: string
|
||||
enum: [sync, async, webhook]
|
||||
default: sync
|
||||
webhook_url:
|
||||
type: string
|
||||
format: uri
|
||||
description: Pflicht bei `mode=webhook`
|
||||
reference:
|
||||
type: string
|
||||
maxLength: 128
|
||||
description: Eigene Referenz (Mandanten-ID, Akten-Nr.)
|
||||
viewport:
|
||||
type: object
|
||||
properties:
|
||||
width:
|
||||
type: integer
|
||||
minimum: 360
|
||||
maximum: 2560
|
||||
default: 1280
|
||||
height:
|
||||
type: integer
|
||||
minimum: 480
|
||||
maximum: 4096
|
||||
default: 800
|
||||
wait_until:
|
||||
type: string
|
||||
enum: [load, domcontentloaded, networkidle]
|
||||
default: networkidle
|
||||
full_page:
|
||||
type: boolean
|
||||
default: true
|
||||
description: Komplette Seite scrollen
|
||||
co_branding:
|
||||
type: object
|
||||
description: Eigenes Logo & Footer im PDF (ab Tarif Growth)
|
||||
properties:
|
||||
logo_url:
|
||||
type: string
|
||||
format: uri
|
||||
footer_text:
|
||||
type: string
|
||||
maxLength: 200
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
Capture:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
example: 550e8400-e29b-41d4-a716-446655440000
|
||||
status:
|
||||
type: string
|
||||
enum: [queued, rendering, ready, failed]
|
||||
url:
|
||||
type: string
|
||||
format: uri
|
||||
description: Aufgelöste End-URL (nach Shortlink-Auflösung)
|
||||
url_input:
|
||||
type: string
|
||||
format: uri
|
||||
description: Vom Caller übergebene URL (für die Beweisführung)
|
||||
reference:
|
||||
type: string
|
||||
nullable: true
|
||||
pdf_url:
|
||||
type: string
|
||||
format: uri
|
||||
nullable: true
|
||||
description: Authentifizierter Download-Endpoint
|
||||
verify_url:
|
||||
type: string
|
||||
format: uri
|
||||
description: Öffentliche Verifikations-URL
|
||||
timestamp:
|
||||
$ref: "#/components/schemas/Timestamp"
|
||||
document_hash:
|
||||
type: string
|
||||
example: sha256:a3f2...
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
completed_at:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
required: [id, status, created_at]
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
CaptureQueued:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
status:
|
||||
type: string
|
||||
enum: [queued]
|
||||
poll_url:
|
||||
type: string
|
||||
format: uri
|
||||
description: Endpoint für Status-Polling (nur bei `mode=async`)
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
required: [id, status, created_at]
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
Timestamp:
|
||||
type: object
|
||||
properties:
|
||||
tsa:
|
||||
type: string
|
||||
example: open-tsa.eu
|
||||
issued_at:
|
||||
type: string
|
||||
format: date-time
|
||||
algorithm:
|
||||
type: string
|
||||
example: SHA-256
|
||||
serial:
|
||||
type: string
|
||||
example: "0x4F8B..."
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
VerifyResult:
|
||||
type: object
|
||||
properties:
|
||||
valid:
|
||||
type: boolean
|
||||
capture_id:
|
||||
type: string
|
||||
format: uuid
|
||||
document_hash:
|
||||
type: string
|
||||
timestamp:
|
||||
type: object
|
||||
properties:
|
||||
tsa:
|
||||
type: string
|
||||
issued_at:
|
||||
type: string
|
||||
format: date-time
|
||||
valid:
|
||||
type: boolean
|
||||
chain_valid:
|
||||
type: boolean
|
||||
audit_log:
|
||||
type: object
|
||||
properties:
|
||||
present:
|
||||
type: boolean
|
||||
chain_valid:
|
||||
type: boolean
|
||||
anchored_in_open_tsa:
|
||||
type: boolean
|
||||
details:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
check:
|
||||
type: string
|
||||
example: tsr_signature
|
||||
status:
|
||||
type: string
|
||||
enum: [pass, fail, warn]
|
||||
message:
|
||||
type: string
|
||||
required: [valid]
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
Usage:
|
||||
type: object
|
||||
properties:
|
||||
plan:
|
||||
type: string
|
||||
example: growth
|
||||
period_start:
|
||||
type: string
|
||||
format: date
|
||||
period_end:
|
||||
type: string
|
||||
format: date
|
||||
included_calls:
|
||||
type: integer
|
||||
used_calls:
|
||||
type: integer
|
||||
overage_calls:
|
||||
type: integer
|
||||
overage_cost_eur:
|
||||
type: number
|
||||
format: float
|
||||
rate_limit:
|
||||
type: object
|
||||
properties:
|
||||
per_minute:
|
||||
type: integer
|
||||
current_minute:
|
||||
type: integer
|
||||
|
||||
# ─────────────────────────────────────────────────────────
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
error:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: string
|
||||
example: quota_exceeded
|
||||
message:
|
||||
type: string
|
||||
request_id:
|
||||
type: string
|
||||
example: req_4xK7p2nQ8mR9
|
||||
required: [code, message, request_id]
|
||||
required: [error]
|
||||
|
||||
responses:
|
||||
BadRequest:
|
||||
description: Validierungsfehler
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
Unauthorized:
|
||||
description: API-Key fehlt, abgelaufen oder widerrufen
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
QuotaExceeded:
|
||||
description: Monats-Quota voll, kein PAYG aktiv
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
CaptureNotFound:
|
||||
description: Capture-ID existiert nicht oder gehört zu fremdem Key
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
UnreachableUrl:
|
||||
description: Quellseite konnte nicht geladen werden
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
RateLimited:
|
||||
description: |
|
||||
Zu viele Anfragen pro Minute. Header `Retry-After` beachten.
|
||||
headers:
|
||||
Retry-After:
|
||||
schema:
|
||||
type: integer
|
||||
description: Sekunden bis zum nächsten erlaubten Request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
TsaUnavailable:
|
||||
description: |
|
||||
open-tsa.eu temporär nicht erreichbar. Automatischer Retry empfohlen.
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Error"
|
||||
|
||||
webhooks:
|
||||
capture.ready:
|
||||
post:
|
||||
tags: [Webhook-Events]
|
||||
summary: Capture fertig (PDF und Zeitstempel verfügbar)
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
event:
|
||||
type: string
|
||||
enum: [capture.ready]
|
||||
capture:
|
||||
$ref: "#/components/schemas/Capture"
|
||||
required: [event, capture]
|
||||
responses:
|
||||
"200":
|
||||
description: Webhook empfangen
|
||||
|
||||
capture.failed:
|
||||
post:
|
||||
tags: [Webhook-Events]
|
||||
summary: Capture fehlgeschlagen
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
event:
|
||||
type: string
|
||||
enum: [capture.failed]
|
||||
capture:
|
||||
$ref: "#/components/schemas/Capture"
|
||||
error:
|
||||
$ref: "#/components/schemas/Error"
|
||||
required: [event, capture]
|
||||
responses:
|
||||
"200":
|
||||
description: Webhook empfangen
|
||||
Loading…
Add table
Reference in a new issue