Files
GameTime/server/openapi.yaml
Blomios 917777e18b chore(wip): consolidation intermédiaire multi-tickets (sprints Statistiques, UI, Bug resolution, Serveur-client)
Regroupe l'état de travail en cours réalisé dans un même worktree sur
plusieurs tickets/sprints (#85, #136, #145, #155-160, #162-164),
mélangeant des tickets QA et inProgress. Ne constitue pas une feature
terminée : commit de sauvegarde avant triage/split par ticket en
branches feature/* dédiées. Exclut les dossiers d'environnement de
build locaux et le heap dump parasite (.gitignore mis à jour).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 16:48:54 +02:00

633 lines
16 KiB
YAML

openapi: 3.0.3
info:
title: GameTime Server API
version: 0.1.0
description: Headless API for GameTime authentication, incremental sync and targeted sharing.
servers:
- url: http://localhost:8080
description: Local Docker or development server
tags:
- name: Health
- name: Auth
- name: Sync
- name: Shares
paths:
/health:
get:
tags: [Health]
summary: Healthcheck
responses:
'200':
description: Server is reachable.
content:
application/json:
schema:
$ref: '#/components/schemas/HealthResponse'
/auth/register:
post:
tags: [Auth]
summary: Register a user account
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RegisterRequest'
responses:
'201':
description: User created.
content:
application/json:
schema:
$ref: '#/components/schemas/RegisterResponse'
'400':
$ref: '#/components/responses/BadRequest'
'409':
description: Email already taken.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/auth/login:
post:
tags: [Auth]
summary: Login and create an API token session
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
responses:
'200':
description: Login accepted. The clear token is returned once.
content:
application/json:
schema:
$ref: '#/components/schemas/LoginResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/auth/logout:
post:
tags: [Auth]
summary: Revoke the current API token session
security:
- bearerAuth: []
responses:
'204':
description: Session revoked.
'401':
$ref: '#/components/responses/Unauthorized'
/sync/push:
post:
tags: [Sync]
summary: Push client-side resource mutations
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SyncPushRequest'
responses:
'200':
description: Batch processed. Item-level validation errors are returned in results.
content:
application/json:
schema:
$ref: '#/components/schemas/SyncPushResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/sync/pull:
get:
tags: [Sync]
summary: Pull resources updated after a server cursor
security:
- bearerAuth: []
parameters:
- name: since
in: query
required: false
schema:
type: string
format: date-time
description: ISO8601 UTC server cursor. If omitted, returns all resources.
responses:
'200':
description: Resources for the authenticated user.
content:
application/json:
schema:
$ref: '#/components/schemas/SyncPullResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/sync/exchange:
post:
tags: [Sync]
summary: Push then pull in one request
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SyncExchangeRequest'
responses:
'200':
description: Pull response after applying the push batch.
content:
application/json:
schema:
$ref: '#/components/schemas/SyncExchangeResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/shares:
post:
tags: [Shares]
summary: Create a targeted share
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateShareRequest'
responses:
'201':
description: Share created. Unknown recipient emails are reported but do not fail the request.
content:
application/json:
schema:
$ref: '#/components/schemas/CreateShareResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
/shares/inbox:
get:
tags: [Shares]
summary: List shares received by the authenticated user
security:
- bearerAuth: []
responses:
'200':
description: Inbox sorted from newest to oldest.
content:
application/json:
schema:
$ref: '#/components/schemas/ShareInboxResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/shares/{id}/accept:
post:
tags: [Shares]
summary: Accept a received share
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/ShareId'
responses:
'200':
description: Share accepted and copied into synced resources.
content:
application/json:
schema:
$ref: '#/components/schemas/AcceptShareResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
/shares/{id}/decline:
post:
tags: [Shares]
summary: Decline a received share
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/ShareId'
responses:
'204':
description: Share declined.
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'409':
$ref: '#/components/responses/Conflict'
/shares/{id}/revoke:
post:
tags: [Shares]
summary: Revoke a share sent by the authenticated user
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/ShareId'
responses:
'204':
description: Share revoked.
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: opaque
parameters:
ShareId:
name: id
in: path
required: true
schema:
type: string
description: Share identifier.
responses:
BadRequest:
description: Invalid JSON body, invalid parameter, or validation failure.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Unauthorized:
description: Missing, malformed, expired, revoked or unknown bearer token.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
NotFound:
description: Resource not found or not accessible by the authenticated user.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
Conflict:
description: Current resource state rejects the requested transition.
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
schemas:
ErrorResponse:
type: object
required: [error]
properties:
error:
type: string
HealthResponse:
type: object
required: [status]
properties:
status:
type: string
enum: [ok]
RegisterRequest:
type: object
required: [email, password]
properties:
email:
type: string
format: email
password:
type: string
minLength: 8
displayName:
type: string
nullable: true
RegisterResponse:
type: object
required: [userId, email]
properties:
userId:
type: string
email:
type: string
format: email
LoginRequest:
type: object
required: [email, password]
properties:
email:
type: string
format: email
password:
type: string
deviceLabel:
type: string
nullable: true
LoginResponse:
type: object
required: [token, expiresAt]
properties:
token:
type: string
expiresAt:
type: string
format: date-time
ResourceType:
type: string
enum: [exercise, program, workoutTemplate, workoutHistory, mediaAsset]
ShareResourceType:
type: string
enum: [program, workoutTemplate]
ShareKind:
type: string
enum: [single, pack]
ShareRecipientStatus:
type: string
enum: [pending, accepted, declined, revoked]
JsonObject:
type: object
additionalProperties: true
SyncPushRequest:
type: object
required: [items]
properties:
deviceId:
type: string
nullable: true
description: Required by the application use case for each valid item.
items:
type: array
items:
$ref: '#/components/schemas/SyncPushItem'
SyncPushItem:
type: object
required: [resourceType, clientId, schemaVersion, clientUpdatedAt, payload]
properties:
resourceType:
$ref: '#/components/schemas/ResourceType'
clientId:
type: string
schemaVersion:
type: integer
minimum: 1
clientUpdatedAt:
type: string
format: date-time
deletedAt:
type: string
format: date-time
nullable: true
payload:
$ref: '#/components/schemas/JsonObject'
SyncPushResponse:
type: object
required: [serverCursor, results]
properties:
serverCursor:
type: string
format: date-time
results:
type: array
items:
$ref: '#/components/schemas/SyncPushResultItem'
SyncPushResultItem:
type: object
required: [status]
properties:
resourceType:
type: string
nullable: true
clientId:
type: string
nullable: true
serverId:
type: string
nullable: true
status:
type: string
enum: [accepted, ignoredOlder, error]
serverUpdatedAt:
type: string
format: date-time
nullable: true
message:
type: string
SyncPullResponse:
type: object
required: [serverCursor, items]
properties:
serverCursor:
type: string
format: date-time
items:
type: array
items:
$ref: '#/components/schemas/SyncedResourceItem'
SyncExchangeRequest:
allOf:
- $ref: '#/components/schemas/SyncPushRequest'
- type: object
properties:
since:
type: string
format: date-time
nullable: true
SyncExchangeResponse:
type: object
required: [serverCursor, pushResults, items]
properties:
serverCursor:
type: string
format: date-time
pushResults:
type: array
items:
$ref: '#/components/schemas/SyncPushResultItem'
items:
type: array
items:
$ref: '#/components/schemas/SyncedResourceItem'
SyncedResourceItem:
type: object
required:
- resourceType
- clientId
- serverId
- schemaVersion
- clientUpdatedAt
- serverUpdatedAt
- payload
properties:
resourceType:
$ref: '#/components/schemas/ResourceType'
clientId:
type: string
serverId:
type: string
schemaVersion:
type: integer
minimum: 1
clientUpdatedAt:
type: string
format: date-time
serverUpdatedAt:
type: string
format: date-time
deletedAt:
type: string
format: date-time
nullable: true
payload:
$ref: '#/components/schemas/JsonObject'
CreateShareRequest:
type: object
required: [recipientEmails]
properties:
shareKind:
description: Defaults to single when omitted.
allOf:
- $ref: '#/components/schemas/ShareKind'
packName:
type: string
nullable: true
resourceType:
nullable: true
allOf:
- $ref: '#/components/schemas/ShareResourceType'
payload:
$ref: '#/components/schemas/JsonObject'
nullable: true
items:
type: array
items:
$ref: '#/components/schemas/SharePackItem'
recipientEmails:
type: array
minItems: 1
items:
type: string
format: email
SharePackItem:
type: object
required: [resourceType, payload]
properties:
resourceType:
$ref: '#/components/schemas/ShareResourceType'
payload:
$ref: '#/components/schemas/JsonObject'
CreateShareResponse:
type: object
required: [shareId, shareKind, recipientUserIds, unresolvedEmails]
properties:
shareId:
type: string
shareKind:
$ref: '#/components/schemas/ShareKind'
recipientUserIds:
type: array
items:
type: string
unresolvedEmails:
type: array
items:
type: string
format: email
ShareInboxResponse:
type: object
required: [items]
properties:
items:
type: array
items:
$ref: '#/components/schemas/ShareInboxItem'
ShareInboxItem:
type: object
required:
- shareId
- senderUserId
- shareKind
- payload
- status
- createdAt
properties:
shareId:
type: string
senderUserId:
type: string
shareKind:
$ref: '#/components/schemas/ShareKind'
packName:
type: string
nullable: true
resourceType:
nullable: true
allOf:
- $ref: '#/components/schemas/ShareResourceType'
payload:
$ref: '#/components/schemas/JsonObject'
status:
$ref: '#/components/schemas/ShareRecipientStatus'
createdAt:
type: string
format: date-time
respondedAt:
type: string
format: date-time
nullable: true
AcceptShareResponse:
type: object
required: [createdResources]
properties:
createdResource:
$ref: '#/components/schemas/SyncedResourceItem'
description: Present only for single-resource shares.
createdResources:
type: array
items:
$ref: '#/components/schemas/SyncedResourceItem'