web/docs/api/member-channel.openapi.yaml

398 lines
9.9 KiB
YAML

openapi: 3.1.0
info:
title: EDUT Member App Channel API
version: 1.0.0
description: |
Deterministic member communication channel contract.
App notifications are derived from wallet-authenticated membership and entitlement state.
servers:
- url: https://api.edut.ai
security:
- WalletSession: []
paths:
/member/channel/device/register:
post:
summary: Register or refresh a member app device channel binding.
operationId: registerMemberDevice
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceRegisterRequest'
responses:
'200':
description: Device channel binding active.
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceRegisterResponse'
'403':
description: Membership is not active for this wallet.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/member/channel/device/unregister:
post:
summary: Remove a device channel binding.
operationId: unregisterMemberDevice
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceUnregisterRequest'
responses:
'200':
description: Device channel binding removed.
content:
application/json:
schema:
$ref: '#/components/schemas/DeviceUnregisterResponse'
'404':
description: Device channel binding not found.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/member/channel/events:
get:
summary: Poll deterministic member channel events.
operationId: listMemberChannelEvents
parameters:
- in: query
name: wallet
required: true
schema:
type: string
description: Wallet address tied to session.
- in: query
name: device_id
required: true
schema:
type: string
- in: query
name: cursor
required: false
schema:
type: string
- in: query
name: limit
required: false
schema:
type: integer
minimum: 1
maximum: 100
default: 25
responses:
'200':
description: Event page for in-app inbox rendering.
content:
application/json:
schema:
$ref: '#/components/schemas/EventListResponse'
'403':
description: Membership inactive or suspended.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/member/channel/events/{event_id}/ack:
post:
summary: Acknowledge event delivery/read state.
operationId: acknowledgeMemberChannelEvent
parameters:
- in: path
name: event_id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EventAckRequest'
responses:
'200':
description: Event acknowledged.
content:
application/json:
schema:
$ref: '#/components/schemas/EventAckResponse'
'404':
description: Event not found.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/member/channel/support/ticket:
post:
summary: Open support/admin ticket (org root owner only).
operationId: createOwnerSupportTicket
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SupportTicketRequest'
responses:
'200':
description: Support ticket accepted.
content:
application/json:
schema:
$ref: '#/components/schemas/SupportTicketResponse'
'403':
description: Principal is not org root owner.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
components:
securitySchemes:
WalletSession:
type: http
scheme: bearer
bearerFormat: EDUT-WALLET-SESSION
schemas:
DeviceRegisterRequest:
type: object
required:
- wallet
- chain_id
- device_id
- platform
- org_root_id
- principal_id
- principal_role
- app_version
properties:
wallet:
type: string
description: Hex wallet address.
chain_id:
type: integer
description: Active chain id in app session.
device_id:
type: string
description: Stable app-install identifier.
platform:
type: string
enum: [ios, android, desktop]
org_root_id:
type: string
description: Organization boundary id for channel scoping.
principal_id:
type: string
description: Human principal id for this session.
principal_role:
type: string
enum: [workspace_member, org_root_owner]
app_version:
type: string
push_provider:
type: string
enum: [apns, fcm, webpush, none]
default: none
push_token:
type: string
description: Provider token if push is enabled.
DeviceRegisterResponse:
type: object
required:
- channel_binding_id
- status
- poll_interval_seconds
- server_time
properties:
channel_binding_id:
type: string
status:
type: string
enum: [active]
poll_interval_seconds:
type: integer
minimum: 10
server_time:
type: string
format: date-time
DeviceUnregisterRequest:
type: object
required:
- wallet
- device_id
properties:
wallet:
type: string
device_id:
type: string
DeviceUnregisterResponse:
type: object
required:
- status
- wallet
- device_id
properties:
status:
type: string
enum: [removed]
wallet:
type: string
device_id:
type: string
EventListResponse:
type: object
required:
- wallet
- device_id
- org_root_id
- principal_id
- events
- next_cursor
- server_time
properties:
wallet:
type: string
device_id:
type: string
org_root_id:
type: string
principal_id:
type: string
events:
type: array
items:
$ref: '#/components/schemas/MemberEvent'
next_cursor:
type: string
nullable: true
server_time:
type: string
format: date-time
MemberEvent:
type: object
required:
- event_id
- class
- created_at
- title
- body
- dedupe_key
- policy_hash
properties:
event_id:
type: string
class:
type: string
enum:
- offer_available
- entitlement_activated
- platform_update
- publisher_update
- membership_policy
- admin_health
- admin_config
- admin_update
created_at:
type: string
format: date-time
title:
type: string
body:
type: string
dedupe_key:
type: string
requires_ack:
type: boolean
default: true
policy_hash:
type: string
payload:
type: object
additionalProperties: true
visibility_scope:
type: string
enum: [member, owner_admin]
default: member
EventAckRequest:
type: object
required:
- wallet
- device_id
- acknowledged_at
properties:
wallet:
type: string
device_id:
type: string
acknowledged_at:
type: string
format: date-time
EventAckResponse:
type: object
required:
- status
- event_id
- acknowledged_at
properties:
status:
type: string
enum: [acknowledged]
event_id:
type: string
acknowledged_at:
type: string
format: date-time
ErrorResponse:
type: object
required:
- error
- code
properties:
error:
type: string
code:
type: string
correlation_id:
type: string
SupportTicketRequest:
type: object
required:
- wallet
- org_root_id
- principal_id
- category
- summary
properties:
wallet:
type: string
org_root_id:
type: string
principal_id:
type: string
category:
type: string
enum: [admin_support, health_diagnostic, boundary_issue, update_control]
summary:
type: string
context:
type: object
additionalProperties: true
SupportTicketResponse:
type: object
required:
- status
- ticket_id
- created_at
properties:
status:
type: string
enum: [accepted]
ticket_id:
type: string
created_at:
type: string
format: date-time