Files
Arkie-Library-Backend/docs/API.md
2026-05-18 07:56:27 +08:00

361 lines
6.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# API Reference
Base URL in local development: `http://localhost:8080`.
Frontend usually calls paths like `/api/resources`; uploaded files are available under `/uploads/...`.
## Response style
Most responses are JSON. Errors use plain text via `http.Error`, for example `unauthorized` or `bad json`.
## Health
### `GET /healthz`
Returns plain text:
```text
ok
```
### `GET /health`
Same as `/healthz`.
## Public categories/resources
### `GET /api/categories`
Query/header language behavior:
- `?lang=zh-CN` returns Simplified Chinese name when available.
- `?lang=en` returns English name when available.
- otherwise Traditional Chinese is preferred.
Response:
```json
[
{
"id": 1,
"slug": "project-ppt",
"name": "項目資料PPT",
"description": "ARK 項目介紹、簡報與對外展示資料",
"iconKey": "folder",
"sortOrder": 1,
"updatedAt": "2026-01-01T00:00:00Z"
}
]
```
### `GET /api/resources`
Returns paginated public resources.
Query params:
| Param | Meaning |
| --- | --- |
| `page` | page number, default 1 |
| `limit` | page size, default 20, max 100 |
| `q` | search title/description/tag name |
| `type` | resource type; `all` means no filter |
| `language` | exact resource language filter |
| `category` | category slug |
| `tag` | tag slug or tag name, case-insensitive |
| `sort` | `latest` default, `published`, `recommended`, `popular` |
| `lang` | category display language, e.g. `en`, `zh-CN` |
Response:
```json
{
"items": [
{
"id": "uuid",
"title": "ARK 項目介紹簡報(示例)",
"description": "適合線下宣講與新人培訓。",
"type": "ppt",
"language": "zh-TW",
"categoryId": 1,
"categorySlug": "project-ppt",
"categoryName": "項目資料PPT",
"coverImage": "/uploads/placeholder-cover.svg",
"fileUrl": "/uploads/placeholder-cover.svg",
"isDownloadable": true,
"isRecommended": true,
"publishedAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-01T00:00:00Z",
"tags": ["官方推薦"]
}
],
"page": 1,
"limit": 20,
"total": 1
}
```
### `GET /api/resources/recommended?limit=12`
Returns recommended resources:
```json
{ "items": [] }
```
Max limit is 50.
### `GET /api/resources/latest?limit=12`
Returns latest resources:
```json
{ "items": [] }
```
### `GET /api/resources/popular?limit=12`
Returns resources ordered by download + favorite + share count:
```json
{ "items": [] }
```
### `GET /api/resources/{id}`
Returns one published public resource. `{id}` must be a UUID.
### `GET /api/resources/{id}/related`
Returns up to 8 resources from the same category:
```json
{ "items": [] }
```
## Public activity endpoints
### `POST /api/search-log`
Request:
```json
{ "query": "ark" }
```
Response:
```json
{ "ok": true }
```
### `POST /api/resources/{id}/view`
Increments view count.
Response:
```json
{ "ok": true }
```
### `POST /api/resources/{id}/download`
Increments download count.
### `POST /api/resources/{id}/share`
Increments share count.
### `POST /api/resources/{id}/favorite`
Request:
```json
{ "add": true }
```
- `add: true` increments favorite count.
- `add: false` decrements favorite count but not below zero.
## Wallet auth
Wallet auth is for normal users, not admin users.
### `POST /api/auth/wallet/nonce`
Request:
```json
{ "address": "0x0000000000000000000000000000000000000000" }
```
Response:
```json
{
"nonce": "hex-code",
"message": "ARK Database — wallet sign-in\n\nWallet: 0x...\nOne-time code: ..."
}
```
The frontend asks the wallet to sign `message`.
### `POST /api/auth/wallet/verify`
Request:
```json
{
"address": "0x0000000000000000000000000000000000000000",
"message": "same message from nonce endpoint",
"signature": "0x..."
}
```
Response:
```json
{
"token": "jwt",
"wallet": "0xChecksumAddress"
}
```
### `GET /api/auth/wallet/me`
Requires header:
```http
Authorization: Bearer <wallet-jwt>
```
Response:
```json
{ "wallet": "0xChecksumAddress", "role": "user" }
```
## Admin auth
### `POST /api/admin/login`
Request:
```json
{ "email": "admin@ark.local", "password": "admin123" }
```
Response:
```json
{ "token": "admin-jwt" }
```
Use this token for admin endpoints:
```http
Authorization: Bearer <admin-jwt>
```
## Admin endpoints
All endpoints below require admin JWT.
### `GET /api/admin/dashboard`
Response includes counts and hot resources:
```json
{
"totalResources": 10,
"published": 8,
"todayNew": 1,
"totalViews": 100,
"totalDownloads": 20,
"totalFavorites": 5,
"totalShares": 3,
"hotResources": []
}
```
### `GET /api/admin/search-logs?limit=200`
Max limit is 500.
Response:
```json
{ "items": [{ "id": 1, "query": "ark", "createdAt": "2026-01-01T00:00:00Z" }] }
```
### `GET /api/admin/resources?page=1&limit=20`
Lists all resources, including drafts/private resources.
### `GET /api/admin/resources/{id}`
Gets one resource by UUID.
### `POST /api/admin/resources`
Creates a resource.
Example request body:
```json
{
"title": "Example",
"description": "Short text",
"type": "ppt",
"language": "zh-TW",
"categoryId": 1,
"coverImage": "/uploads/example.svg",
"fileUrl": "/uploads/example.pdf",
"previewUrl": "",
"externalUrl": "",
"bodyText": "",
"badgeLabel": "新人必看",
"isPublic": true,
"isDownloadable": true,
"isRecommended": false,
"sortOrder": 0,
"status": "draft",
"tags": ["教程"]
}
```
### `PUT /api/admin/resources/{id}`
Updates a resource. Body shape is the same as create.
### `DELETE /api/admin/resources/{id}`
Deletes a resource.
Response:
```json
{ "ok": true }
```
### `POST /api/admin/upload`
Multipart upload with field name `file`.
Response for local storage:
```json
{ "url": "/uploads/generated-name.ext", "filename": "generated-name.ext", "storage": "local" }
```
Response for S3:
```json
{ "url": "https://...", "filename": "generated-name.ext", "storage": "s3" }
```
### `GET /api/admin/categories`
Same handler as public categories; returns visible categories.