@host = http://localhost:8080 @tenantCode = 2s # NOTE: # - tenant module requires JWT auth + tenant membership. # - Get a token via `tests/super.http` (`/super/v1/auth/token`) then paste it below. @token = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoyLCJpc3MiOiJ2MiIsImV4cCI6MTc2NjYzMzAyMSwibmJmIjoxNzY2MDI4MjExfQ.RjLVil6EnbPi4LMPyVBzR2vFaeXelypk5fKInsAzqc8 ### Tenant Join - Join by invite (JWT required, membership NOT required) POST {{ host }}/t/{{ tenantCode }}/v1/join/invite Content-Type: application/json Authorization: Bearer {{ token }} { "invite_code": "paste_invite_code_here" } ### Tenant Join - Create join request (JWT required, membership NOT required) POST {{ host }}/t/{{ tenantCode }}/v1/join/request Content-Type: application/json Authorization: Bearer {{ token }} { "reason": "申请加入租户用于联调" } ### Tenant - Me (resolved tenant/user/tenant_user) GET {{ host }}/t/{{ tenantCode }}/v1/me Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - My balance GET {{ host }}/t/{{ tenantCode }}/v1/me/balance Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - My ledgers (paged) GET {{ host }}/t/{{ tenantCode }}/v1/me/ledgers?page=1&limit=20 Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - Contents list (published) GET {{ host }}/t/{{ tenantCode }}/v1/contents?page=1&limit=10 Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - Content detail (visibility + access check) @contentID = 1 GET {{ host }}/t/{{ tenantCode }}/v1/contents/{{ contentID }} Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - Preview assets (role=preview) GET {{ host }}/t/{{ tenantCode }}/v1/contents/{{ contentID }}/preview Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - Media play (token-based; no auth header needed) # Copy a `play_url` from preview/assets response and paste it here (or set @playToken). @playToken = paste_play_token_here GET {{ host }}/t/{{ tenantCode }}/v1/media/play?token={{ playToken }} ### Tenant - Main assets (role=main, requires access unless free/owner) GET {{ host }}/t/{{ tenantCode }}/v1/contents/{{ contentID }}/assets Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - Purchase content (tenant balance) POST {{ host }}/t/{{ tenantCode }}/v1/contents/{{ contentID }}/purchase Content-Type: application/json Authorization: Bearer {{ token }} { "idempotency_key": "purchase-{{ contentID }}-001" } ### Tenant - My orders list GET {{ host }}/t/{{ tenantCode }}/v1/orders?page=1&limit=10 Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - My orders list (filter by status/content_id/paid_at window) GET {{ host }}/t/{{ tenantCode }}/v1/orders?page=1&limit=10&status=paid&content_id={{ contentID }} Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant - My order detail GET {{ host }}/t/{{ tenantCode }}/v1/orders/{{ orderID }} Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Create content draft POST {{ host }}/t/{{ tenantCode }}/v1/admin/contents Content-Type: application/json Authorization: Bearer {{ token }} { "title": "示例内容", "description": "这是一个内容草稿,用于联调", "visibility": "tenant_only", "preview_seconds": 60 } ### Tenant Admin - Update content (publish/unpublish/title/description/preview_seconds) PATCH {{ host }}/t/{{ tenantCode }}/v1/admin/contents/{{ contentID }} Content-Type: application/json Authorization: Bearer {{ token }} { "title": "示例内容(已更新)", "status": "published" } ### Tenant Admin - Upsert content price/discount PUT {{ host }}/t/{{ tenantCode }}/v1/admin/contents/{{ contentID }}/price Content-Type: application/json Authorization: Bearer {{ token }} { "currency": "CNY", "price_amount": 990, "discount_type": "none", "discount_value": 0 } ### Tenant Admin - MediaAsset upload init (create asset + upload params) POST {{ host }}/t/{{ tenantCode }}/v1/admin/media_assets/upload_init Content-Type: application/json Authorization: Bearer {{ token }} { "type": "video", "content_type": "video/mp4", "file_size": 12345678, "sha256": "" } ### Tenant Admin - MediaAsset upload complete (uploaded -> processing) @assetID = 1 POST {{ host }}/t/{{ tenantCode }}/v1/admin/media_assets/{{ assetID }}/upload_complete Content-Type: application/json Authorization: Bearer {{ token }} { "etag": "", "content_type": "video/mp4", "file_size": 12345678, "sha256": "" } ### Tenant Admin - MediaAssets list (paged) GET {{ host }}/t/{{ tenantCode }}/v1/admin/media_assets?page=1&limit=20 Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - MediaAssets list (filter + sort) GET {{ host }}/t/{{ tenantCode }}/v1/admin/media_assets?page=1&limit=20&type=video&status=processing&created_at_from=2025-01-01T00:00:00Z&created_at_to=2026-01-01T00:00:00Z&asc=created_at&desc=updated_at Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - MediaAsset detail GET {{ host }}/t/{{ tenantCode }}/v1/admin/media_assets/{{ assetID }} Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - MediaAsset delete (soft delete; ready/failed only) DELETE {{ host }}/t/{{ tenantCode }}/v1/admin/media_assets/{{ assetID }} Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Attach asset to content (main/cover/preview) @assetID = 1 POST {{ host }}/t/{{ tenantCode }}/v1/admin/contents/{{ contentID }}/assets Content-Type: application/json Authorization: Bearer {{ token }} { "asset_id": {{ assetID }}, "role": "main", "sort": 0 } ### Tenant Admin - Orders list GET {{ host }}/t/{{ tenantCode }}/v1/admin/orders?page=1&limit=10 Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Orders list (filter by user_id/content_id/paid_at range/amount_paid range) GET {{ host }}/t/{{ tenantCode }}/v1/admin/orders?page=1&limit=10&user_id=2&content_id={{ contentID }}&paid_at_from=2025-01-01T00:00:00Z&paid_at_to=2026-01-01T00:00:00Z&amount_paid_min=1&amount_paid_max=99999999 Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Orders list (filter by username/content_title/created_at/type) GET {{ host }}/t/{{ tenantCode }}/v1/admin/orders?page=1&limit=10&username=alice&content_title=Go&created_at_from=2025-01-01T00:00:00Z&created_at_to=2026-01-01T00:00:00Z&type=content_purchase&asc=amount_paid&desc=paid_at Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Orders export (CSV text) GET {{ host }}/t/{{ tenantCode }}/v1/admin/orders/export?username=alice&content_title=Go&type=content_purchase&desc=paid_at Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Order detail @orderID = 1 GET {{ host }}/t/{{ tenantCode }}/v1/admin/orders/{{ orderID }} Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Refund order (default window paid_at + 24h) POST {{ host }}/t/{{ tenantCode }}/v1/admin/orders/{{ orderID }}/refund Content-Type: application/json Authorization: Bearer {{ token }} { "force": false, "reason": "联调退款", "idempotency_key": "refund-{{ orderID }}-001" } ### Tenant Admin - Topup a tenant member @topupUserID = 2 POST {{ host }}/t/{{ tenantCode }}/v1/admin/users/{{ topupUserID }}/topup Content-Type: application/json Authorization: Bearer {{ token }} { "amount": 1000, "reason": "联调充值", "idempotency_key": "topup-{{ topupUserID }}-001" } ### Tenant Admin - Batch topup users POST {{ host }}/t/{{ tenantCode }}/v1/admin/users/topup/batch Content-Type: application/json Authorization: Bearer {{ token }} { "batch_idempotency_key": "batch-topup-001", "items": [ { "user_id": 2, "amount": 1000, "reason": "批量充值-1" }, { "user_id": 3, "amount": 2000, "reason": "批量充值-2" } ] } ### Tenant Admin - Join a user to tenant (add member) @joinUserID = 3 POST {{ host }}/t/{{ tenantCode }}/v1/admin/users/{{ joinUserID }}/join Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Set member role PATCH {{ host }}/t/{{ tenantCode }}/v1/admin/users/{{ joinUserID }}/role Content-Type: application/json Authorization: Bearer {{ token }} { "role": "tenant_admin" } ### Tenant Admin - Tenant members list GET {{ host }}/t/{{ tenantCode }}/v1/admin/users?page=1&limit=20 Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Create invite POST {{ host }}/t/{{ tenantCode }}/v1/admin/invites Content-Type: application/json Authorization: Bearer {{ token }} { "code": "", "max_uses": 1, "remark": "联调用邀请码" } ### Tenant Admin - Invite list GET {{ host }}/t/{{ tenantCode }}/v1/admin/invites?page=1&limit=20 Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Disable invite @inviteID = 1 PATCH {{ host }}/t/{{ tenantCode }}/v1/admin/invites/{{ inviteID }}/disable Content-Type: application/json Authorization: Bearer {{ token }} { "reason": "联调禁用" } ### Tenant Admin - Join requests list GET {{ host }}/t/{{ tenantCode }}/v1/admin/join-requests?page=1&limit=20&status=pending Content-Type: application/json Authorization: Bearer {{ token }} ### Tenant Admin - Approve join request @requestID = 1 POST {{ host }}/t/{{ tenantCode }}/v1/admin/join-requests/{{ requestID }}/approve Content-Type: application/json Authorization: Bearer {{ token }} { "reason": "联调通过" } ### Tenant Admin - Reject join request POST {{ host }}/t/{{ tenantCode }}/v1/admin/join-requests/{{ requestID }}/reject Content-Type: application/json Authorization: Bearer {{ token }} { "reason": "联调拒绝" }