member_center/docs/openapi.yaml
2026-01-30 16:57:29 +09:00

604 lines
15 KiB
YAML

openapi: 3.1.0
info:
title: Member Center API
version: 0.1.0
description: OAuth2/OIDC + Newsletter Subscription API
servers:
- url: /api
security:
- BearerAuth: []
paths:
/oauth/authorize:
get:
summary: OAuth2 Authorization Endpoint
description: Authorization Code + PKCE flow
parameters:
- in: query
name: client_id
required: true
schema: { type: string }
- in: query
name: redirect_uri
required: true
schema: { type: string }
- in: query
name: response_type
required: true
schema: { type: string, enum: [code] }
- in: query
name: scope
required: true
schema: { type: string }
- in: query
name: code_challenge
required: true
schema: { type: string }
- in: query
name: code_challenge_method
required: true
schema: { type: string, enum: [S256] }
- in: query
name: state
required: false
schema: { type: string }
responses:
'302':
description: Redirect to client with code
/oauth/token:
post:
summary: OAuth2 Token Endpoint
requestBody:
required: true
content:
application/x-www-form-urlencoded:
schema:
type: object
required: [grant_type, code, redirect_uri, client_id, code_verifier]
properties:
grant_type: { type: string, enum: [authorization_code, refresh_token] }
code: { type: string }
redirect_uri: { type: string }
client_id: { type: string }
code_verifier: { type: string }
refresh_token: { type: string }
responses:
'200':
description: Token response
content:
application/json:
schema:
$ref: '#/components/schemas/TokenResponse'
/.well-known/openid-configuration:
get:
summary: OIDC Discovery
responses:
'200':
description: OIDC discovery document
/.well-known/jwks.json:
get:
summary: JWKS
responses:
'200':
description: JSON Web Key Set
/auth/register:
post:
summary: Register user
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegisterRequest'
responses:
'200':
description: Registered
content:
application/json:
schema:
$ref: '#/components/schemas/UserProfile'
/auth/login:
post:
summary: API login
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
responses:
'200':
description: Token response
content:
application/json:
schema:
$ref: '#/components/schemas/TokenResponse'
/auth/refresh:
post:
summary: Refresh token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RefreshRequest'
responses:
'200':
description: Token response
content:
application/json:
schema:
$ref: '#/components/schemas/TokenResponse'
/auth/logout:
post:
summary: Logout (revoke refresh token)
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
refresh_token:
type: string
responses:
'204':
description: Logged out
/auth/password/forgot:
post:
summary: Request password reset
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ForgotPasswordRequest'
responses:
'204':
description: Email sent
/auth/password/reset:
post:
summary: Reset password
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ResetPasswordRequest'
responses:
'204':
description: Password reset
/auth/email/verify:
get:
summary: Verify email
parameters:
- in: query
name: token
required: true
schema: { type: string }
responses:
'200':
description: Email verified
/user/profile:
get:
summary: Get current user profile
security:
- BearerAuth: []
responses:
'200':
description: Profile
content:
application/json:
schema:
$ref: '#/components/schemas/UserProfile'
/newsletter/subscribe:
post:
summary: Subscribe (unauthenticated allowed)
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SubscribeRequest'
responses:
'200':
description: Pending subscription
content:
application/json:
schema:
$ref: '#/components/schemas/Subscription'
/newsletter/confirm:
get:
summary: Confirm subscription (double opt-in)
parameters:
- in: query
name: token
required: true
schema: { type: string }
responses:
'200':
description: Active subscription
content:
application/json:
schema:
$ref: '#/components/schemas/Subscription'
/newsletter/unsubscribe:
post:
summary: Unsubscribe single list
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [token]
properties:
token: { type: string }
responses:
'200':
description: Unsubscribed
content:
application/json:
schema:
$ref: '#/components/schemas/Subscription'
/newsletter/preferences:
get:
summary: Get preferences
parameters:
- in: query
name: subscription_id
required: false
schema: { type: string }
- in: query
name: tenant_id
required: false
schema: { type: string }
- in: query
name: email
required: false
schema: { type: string, format: email }
responses:
'200':
description: Preferences
content:
application/json:
schema:
$ref: '#/components/schemas/Subscription'
post:
summary: Update preferences
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [subscription_id, preferences]
properties:
subscription_id: { type: string }
preferences: { type: object }
responses:
'200':
description: Updated
content:
application/json:
schema:
$ref: '#/components/schemas/Subscription'
/admin/tenants:
get:
summary: List tenants
security: [{ BearerAuth: [] }]
responses:
'200':
description: List
post:
summary: Create tenant
security: [{ BearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Tenant'
responses:
'201':
description: Created
/admin/tenants/{id}:
get:
summary: Get tenant
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
responses:
'200':
description: Tenant
put:
summary: Update tenant
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Tenant'
responses:
'200':
description: Updated
delete:
summary: Delete tenant
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
responses:
'204':
description: Deleted
/admin/newsletter-lists:
get:
summary: List newsletter lists
security: [{ BearerAuth: [] }]
responses:
'200':
description: List
post:
summary: Create list
security: [{ BearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NewsletterList'
responses:
'201':
description: Created
/admin/newsletter-lists/{id}:
get:
summary: Get list
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
responses:
'200':
description: List
put:
summary: Update list
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/NewsletterList'
responses:
'200':
description: Updated
delete:
summary: Delete list
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
responses:
'204':
description: Deleted
/admin/oauth-clients:
get:
summary: List OAuth clients
security: [{ BearerAuth: [] }]
responses:
'200':
description: List
post:
summary: Create OAuth client
security: [{ BearerAuth: [] }]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClient'
responses:
'201':
description: Created
/admin/oauth-clients/{id}:
get:
summary: Get OAuth client
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
responses:
'200':
description: OAuth client
put:
summary: Update OAuth client
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OAuthClient'
responses:
'200':
description: Updated
delete:
summary: Delete OAuth client
security: [{ BearerAuth: [] }]
parameters:
- in: path
name: id
required: true
schema: { type: string }
responses:
'204':
description: Deleted
components:
securitySchemes:
OAuth2:
type: oauth2
flows:
authorizationCode:
authorizationUrl: /api/oauth/authorize
tokenUrl: /api/oauth/token
scopes:
openid: OpenID Connect
email: Email
profile: Basic profile
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
TokenResponse:
type: object
properties:
access_token: { type: string }
refresh_token: { type: string }
id_token: { type: string }
token_type: { type: string, example: Bearer }
expires_in: { type: integer }
RegisterRequest:
type: object
required: [email, password]
properties:
email: { type: string, format: email }
password: { type: string }
LoginRequest:
type: object
required: [email, password, client_id]
properties:
email: { type: string, format: email }
password: { type: string }
client_id: { type: string }
scope: { type: string }
RefreshRequest:
type: object
required: [refresh_token, client_id]
properties:
refresh_token: { type: string }
client_id: { type: string }
ForgotPasswordRequest:
type: object
required: [email]
properties:
email: { type: string, format: email }
ResetPasswordRequest:
type: object
required: [token, new_password]
properties:
token: { type: string }
new_password: { type: string }
UserProfile:
type: object
properties:
id: { type: string }
email: { type: string, format: email }
email_verified: { type: boolean }
created_at: { type: string, format: date-time }
SubscribeRequest:
type: object
required: [tenant_id, list_id, email]
properties:
tenant_id: { type: string }
list_id: { type: string }
email: { type: string, format: email }
preferences: { type: object }
source: { type: string }
Subscription:
type: object
properties:
id: { type: string }
tenant_id: { type: string }
list_id: { type: string }
email: { type: string, format: email }
status: { type: string, enum: [pending, active, unsubscribed] }
preferences: { type: object }
created_at: { type: string, format: date-time }
Tenant:
type: object
properties:
id: { type: string }
name: { type: string }
domains: { type: array, items: { type: string } }
status: { type: string }
NewsletterList:
type: object
properties:
id: { type: string }
tenant_id: { type: string }
name: { type: string }
status: { type: string }
OAuthClient:
type: object
properties:
id: { type: string }
tenant_id: { type: string }
name: { type: string }
redirect_uris: { type: array, items: { type: string } }
client_type: { type: string, enum: [public, confidential] }