From a9829598c509a230672daf53bb8656eb20f1a902 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 8 Mar 2026 18:53:51 +0000 Subject: [PATCH] docs: add API tokens and webhook ingestion documentation Update API.md with API token management endpoints, usage examples, and authentication guide. Update UserGuide.md with webhook ingestion and API tokens sections. Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- app/auth.py | 21 ++++---- docs/API.md | 133 +++++++++++++++++++++++++++++++++++++++++++++- docs/UserGuide.md | 47 ++++++++++++++++ 3 files changed, 191 insertions(+), 10 deletions(-) diff --git a/app/auth.py b/app/auth.py index 801f53dc..bc1dfcda 100644 --- a/app/auth.py +++ b/app/auth.py @@ -55,7 +55,7 @@ router = APIRouter() def get_current_user(request: Request): # Check for Bearer token auth first (API tokens) api_user = getattr(request.state, "api_token_user", None) - if api_user: + if isinstance(api_user, dict): return api_user return request.session.get("user") @@ -71,11 +71,11 @@ def _resolve_bearer_user(request: Request, db: Session) -> dict | None: A user dict or ``None`` if no valid Bearer token is present. """ auth_header = request.headers.get("authorization", "") - if not auth_header.startswith("Bearer "): + if not isinstance(auth_header, str) or not auth_header.startswith("Bearer "): return None raw_token = auth_header[7:] - if not raw_token: + if not raw_token or not isinstance(raw_token, str): return None from app.models import ApiToken @@ -145,13 +145,16 @@ def require_login(func): # Fall back to Bearer token auth for API endpoints url_path = urlparse(str(request.url)).path if url_path.startswith("/api/"): - from app.database import SessionLocal - - db = SessionLocal() try: - api_user = _resolve_bearer_user(request, db) - finally: - db.close() + from app.database import SessionLocal + + db = SessionLocal() + try: + api_user = _resolve_bearer_user(request, db) + finally: + db.close() + except Exception: + api_user = None if api_user: request.state.api_token_user = api_user diff --git a/docs/API.md b/docs/API.md index 2d837977..7766e8d9 100644 --- a/docs/API.md +++ b/docs/API.md @@ -86,7 +86,38 @@ def make_api_request(url, max_retries=3): ## Authentication -When authentication is enabled, you must include an authentication token in your requests: +When authentication is enabled, you must include an authentication token in your requests. + +### API Tokens (Recommended) + +DocuElevate supports personal API tokens for programmatic access. Tokens are the recommended +way to authenticate scripts, CI/CD pipelines, and webhook integrations. + +**Creating a token:** + +1. Log in to DocuElevate and navigate to **API Tokens** (available in your user menu or at `/api-tokens`). +2. Enter a descriptive name (e.g. "CI Pipeline", "Scanner Integration") and click **Create Token**. +3. Copy the token immediately — it is shown only once. + +**Using a token:** + +```bash +curl -X GET "http:///api/files" \ + -H "Authorization: Bearer " +``` + +**Managing tokens programmatically:** + +| Method | Endpoint | Description | +|--------|----------|-------------| +| `POST` | `/api/api-tokens/` | Create a new token | +| `GET` | `/api/api-tokens/` | List all your tokens | +| `DELETE` | `/api/api-tokens/{id}` | Revoke a token | + +### Session Authentication + +Browser-based users authenticate via OAuth or local login. Session cookies are set +automatically and used for subsequent requests: ```bash curl -X GET "http:///api/files" \ @@ -1900,6 +1931,106 @@ Pass no `pipeline_id` query parameter (or omit it) to clear the assignment. ``` +## API Tokens + +Personal API tokens allow programmatic access to the DocuElevate API without +session cookies. Tokens are ideal for CI/CD pipelines, webhook integrations, +and automation scripts. + +Each token is prefixed with `de_` for easy identification. Only a SHA-256 hash +is stored server-side; the plaintext is returned exactly once at creation time. + +Usage tracking records when each token was last used and from which IP address. + +### POST /api/api-tokens/ + +Create a new API token. + +**Request:** +```json +{ + "name": "CI Pipeline" +} +``` + +**Response (201 Created):** +```json +{ + "id": 1, + "name": "CI Pipeline", + "token_prefix": "de_Ab3xY7kL", + "token": "de_Ab3xY7kLmN9pQrStUvWxYz0123456789abcdef", + "is_active": true, + "last_used_at": null, + "last_used_ip": null, + "created_at": "2026-03-08T12:00:00Z", + "revoked_at": null +} +``` + +> **Important:** The `token` field is only included in the creation response. +> Copy it immediately — it will not be shown again. + +### GET /api/api-tokens/ + +List all tokens for the authenticated user. The full token value is never included. + +**Response (200):** +```json +[ + { + "id": 1, + "name": "CI Pipeline", + "token_prefix": "de_Ab3xY7kL", + "is_active": true, + "last_used_at": "2026-03-08T15:30:00Z", + "last_used_ip": "203.0.113.42", + "created_at": "2026-03-08T12:00:00Z", + "revoked_at": null + } +] +``` + +### DELETE /api/api-tokens/{token_id} + +Revoke a token. The token is soft-deleted (kept for audit purposes) and can no +longer be used for authentication. + +**Response (200):** +```json +{ + "detail": "Token revoked" +} +``` + +### Using API Tokens + +Include the token in the `Authorization` header of any API request: + +```bash +# Upload a document +curl -X POST "http://your-instance/api/files/ui-upload" \ + -H "Authorization: Bearer de_your_token_here" \ + -F "file=@/path/to/document.pdf" + +# List files +curl -X GET "http://your-instance/api/files" \ + -H "Authorization: Bearer de_your_token_here" +``` + +**Python example:** +```python +import requests + +response = requests.post( + "http://your-instance/api/files/ui-upload", + headers={"Authorization": "Bearer de_your_token_here"}, + files={"file": open("document.pdf", "rb")}, +) +print(response.json()) +``` + + ## Further Assistance For additional help with the API, please contact our support team or refer to the [Development Guide](../CONTRIBUTING.md). diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7cb85543..7ad1776d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -165,6 +165,7 @@ The **Integrations** page (`/integrations`) provides a unified view of all your - **Email Forward** — recipient email address - **Watch Folder** — folder path - **Paperless NGX** — URL and API token + - **Webhook** — no configuration needed; the form shows a quick-start guide with sample `curl` and Python snippets for uploading documents via the API 5. Click **Test Connection** to verify the settings before saving. 6. Click **Save** to persist the integration. @@ -193,6 +194,52 @@ DocuElevate can poll an FTP or SFTP directory for new files. Enable this with `F See [Configuration Guide — Watch Folder Ingestion](ConfigurationGuide.md#watch-folder-ingestion) for full setup instructions. +### Webhook Ingestion (API Upload) + +Webhook integrations allow external systems to push documents directly into DocuElevate +via the REST API. Instead of DocuElevate polling for new files, **your application sends +files to DocuElevate** using an HTTP request with an API token for authentication. + +This is ideal for: +- **CI/CD pipelines** — upload build artifacts or generated reports +- **Scanner integrations** — push scanned documents from network scanners +- **Automation scripts** — send documents from any system with HTTP support + +To set up webhook ingestion: + +1. Go to **Integrations** and add a new **Source → Webhook** integration. + The integration form shows copy-ready code snippets. +2. Go to **API Tokens** (in your user menu) and create a personal API token. +3. Use the token to upload documents: + +```bash +curl -X POST "https://your-instance/api/files/ui-upload" \ + -H "Authorization: Bearer de_your_token_here" \ + -F "file=@/path/to/document.pdf" +``` + +See the [API Documentation](API.md#api-tokens) for detailed API token management. + +### API Tokens + +API tokens provide secure, programmatic access to the DocuElevate API. Each user +can create multiple tokens, each with a descriptive name. + +**Features:** +- **Multiple tokens** — create separate tokens for different scripts or integrations +- **Usage tracking** — see when each token was last used and from which IP address +- **Revocation** — instantly disable a compromised token without affecting others + +**Managing tokens:** + +1. Click your avatar in the top navigation and select **API Tokens**, or go to `/api-tokens`. +2. Enter a descriptive name and click **Create Token**. +3. Copy the token immediately — it is shown only once. +4. To revoke a token, click **Revoke** next to it in the token list. + +> **Security tip:** Create a dedicated token for each integration and revoke it +> immediately if compromised. Never share tokens or commit them to source control. + ## Managing Documents The **Files** page provides access to all processed documents: