优化
This commit is contained in:
@@ -2,112 +2,173 @@ openapi: 3.0.3
|
||||
info:
|
||||
title: IAM Notification Center API
|
||||
version: 1.0.0
|
||||
description: First release is in-app notifications only. There is no clear-read/delete operation in this release.
|
||||
servers:
|
||||
- url: /api
|
||||
description: First release supports IN_APP only and does not support deleting or clearing read messages.
|
||||
servers: [{url: /api}]
|
||||
tags:
|
||||
- name: Notification inbox
|
||||
- name: Platform notification administration
|
||||
- {name: Notification inbox}
|
||||
- {name: Platform notification administration}
|
||||
paths:
|
||||
/{app}/v1/notifications:
|
||||
get:
|
||||
tags: [Notification inbox]
|
||||
summary: List current user's inbox
|
||||
parameters:
|
||||
- {name: app, in: path, required: true, schema: {type: string, enum: [platform, merchant]}}
|
||||
- {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
|
||||
- {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
|
||||
- {$ref: '#/components/parameters/AppPath'}
|
||||
- {$ref: '#/components/parameters/Page'}
|
||||
- {$ref: '#/components/parameters/Size'}
|
||||
- {name: status, in: query, schema: {type: string, enum: [UNREAD, READ]}}
|
||||
- {name: category, in: query, schema: {type: string, maxLength: 64}}
|
||||
responses:
|
||||
'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/InboxPageResponse'}}}}
|
||||
responses: {'200': {$ref: '#/components/responses/InboxPage'}}
|
||||
/{app}/v1/notifications/unread-count:
|
||||
get:
|
||||
tags: [Notification inbox]
|
||||
summary: Count current user's unread inbox messages
|
||||
parameters:
|
||||
- {name: app, in: path, required: true, schema: {type: string, enum: [platform, merchant]}}
|
||||
responses:
|
||||
'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/UnreadCountResponse'}}}}
|
||||
summary: Count current user's unread messages
|
||||
parameters: [{$ref: '#/components/parameters/AppPath'}]
|
||||
responses: {'200': {$ref: '#/components/responses/UnreadCount'}}
|
||||
/{app}/v1/notifications/{id}:
|
||||
get:
|
||||
tags: [Notification inbox]
|
||||
summary: Get one inbox message
|
||||
parameters:
|
||||
- {name: app, in: path, required: true, schema: {type: string, enum: [platform, merchant]}}
|
||||
- {name: id, in: path, required: true, schema: {type: integer, format: int64}}
|
||||
responses:
|
||||
'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/InboxDetailResponse'}}}}
|
||||
parameters: [{$ref: '#/components/parameters/AppPath'}, {$ref: '#/components/parameters/IdPath'}]
|
||||
responses: {'200': {$ref: '#/components/responses/InboxDetail'}}
|
||||
/{app}/v1/notifications/{id}/read:
|
||||
put:
|
||||
tags: [Notification inbox]
|
||||
summary: Mark one message as read (idempotent)
|
||||
parameters:
|
||||
- {name: app, in: path, required: true, schema: {type: string, enum: [platform, merchant]}}
|
||||
- {name: id, in: path, required: true, schema: {type: integer, format: int64}}
|
||||
responses:
|
||||
'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/InboxDetailResponse'}}}}
|
||||
parameters: [{$ref: '#/components/parameters/AppPath'}, {$ref: '#/components/parameters/IdPath'}]
|
||||
responses: {'200': {$ref: '#/components/responses/InboxDetail'}}
|
||||
/{app}/v1/notifications/read-all:
|
||||
put:
|
||||
tags: [Notification inbox]
|
||||
summary: Mark all current-user messages as read (idempotent)
|
||||
parameters:
|
||||
- {name: app, in: path, required: true, schema: {type: string, enum: [platform, merchant]}}
|
||||
responses:
|
||||
'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/ReadAllResponse'}}}}
|
||||
parameters: [{$ref: '#/components/parameters/AppPath'}]
|
||||
responses: {'200': {$ref: '#/components/responses/ReadAll'}}
|
||||
/platform/v1/notifications:
|
||||
post:
|
||||
tags: [Platform notification administration]
|
||||
summary: Create an in-app notification task
|
||||
responses:
|
||||
'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskResponse'}}}}
|
||||
summary: Create an IN_APP notification task
|
||||
requestBody: {$ref: '#/components/requestBodies/CreateNotification'}
|
||||
responses: {'200': {$ref: '#/components/responses/TaskDetail'}}
|
||||
/platform/v1/notification-templates:
|
||||
get:
|
||||
tags: [Platform notification administration]
|
||||
summary: List templates
|
||||
parameters: [{name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}, {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}, {name: status, in: query, schema: {type: string, enum: [DRAFT, ACTIVE, DISABLED]}}]
|
||||
responses: {'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TemplatePageResponse'}}}}}
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/Page'}
|
||||
- {$ref: '#/components/parameters/Size'}
|
||||
- {name: templateCode, in: query, schema: {type: string, maxLength: 64}}
|
||||
- {name: category, in: query, schema: {type: string, maxLength: 64}}
|
||||
- {name: title, in: query, description: Fuzzy match template name or title template, schema: {type: string, maxLength: 128}}
|
||||
- {name: status, in: query, schema: {type: string, enum: [DRAFT, ACTIVE, DISABLED]}}
|
||||
responses: {'200': {$ref: '#/components/responses/TemplatePage'}}
|
||||
post:
|
||||
tags: [Platform notification administration]
|
||||
summary: Create a DRAFT template
|
||||
responses: {'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TemplateResponse'}}}}}
|
||||
requestBody: {$ref: '#/components/requestBodies/CreateTemplate'}
|
||||
responses: {'200': {$ref: '#/components/responses/TemplateDetail'}}
|
||||
/platform/v1/notification-templates/{id}:
|
||||
put:
|
||||
tags: [Platform notification administration]
|
||||
summary: Edit a DRAFT template only
|
||||
responses: {'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TemplateResponse'}}}}}
|
||||
parameters: [{$ref: '#/components/parameters/IdPath'}]
|
||||
requestBody: {$ref: '#/components/requestBodies/UpdateTemplate'}
|
||||
responses: {'200': {$ref: '#/components/responses/TemplateDetail'}}
|
||||
/platform/v1/notification-templates/{id}/status:
|
||||
put:
|
||||
tags: [Platform notification administration]
|
||||
summary: Activate or disable a template; only DRAFT->ACTIVE or ACTIVE->DISABLED
|
||||
responses: {'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TemplateResponse'}}}}}
|
||||
summary: Change template status
|
||||
description: Only DRAFT to ACTIVE and ACTIVE to DISABLED are valid. DISABLED cannot return to ACTIVE; copy it to a new DRAFT instead.
|
||||
parameters: [{$ref: '#/components/parameters/IdPath'}]
|
||||
requestBody: {$ref: '#/components/requestBodies/ChangeTemplateStatus'}
|
||||
responses: {'200': {$ref: '#/components/responses/TemplateDetail'}}
|
||||
/platform/v1/notification-tasks:
|
||||
get:
|
||||
tags: [Platform notification administration]
|
||||
summary: List tasks
|
||||
parameters: [{name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}, {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}, {name: status, in: query, schema: {type: string, enum: [CREATED, SCHEDULED, DISPATCHING, RETRYING, SENT, DEAD, CANCELLED]}}]
|
||||
responses: {'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskPageResponse'}}}}}
|
||||
summary: List notification tasks
|
||||
parameters:
|
||||
- {$ref: '#/components/parameters/Page'}
|
||||
- {$ref: '#/components/parameters/Size'}
|
||||
- {name: taskNo, in: query, schema: {type: string, maxLength: 64}}
|
||||
- {name: category, in: query, schema: {type: string, maxLength: 64}}
|
||||
- {name: title, in: query, description: Fuzzy match rendered title, schema: {type: string, maxLength: 128}}
|
||||
- {name: status, in: query, schema: {type: string, enum: [CREATED, SCHEDULED, DISPATCHING, RETRYING, SENT, DEAD, CANCELLED]}}
|
||||
responses: {'200': {$ref: '#/components/responses/TaskPage'}}
|
||||
/platform/v1/notification-tasks/{id}/cancel:
|
||||
put:
|
||||
tags: [Platform notification administration]
|
||||
summary: Cancel CREATED or SCHEDULED task
|
||||
responses: {'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskResponse'}}}}}
|
||||
summary: Cancel a CREATED or SCHEDULED task
|
||||
parameters: [{$ref: '#/components/parameters/IdPath'}]
|
||||
responses: {'200': {$ref: '#/components/responses/TaskDetail'}}
|
||||
/platform/v1/notification-tasks/{id}/retry:
|
||||
put:
|
||||
tags: [Platform notification administration]
|
||||
summary: Retry RETRYING or DEAD task
|
||||
responses: {'200': {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskResponse'}}}}}
|
||||
summary: Retry a RETRYING or DEAD task
|
||||
parameters: [{$ref: '#/components/parameters/IdPath'}]
|
||||
responses: {'200': {$ref: '#/components/responses/TaskDetail'}}
|
||||
components:
|
||||
parameters:
|
||||
AppPath: {name: app, in: path, required: true, schema: {type: string, enum: [platform, merchant]}}
|
||||
IdPath: {name: id, in: path, required: true, schema: {type: integer, format: int64}}
|
||||
Page: {name: page, in: query, schema: {type: integer, minimum: 1, default: 1}}
|
||||
Size: {name: size, in: query, schema: {type: integer, minimum: 1, maximum: 200, default: 20}}
|
||||
requestBodies:
|
||||
CreateNotification: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/CreateNotificationRequest'}}}}
|
||||
CreateTemplate: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/CreateTemplateRequest'}}}}
|
||||
UpdateTemplate: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/UpdateTemplateRequest'}}}}
|
||||
ChangeTemplateStatus: {required: true, content: {application/json: {schema: {$ref: '#/components/schemas/ChangeTemplateStatusRequest'}}}}
|
||||
responses:
|
||||
InboxPage: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/InboxPageResponse'}}}}
|
||||
InboxDetail: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/InboxDetailResponse'}}}}
|
||||
UnreadCount: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/UnreadCountResponse'}}}}
|
||||
ReadAll: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/ReadAllResponse'}}}}
|
||||
TemplatePage: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TemplatePageResponse'}}}}
|
||||
TemplateDetail: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TemplateDetailResponse'}}}}
|
||||
TaskPage: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskPageResponse'}}}}
|
||||
TaskDetail: {description: OK, content: {application/json: {schema: {$ref: '#/components/schemas/TaskDetailResponse'}}}}
|
||||
schemas:
|
||||
PageMeta: {type: object, required: [page, size, total, pages], properties: {page: {type: integer, format: int64}, size: {type: integer, format: int64}, total: {type: integer, format: int64}, pages: {type: integer, format: int64}}}
|
||||
InboxItem: {type: object, properties: {id: {type: integer, format: int64}, category: {type: string}, title: {type: string}, status: {type: string, enum: [UNREAD, READ]}, sentAt: {type: string, format: date-time}, readAt: {type: string, format: date-time, nullable: true}}}
|
||||
InboxDetail: {allOf: [{$ref: '#/components/schemas/InboxItem'}, {type: object, properties: {body: {type: string}, sourceType: {type: string}, sourceId: {type: string}}}]}
|
||||
InboxPageResponse: {type: object, properties: {code: {type: string, example: '200'}, data: {type: object, properties: {records: {type: array, items: {$ref: '#/components/schemas/InboxItem'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}}}
|
||||
InboxDetailResponse: {type: object, properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/InboxDetail'}}}
|
||||
UnreadCountResponse: {type: object, properties: {code: {type: string, example: '200'}, data: {type: object, properties: {unreadCount: {type: integer, format: int64}}}}}
|
||||
ReadAllResponse: {type: object, properties: {code: {type: string, example: '200'}, data: {type: object, properties: {updatedCount: {type: integer, format: int64}}}}}
|
||||
CreateNotificationRequest: {type: object, required: [tenantId, templateCode, recipientType, variables, idempotencyKey], properties: {tenantId: {type: integer, format: int64, minimum: 0}, templateCode: {type: string, maxLength: 64}, recipientType: {type: string, enum: [USER, MEMBERSHIP, TENANT_ROLE, TENANT_ALL, PLATFORM_ROLE]}, recipientIds: {type: array, maxItems: 1000, items: {type: integer, format: int64}}, roleCode: {type: string, maxLength: 64}, variables: {type: object, additionalProperties: {type: string}}, scheduledAt: {type: string, format: date-time, nullable: true}, idempotencyKey: {type: string, minLength: 8, maxLength: 128}, sourceEventId: {type: string, maxLength: 128, nullable: true}}}
|
||||
TemplateResponse: {type: object, properties: {id: {type: integer, format: int64}, templateCode: {type: string}, templateName: {type: string}, category: {type: string}, channel: {type: string, enum: [IN_APP]}, titleTemplate: {type: string}, bodyTemplate: {type: string}, variableWhitelist: {type: array, items: {type: string}}, status: {type: string, enum: [DRAFT, ACTIVE, DISABLED]}, version: {type: integer}}}
|
||||
TemplatePageResponse: {type: object, properties: {code: {type: string, example: '200'}, data: {type: object, properties: {records: {type: array, items: {$ref: '#/components/schemas/TemplateResponse'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}}}
|
||||
TaskResponse: {type: object, properties: {id: {type: integer, format: int64}, taskNo: {type: string}, status: {type: string, enum: [CREATED, SCHEDULED, DISPATCHING, RETRYING, SENT, DEAD, CANCELLED]}, recipientCount: {type: integer}, scheduledAt: {type: string, format: date-time, nullable: true}, sentAt: {type: string, format: date-time, nullable: true}, duplicated: {type: boolean}}}
|
||||
TaskPageResponse: {type: object, properties: {code: {type: string, example: '200'}, data: {type: object, properties: {records: {type: array, items: {$ref: '#/components/schemas/TaskResponse'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}}}
|
||||
CreateNotificationRequest:
|
||||
type: object
|
||||
required: [tenantId, templateCode, recipientType, variables, idempotencyKey]
|
||||
description: tenantId is a backend compatibility field. 0 means platform scope and a positive value is the customer (enterprise) ID; UI copy must use customer or enterprise, never tenant.
|
||||
properties:
|
||||
tenantId: {type: integer, format: int64, minimum: 0}
|
||||
templateCode: {type: string, maxLength: 64}
|
||||
recipientType: {type: string, enum: [USER, MEMBERSHIP, TENANT_ROLE, TENANT_ALL, PLATFORM_ROLE]}
|
||||
recipientIds: {type: array, maxItems: 1000, items: {type: integer, format: int64}, description: Required for USER or MEMBERSHIP; forbidden for role/all recipient types.}
|
||||
roleCode: {type: string, maxLength: 64, description: Required for TENANT_ROLE or PLATFORM_ROLE; forbidden otherwise.}
|
||||
variables: {type: object, maxProperties: 32, additionalProperties: {type: string, maxLength: 2000}}
|
||||
scheduledAt: {type: string, format: date-time, nullable: true}
|
||||
idempotencyKey: {type: string, minLength: 8, maxLength: 128}
|
||||
sourceEventId: {type: string, maxLength: 128, nullable: true}
|
||||
allOf:
|
||||
- if: {properties: {recipientType: {enum: [USER, MEMBERSHIP]}}}
|
||||
then: {required: [recipientIds]}
|
||||
- if: {properties: {recipientType: {enum: [TENANT_ROLE, PLATFORM_ROLE]}}}
|
||||
then: {required: [roleCode]}
|
||||
CreateTemplateRequest:
|
||||
type: object
|
||||
required: [templateCode, templateName, category, titleTemplate, bodyTemplate, variableWhitelist]
|
||||
properties: {templateCode: {type: string, pattern: '^[A-Z][A-Z0-9_]{0,63}$'}, templateName: {type: string, maxLength: 128}, category: {type: string, maxLength: 64}, titleTemplate: {type: string, maxLength: 256}, bodyTemplate: {type: string, maxLength: 10000}, variableWhitelist: {type: array, maxItems: 32, uniqueItems: true, items: {type: string, pattern: '^[a-z][a-z0-9_]{0,31}$'}}}
|
||||
UpdateTemplateRequest:
|
||||
type: object
|
||||
required: [templateName, category, titleTemplate, bodyTemplate, variableWhitelist, version]
|
||||
properties: {templateName: {type: string, maxLength: 128}, category: {type: string, maxLength: 64}, titleTemplate: {type: string, maxLength: 256}, bodyTemplate: {type: string, maxLength: 10000}, variableWhitelist: {type: array, maxItems: 32, uniqueItems: true, items: {type: string, pattern: '^[a-z][a-z0-9_]{0,31}$'}}, version: {type: integer, minimum: 1}}
|
||||
ChangeTemplateStatusRequest:
|
||||
type: object
|
||||
required: [targetStatus, version]
|
||||
properties: {targetStatus: {type: string, enum: [ACTIVE, DISABLED], description: ACTIVE is accepted only from DRAFT; DISABLED only from ACTIVE.}, version: {type: integer, minimum: 1}}
|
||||
InboxItem: {type: object, required: [id, category, title, status, sentAt], properties: {id: {type: integer, format: int64}, category: {type: string}, title: {type: string}, status: {type: string, enum: [UNREAD, READ]}, sentAt: {type: string, format: date-time}, readAt: {type: string, format: date-time, nullable: true}}}
|
||||
InboxDetail: {allOf: [{$ref: '#/components/schemas/InboxItem'}, {type: object, required: [body], properties: {body: {type: string}, sourceType: {type: string, nullable: true}, sourceId: {type: string, nullable: true}}}]}
|
||||
TemplateItem: {type: object, required: [id, templateCode, templateName, category, channel, titleTemplate, bodyTemplate, variableWhitelist, status, version], properties: {id: {type: integer, format: int64}, templateCode: {type: string}, templateName: {type: string}, category: {type: string}, channel: {type: string, enum: [IN_APP]}, titleTemplate: {type: string}, bodyTemplate: {type: string}, variableWhitelist: {type: array, items: {type: string}}, status: {type: string, enum: [DRAFT, ACTIVE, DISABLED]}, version: {type: integer}}}
|
||||
TaskItem: {type: object, required: [id, taskNo, category, title, status, recipientCount, duplicated], properties: {id: {type: integer, format: int64}, taskNo: {type: string}, category: {type: string}, title: {type: string}, status: {type: string, enum: [CREATED, SCHEDULED, DISPATCHING, RETRYING, SENT, DEAD, CANCELLED]}, recipientCount: {type: integer}, scheduledAt: {type: string, format: date-time, nullable: true}, sentAt: {type: string, format: date-time, nullable: true}, duplicated: {type: boolean}}}
|
||||
InboxPageData: {type: object, required: [records, page, size, total, pages], properties: {records: {type: array, items: {$ref: '#/components/schemas/InboxItem'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}
|
||||
TemplatePageData: {type: object, required: [records, page, size, total, pages], properties: {records: {type: array, items: {$ref: '#/components/schemas/TemplateItem'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}
|
||||
TaskPageData: {type: object, required: [records, page, size, total, pages], properties: {records: {type: array, items: {$ref: '#/components/schemas/TaskItem'}}, page: {type: integer}, size: {type: integer}, total: {type: integer}, pages: {type: integer}}}
|
||||
InboxPageResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/InboxPageData'}}}
|
||||
InboxDetailResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/InboxDetail'}}}
|
||||
UnreadCountResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {type: object, required: [unreadCount], properties: {unreadCount: {type: integer, format: int64}}}}}
|
||||
ReadAllResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {type: object, required: [updatedCount], properties: {updatedCount: {type: integer, format: int64}}}}}
|
||||
TemplatePageResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TemplatePageData'}}}
|
||||
TemplateDetailResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TemplateItem'}}}
|
||||
TaskPageResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TaskPageData'}}}
|
||||
TaskDetailResponse: {type: object, required: [code, data], properties: {code: {type: string, example: '200'}, data: {$ref: '#/components/schemas/TaskItem'}}}
|
||||
|
||||
Reference in New Issue
Block a user