Files
parenthese/backend/openapi/v1.yaml
T
IliesAllaliandClaude Opus 5.5 e596887a44 Invitations à créer son arbre, coupées en auto-hébergement (SIGNUP_PROMPTS) (#202)
- La famille sans compte trouve « Faire le mien » en bas du menu Ajouter ; la ligne quitte le menu du
  compte. Après l'inscription, l'arbre de la famille est rattaché et l'assistant de création s'ouvre.
- Démo : les messages des liens et la bulle après « Enregistrer et quitter » proposent l'inscription
  (lien cliquable, message gardé 6 s). La démo lit aussi les options de l'instance.
- Message d'invitation de Noël du 1er décembre au 6 janvier.
- SIGNUP_PROMPTS (API, /auth/options.signupPrompts) : éteint par défaut, allumé pour l'instance hébergée
  dans ecosystem.config.cjs, toujours coupé quand l'inscription est fermée. README, .env.example, OpenAPI.
- Mesures : via sur create_account_clicked et account_screen_viewed, source arbre-partage ou demo
  quand l'adresse n'en porte pas.
- « Quitter l'édition ? » dans la démo ne dit plus que les modifications restent sur l'appareil :
  la démo n'enregistre rien et tout disparaît au rechargement.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 18:17:59 +01:00

2180 lines
58 KiB
YAML

openapi: 3.0.3
info:
title: Arbre Genealogique API
version: 1.0.0
description: Contrats V1 prioritaires (auth, trees, partage, graph read).
servers:
- url: http://localhost:4000
tags:
- name: Auth
- name: Trees
- name: Graph
- name: Contributions
- name: Public
components:
securitySchemes:
BearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
schemas:
ErrorResponse:
type: object
properties:
error:
type: string
required: [error]
Credentials:
type: object
properties:
email:
type: string
format: email
password:
type: string
minLength: 8
maxLength: 128
required: [email, password]
User:
type: object
properties:
id:
type: string
email:
type: string
format: email
required: [id, email]
AuthResponse:
type: object
properties:
token:
type: string
user:
$ref: '#/components/schemas/User'
required: [token, user]
Tree:
type: object
properties:
id:
type: string
slug:
type: string
name:
type: string
description:
type: string
nullable: true
rootPersonId:
type: string
nullable: true
required: [id, slug, name]
CreateTreeRequest:
type: object
properties:
name:
type: string
slug:
type: string
pattern: '^[a-z0-9-]{3,64}$'
description:
type: string
nullable: true
visitorPassword:
type: string
minLength: 8
contributorPassword:
type: string
minLength: 8
required: [name, slug, visitorPassword, contributorPassword]
PatchTreeRequest:
type: object
properties:
name:
type: string
slug:
type: string
pattern: '^[a-z0-9-]{3,64}$'
description:
type: string
nullable: true
rootPersonId:
type: string
nullable: true
UnlockRequest:
type: object
properties:
password:
type: string
required: [password]
UnlockResponse:
type: object
properties:
token:
type: string
treeId:
type: string
role:
type: string
enum: [visitor, contributor]
required: [token, treeId, role]
PatchPasswordsRequest:
type: object
properties:
visitorPassword:
type: string
minLength: 8
contributorPassword:
type: string
minLength: 8
PatchTreeSettingsRequest:
type: object
properties:
memberContributionPolicy:
type: string
enum: [direct, pending]
contributorPolicy:
type: string
enum: [direct, pending]
TreeSettings:
type: object
properties:
treeId:
type: string
memberContributionPolicy:
type: string
enum: [direct, pending]
visitorPolicy:
type: string
enum: [read_only]
contributorPolicy:
type: string
enum: [direct, pending]
updatedAt:
type: string
format: date-time
required: [treeId, memberContributionPolicy, visitorPolicy, contributorPolicy]
TreeStats:
type: object
properties:
persons:
type: integer
unions:
type: integer
filiations:
type: integer
medias:
type: integer
pendingContributions:
type: integer
totalContributions:
type: integer
required: [persons, unions, filiations, medias, pendingContributions, totalContributions]
AuditLogEntry:
type: object
properties:
id:
type: string
treeId:
type: string
actorType:
type: string
actorId:
type: string
nullable: true
action:
type: string
entityType:
type: string
entityId:
type: string
payloadJson:
nullable: true
createdAt:
type: string
format: date-time
required: [id, treeId, actorType, action, entityType, entityId, createdAt]
CreatePersonRequest:
type: object
properties:
firstName:
type: string
lastName:
type: string
birthDate:
type: string
nullable: true
deathDate:
type: string
nullable: true
sex:
type: string
nullable: true
notes:
type: string
nullable: true
required: [firstName, lastName]
PatchPersonRequest:
type: object
properties:
firstName:
type: string
lastName:
type: string
birthDate:
type: string
nullable: true
deathDate:
type: string
nullable: true
sex:
type: string
nullable: true
notes:
type: string
nullable: true
CreateUnionRequest:
type: object
properties:
partner1PersonId:
type: string
partner2PersonId:
type: string
nullable: true
unionType:
type: string
nullable: true
startDate:
type: string
nullable: true
endDate:
type: string
nullable: true
displayOrder:
type: integer
required: [partner1PersonId]
PatchUnionRequest:
type: object
properties:
partner1PersonId:
type: string
partner2PersonId:
type: string
nullable: true
unionType:
type: string
nullable: true
startDate:
type: string
nullable: true
endDate:
type: string
nullable: true
displayOrder:
type: integer
CreateParentChildLinkRequest:
type: object
properties:
parentPersonId:
type: string
childPersonId:
type: string
viaUnionId:
type: string
nullable: true
parentageType:
type: string
nullable: true
displayOrder:
type: integer
required: [parentPersonId, childPersonId]
ChildrenOrderRequest:
type: object
required: [order]
properties:
order:
type: array
minItems: 2
maxItems: 200
description: Children in the wanted order, each with the links that attach it to its parents
items:
type: object
required: [childId, linkIds]
properties:
childId:
type: string
linkIds:
type: array
minItems: 1
maxItems: 4
items:
type: string
PatchParentChildLinkRequest:
type: object
properties:
parentPersonId:
type: string
childPersonId:
type: string
viaUnionId:
type: string
nullable: true
parentageType:
type: string
nullable: true
displayOrder:
type: integer
UploadMediaRequest:
type: object
properties:
type:
type: string
enum: [photo, video, audio, document, citation]
fileName:
type: string
mimeType:
type: string
sizeBytes:
type: integer
dataBase64:
type: string
caption:
type: string
nullable: true
required: [type, fileName, mimeType, sizeBytes, dataBase64]
ReorderMediaRequest:
type: object
properties:
orderedMediaIds:
type: array
items:
type: string
required: [orderedMediaIds]
GraphPerson:
type: object
properties:
id:
type: string
firstName:
type: string
lastName:
type: string
birthDate:
type: string
nullable: true
deathDate:
type: string
nullable: true
sex:
type: string
nullable: true
notes:
type: string
nullable: true
required: [id, firstName, lastName]
GraphUnion:
type: object
properties:
id:
type: string
partner1PersonId:
type: string
partner2PersonId:
type: string
nullable: true
unionType:
type: string
nullable: true
startDate:
type: string
nullable: true
endDate:
type: string
nullable: true
displayOrder:
type: integer
required: [id, partner1PersonId, displayOrder]
GraphFiliation:
type: object
properties:
id:
type: string
parentPersonId:
type: string
childPersonId:
type: string
viaUnionId:
type: string
nullable: true
parentageType:
type: string
nullable: true
displayOrder:
type: integer
required: [id, parentPersonId, childPersonId, displayOrder]
GraphMedia:
type: object
properties:
id:
type: string
personId:
type: string
type:
type: string
mimeType:
type: string
urlPath:
type: string
caption:
type: string
nullable: true
displayOrder:
type: integer
isFeatured:
type: boolean
required: [id, personId, type, mimeType, urlPath, displayOrder, isFeatured]
ContributionChangeInput:
type: object
properties:
entityType:
type: string
enum: [person, union, parent_child_link]
action:
type: string
enum: [create, update, delete, reorder]
entityId:
type: string
nullable: true
before:
nullable: true
after:
nullable: true
conflictState:
type: string
enum: [none, needs_review]
required: [entityType, action]
ContributionSessionCreateRequest:
type: object
properties:
title:
type: string
submittedByLabel:
type: string
changes:
type: array
minItems: 1
items:
$ref: '#/components/schemas/ContributionChangeInput'
required: [title, changes]
ContributionSession:
type: object
properties:
id:
type: string
treeId:
type: string
submittedByUserId:
type: string
nullable: true
submittedByLabel:
type: string
mode:
type: string
enum: [user, tree_access]
status:
type: string
enum: [pending, approved, rejected]
title:
type: string
changes:
type: array
items:
$ref: '#/components/schemas/ContributionSessionChange'
required: [id, treeId, submittedByLabel, mode, status, title]
ContributionSessionChange:
type: object
properties:
id:
type: string
entityType:
type: string
enum: [person, union, parent_child_link]
entityId:
type: string
nullable: true
action:
type: string
enum: [create, update, delete, reorder]
beforeJson:
nullable: true
afterJson:
nullable: true
conflictState:
type: string
enum: [none, needs_review]
decision:
type: string
enum: [approved, rejected]
nullable: true
required: [id, entityType, action, conflictState]
ContributionReviewRequest:
type: object
properties:
decision:
type: string
enum: [approved, rejected]
changeDecisions:
type: array
items:
type: object
properties:
changeId:
type: string
decision:
type: string
enum: [approved, rejected]
required: [changeId, decision]
required: [decision]
paths:
/auth/options:
get:
tags: [Auth]
summary: What the sign-in screen can offer on this instance
responses:
'200':
description: Instance options
content:
application/json:
schema:
type: object
properties:
registration:
type: boolean
description: false when ALLOW_REGISTRATION=false and the instance already has an account
passwordLogin:
type: boolean
description: false when PASSWORD_LOGIN=false (sign-in through the OIDC provider only)
oidc:
type: object
nullable: true
description: OIDC provider shown on the sign-in screen, null when OIDC_ISSUER is not set
properties:
name:
type: string
signupPrompts:
type: boolean
description: true when SIGNUP_PROMPTS=true and accounts can be created. The app then suggests starting one's own tree to relatives and demo visitors
required: [registration, passwordLogin, oidc, signupPrompts]
/auth/oidc/start:
get:
tags: [Auth]
summary: Start an OIDC sign-in (browser navigation)
description: Sets a signed, httpOnly cookie holding state, nonce and PKCE verifier, then redirects to the provider. Only exists when OIDC_ISSUER is set.
parameters:
- name: returnTo
in: query
required: false
schema:
type: string
description: Either / or /arbre/<slug>, anything else falls back to /
responses:
'302':
description: Redirect to the provider, or back to the app with "#oidc_error=oidc_unavailable"
/auth/oidc/callback:
get:
tags: [Auth]
summary: Provider redirect target (browser navigation)
description: Checks the cookie, then lets openid-client exchange the code and verify the ID token (signature, issuer, audience, expiry, nonce, state, PKCE). Finds the account by provider subject, links a verified email, or creates an account when registration allows it.
responses:
'302':
description: Back to the app with "#oidc=<one-time handoff>" or "#oidc_error=oidc_failed|oidc_email_unverified|oidc_email_missing|registration_closed"
/auth/oidc/exchange:
post:
tags: [Auth]
summary: Trade the one-time handoff for a session
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
code:
type: string
required: [code]
responses:
'200':
description: Session
content:
application/json:
schema:
$ref: '#/components/schemas/AuthResponse'
'401':
description: Handoff invalid, expired or already used (invalid_handoff)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/auth/register:
post:
tags: [Auth]
summary: Register user account
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Credentials'
responses:
'201':
description: Registered
content:
application/json:
schema:
$ref: '#/components/schemas/AuthResponse'
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Registration closed on this instance (registration_closed), or PASSWORD_LOGIN=false (password_login_disabled)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Email already exists
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/auth/login:
post:
tags: [Auth]
summary: Login user
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Credentials'
responses:
'200':
description: Logged in
content:
application/json:
schema:
$ref: '#/components/schemas/AuthResponse'
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: PASSWORD_LOGIN=false (password_login_disabled)
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Invalid credentials
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/auth/logout:
post:
tags: [Auth]
summary: Logout current session
security:
- BearerAuth: []
responses:
'200':
description: Logged out
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/auth/me:
delete:
tags: [Auth]
summary: Permanently delete the current account
description: >
Requires the current password. Permanently deletes every tree owned by the user
(including trees already marked as deleted) with their media files, then the account.
Trees where the user is only a member or has shared access are kept.
The token used for the request is revoked.
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [password]
properties:
password:
type: string
minLength: 1
maxLength: 128
responses:
'200':
description: Account deleted
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Invalid password
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees:
get:
tags: [Trees]
summary: List trees for current user
security:
- BearerAuth: []
responses:
'200':
description: Trees list
content:
application/json:
schema:
type: object
properties:
trees:
type: array
items:
allOf:
- $ref: '#/components/schemas/Tree'
- type: object
properties:
role:
type: string
enum: [owner, admin, member]
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
post:
tags: [Trees]
summary: Create tree
security:
- BearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateTreeRequest'
responses:
'201':
description: Tree created
content:
application/json:
schema:
type: object
properties:
tree:
$ref: '#/components/schemas/Tree'
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Slug already exists
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}:
get:
tags: [Trees]
summary: Get tree metadata
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: Tree metadata
'400':
description: Invalid tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
patch:
tags: [Trees]
summary: Update tree metadata
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchTreeRequest'
responses:
'200':
description: Tree updated
'400':
description: Invalid payload or tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Slug already exists
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags: [Trees]
summary: Permanently delete a tree
description: >
Owner only. Deletes the tree and all its data (persons, links, media, annotations,
contributions, audit log) and removes its media directory.
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: Tree deleted
'400':
description: Invalid tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/access/unlock:
post:
tags: [Trees]
summary: Unlock tree access with visitor/contributor password
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UnlockRequest'
responses:
'200':
description: Access granted
content:
application/json:
schema:
$ref: '#/components/schemas/UnlockResponse'
'400':
description: Invalid payload or tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Invalid password
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'429':
description: Too many requests
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/access/passwords:
patch:
tags: [Trees]
summary: Rotate visitor/contributor passwords
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchPasswordsRequest'
responses:
'200':
description: Passwords updated
'400':
description: Invalid payload or tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/stats:
get:
tags: [Trees]
summary: Get admin statistics for a tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: Tree statistics
content:
application/json:
schema:
type: object
properties:
stats:
$ref: '#/components/schemas/TreeStats'
required: [stats]
'400':
description: Invalid tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/settings:
get:
tags: [Trees]
summary: Get tree contribution settings (admin only)
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: Tree settings
content:
application/json:
schema:
type: object
properties:
settings:
$ref: '#/components/schemas/TreeSettings'
required: [settings]
'400':
description: Invalid tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
patch:
tags: [Trees]
summary: Update tree contribution settings (admin only)
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchTreeSettingsRequest'
responses:
'200':
description: Tree settings updated
content:
application/json:
schema:
type: object
properties:
settings:
$ref: '#/components/schemas/TreeSettings'
required: [settings]
'400':
description: Invalid payload or tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/audit:
get:
tags: [Trees]
summary: List admin audit logs for a tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: query
name: limit
required: false
schema:
type: integer
minimum: 1
maximum: 100
- in: query
name: offset
required: false
schema:
type: integer
minimum: 0
- in: query
name: action
required: false
schema:
type: string
responses:
'200':
description: Audit log entries
content:
application/json:
schema:
type: object
properties:
logs:
type: array
items:
$ref: '#/components/schemas/AuditLogEntry'
nextOffset:
type: integer
nullable: true
required: [logs, nextOffset]
'400':
description: Invalid query or tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/graph:
get:
tags: [Graph]
summary: Read tree graph payload
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
'200':
description: Graph payload
content:
application/json:
schema:
type: object
properties:
treeId:
type: string
rootPersonId:
type: string
nullable: true
graph:
type: object
properties:
persons:
type: array
items:
$ref: '#/components/schemas/GraphPerson'
unions:
type: array
items:
$ref: '#/components/schemas/GraphUnion'
filiations:
type: array
items:
$ref: '#/components/schemas/GraphFiliation'
medias:
type: array
items:
$ref: '#/components/schemas/GraphMedia'
'400':
description: Invalid tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/persons:
post:
tags: [Trees]
summary: Create a person in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreatePersonRequest'
responses:
'201':
description: Person created
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/persons/{personId}:
patch:
tags: [Trees]
summary: Update a person in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: personId
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchPersonRequest'
responses:
'200':
description: Person updated
'400':
description: Invalid payload or params
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Person not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags: [Trees]
summary: Soft-delete a person in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: personId
required: true
schema:
type: string
responses:
'200':
description: Person soft-deleted
'400':
description: Invalid params
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Person not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/unions:
post:
tags: [Trees]
summary: Create a union in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUnionRequest'
responses:
'201':
description: Union created
'400':
description: Invalid payload or reference
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/unions/{unionId}:
patch:
tags: [Trees]
summary: Update a union in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: unionId
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchUnionRequest'
responses:
'200':
description: Union updated
'400':
description: Invalid payload, params or person reference
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Union not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags: [Trees]
summary: Soft-delete a union in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: unionId
required: true
schema:
type: string
responses:
'200':
description: Union soft-deleted
'400':
description: Invalid params
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Union not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/links:
post:
tags: [Trees]
summary: Create a parent-child link in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateParentChildLinkRequest'
responses:
'201':
description: Link created
'400':
description: Invalid payload or reference
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/links/order:
put:
tags: [Trees]
summary: Reorder siblings (rewrites displayOrder of their parent-child links)
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ChildrenOrderRequest'
responses:
'200':
description: Order saved
'400':
description: Invalid payload, links that do not belong to their child, or children without a shared parent
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Link not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/links/{linkId}:
patch:
tags: [Trees]
summary: Update a parent-child link in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: linkId
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PatchParentChildLinkRequest'
responses:
'200':
description: Link updated
'400':
description: Invalid payload, params or references
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Link not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
delete:
tags: [Trees]
summary: Soft-delete a parent-child link in the tree
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: linkId
required: true
schema:
type: string
responses:
'200':
description: Link soft-deleted
'400':
description: Invalid params
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Link not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/persons/{personId}/media:
post:
tags: [Trees]
summary: Upload media for a person
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: personId
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UploadMediaRequest'
responses:
'201':
description: Media uploaded
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree or person not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/persons/{personId}/media/reorder:
patch:
tags: [Trees]
summary: Reorder person media
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: personId
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ReorderMediaRequest'
responses:
'200':
description: Media reordered
'400':
description: Invalid payload
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/persons/{personId}/media/{mediaId}:
delete:
tags: [Trees]
summary: Soft-delete person media
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: personId
required: true
schema:
type: string
- in: path
name: mediaId
required: true
schema:
type: string
responses:
'200':
description: Media deleted
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Media not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/media/{mediaId}:
get:
tags: [Graph]
summary: Download media file by tree and media id
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: mediaId
required: true
schema:
type: string
- in: query
name: token
required: false
schema:
type: string
responses:
'200':
description: Media binary content
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Media not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/contributions/sessions:
post:
tags: [Contributions]
summary: Submit a contribution session
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContributionSessionCreateRequest'
responses:
'201':
description: Contribution session submitted
content:
application/json:
schema:
type: object
properties:
session:
$ref: '#/components/schemas/ContributionSession'
changesCount:
type: integer
required: [session, changesCount]
'400':
description: Invalid payload or tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
get:
tags: [Contributions]
summary: List contribution sessions (admin only)
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: query
name: status
required: false
schema:
type: string
enum: [pending, approved, rejected]
responses:
'200':
description: Sessions list
content:
application/json:
schema:
type: object
properties:
sessions:
type: array
items:
$ref: '#/components/schemas/ContributionSession'
required: [sessions]
'400':
description: Invalid query or tree id
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/trees/{id}/contributions/sessions/{sessionId}/review:
post:
tags: [Contributions]
summary: Review contribution session (admin only)
security:
- BearerAuth: []
parameters:
- in: path
name: id
required: true
schema:
type: string
- in: path
name: sessionId
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ContributionReviewRequest'
responses:
'200':
description: Session reviewed
content:
application/json:
schema:
type: object
properties:
session:
$ref: '#/components/schemas/ContributionSession'
approvedCount:
type: integer
rejectedCount:
type: integer
required: [session, approvedCount, rejectedCount]
'400':
description: Invalid payload or params
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Authentication required
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Contribution session or tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'409':
description: Contribution session already reviewed
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
/arbre/{slug}:
get:
tags: [Public]
summary: Resolve slug to tree metadata
parameters:
- in: path
name: slug
required: true
schema:
type: string
responses:
'200':
description: Tree found
content:
application/json:
schema:
type: object
properties:
tree:
$ref: '#/components/schemas/Tree'
'400':
description: Invalid slug
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'404':
description: Tree not found
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'