RemoteAPI.openapi.yaml 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  1. openapi: 3.1.0
  2. info:
  3. title: Celestia Trace iOS Remote API
  4. version: 2026-07-24
  5. description: |
  6. iOS 客户端实际调用的远程接口契约。
  7. 维护规则:
  8. 1. backend 路由、请求字段或响应字段变化时,先更新本文件,再更新 Swift 模型。
  9. 2. 所有 JSON 接口使用统一响应 `{code, message, data}`。
  10. 3. 除登录、注册和刷新令牌外,接口均使用 Bearer access token。
  11. 4. 公网网关保留 `/celestia-trace/v1`;后端 Gin 路由本身使用 `/v1`。
  12. 5. 服务端时间使用 RFC 3339 / ISO 8601,客户端同时兼容带或不带小数秒。
  13. x-client-sources:
  14. - CelestiaTrace/Services/Network/APIClient.swift
  15. - CelestiaTrace/Services/Network/RemoteNetworkService.swift
  16. - CelestiaTrace/Services/Auth/RemoteAuthService.swift
  17. servers:
  18. - url: https://api.ccdw.life/celestia-trace/v1
  19. description: Production
  20. tags:
  21. - name: Health
  22. - name: Auth
  23. - name: User
  24. - name: Devices
  25. - name: Sessions
  26. - name: Assets
  27. - name: Sync
  28. paths:
  29. /health:
  30. get:
  31. tags: [Health]
  32. operationId: getHealth
  33. security: []
  34. responses:
  35. "200":
  36. description: API and database are healthy
  37. content:
  38. application/json:
  39. schema:
  40. $ref: "#/components/schemas/HealthEnvelope"
  41. "503":
  42. $ref: "#/components/responses/Error"
  43. /auth/register:
  44. post:
  45. tags: [Auth]
  46. operationId: register
  47. security: []
  48. requestBody:
  49. required: true
  50. content:
  51. application/json:
  52. schema:
  53. $ref: "#/components/schemas/RegisterRequest"
  54. responses:
  55. "200":
  56. description: Account and login session created
  57. content:
  58. application/json:
  59. schema:
  60. $ref: "#/components/schemas/AuthEnvelope"
  61. "400":
  62. $ref: "#/components/responses/Error"
  63. "409":
  64. $ref: "#/components/responses/Error"
  65. /auth/login:
  66. post:
  67. tags: [Auth]
  68. operationId: login
  69. security: []
  70. requestBody:
  71. required: true
  72. content:
  73. application/json:
  74. schema:
  75. $ref: "#/components/schemas/LoginRequest"
  76. responses:
  77. "200":
  78. description: Login session created
  79. content:
  80. application/json:
  81. schema:
  82. $ref: "#/components/schemas/AuthEnvelope"
  83. "400":
  84. $ref: "#/components/responses/Error"
  85. "401":
  86. $ref: "#/components/responses/Error"
  87. /auth/refresh:
  88. post:
  89. tags: [Auth]
  90. operationId: refreshAccessToken
  91. security: []
  92. requestBody:
  93. required: true
  94. content:
  95. application/json:
  96. schema:
  97. type: object
  98. required: [refreshToken]
  99. properties:
  100. refreshToken:
  101. type: string
  102. responses:
  103. "200":
  104. description: Tokens rotated; the old refresh token is no longer valid
  105. content:
  106. application/json:
  107. schema:
  108. $ref: "#/components/schemas/AuthEnvelope"
  109. "401":
  110. $ref: "#/components/responses/Error"
  111. /auth/logout:
  112. post:
  113. tags: [Auth]
  114. operationId: logout
  115. responses:
  116. "200":
  117. $ref: "#/components/responses/EmptySuccess"
  118. "401":
  119. $ref: "#/components/responses/Error"
  120. /user/profile:
  121. get:
  122. tags: [User]
  123. operationId: getProfile
  124. responses:
  125. "200":
  126. description: Current user
  127. content:
  128. application/json:
  129. schema:
  130. $ref: "#/components/schemas/UserEnvelope"
  131. "401":
  132. $ref: "#/components/responses/Error"
  133. put:
  134. tags: [User]
  135. operationId: updateProfile
  136. requestBody:
  137. required: true
  138. content:
  139. application/json:
  140. schema:
  141. $ref: "#/components/schemas/UpdateProfileRequest"
  142. responses:
  143. "200":
  144. description: Updated user
  145. content:
  146. application/json:
  147. schema:
  148. $ref: "#/components/schemas/UserEnvelope"
  149. "400":
  150. $ref: "#/components/responses/Error"
  151. "401":
  152. $ref: "#/components/responses/Error"
  153. "409":
  154. $ref: "#/components/responses/Error"
  155. /user/change-password:
  156. post:
  157. tags: [User]
  158. operationId: changePassword
  159. requestBody:
  160. required: true
  161. content:
  162. application/json:
  163. schema:
  164. type: object
  165. required: [oldPassword, newPassword]
  166. properties:
  167. oldPassword:
  168. type: string
  169. newPassword:
  170. type: string
  171. minLength: 6
  172. responses:
  173. "200":
  174. $ref: "#/components/responses/EmptySuccess"
  175. "400":
  176. $ref: "#/components/responses/Error"
  177. "401":
  178. $ref: "#/components/responses/Error"
  179. /devices:
  180. post:
  181. tags: [Devices]
  182. operationId: bindDevice
  183. requestBody:
  184. required: true
  185. content:
  186. application/json:
  187. schema:
  188. $ref: "#/components/schemas/BindDeviceRequest"
  189. responses:
  190. "200":
  191. description: Bound or updated cloud device
  192. content:
  193. application/json:
  194. schema:
  195. $ref: "#/components/schemas/DeviceEnvelope"
  196. "400":
  197. $ref: "#/components/responses/Error"
  198. "401":
  199. $ref: "#/components/responses/Error"
  200. /devices/{deviceId}:
  201. parameters:
  202. - $ref: "#/components/parameters/DeviceId"
  203. put:
  204. tags: [Devices]
  205. operationId: updateDevice
  206. requestBody:
  207. required: true
  208. content:
  209. application/json:
  210. schema:
  211. $ref: "#/components/schemas/UpdateDeviceRequest"
  212. responses:
  213. "200":
  214. description: Updated cloud device
  215. content:
  216. application/json:
  217. schema:
  218. $ref: "#/components/schemas/DeviceEnvelope"
  219. "401":
  220. $ref: "#/components/responses/Error"
  221. "404":
  222. $ref: "#/components/responses/Error"
  223. delete:
  224. tags: [Devices]
  225. operationId: unbindDevice
  226. responses:
  227. "200":
  228. description: Device unbound
  229. content:
  230. application/json:
  231. schema:
  232. $ref: "#/components/schemas/DeleteEnvelope"
  233. "401":
  234. $ref: "#/components/responses/Error"
  235. "404":
  236. $ref: "#/components/responses/Error"
  237. /sessions:
  238. get:
  239. tags: [Sessions, Sync]
  240. operationId: getSessionSyncIndex
  241. description: |
  242. Lightweight first phase of field-record synchronization. Returns one
  243. timestamped row per record without events or assets. The client compares
  244. `updatedAt` (and `revision` as a monotonic guard) with local state, then
  245. fetches concrete content only for new or changed records from
  246. `/sessions/{sessionId}`.
  247. parameters:
  248. - name: includeDeleted
  249. in: query
  250. schema:
  251. type: boolean
  252. default: true
  253. description: iOS uses true to receive deletion tombstones.
  254. - name: updatedAfter
  255. in: query
  256. schema:
  257. type: string
  258. format: date-time
  259. description: Optional exclusive timestamp cursor for incremental checks.
  260. responses:
  261. "200":
  262. description: Timestamp index for records visible to the current user
  263. content:
  264. application/json:
  265. schema:
  266. $ref: "#/components/schemas/SessionSyncIndexEnvelope"
  267. "400":
  268. $ref: "#/components/responses/Error"
  269. "401":
  270. $ref: "#/components/responses/Error"
  271. post:
  272. tags: [Sessions]
  273. operationId: upsertSession
  274. description: |
  275. Idempotent upsert by `(userId, clientId)`.
  276. Existing sessions must send `baseRevision`; a mismatch returns HTTP/code 409.
  277. `deletedEventClientIds` removes events deleted locally since the last pull.
  278. requestBody:
  279. required: true
  280. content:
  281. application/json:
  282. schema:
  283. $ref: "#/components/schemas/SessionUpsertRequest"
  284. responses:
  285. "200":
  286. description: Created or updated session
  287. content:
  288. application/json:
  289. schema:
  290. $ref: "#/components/schemas/SessionEnvelope"
  291. "400":
  292. $ref: "#/components/responses/Error"
  293. "401":
  294. $ref: "#/components/responses/Error"
  295. "409":
  296. description: Optimistic-lock conflict
  297. content:
  298. application/json:
  299. schema:
  300. $ref: "#/components/schemas/ConflictEnvelope"
  301. /sessions/{sessionId}:
  302. parameters:
  303. - $ref: "#/components/parameters/SessionId"
  304. get:
  305. tags: [Sessions]
  306. operationId: getSessionDetail
  307. description: Second synchronization phase for one new or changed record.
  308. responses:
  309. "200":
  310. description: Complete session metadata, events, and asset descriptors
  311. content:
  312. application/json:
  313. schema:
  314. $ref: "#/components/schemas/SessionEnvelope"
  315. "401":
  316. $ref: "#/components/responses/Error"
  317. "404":
  318. $ref: "#/components/responses/Error"
  319. delete:
  320. tags: [Sessions]
  321. operationId: deleteSession
  322. description: Soft-deletes the session and its assets for the current user.
  323. responses:
  324. "200":
  325. description: Session deleted
  326. content:
  327. application/json:
  328. schema:
  329. $ref: "#/components/schemas/DeleteEnvelope"
  330. "401":
  331. $ref: "#/components/responses/Error"
  332. "404":
  333. $ref: "#/components/responses/Error"
  334. /sessions/{sessionId}/assets:
  335. parameters:
  336. - $ref: "#/components/parameters/SessionId"
  337. post:
  338. tags: [Assets]
  339. operationId: uploadAsset
  340. description: |
  341. Used for files smaller than 16 MiB. `clientId` makes retries idempotent.
  342. A new upload returns `{asset, sessionRevision}`. An idempotent replay may
  343. return the asset directly; the iOS decoder intentionally accepts both.
  344. requestBody:
  345. required: true
  346. content:
  347. multipart/form-data:
  348. schema:
  349. type: object
  350. required: [clientId, kind, file]
  351. properties:
  352. clientId:
  353. type: string
  354. kind:
  355. $ref: "#/components/schemas/AssetKind"
  356. file:
  357. type: string
  358. format: binary
  359. responses:
  360. "200":
  361. description: Uploaded asset or idempotent existing asset
  362. content:
  363. application/json:
  364. schema:
  365. $ref: "#/components/schemas/AssetUploadEnvelope"
  366. "401":
  367. $ref: "#/components/responses/Error"
  368. "404":
  369. $ref: "#/components/responses/Error"
  370. "413":
  371. $ref: "#/components/responses/QuotaError"
  372. /sessions/{sessionId}/assets/init:
  373. parameters:
  374. - $ref: "#/components/parameters/SessionId"
  375. post:
  376. tags: [Assets]
  377. operationId: initializeChunkedUpload
  378. description: iOS uses this flow for files at least 16 MiB, with 8 MiB chunks.
  379. requestBody:
  380. required: true
  381. content:
  382. application/json:
  383. schema:
  384. $ref: "#/components/schemas/ChunkUploadInitRequest"
  385. responses:
  386. "200":
  387. description: Chunked upload initialized
  388. content:
  389. application/json:
  390. schema:
  391. $ref: "#/components/schemas/ChunkUploadInitEnvelope"
  392. "401":
  393. $ref: "#/components/responses/Error"
  394. "404":
  395. $ref: "#/components/responses/Error"
  396. "413":
  397. $ref: "#/components/responses/QuotaError"
  398. /sessions/{sessionId}/assets/chunk:
  399. parameters:
  400. - $ref: "#/components/parameters/SessionId"
  401. post:
  402. tags: [Assets]
  403. operationId: uploadChunk
  404. requestBody:
  405. required: true
  406. content:
  407. multipart/form-data:
  408. schema:
  409. type: object
  410. required: [uploadId, chunkIndex, file]
  411. properties:
  412. uploadId:
  413. type: string
  414. format: uuid
  415. chunkIndex:
  416. type: integer
  417. minimum: 0
  418. file:
  419. type: string
  420. format: binary
  421. responses:
  422. "200":
  423. description: Chunk accepted
  424. content:
  425. application/json:
  426. schema:
  427. $ref: "#/components/schemas/ChunkProgressEnvelope"
  428. "400":
  429. $ref: "#/components/responses/Error"
  430. "401":
  431. $ref: "#/components/responses/Error"
  432. "404":
  433. $ref: "#/components/responses/Error"
  434. "410":
  435. $ref: "#/components/responses/Error"
  436. /sessions/{sessionId}/assets/complete:
  437. parameters:
  438. - $ref: "#/components/parameters/SessionId"
  439. post:
  440. tags: [Assets]
  441. operationId: completeChunkedUpload
  442. requestBody:
  443. required: true
  444. content:
  445. application/json:
  446. schema:
  447. type: object
  448. required: [uploadId, totalChunks]
  449. properties:
  450. uploadId:
  451. type: string
  452. format: uuid
  453. totalChunks:
  454. type: integer
  455. minimum: 1
  456. responses:
  457. "200":
  458. description: Chunks merged and asset created
  459. content:
  460. application/json:
  461. schema:
  462. $ref: "#/components/schemas/AssetUploadEnvelope"
  463. "400":
  464. $ref: "#/components/responses/Error"
  465. "401":
  466. $ref: "#/components/responses/Error"
  467. "404":
  468. $ref: "#/components/responses/Error"
  469. "410":
  470. $ref: "#/components/responses/Error"
  471. /sessions/{sessionId}/assets/{assetId}:
  472. parameters:
  473. - $ref: "#/components/parameters/SessionId"
  474. - $ref: "#/components/parameters/AssetId"
  475. get:
  476. tags: [Assets]
  477. operationId: downloadAsset
  478. responses:
  479. "200":
  480. description: Attachment bytes; Content-Disposition contains the original filename
  481. content:
  482. application/octet-stream:
  483. schema:
  484. type: string
  485. format: binary
  486. "401":
  487. $ref: "#/components/responses/Error"
  488. "404":
  489. $ref: "#/components/responses/Error"
  490. /storage/quota:
  491. get:
  492. tags: [Sync]
  493. operationId: getStorageQuota
  494. description: Called before uploading the pending assets for a session.
  495. responses:
  496. "200":
  497. description: Current storage quota in bytes
  498. content:
  499. application/json:
  500. schema:
  501. $ref: "#/components/schemas/StorageQuotaEnvelope"
  502. "401":
  503. $ref: "#/components/responses/Error"
  504. /sync/trigger:
  505. post:
  506. tags: [Sync]
  507. operationId: recordSyncCheckpoint
  508. description: Called only after all session metadata and assets finish syncing.
  509. responses:
  510. "200":
  511. description: Client sync checkpoint recorded
  512. content:
  513. application/json:
  514. schema:
  515. $ref: "#/components/schemas/SyncCheckpointEnvelope"
  516. "401":
  517. $ref: "#/components/responses/Error"
  518. components:
  519. securitySchemes:
  520. bearerAuth:
  521. type: http
  522. scheme: bearer
  523. bearerFormat: JWT
  524. parameters:
  525. DeviceId:
  526. name: deviceId
  527. in: path
  528. required: true
  529. schema:
  530. type: string
  531. format: uuid
  532. SessionId:
  533. name: sessionId
  534. in: path
  535. required: true
  536. schema:
  537. type: string
  538. format: uuid
  539. AssetId:
  540. name: assetId
  541. in: path
  542. required: true
  543. schema:
  544. type: string
  545. format: uuid
  546. responses:
  547. EmptySuccess:
  548. description: Success without a data payload
  549. content:
  550. application/json:
  551. schema:
  552. $ref: "#/components/schemas/EmptyEnvelope"
  553. Error:
  554. description: Request failed
  555. content:
  556. application/json:
  557. schema:
  558. $ref: "#/components/schemas/ErrorEnvelope"
  559. QuotaError:
  560. description: Storage quota exceeded
  561. content:
  562. application/json:
  563. schema:
  564. $ref: "#/components/schemas/QuotaErrorEnvelope"
  565. schemas:
  566. EnvelopeBase:
  567. type: object
  568. required: [code, message]
  569. properties:
  570. code:
  571. type: integer
  572. message:
  573. type: string
  574. EmptyEnvelope:
  575. allOf:
  576. - $ref: "#/components/schemas/EnvelopeBase"
  577. - type: object
  578. properties:
  579. data:
  580. type: "null"
  581. ErrorEnvelope:
  582. allOf:
  583. - $ref: "#/components/schemas/EnvelopeBase"
  584. - type: object
  585. properties:
  586. data: {}
  587. HealthEnvelope:
  588. allOf:
  589. - $ref: "#/components/schemas/EnvelopeBase"
  590. - type: object
  591. required: [data]
  592. properties:
  593. data:
  594. type: string
  595. const: healthy
  596. RegisterRequest:
  597. type: object
  598. required: [username, identifier, password]
  599. properties:
  600. username:
  601. type: string
  602. minLength: 2
  603. identifier:
  604. type: string
  605. description: Email address or phone number.
  606. password:
  607. type: string
  608. minLength: 6
  609. LoginRequest:
  610. type: object
  611. required: [identifier, password]
  612. properties:
  613. identifier:
  614. type: string
  615. description: Username, email address, or phone number.
  616. password:
  617. type: string
  618. UpdateProfileRequest:
  619. type: object
  620. properties:
  621. username:
  622. type: [string, "null"]
  623. email:
  624. type: [string, "null"]
  625. phoneNumber:
  626. type: [string, "null"]
  627. avatarURL:
  628. type: [string, "null"]
  629. User:
  630. type: object
  631. required: [id, username, registeredAt]
  632. properties:
  633. id:
  634. type: string
  635. format: uuid
  636. username:
  637. type: string
  638. email:
  639. type: string
  640. phoneNumber:
  641. type: string
  642. avatarURL:
  643. type: string
  644. format: uri
  645. registeredAt:
  646. type: string
  647. format: date-time
  648. updatedAt:
  649. type: string
  650. format: date-time
  651. AuthData:
  652. type: object
  653. required: [user, token, refreshToken, expiresAt]
  654. properties:
  655. user:
  656. $ref: "#/components/schemas/User"
  657. token:
  658. type: string
  659. description: Short-lived access JWT.
  660. refreshToken:
  661. type: string
  662. description: Rotated on every refresh.
  663. expiresAt:
  664. type: string
  665. format: date-time
  666. AuthEnvelope:
  667. allOf:
  668. - $ref: "#/components/schemas/EnvelopeBase"
  669. - type: object
  670. required: [data]
  671. properties:
  672. data:
  673. $ref: "#/components/schemas/AuthData"
  674. UserEnvelope:
  675. allOf:
  676. - $ref: "#/components/schemas/EnvelopeBase"
  677. - type: object
  678. required: [data]
  679. properties:
  680. data:
  681. $ref: "#/components/schemas/User"
  682. BindDeviceRequest:
  683. type: object
  684. required: [name]
  685. properties:
  686. name:
  687. type: string
  688. peripheralUUID:
  689. type: string
  690. hardwareMAC:
  691. type: [string, "null"]
  692. firmwareVersion:
  693. type: [string, "null"]
  694. batteryLevel:
  695. type: [integer, "null"]
  696. minimum: 0
  697. maximum: 100
  698. freeStorageMB:
  699. type: [integer, "null"]
  700. totalStorageMB:
  701. type: [integer, "null"]
  702. UpdateDeviceRequest:
  703. type: object
  704. properties:
  705. name:
  706. type: [string, "null"]
  707. batteryLevel:
  708. type: [integer, "null"]
  709. minimum: 0
  710. maximum: 100
  711. isConnected:
  712. type: [boolean, "null"]
  713. firmwareVersion:
  714. type: [string, "null"]
  715. freeStorageMB:
  716. type: [integer, "null"]
  717. totalStorageMB:
  718. type: [integer, "null"]
  719. Device:
  720. type: object
  721. required: [id, name, peripheralUUID]
  722. properties:
  723. id:
  724. type: string
  725. format: uuid
  726. userId:
  727. type: string
  728. format: uuid
  729. name:
  730. type: string
  731. peripheralUUID:
  732. type: string
  733. hardwareMAC:
  734. type: string
  735. batteryLevel:
  736. type: integer
  737. firmwareVersion:
  738. type: string
  739. freeStorageMB:
  740. type: integer
  741. totalStorageMB:
  742. type: integer
  743. isConnected:
  744. type: boolean
  745. boundAt:
  746. type: string
  747. format: date-time
  748. updatedAt:
  749. type: string
  750. format: date-time
  751. DeviceEnvelope:
  752. allOf:
  753. - $ref: "#/components/schemas/EnvelopeBase"
  754. - type: object
  755. required: [data]
  756. properties:
  757. data:
  758. $ref: "#/components/schemas/Device"
  759. EventUpsert:
  760. type: object
  761. required: [clientId, relativeTimeMs, eventType]
  762. properties:
  763. clientId:
  764. type: string
  765. relativeTimeMs:
  766. type: integer
  767. format: int64
  768. eventType:
  769. type: string
  770. enum: [PHOTO, NOTE, MARKER, VOICE, CONTINUATION]
  771. textContent:
  772. type: [string, "null"]
  773. voiceStartOffsetMs:
  774. type: [integer, "null"]
  775. format: int64
  776. voiceEndOffsetMs:
  777. type: [integer, "null"]
  778. format: int64
  779. locationName:
  780. type: [string, "null"]
  781. locationAddress:
  782. type: [string, "null"]
  783. latitude:
  784. type: [number, "null"]
  785. format: double
  786. minimum: -90
  787. maximum: 90
  788. longitude:
  789. type: [number, "null"]
  790. format: double
  791. minimum: -180
  792. maximum: 180
  793. SessionUpsertRequest:
  794. type: object
  795. required: [clientId, title, startTime, durationMs, events, deletedEventClientIds]
  796. properties:
  797. clientId:
  798. type: string
  799. title:
  800. type: string
  801. startTime:
  802. type: string
  803. format: date-time
  804. endTime:
  805. type: [string, "null"]
  806. format: date-time
  807. durationMs:
  808. type: integer
  809. format: int64
  810. events:
  811. type: array
  812. items:
  813. $ref: "#/components/schemas/EventUpsert"
  814. baseRevision:
  815. type: [integer, "null"]
  816. format: int64
  817. deletedEventClientIds:
  818. type: array
  819. items:
  820. type: string
  821. RemoteEvent:
  822. allOf:
  823. - $ref: "#/components/schemas/EventUpsert"
  824. - type: object
  825. required: [id]
  826. properties:
  827. id:
  828. type: string
  829. format: uuid
  830. clientId:
  831. type: [string, "null"]
  832. createdAt:
  833. type: string
  834. format: date-time
  835. RemoteSession:
  836. type: object
  837. required: [id, title, startTime, durationMs, revision, updatedAt]
  838. properties:
  839. id:
  840. type: string
  841. format: uuid
  842. clientId:
  843. type: [string, "null"]
  844. title:
  845. type: string
  846. startTime:
  847. type: string
  848. format: date-time
  849. endTime:
  850. type: [string, "null"]
  851. format: date-time
  852. durationMs:
  853. type: integer
  854. format: int64
  855. revision:
  856. type: integer
  857. format: int64
  858. updatedAt:
  859. type: string
  860. format: date-time
  861. deletedAt:
  862. type: [string, "null"]
  863. format: date-time
  864. events:
  865. type: array
  866. items:
  867. $ref: "#/components/schemas/RemoteEvent"
  868. assets:
  869. type: array
  870. items:
  871. $ref: "#/components/schemas/Asset"
  872. SessionSyncIndexItem:
  873. type: object
  874. required:
  875. [id, title, startTime, durationMs, photoCount, noteCount, revision, updatedAt]
  876. properties:
  877. id:
  878. type: string
  879. format: uuid
  880. clientId:
  881. type: [string, "null"]
  882. title:
  883. type: string
  884. startTime:
  885. type: string
  886. format: date-time
  887. endTime:
  888. type: [string, "null"]
  889. format: date-time
  890. durationMs:
  891. type: integer
  892. format: int64
  893. photoCount:
  894. type: integer
  895. minimum: 0
  896. noteCount:
  897. type: integer
  898. minimum: 0
  899. revision:
  900. type: integer
  901. format: int64
  902. updatedAt:
  903. type: string
  904. format: date-time
  905. deletedAt:
  906. type: [string, "null"]
  907. format: date-time
  908. SessionEnvelope:
  909. allOf:
  910. - $ref: "#/components/schemas/EnvelopeBase"
  911. - type: object
  912. required: [data]
  913. properties:
  914. data:
  915. $ref: "#/components/schemas/RemoteSession"
  916. SessionSyncIndexEnvelope:
  917. allOf:
  918. - $ref: "#/components/schemas/EnvelopeBase"
  919. - type: object
  920. required: [data]
  921. properties:
  922. data:
  923. type: array
  924. items:
  925. $ref: "#/components/schemas/SessionSyncIndexItem"
  926. ConflictEnvelope:
  927. allOf:
  928. - $ref: "#/components/schemas/EnvelopeBase"
  929. - type: object
  930. required: [data]
  931. properties:
  932. data:
  933. type: object
  934. required: [serverRevision]
  935. properties:
  936. serverRevision:
  937. type: integer
  938. format: int64
  939. AssetKind:
  940. type: string
  941. enum: [AUDIO, PHOTO]
  942. Asset:
  943. type: object
  944. required: [id, clientId, kind, fileName, mimeType, sizeBytes, sha256]
  945. properties:
  946. id:
  947. type: string
  948. format: uuid
  949. clientId:
  950. type: string
  951. kind:
  952. $ref: "#/components/schemas/AssetKind"
  953. fileName:
  954. type: string
  955. mimeType:
  956. type: string
  957. sizeBytes:
  958. type: integer
  959. format: int64
  960. sha256:
  961. type: string
  962. pattern: "^[a-fA-F0-9]{64}$"
  963. createdAt:
  964. type: string
  965. format: date-time
  966. AssetUploadData:
  967. type: object
  968. required: [asset, sessionRevision]
  969. properties:
  970. asset:
  971. $ref: "#/components/schemas/Asset"
  972. sessionRevision:
  973. type: integer
  974. format: int64
  975. AssetUploadEnvelope:
  976. allOf:
  977. - $ref: "#/components/schemas/EnvelopeBase"
  978. - type: object
  979. required: [data]
  980. properties:
  981. data:
  982. oneOf:
  983. - $ref: "#/components/schemas/AssetUploadData"
  984. - $ref: "#/components/schemas/Asset"
  985. ChunkUploadInitRequest:
  986. type: object
  987. required: [clientId, kind, fileName, mimeType, fileSize, chunkSize]
  988. properties:
  989. clientId:
  990. type: string
  991. kind:
  992. $ref: "#/components/schemas/AssetKind"
  993. fileName:
  994. type: string
  995. mimeType:
  996. type: string
  997. fileSize:
  998. type: integer
  999. format: int64
  1000. minimum: 1
  1001. chunkSize:
  1002. type: integer
  1003. minimum: 1
  1004. ChunkUploadInitEnvelope:
  1005. allOf:
  1006. - $ref: "#/components/schemas/EnvelopeBase"
  1007. - type: object
  1008. required: [data]
  1009. properties:
  1010. data:
  1011. type: object
  1012. required: [uploadId, totalChunks, chunkSize, expiresAt]
  1013. properties:
  1014. uploadId:
  1015. type: string
  1016. format: uuid
  1017. totalChunks:
  1018. type: integer
  1019. chunkSize:
  1020. type: integer
  1021. expiresAt:
  1022. type: string
  1023. format: date-time
  1024. ChunkProgressEnvelope:
  1025. allOf:
  1026. - $ref: "#/components/schemas/EnvelopeBase"
  1027. - type: object
  1028. required: [data]
  1029. properties:
  1030. data:
  1031. type: object
  1032. required: [uploadId, chunkIndex, uploadedChunks, totalChunks]
  1033. properties:
  1034. uploadId:
  1035. type: string
  1036. format: uuid
  1037. chunkIndex:
  1038. type: integer
  1039. uploadedChunks:
  1040. type: integer
  1041. totalChunks:
  1042. type: integer
  1043. StorageQuota:
  1044. type: object
  1045. required: [totalBytes, usedBytes, remainingBytes]
  1046. properties:
  1047. totalBytes:
  1048. type: integer
  1049. format: int64
  1050. usedBytes:
  1051. type: integer
  1052. format: int64
  1053. remainingBytes:
  1054. type: integer
  1055. format: int64
  1056. StorageQuotaEnvelope:
  1057. allOf:
  1058. - $ref: "#/components/schemas/EnvelopeBase"
  1059. - type: object
  1060. required: [data]
  1061. properties:
  1062. data:
  1063. $ref: "#/components/schemas/StorageQuota"
  1064. QuotaErrorEnvelope:
  1065. allOf:
  1066. - $ref: "#/components/schemas/EnvelopeBase"
  1067. - type: object
  1068. required: [data]
  1069. properties:
  1070. data:
  1071. allOf:
  1072. - $ref: "#/components/schemas/StorageQuota"
  1073. - type: object
  1074. required: [requiredBytes]
  1075. properties:
  1076. requiredBytes:
  1077. type: integer
  1078. format: int64
  1079. SyncCheckpointEnvelope:
  1080. allOf:
  1081. - $ref: "#/components/schemas/EnvelopeBase"
  1082. - type: object
  1083. required: [data]
  1084. properties:
  1085. data:
  1086. type: object
  1087. required: [syncedAt, message]
  1088. properties:
  1089. syncedAt:
  1090. type: string
  1091. format: date-time
  1092. message:
  1093. type: string
  1094. DeleteEnvelope:
  1095. allOf:
  1096. - $ref: "#/components/schemas/EnvelopeBase"
  1097. - type: object
  1098. required: [data]
  1099. properties:
  1100. data:
  1101. type: object
  1102. required: [deletedId]
  1103. properties:
  1104. deletedId:
  1105. type: string
  1106. security:
  1107. - bearerAuth: []