Scaffold backend gateway and integration docs

This commit is contained in:
Rijad Zuzo
2026-02-14 20:10:16 +01:00
commit 577c4b33b7
166 changed files with 13382 additions and 0 deletions
+344
View File
@@ -0,0 +1,344 @@
openapi: 3.0.3
info:
title: Relationship Saver API
version: 0.1.0
description: |
Backend contract for auth, sync, signals, and upload scaffolding.
servers:
- url: https://api.example.com
paths:
/v1/auth/sign-in:
post:
summary: Sign in
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SignInRequest'
responses:
'200':
description: Signed-in session
content:
application/json:
schema:
$ref: '#/components/schemas/AuthSession'
/v1/auth/refresh:
post:
summary: Refresh session
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AuthRefreshRequest'
responses:
'200':
description: Refreshed token bundle
content:
application/json:
schema:
$ref: '#/components/schemas/AuthRefreshResponse'
/v1/auth/sign-out:
post:
summary: Sign out
responses:
'204':
description: Signed out
/v1/me:
get:
summary: Current user profile
responses:
'200':
description: Profile
content:
application/json:
schema:
$ref: '#/components/schemas/UserProfile'
/v1/sync/push:
post:
summary: Push local changes
parameters:
- in: header
name: Idempotency-Key
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SyncPushRequest'
responses:
'200':
description: Push result
content:
application/json:
schema:
$ref: '#/components/schemas/SyncPushResult'
/v1/sync/pull:
get:
summary: Pull remote changes
parameters:
- in: query
name: cursor
schema:
type: string
- in: query
name: limit
schema:
type: integer
default: 200
responses:
'200':
description: Pull result
content:
application/json:
schema:
$ref: '#/components/schemas/SyncPullResult'
/v1/signals:
get:
summary: Fetch signals feed
parameters:
- in: query
name: cursor
schema:
type: string
- in: query
name: since
schema:
type: string
format: date-time
- in: query
name: limit
schema:
type: integer
default: 50
- in: query
name: personId
schema:
type: array
items:
type: string
responses:
'200':
description: Signals page
content:
application/json:
schema:
$ref: '#/components/schemas/SignalsFeed'
/v1/signals/{id}/ack:
post:
summary: Acknowledge signal
parameters:
- in: path
name: id
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SignalAckRequest'
responses:
'204':
description: Acknowledged
/v1/uploads:
post:
summary: Initialize upload
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/UploadInitRequest'
responses:
'200':
description: Upload URL
content:
application/json:
schema:
$ref: '#/components/schemas/UploadInitResult'
/v1/files/{fileId}:
get:
summary: Resolve file download URL
parameters:
- in: path
name: fileId
required: true
schema:
type: string
responses:
'200':
description: Download URL
content:
application/json:
schema:
$ref: '#/components/schemas/DownloadUrl'
components:
schemas:
SignInRequest:
type: object
properties:
method:
type: string
enum: [email_magic_link, password, oidc]
email:
type: string
format: email
password:
type: string
idToken:
type: string
required: [method]
UserProfile:
type: object
properties:
id: { type: string }
email: { type: string, format: email }
displayName: { type: string }
avatarFileId: { type: string }
required: [id]
AuthSession:
type: object
properties:
accessToken: { type: string }
refreshToken: { type: string }
expiresAt: { type: string, format: date-time }
user:
$ref: '#/components/schemas/UserProfile'
required: [accessToken, refreshToken, expiresAt, user]
AuthRefreshRequest:
type: object
properties:
refreshToken: { type: string }
required: [refreshToken]
AuthRefreshResponse:
type: object
properties:
accessToken: { type: string }
refreshToken: { type: string }
expiresAt: { type: string, format: date-time }
required: [accessToken, expiresAt]
ChangeEnvelope:
type: object
properties:
schemaVersion: { type: integer }
entityType: { type: string }
entityId: { type: string }
op:
type: string
enum: [upsert, delete]
modifiedAt:
type: string
format: date-time
clientMutationId: { type: string }
payload:
type: object
nullable: true
additionalProperties: true
required:
[schemaVersion, entityType, entityId, op, modifiedAt, clientMutationId]
SyncPushRequest:
type: object
properties:
deviceId: { type: string }
cursor: { type: string }
changes:
type: array
items:
$ref: '#/components/schemas/ChangeEnvelope'
idempotencyKey: { type: string }
required: [deviceId, changes, idempotencyKey]
MutationAck:
type: object
properties:
clientMutationId: { type: string }
serverMutationId: { type: string }
acceptedAt: { type: string, format: date-time }
required: [clientMutationId]
MutationRejection:
type: object
properties:
clientMutationId: { type: string }
code: { type: string }
message: { type: string }
required: [clientMutationId, code, message]
SyncPushResult:
type: object
properties:
cursor: { type: string }
accepted:
type: array
items:
$ref: '#/components/schemas/MutationAck'
rejected:
type: array
items:
$ref: '#/components/schemas/MutationRejection'
required: [cursor, accepted, rejected]
SyncPullResult:
type: object
properties:
cursor: { type: string }
changes:
type: array
items:
$ref: '#/components/schemas/ChangeEnvelope'
required: [cursor, changes]
SignalItem:
type: object
properties:
id: { type: string }
type: { type: string }
title: { type: string }
description: { type: string }
personId: { type: string }
createdAt: { type: string, format: date-time }
metadata:
type: object
additionalProperties: true
required: [id, type, title, createdAt]
SignalsFeed:
type: object
properties:
cursor: { type: string }
items:
type: array
items:
$ref: '#/components/schemas/SignalItem'
required: [items]
SignalAckRequest:
type: object
properties:
action:
type: string
enum: [viewed, dismissed, saved, purchased]
at:
type: string
format: date-time
required: [action, at]
UploadInitRequest:
type: object
properties:
purpose:
type: string
enum: [avatar, attachment]
contentType: { type: string }
sizeBytes: { type: integer }
required: [purpose, contentType, sizeBytes]
UploadInitResult:
type: object
properties:
uploadUrl: { type: string }
fileId: { type: string }
expiresAt: { type: string, format: date-time }
required: [uploadUrl, fileId, expiresAt]
DownloadUrl:
type: object
properties:
downloadUrl: { type: string }
expiresAt: { type: string, format: date-time }
required: [downloadUrl, expiresAt]