- API-Klasse mit allen CRUD-Operationen für Bookmarks - Login/Authentifizierung mit Bearer Token - Bookmarks abrufen (Liste und Details) - Artikel-Inhalt abrufen - DTO-Strukturen in separate Dateien aufgeteilt - UserDto für Authentifizierung - BookmarkDto für Bookmark-Listen - BookmarkDetailDto mit vollständigen Metadaten - MVVM-Architektur mit @Observable - SettingsViewModel für Anmeldung - BookmarksViewModel für Bookmark-Verwaltung - SwiftUI Views mit modernem Design - SettingsView mit Eingabefeldern und Validierung - BookmarksView mit Pull-to-Refresh und Leerzustand - MainTabView als Navigation - Use Case Pattern implementiert - LoginUseCase für Authentifizierung - GetBookmarksUseCase für Datenabfrage - DefaultUseCaseFactory für Dependency Injection - Fehlerbehandlung und Loading States - Protocol-basierte Architektur für bessere Testbarkeit
340 lines
8.1 KiB
YAML
340 lines
8.1 KiB
YAML
---
|
|
# SPDX-FileCopyrightText: © 2023 Olivier Meunier <olivier@neokraft.net>
|
|
#
|
|
# SPDX-License-Identifier: AGPL-3.0-only
|
|
|
|
openapi: 3.0.0
|
|
info:
|
|
version: 1.0.0
|
|
title: Readeck API
|
|
description: |
|
|
# Introduction
|
|
|
|
The Readeck API provides REST endpoints that can be used for any purpose, should it be a
|
|
mobile application, a script, you name it.
|
|
|
|
## API Endpoint
|
|
|
|
You can access this API on `__BASE_URI__`.
|
|
|
|
Most of your requests and responses are using JSON as the exchange format.
|
|
|
|
## Authentication
|
|
|
|
To use the API, you first need to [create an authentication token](../profile/tokens). You can
|
|
then use your new token using the `Bearer` HTTP authorization scheme.
|
|
|
|
For example, you first request will look like:
|
|
|
|
```sh
|
|
curl -H "Authorization: Bearer <TOKEN>" __BASE_URI__/bookmarks
|
|
```
|
|
|
|
Or, in NodeJS:
|
|
|
|
```js
|
|
fetch("__BASE_URI__/bookmarks", {
|
|
headers: {
|
|
"Authorization": "Bearer <TOKEN>",
|
|
},
|
|
})
|
|
```
|
|
|
|
## First time authentication
|
|
|
|
While you can create an authentication token from Readeck, you can also get one directly from
|
|
the API. This provides a mechanism to ask for user credentials and obtain a token for your app
|
|
only.
|
|
|
|
Please refer to [POST /auth](#post-/auth) for more information.
|
|
|
|
## Test the API
|
|
|
|
On this documentation, you can test every route.
|
|
|
|
If you don't provide an API token in [Authentication](#auth), you can still test all the routes
|
|
but note that the given curl examples only work with an API token.
|
|
|
|
|
|
servers:
|
|
- url: __BASE_URI__
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearer:
|
|
type: http
|
|
scheme: Bearer
|
|
|
|
schemas:
|
|
$merge:
|
|
- "types.yaml#.schemas"
|
|
- "bookmarks/types.yaml#.schemas"
|
|
- "profile/types.yaml#.schemas"
|
|
|
|
security:
|
|
- bearer: []
|
|
|
|
tags:
|
|
- name: user profile
|
|
- name: bookmarks
|
|
- name: bookmark export
|
|
- name: bookmark sharing
|
|
- name: bookmark labels
|
|
- name: bookmark highlights
|
|
- name: bookmark collections
|
|
- name: bookmarks import
|
|
- name: dev tools
|
|
|
|
paths:
|
|
/auth:
|
|
post:
|
|
tags: [user profile]
|
|
$merge:
|
|
- "profile/routes.yaml#.auth"
|
|
|
|
/profile:
|
|
get:
|
|
tags: [user profile]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "profile/routes.yaml#.profile"
|
|
|
|
/bookmarks:
|
|
get:
|
|
tags: [bookmarks]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.paginated"
|
|
- "bookmarks/traits.yaml#.sortable"
|
|
- "bookmarks/routes.yaml#.list"
|
|
|
|
post:
|
|
tags: [bookmarks]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "traits.yaml#.deferred"
|
|
- "bookmarks/routes.yaml#.create"
|
|
|
|
/bookmarks/{id}:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withBookmark"
|
|
|
|
get:
|
|
tags: [bookmarks]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.retrieve"
|
|
|
|
patch:
|
|
tags: [bookmarks]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "bookmarks/routes.yaml#.update"
|
|
|
|
delete:
|
|
tags: [bookmarks]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.delete"
|
|
|
|
/bookmarks/{id}/article:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withBookmark"
|
|
|
|
get:
|
|
tags: [bookmark export]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.article"
|
|
|
|
/bookmarks/{id}/article.{format}:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withBookmark"
|
|
|
|
get:
|
|
tags: [bookmark export]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.export"
|
|
|
|
/bookmarks/{id}/share/link:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withBookmark"
|
|
|
|
get:
|
|
tags: [bookmark sharing]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.shareLink"
|
|
|
|
/bookmarks/{id}/share/email:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withBookmark"
|
|
|
|
post:
|
|
tags: [bookmark sharing]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.shareEmail"
|
|
|
|
/bookmarks/labels:
|
|
get:
|
|
tags: [bookmark labels]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.labels"
|
|
|
|
/bookmarks/labels/{name}:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withLabel"
|
|
|
|
get:
|
|
tags: [bookmark labels]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.labelInfo"
|
|
|
|
patch:
|
|
tags: [bookmark labels]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "bookmarks/routes.yaml#.labelUpdate"
|
|
|
|
delete:
|
|
tags: [bookmark labels]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.labelDelete"
|
|
|
|
/bookmarks/annotations:
|
|
get:
|
|
tags: [bookmark highlights]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.paginated"
|
|
- "bookmarks/routes.yaml#.annotationList"
|
|
|
|
/bookmarks/{id}/annotations:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withBookmark"
|
|
|
|
get:
|
|
tags: [bookmark highlights]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.bookmarkAnnotationList"
|
|
|
|
post:
|
|
tags: [bookmark highlights]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "traits.yaml#.created"
|
|
- "bookmarks/routes.yaml#.bookmarkAnnotationCreate"
|
|
|
|
/bookmarks/{id}/annotations/{annotation_id}:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withBookmark"
|
|
|
|
patch:
|
|
tags: [bookmark highlights]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "bookmarks/routes.yaml#.withAnnotation"
|
|
- "bookmarks/routes.yaml#.bookmarkAnnotationUpdate"
|
|
|
|
delete:
|
|
tags: [bookmark highlights]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.withAnnotation"
|
|
- "bookmarks/routes.yaml#.bookmarkAnnotationDelete"
|
|
|
|
/bookmarks/collections:
|
|
get:
|
|
tags: [bookmark collections]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.paginated"
|
|
- "bookmarks/routes.yaml#.collectionList"
|
|
|
|
post:
|
|
tags: [bookmark collections]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.created"
|
|
- "bookmarks/routes.yaml#.collectionCreate"
|
|
|
|
/bookmarks/collections/{id}:
|
|
$merge:
|
|
- "bookmarks/routes.yaml#.withCollection"
|
|
|
|
get:
|
|
tags: [bookmark collections]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.collectionInfo"
|
|
|
|
patch:
|
|
tags: [bookmark collections]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.collectionUpdate"
|
|
|
|
delete:
|
|
tags: [bookmark collections]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "bookmarks/routes.yaml#.collectionDelete"
|
|
|
|
/bookmarks/import/text:
|
|
post:
|
|
tags: [bookmarks import]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "traits.yaml#.deferred"
|
|
- "bookmarks/routes.yaml#.importMultipartGeneric"
|
|
- "bookmarks/routes.yaml#.importTextFile"
|
|
|
|
/bookmarks/import/browser:
|
|
post:
|
|
tags: [bookmarks import]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "traits.yaml#.deferred"
|
|
- "bookmarks/routes.yaml#.importMultipartGeneric"
|
|
- "bookmarks/routes.yaml#.importBrowserBookmarks"
|
|
|
|
/bookmarks/import/pocket-file:
|
|
post:
|
|
tags: [bookmarks import]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "traits.yaml#.deferred"
|
|
- "bookmarks/routes.yaml#.importMultipartGeneric"
|
|
- "bookmarks/routes.yaml#.importPocket"
|
|
|
|
/bookmarks/import/wallabag:
|
|
post:
|
|
tags: [bookmarks import]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "traits.yaml#.validator"
|
|
- "traits.yaml#.deferred"
|
|
- "bookmarks/routes.yaml#.importWallabag"
|
|
|
|
|
|
/cookbook/extract:
|
|
get:
|
|
tags: [dev tools]
|
|
$merge:
|
|
- "traits.yaml#.authenticated"
|
|
- "cookbook/routes.yaml#.extract"
|