{"openapi": "3.0.3", "info": {"title": "Lumin Notify API", "version": "1.0.0", "description": "Multi-user named Weixin notification channels. API keys only authorize resources owned by their user. Delivery status is asynchronous; sent means the provider accepted the message, not read by recipient."}, "servers": [{"url": "https://notify.lumin-dev.cn"}], "components": {"securitySchemes": {"bearerAuth": {"type": "http", "scheme": "bearer"}}, "schemas": {"MessageInput": {"type": "object", "required": ["channel_id", "text"], "properties": {"channel_id": {"type": "string", "format": "uuid"}, "title": {"type": "string", "maxLength": 120}, "text": {"type": "string", "minLength": 1, "maxLength": 60000}, "metadata": {"type": "object"}, "ttl_seconds": {"type": "integer", "minimum": 60, "maximum": 86400, "default": 3600}}}, "EventInput": {"type": "object", "required": ["event_id", "type", "text"], "properties": {"event_id": {"type": "string", "maxLength": 160}, "type": {"type": "string", "example": "voice.call_completed"}, "title": {"type": "string"}, "text": {"type": "string"}, "metadata": {"type": "object"}}}}}, "security": [{"bearerAuth": []}], "paths": {"/api/v1/channels": {"get": {"summary": "List channels owned by the API key user", "responses": {"200": {"description": "Channel list"}, "401": {"description": "Invalid key"}}}}, "/api/v1/messages": {"post": {"summary": "Queue a notification", "parameters": [{"in": "header", "name": "Idempotency-Key", "schema": {"type": "string"}, "description": "Repeat the same key/body to obtain the original message. Different body with the same key returns409."}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MessageInput"}}}}, "responses": {"202": {"description": "Queued; returns message id/status"}, "200": {"description": "Existing idempotent message"}, "409": {"description": "Idempotency conflict"}}}, "get": {"summary": "List recent messages", "responses": {"200": {"description": "Messages with delivery status"}}}}, "/api/v1/messages/{id}": {"get": {"summary": "Query message status", "parameters": [{"in": "path", "name": "id", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "queued/waiting_channel/sending/sent/failed/unknown/expired/cancelled"}, "404": {"description": "Not found or not owned"}}}}, "/api/v1/events": {"post": {"summary": "Publish an idempotent event to matching subscriptions", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/EventInput"}}}}, "responses": {"202": {"description": "Stored; dispatched, waiting_route, or expired. Returns resulting message IDs."}, "409": {"description": "Event id reused with different content"}}}}, "/api/v1/channels/{id}": {"get": {"summary": "Get an owned channel", "parameters": [{"in": "path", "name": "id", "required": true, "schema": {"type": "string", "format": "uuid"}}], "responses": {"200": {"description": "Channel connection state; no provider credentials"}, "404": {"description": "Not found or not owned"}}}}}}