# Internal API Handoff ## Base URL - Local: `http://127.0.0.1:8000` - Prod: 由部署環境提供 ## Auth Headers(每支 `/internal/*` 都必帶) - `X-Client-Key: ` - `X-API-Key: ` ## Common Error Response ```json { "detail": "error_code" } ``` 常見 `detail`: - `invalid_client`(401) - `invalid_api_key`(401) - `client_expired`(401) - `origin_not_allowed`(403) - `ip_not_allowed`(403) - `path_not_allowed`(403) ## Endpoints ### GET `/internal/systems` Response: ```json { "items": [ { "id": "uuid", "system_key": "ST20260331X1234", "name": "Marketing", "status": "active" } ], "total": 1, "limit": 200, "offset": 0 } ``` ### GET `/internal/modules` Response: ```json { "items": [ { "id": "uuid", "module_key": "MD20260331X5678", "system_key": "ST20260331X1234", "name": "Campaign", "status": "active" } ], "total": 1, "limit": 500, "offset": 0 } ``` ### GET `/internal/companies` Query: - `keyword`(optional) - `limit`(default 500) - `offset`(default 0) Response: ```json { "items": [ { "id": "uuid", "company_key": "CP20260331X9999", "name": "OSE", "status": "active" } ], "total": 1, "limit": 500, "offset": 0 } ``` ### GET `/internal/sites` Query: - `company_key`(optional) - `limit`(default 500) - `offset`(default 0) Response: ```json { "items": [ { "id": "uuid", "site_key": "ST20260331X1111", "company_key": "CP20260331X9999", "name": "main-site", "status": "active" } ], "total": 1, "limit": 500, "offset": 0 } ``` ### GET `/internal/members` Query: - `keyword`(optional) - `limit`(default 500) - `offset`(default 0) Response: ```json { "items": [ { "id": "uuid", "user_sub": "authentik-uid", "username": "chris", "email": "chris@ose.tw", "display_name": "Chris", "is_active": true } ], "total": 1, "limit": 500, "offset": 0 } ``` ### POST `/internal/users/upsert-by-sub` Request: ```json { "user_sub": "authentik-uid", "username": "chris", "email": "chris@ose.tw", "display_name": "Chris", "is_active": true } ``` Response: ```json { "id": "uuid", "user_sub": "authentik-uid", "idp_user_id": "idp-user-id-or-uuid", "username": "chris", "email": "chris@ose.tw", "display_name": "Chris", "is_active": true } ``` ### GET `/internal/permissions/{user_sub}/snapshot` Response: ```json { "user_sub": "authentik-uid", "permissions": [ { "scope_type": "site", "scope_id": "ST20260331X1111", "system": "ST20260331X1234", "module": "MD20260331X5678", "actions": ["view", "edit"] } ] } ``` ### POST `/internal/idp/users/ensure` (相容路徑:`/internal/authentik/users/ensure`) Request: ```json { "user_sub": "authentik-uid", "email": "user@example.com", "username": "user1", "display_name": "User One", "is_active": true } ``` Response: ```json { "idp_user_id": "idp-user-id-or-uuid", "action": "created" } ``` `action` 可能值:`created` / `updated`