Scaffold backend gateway and integration docs
This commit is contained in:
@@ -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]
|
||||
Reference in New Issue
Block a user