@nasebanal/cli 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/specs/target.yaml CHANGED
@@ -1,14 +1,8 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: NASEBANAL - Target API
4
- description: >-
5
- Target API for NASEBANAL. Provides hierarchical target management: users define goals and organize them in a tree
6
- structure. Parent-child links are persisted via `targets.parent_target_id` (authoritative since migration 0017); a
7
- legacy cell-based storage layer is kept in sync best-effort for backward compatibility. Targets can be shared with
8
- other users (read/write, optionally including the subtree and linked Recorder data), and ownership of a personal
9
- target subtree can be transferred to a recipient via an email-approved migration flow. Supports user authentication
10
- via Auth0 JWT and Personal Access Tokens (PAT).
11
- version: 1.4.1
4
+ description: "Target API for NASEBANAL. Provides hierarchical target management: users define goals and organize them in a tree structure. Parent-child links are persisted via `targets.parent_target_id` (authoritative since migration 0017); a legacy cell-based storage layer is kept in sync best-effort for backward compatibility. Targets can be shared with other users (read/write, optionally including the subtree and linked Recorder data), and ownership of a personal target subtree can be transferred to a recipient via an email-approved migration flow. Supports user authentication via Auth0 JWT and Personal Access Tokens (PAT)."
5
+ version: 1.5.0
12
6
  contact:
13
7
  name: NASEBANAL
14
8
  url: https://www.nasebanal.com
@@ -29,7 +23,7 @@ paths:
29
23
  description: Returns the health status of the API.
30
24
  security: []
31
25
  responses:
32
- '200':
26
+ "200":
33
27
  description: API is healthy
34
28
  content:
35
29
  application/json:
@@ -41,7 +35,8 @@ paths:
41
35
  properties:
42
36
  success:
43
37
  type: boolean
44
- enum: [true]
38
+ enum:
39
+ - true
45
40
  data:
46
41
  type: object
47
42
  properties:
@@ -59,26 +54,21 @@ paths:
59
54
  summary: Get current user profile
60
55
  description: Returns the authenticated user's profile information (resolved from the Account API).
61
56
  responses:
62
- '200':
57
+ "200":
63
58
  description: User profile
64
59
  content:
65
60
  application/json:
66
61
  schema:
67
- $ref: '#/components/schemas/UserResponse'
68
- '401':
69
- $ref: '#/components/responses/Unauthorized'
62
+ $ref: "#/components/schemas/UserResponse"
63
+ "401":
64
+ $ref: "#/components/responses/Unauthorized"
70
65
  /api/v1/targets:
71
66
  get:
72
67
  operationId: listTargets
73
68
  tags:
74
69
  - Targets
75
70
  summary: List targets
76
- description: >-
77
- Returns all targets belonging to the authenticated user in the active namespace (personal, or the active
78
- organization), ordered by last updated. By default each target includes its storage cells so clients do not
79
- need to issue a follow-up GET /targets/{id} per row. Pass `fields=summary` to omit `cells` and reduce payload
80
- size for callers (e.g. a tree/chart view) that only need `progress` — fetch full detail on demand via
81
- GET /targets/{id}.
71
+ description: Returns all targets belonging to the authenticated user in the active namespace (personal, or the active organization), ordered by last updated. By default each target includes its storage cells so clients do not need to issue a follow-up GET /targets/{id} per row. Pass `fields=summary` to omit `cells` and reduce payload size for callers (e.g. a tree/chart view) that only need `progress` — fetch full detail on demand via GET /targets/{id}.
82
72
  parameters:
83
73
  - name: fields
84
74
  in: query
@@ -89,11 +79,9 @@ paths:
89
79
  - full
90
80
  - summary
91
81
  default: full
92
- description: >-
93
- `full` (default) returns every target's complete `cells` array — today's exact behavior, unchanged for
94
- callers that omit this param. `summary` omits `cells`; `progress` is present in both modes.
82
+ description: "`full` (default) returns every target's complete `cells` array — today's exact behavior, unchanged for callers that omit this param. `summary` omits `cells`; `progress` is present in both modes."
95
83
  responses:
96
- '200':
84
+ "200":
97
85
  description: List of targets with cells (or, with fields=summary, without cells)
98
86
  content:
99
87
  application/json:
@@ -105,7 +93,8 @@ paths:
105
93
  properties:
106
94
  success:
107
95
  type: boolean
108
- enum: [true]
96
+ enum:
97
+ - true
109
98
  data:
110
99
  type: object
111
100
  required:
@@ -115,7 +104,7 @@ paths:
115
104
  data:
116
105
  type: array
117
106
  items:
118
- $ref: '#/components/schemas/TargetWithCells'
107
+ $ref: "#/components/schemas/TargetWithCells"
119
108
  total:
120
109
  type: integer
121
110
  examples:
@@ -137,8 +126,8 @@ paths:
137
126
  recorder_goal_id: null
138
127
  progress: 40
139
128
  own_progress: 40
140
- created_at: '2026-05-14T12:00:00Z'
141
- updated_at: '2026-05-14T12:00:00Z'
129
+ created_at: 2026-05-14T12:00:00Z
130
+ updated_at: 2026-05-14T12:00:00Z
142
131
  owner_email: user@example.com
143
132
  owner_name: Sample User
144
133
  created_by_email: user@example.com
@@ -151,8 +140,8 @@ paths:
151
140
  text: Learn Japanese
152
141
  progress: 40
153
142
  created_by_user_id: 42
154
- created_at: '2026-05-14T12:00:00Z'
155
- updated_at: '2026-05-14T12:00:00Z'
143
+ created_at: 2026-05-14T12:00:00Z
144
+ updated_at: 2026-05-14T12:00:00Z
156
145
  total: 1
157
146
  summary:
158
147
  summary: fields=summary
@@ -172,67 +161,63 @@ paths:
172
161
  recorder_goal_id: null
173
162
  progress: 40
174
163
  own_progress: 40
175
- created_at: '2026-05-14T12:00:00Z'
176
- updated_at: '2026-05-14T12:00:00Z'
164
+ created_at: 2026-05-14T12:00:00Z
165
+ updated_at: 2026-05-14T12:00:00Z
177
166
  owner_email: user@example.com
178
167
  owner_name: Sample User
179
168
  created_by_email: user@example.com
180
169
  created_by_name: Sample User
181
170
  created_by_deleted: false
182
171
  total: 1
183
- '401':
184
- $ref: '#/components/responses/Unauthorized'
172
+ "401":
173
+ $ref: "#/components/responses/Unauthorized"
185
174
  post:
186
175
  operationId: createTarget
187
176
  tags:
188
177
  - Targets
189
178
  summary: Create target
190
- description: >-
191
- Creates a new target. The storage cells are initialized with the target title pre-populated at position 40 (the
192
- slot reserved for the target's own label). Optionally nests the new target under an existing parent.
179
+ description: Creates a new target. The storage cells are initialized with the target title pre-populated at position 40 (the slot reserved for the target's own label). Optionally nests the new target under an existing parent.
193
180
  requestBody:
194
181
  required: true
195
182
  content:
196
183
  application/json:
197
184
  schema:
198
- $ref: '#/components/schemas/CreateTargetInput'
185
+ $ref: "#/components/schemas/CreateTargetInput"
199
186
  responses:
200
- '201':
187
+ "201":
201
188
  description: Target created with its storage cells
202
189
  content:
203
190
  application/json:
204
191
  schema:
205
- $ref: '#/components/schemas/TargetWithCellsResponse'
206
- '400':
207
- $ref: '#/components/responses/ValidationError'
208
- '401':
209
- $ref: '#/components/responses/Unauthorized'
210
- '403':
211
- $ref: '#/components/responses/Forbidden'
212
- '404':
213
- $ref: '#/components/responses/NotFound'
192
+ $ref: "#/components/schemas/TargetWithCellsResponse"
193
+ "400":
194
+ $ref: "#/components/responses/ValidationError"
195
+ "401":
196
+ $ref: "#/components/responses/Unauthorized"
197
+ "403":
198
+ $ref: "#/components/responses/Forbidden"
199
+ "404":
200
+ $ref: "#/components/responses/NotFound"
214
201
  /api/v1/targets/{id}:
215
202
  get:
216
203
  operationId: getTarget
217
204
  tags:
218
205
  - Targets
219
206
  summary: Get target
220
- description: >-
221
- Returns a single target with its storage cells. Accessible by the owner, by a user the target is shared with,
222
- or by an admin of the organization that owns the target.
207
+ description: Returns a single target with its storage cells. Accessible by the owner, by a user the target is shared with, or by an admin of the organization that owns the target.
223
208
  parameters:
224
- - $ref: '#/components/parameters/TargetId'
209
+ - $ref: "#/components/parameters/TargetId"
225
210
  responses:
226
- '200':
211
+ "200":
227
212
  description: Target with cells
228
213
  content:
229
214
  application/json:
230
215
  schema:
231
- $ref: '#/components/schemas/TargetWithCellsResponse'
232
- '401':
233
- $ref: '#/components/responses/Unauthorized'
234
- '404':
235
- $ref: '#/components/responses/NotFound'
216
+ $ref: "#/components/schemas/TargetWithCellsResponse"
217
+ "401":
218
+ $ref: "#/components/responses/Unauthorized"
219
+ "404":
220
+ $ref: "#/components/responses/NotFound"
236
221
  put:
237
222
  operationId: updateTarget
238
223
  tags:
@@ -240,15 +225,15 @@ paths:
240
225
  summary: Update target
241
226
  description: Updates a target's title, description, memo, and/or its Recorder tag binding.
242
227
  parameters:
243
- - $ref: '#/components/parameters/TargetId'
228
+ - $ref: "#/components/parameters/TargetId"
244
229
  requestBody:
245
230
  required: true
246
231
  content:
247
232
  application/json:
248
233
  schema:
249
- $ref: '#/components/schemas/UpdateTargetInput'
234
+ $ref: "#/components/schemas/UpdateTargetInput"
250
235
  responses:
251
- '200':
236
+ "200":
252
237
  description: Target updated
253
238
  content:
254
239
  application/json:
@@ -260,15 +245,16 @@ paths:
260
245
  properties:
261
246
  success:
262
247
  type: boolean
263
- enum: [true]
248
+ enum:
249
+ - true
264
250
  data:
265
- $ref: '#/components/schemas/Target'
266
- '400':
267
- $ref: '#/components/responses/ValidationError'
268
- '401':
269
- $ref: '#/components/responses/Unauthorized'
270
- '404':
271
- $ref: '#/components/responses/NotFound'
251
+ $ref: "#/components/schemas/Target"
252
+ "400":
253
+ $ref: "#/components/responses/ValidationError"
254
+ "401":
255
+ $ref: "#/components/responses/Unauthorized"
256
+ "404":
257
+ $ref: "#/components/responses/NotFound"
272
258
  delete:
273
259
  operationId: deleteTarget
274
260
  tags:
@@ -276,18 +262,18 @@ paths:
276
262
  summary: Delete target
277
263
  description: Deletes a target and all its cells.
278
264
  parameters:
279
- - $ref: '#/components/parameters/TargetId'
265
+ - $ref: "#/components/parameters/TargetId"
280
266
  responses:
281
- '200':
267
+ "200":
282
268
  description: Target deleted
283
269
  content:
284
270
  application/json:
285
271
  schema:
286
- $ref: '#/components/schemas/SuccessFlagResponse'
287
- '401':
288
- $ref: '#/components/responses/Unauthorized'
289
- '404':
290
- $ref: '#/components/responses/NotFound'
272
+ $ref: "#/components/schemas/SuccessFlagResponse"
273
+ "401":
274
+ $ref: "#/components/responses/Unauthorized"
275
+ "404":
276
+ $ref: "#/components/responses/NotFound"
291
277
  /api/v1/targets/{id}/cells/{position}:
292
278
  put:
293
279
  operationId: updateTargetCell
@@ -296,7 +282,7 @@ paths:
296
282
  summary: Update target cell
297
283
  description: Updates the text and/or progress of a specific storage cell on a target.
298
284
  parameters:
299
- - $ref: '#/components/parameters/TargetId'
285
+ - $ref: "#/components/parameters/TargetId"
300
286
  - name: position
301
287
  in: path
302
288
  required: true
@@ -310,9 +296,9 @@ paths:
310
296
  content:
311
297
  application/json:
312
298
  schema:
313
- $ref: '#/components/schemas/UpdateTargetCellInput'
299
+ $ref: "#/components/schemas/UpdateTargetCellInput"
314
300
  responses:
315
- '200':
301
+ "200":
316
302
  description: Cell updated
317
303
  content:
318
304
  application/json:
@@ -324,35 +310,33 @@ paths:
324
310
  properties:
325
311
  success:
326
312
  type: boolean
327
- enum: [true]
313
+ enum:
314
+ - true
328
315
  data:
329
- $ref: '#/components/schemas/TargetCell'
330
- '400':
331
- $ref: '#/components/responses/ValidationError'
332
- '401':
333
- $ref: '#/components/responses/Unauthorized'
334
- '404':
335
- $ref: '#/components/responses/NotFound'
316
+ $ref: "#/components/schemas/TargetCell"
317
+ "400":
318
+ $ref: "#/components/responses/ValidationError"
319
+ "401":
320
+ $ref: "#/components/responses/Unauthorized"
321
+ "404":
322
+ $ref: "#/components/responses/NotFound"
336
323
  /api/v1/targets/{id}/parent:
337
324
  put:
338
325
  operationId: setTargetParent
339
326
  tags:
340
327
  - Targets
341
328
  summary: Set target parent
342
- description: >-
343
- Authoritative tree-move endpoint (migration 0017+). Sets or clears `parent_target_id` on the target. Pass
344
- `null` to detach (move to root). The legacy sub-goal cells are updated best-effort to keep older clients in
345
- sync. Parent and child must share the same organization namespace and the same owner; cycles are rejected.
329
+ description: Authoritative tree-move endpoint (migration 0017+). Sets or clears `parent_target_id` on the target. Pass `null` to detach (move to root). The legacy sub-goal cells are updated best-effort to keep older clients in sync. Parent and child must share the same organization namespace and the same owner; cycles are rejected.
346
330
  parameters:
347
- - $ref: '#/components/parameters/TargetId'
331
+ - $ref: "#/components/parameters/TargetId"
348
332
  requestBody:
349
333
  required: true
350
334
  content:
351
335
  application/json:
352
336
  schema:
353
- $ref: '#/components/schemas/SetTargetParentInput'
337
+ $ref: "#/components/schemas/SetTargetParentInput"
354
338
  responses:
355
- '200':
339
+ "200":
356
340
  description: Parent updated; returns the updated target
357
341
  content:
358
342
  application/json:
@@ -364,33 +348,31 @@ paths:
364
348
  properties:
365
349
  success:
366
350
  type: boolean
367
- enum: [true]
351
+ enum:
352
+ - true
368
353
  data:
369
- $ref: '#/components/schemas/Target'
370
- '400':
354
+ $ref: "#/components/schemas/Target"
355
+ "400":
371
356
  description: Invalid move (self-parent, namespace mismatch, or cycle)
372
357
  content:
373
358
  application/json:
374
359
  schema:
375
- $ref: '#/components/schemas/Error'
376
- '401':
377
- $ref: '#/components/responses/Unauthorized'
378
- '403':
379
- $ref: '#/components/responses/Forbidden'
380
- '404':
381
- $ref: '#/components/responses/NotFound'
360
+ $ref: "#/components/schemas/Error"
361
+ "401":
362
+ $ref: "#/components/responses/Unauthorized"
363
+ "403":
364
+ $ref: "#/components/responses/Forbidden"
365
+ "404":
366
+ $ref: "#/components/responses/NotFound"
382
367
  /api/v1/shared-targets:
383
368
  get:
384
369
  operationId: listSharedTargets
385
370
  tags:
386
371
  - Sharing
387
372
  summary: List targets shared with me
388
- description: >-
389
- Returns targets that other users have shared with the authenticated user and accepted (not paused, not hidden),
390
- scoped to the active namespace via each share's `shared_with_org_id`. When `include_descendants` was set on the
391
- share, the whole subtree is expanded. Each row carries the sharing owner and the effective permission.
373
+ description: Returns targets that other users have shared with the authenticated user and accepted (not paused, not hidden), scoped to the active namespace via each share's `shared_with_org_id`. When `include_descendants` was set on the share, the whole subtree is expanded. Each row carries the sharing owner and the effective permission.
392
374
  responses:
393
- '200':
375
+ "200":
394
376
  description: Shared targets
395
377
  content:
396
378
  application/json:
@@ -402,7 +384,8 @@ paths:
402
384
  properties:
403
385
  success:
404
386
  type: boolean
405
- enum: [true]
387
+ enum:
388
+ - true
406
389
  data:
407
390
  type: object
408
391
  required:
@@ -412,48 +395,41 @@ paths:
412
395
  data:
413
396
  type: array
414
397
  items:
415
- $ref: '#/components/schemas/SharedTarget'
398
+ $ref: "#/components/schemas/SharedTarget"
416
399
  total:
417
400
  type: integer
418
- '401':
419
- $ref: '#/components/responses/Unauthorized'
401
+ "401":
402
+ $ref: "#/components/responses/Unauthorized"
420
403
  /api/v1/shares:
421
404
  get:
422
405
  operationId: listMyShares
423
406
  tags:
424
407
  - Sharing
425
408
  summary: List shares I created
426
- description: >-
427
- Returns shares the authenticated user owns (i.e. shares of their own targets), scoped to the active namespace.
428
- Each row is enriched with the recipient email, the owner's plan, and the owner-side target chain.
409
+ description: Returns shares the authenticated user owns (i.e. shares of their own targets), scoped to the active namespace. Each row is enriched with the recipient email, the owner's plan, and the owner-side target chain.
429
410
  responses:
430
- '200':
411
+ "200":
431
412
  description: Shares owned by the caller
432
413
  content:
433
414
  application/json:
434
415
  schema:
435
- $ref: '#/components/schemas/ShareListResponse'
436
- '401':
437
- $ref: '#/components/responses/Unauthorized'
416
+ $ref: "#/components/schemas/ShareListResponse"
417
+ "401":
418
+ $ref: "#/components/responses/Unauthorized"
438
419
  post:
439
420
  operationId: createShare
440
421
  tags:
441
422
  - Sharing
442
423
  summary: Create a share invitation
443
- description: >-
444
- Shares a target the caller owns with another user by email. Sends an invitation email containing an accept
445
- link; the share is `pending` until accepted. Optionally includes the subtree (`include_descendants`) and the
446
- linked Recorder tag data (`include_data`, which cascades matching tag shares to the Recorder API).
447
- `share_context: organization` routes the share into the caller's active organization view and requires the
448
- recipient to be a member of that organization.
424
+ description: "Shares a target the caller owns with another user by email. Sends an invitation email containing an accept link; the share is `pending` until accepted. Optionally includes the subtree (`include_descendants`) and the linked Recorder tag data (`include_data`, which cascades matching tag shares to the Recorder API). `share_context: organization` routes the share into the caller's active organization view and requires the recipient to be a member of that organization."
449
425
  requestBody:
450
426
  required: true
451
427
  content:
452
428
  application/json:
453
429
  schema:
454
- $ref: '#/components/schemas/CreateShareInput'
430
+ $ref: "#/components/schemas/CreateShareInput"
455
431
  responses:
456
- '201':
432
+ "201":
457
433
  description: Share created (pending acceptance)
458
434
  content:
459
435
  application/json:
@@ -465,64 +441,64 @@ paths:
465
441
  properties:
466
442
  success:
467
443
  type: boolean
468
- enum: [true]
444
+ enum:
445
+ - true
469
446
  data:
470
- $ref: '#/components/schemas/Share'
471
- '400':
472
- $ref: '#/components/responses/ValidationError'
473
- '401':
474
- $ref: '#/components/responses/Unauthorized'
475
- '403':
447
+ $ref: "#/components/schemas/Share"
448
+ "400":
449
+ $ref: "#/components/responses/ValidationError"
450
+ "401":
451
+ $ref: "#/components/responses/Unauthorized"
452
+ "403":
476
453
  description: Sharing not permitted (plan limit, or recipient not in organization)
477
454
  content:
478
455
  application/json:
479
456
  schema:
480
- $ref: '#/components/schemas/Error'
481
- '404':
457
+ $ref: "#/components/schemas/Error"
458
+ "404":
482
459
  description: Target not found, or recipient email not registered
483
460
  content:
484
461
  application/json:
485
462
  schema:
486
- $ref: '#/components/schemas/Error'
487
- '409':
488
- $ref: '#/components/responses/Conflict'
463
+ $ref: "#/components/schemas/Error"
464
+ "409":
465
+ $ref: "#/components/responses/Conflict"
489
466
  /api/v1/shares/with-me:
490
467
  get:
491
468
  operationId: listSharesWithMe
492
469
  tags:
493
470
  - Sharing
494
471
  summary: List shares addressed to me
495
- description: >-
496
- Returns shares where the authenticated user is the recipient, scoped to the active namespace. Filter by status
497
- with the `status` query parameter. Each row is enriched with the owner email and the owner-side target chain.
472
+ description: Returns shares where the authenticated user is the recipient, scoped to the active namespace. Filter by status with the `status` query parameter. Each row is enriched with the owner email and the owner-side target chain.
498
473
  parameters:
499
474
  - name: status
500
475
  in: query
501
476
  required: false
502
477
  schema:
503
478
  type: string
504
- enum: [accepted, pending, rejected, all]
479
+ enum:
480
+ - accepted
481
+ - pending
482
+ - rejected
483
+ - all
505
484
  default: accepted
506
485
  description: Which share statuses to return (default `accepted`).
507
486
  responses:
508
- '200':
487
+ "200":
509
488
  description: Shares addressed to the caller
510
489
  content:
511
490
  application/json:
512
491
  schema:
513
- $ref: '#/components/schemas/ShareListResponse'
514
- '401':
515
- $ref: '#/components/responses/Unauthorized'
492
+ $ref: "#/components/schemas/ShareListResponse"
493
+ "401":
494
+ $ref: "#/components/responses/Unauthorized"
516
495
  /api/v1/shares/recipient-context-options:
517
496
  get:
518
497
  operationId: getRecipientContextOptions
519
498
  tags:
520
499
  - Sharing
521
500
  summary: Resolve sharing-context options for a recipient
522
- description: >-
523
- Returns which sharing contexts the caller may offer for a given recipient email. Always includes `personal`;
524
- additionally includes `organization` when the caller is acting under an organization context and the recipient
525
- is a member of that same organization.
501
+ description: Returns which sharing contexts the caller may offer for a given recipient email. Always includes `personal`; additionally includes `organization` when the caller is acting under an organization context and the recipient is a member of that same organization.
526
502
  parameters:
527
503
  - name: email
528
504
  in: query
@@ -532,7 +508,7 @@ paths:
532
508
  format: email
533
509
  description: Recipient email to evaluate.
534
510
  responses:
535
- '200':
511
+ "200":
536
512
  description: Available sharing contexts
537
513
  content:
538
514
  application/json:
@@ -544,7 +520,8 @@ paths:
544
520
  properties:
545
521
  success:
546
522
  type: boolean
547
- enum: [true]
523
+ enum:
524
+ - true
548
525
  data:
549
526
  type: object
550
527
  required:
@@ -554,12 +531,16 @@ paths:
554
531
  type: array
555
532
  items:
556
533
  type: string
557
- enum: [personal, organization]
558
- example: [personal, organization]
559
- '400':
560
- $ref: '#/components/responses/ValidationError'
561
- '401':
562
- $ref: '#/components/responses/Unauthorized'
534
+ enum:
535
+ - personal
536
+ - organization
537
+ example:
538
+ - personal
539
+ - organization
540
+ "400":
541
+ $ref: "#/components/responses/ValidationError"
542
+ "401":
543
+ $ref: "#/components/responses/Unauthorized"
563
544
  /api/v1/shares/accept:
564
545
  post:
565
546
  operationId: acceptShareByToken
@@ -572,92 +553,88 @@ paths:
572
553
  content:
573
554
  application/json:
574
555
  schema:
575
- $ref: '#/components/schemas/TokenInput'
556
+ $ref: "#/components/schemas/TokenInput"
576
557
  responses:
577
- '200':
558
+ "200":
578
559
  description: Share accepted (or already accepted)
579
560
  content:
580
561
  application/json:
581
562
  schema:
582
- $ref: '#/components/schemas/ShareStatusResponse'
583
- '400':
563
+ $ref: "#/components/schemas/ShareStatusResponse"
564
+ "400":
584
565
  description: Invitation expired or already declined
585
566
  content:
586
567
  application/json:
587
568
  schema:
588
- $ref: '#/components/schemas/Error'
589
- '401':
590
- $ref: '#/components/responses/Unauthorized'
591
- '404':
592
- $ref: '#/components/responses/NotFound'
569
+ $ref: "#/components/schemas/Error"
570
+ "401":
571
+ $ref: "#/components/responses/Unauthorized"
572
+ "404":
573
+ $ref: "#/components/responses/NotFound"
593
574
  /api/v1/shares/migrate/accept:
594
575
  post:
595
576
  operationId: acceptMigrationByToken
596
577
  tags:
597
578
  - Sharing
598
579
  summary: Accept an ownership transfer by token
599
- description: >-
600
- Accepts a pending ownership-transfer (data migration) using the token from the migration approval email. On
601
- success the target (and, if the share included descendants, its subtree) is transferred to the caller, and a
602
- reverse read-only share is created so the original owner keeps access.
580
+ description: Accepts a pending ownership-transfer (data migration) using the token from the migration approval email. On success the target (and, if the share included descendants, its subtree) is transferred to the caller, and a reverse read-only share is created so the original owner keeps access.
603
581
  requestBody:
604
582
  required: true
605
583
  content:
606
584
  application/json:
607
585
  schema:
608
- $ref: '#/components/schemas/TokenInput'
586
+ $ref: "#/components/schemas/TokenInput"
609
587
  responses:
610
- '200':
588
+ "200":
611
589
  description: Ownership transferred
612
590
  content:
613
591
  application/json:
614
592
  schema:
615
- $ref: '#/components/schemas/MigrationStatusResponse'
616
- '400':
593
+ $ref: "#/components/schemas/MigrationStatusResponse"
594
+ "400":
617
595
  description: Migration invitation no longer active or expired
618
596
  content:
619
597
  application/json:
620
598
  schema:
621
- $ref: '#/components/schemas/Error'
622
- '401':
623
- $ref: '#/components/responses/Unauthorized'
624
- '404':
625
- $ref: '#/components/responses/NotFound'
599
+ $ref: "#/components/schemas/Error"
600
+ "401":
601
+ $ref: "#/components/responses/Unauthorized"
602
+ "404":
603
+ $ref: "#/components/responses/NotFound"
626
604
  /api/v1/shares/{id}:
627
605
  delete:
628
606
  operationId: deleteShare
629
607
  tags:
630
608
  - Sharing
631
609
  summary: Delete a share
632
- description: >-
633
- Removes a share the caller owns. If the share was created with `include_data`, the matching Recorder tag shares
634
- are revoked unless `cascade_tag_shares=false` is passed. A share with a pending ownership transfer cannot be
635
- deleted until the migration is cancelled.
610
+ description: Removes a share the caller owns. If the share was created with `include_data`, the matching Recorder tag shares are revoked unless `cascade_tag_shares=false` is passed. A share with a pending ownership transfer cannot be deleted until the migration is cancelled.
636
611
  parameters:
637
- - $ref: '#/components/parameters/ShareId'
612
+ - $ref: "#/components/parameters/ShareId"
638
613
  - name: cascade_tag_shares
639
614
  in: query
640
615
  required: false
641
616
  schema:
642
617
  type: string
643
- enum: ['true', 'false']
644
- default: 'true'
618
+ enum:
619
+ - "true"
620
+ - "false"
621
+ default: "true"
645
622
  description: Set to `false` to keep the linked Recorder tag shares when deleting.
646
623
  responses:
647
- '200':
624
+ "200":
648
625
  description: Share deleted
649
626
  content:
650
627
  application/json:
651
628
  schema:
652
- $ref: '#/components/schemas/SuccessFlagResponse'
653
- '400':
654
- $ref: '#/components/responses/ValidationError'
655
- '401':
656
- $ref: '#/components/responses/Unauthorized'
657
- '404':
658
- $ref: '#/components/responses/NotFound'
659
- '409':
660
- $ref: '#/components/responses/Conflict'
629
+ $ref: "#/components/schemas/SuccessFlagResponse"
630
+ "400":
631
+ $ref: "#/components/responses/ValidationError"
632
+ "401":
633
+ $ref: "#/components/responses/Unauthorized"
634
+ "404":
635
+ $ref: "#/components/responses/NotFound"
636
+ "409":
637
+ $ref: "#/components/responses/Conflict"
661
638
  /api/v1/shares/{id}/accept:
662
639
  post:
663
640
  operationId: acceptShareById
@@ -666,24 +643,24 @@ paths:
666
643
  summary: Accept a share invitation (in-app)
667
644
  description: In-app counterpart to POST /shares/accept — accepts a pending share addressed to the caller by id.
668
645
  parameters:
669
- - $ref: '#/components/parameters/ShareId'
646
+ - $ref: "#/components/parameters/ShareId"
670
647
  responses:
671
- '200':
648
+ "200":
672
649
  description: Share accepted (or already accepted)
673
650
  content:
674
651
  application/json:
675
652
  schema:
676
- $ref: '#/components/schemas/ShareStatusResponse'
677
- '400':
653
+ $ref: "#/components/schemas/ShareStatusResponse"
654
+ "400":
678
655
  description: Invitation expired or already declined
679
656
  content:
680
657
  application/json:
681
658
  schema:
682
- $ref: '#/components/schemas/Error'
683
- '401':
684
- $ref: '#/components/responses/Unauthorized'
685
- '404':
686
- $ref: '#/components/responses/NotFound'
659
+ $ref: "#/components/schemas/Error"
660
+ "401":
661
+ $ref: "#/components/responses/Unauthorized"
662
+ "404":
663
+ $ref: "#/components/responses/NotFound"
687
664
  /api/v1/shares/{id}/reject:
688
665
  post:
689
666
  operationId: rejectShare
@@ -692,20 +669,20 @@ paths:
692
669
  summary: Reject a share invitation
693
670
  description: Declines a pending share addressed to the caller. An already-accepted share cannot be rejected (delete it instead).
694
671
  parameters:
695
- - $ref: '#/components/parameters/ShareId'
672
+ - $ref: "#/components/parameters/ShareId"
696
673
  responses:
697
- '200':
674
+ "200":
698
675
  description: Share rejected (or already rejected)
699
676
  content:
700
677
  application/json:
701
678
  schema:
702
- $ref: '#/components/schemas/ShareStatusResponse'
703
- '400':
704
- $ref: '#/components/responses/ValidationError'
705
- '401':
706
- $ref: '#/components/responses/Unauthorized'
707
- '404':
708
- $ref: '#/components/responses/NotFound'
679
+ $ref: "#/components/schemas/ShareStatusResponse"
680
+ "400":
681
+ $ref: "#/components/responses/ValidationError"
682
+ "401":
683
+ $ref: "#/components/responses/Unauthorized"
684
+ "404":
685
+ $ref: "#/components/responses/NotFound"
709
686
  /api/v1/shares/{id}/pause:
710
687
  patch:
711
688
  operationId: toggleSharePaused
@@ -714,7 +691,7 @@ paths:
714
691
  summary: Pause or resume a share
715
692
  description: Owner-only. Pauses or resumes a share without deleting it; a paused share is hidden from the recipient's shared-targets list.
716
693
  parameters:
717
- - $ref: '#/components/parameters/ShareId'
694
+ - $ref: "#/components/parameters/ShareId"
718
695
  requestBody:
719
696
  required: true
720
697
  content:
@@ -727,7 +704,7 @@ paths:
727
704
  is_paused:
728
705
  type: boolean
729
706
  responses:
730
- '200':
707
+ "200":
731
708
  description: Updated share row
732
709
  content:
733
710
  application/json:
@@ -739,13 +716,14 @@ paths:
739
716
  properties:
740
717
  success:
741
718
  type: boolean
742
- enum: [true]
719
+ enum:
720
+ - true
743
721
  data:
744
- $ref: '#/components/schemas/Share'
745
- '401':
746
- $ref: '#/components/responses/Unauthorized'
747
- '404':
748
- $ref: '#/components/responses/NotFound'
722
+ $ref: "#/components/schemas/Share"
723
+ "401":
724
+ $ref: "#/components/responses/Unauthorized"
725
+ "404":
726
+ $ref: "#/components/responses/NotFound"
749
727
  /api/v1/shares/{id}/visibility:
750
728
  patch:
751
729
  operationId: toggleShareVisibility
@@ -754,7 +732,7 @@ paths:
754
732
  summary: Hide or unhide a share
755
733
  description: Recipient-only. Hides or unhides a share from the caller's own shared-targets list.
756
734
  parameters:
757
- - $ref: '#/components/parameters/ShareId'
735
+ - $ref: "#/components/parameters/ShareId"
758
736
  requestBody:
759
737
  required: true
760
738
  content:
@@ -767,7 +745,7 @@ paths:
767
745
  is_hidden:
768
746
  type: boolean
769
747
  responses:
770
- '200':
748
+ "200":
771
749
  description: Updated share row
772
750
  content:
773
751
  application/json:
@@ -779,27 +757,25 @@ paths:
779
757
  properties:
780
758
  success:
781
759
  type: boolean
782
- enum: [true]
760
+ enum:
761
+ - true
783
762
  data:
784
- $ref: '#/components/schemas/Share'
785
- '401':
786
- $ref: '#/components/responses/Unauthorized'
787
- '404':
788
- $ref: '#/components/responses/NotFound'
763
+ $ref: "#/components/schemas/Share"
764
+ "401":
765
+ $ref: "#/components/responses/Unauthorized"
766
+ "404":
767
+ $ref: "#/components/responses/NotFound"
789
768
  /api/v1/shares/{id}/transfer:
790
769
  post:
791
770
  operationId: transferOwnership
792
771
  tags:
793
772
  - Sharing
794
773
  summary: Start an ownership transfer
795
- description: >-
796
- Owner-only. Begins transferring ownership of the shared target (subtree if the share included descendants) to
797
- the recipient by emailing them an approval link. The share must already be accepted. Organization-owned targets
798
- cannot be transferred. The transfer only completes when the recipient accepts.
774
+ description: Owner-only. Begins transferring ownership of the shared target (subtree if the share included descendants) to the recipient by emailing them an approval link. The share must already be accepted. Organization-owned targets cannot be transferred. The transfer only completes when the recipient accepts.
799
775
  parameters:
800
- - $ref: '#/components/parameters/ShareId'
776
+ - $ref: "#/components/parameters/ShareId"
801
777
  responses:
802
- '200':
778
+ "200":
803
779
  description: Migration invitation issued
804
780
  content:
805
781
  application/json:
@@ -811,7 +787,8 @@ paths:
811
787
  properties:
812
788
  success:
813
789
  type: boolean
814
- enum: [true]
790
+ enum:
791
+ - true
815
792
  data:
816
793
  type: object
817
794
  required:
@@ -822,20 +799,21 @@ paths:
822
799
  type: integer
823
800
  migration_status:
824
801
  type: string
825
- enum: [pending]
802
+ enum:
803
+ - pending
826
804
  expires_at:
827
805
  type: string
828
806
  format: date-time
829
- '400':
830
- $ref: '#/components/responses/ValidationError'
831
- '401':
832
- $ref: '#/components/responses/Unauthorized'
833
- '403':
834
- $ref: '#/components/responses/Forbidden'
835
- '404':
836
- $ref: '#/components/responses/NotFound'
837
- '409':
838
- $ref: '#/components/responses/Conflict'
807
+ "400":
808
+ $ref: "#/components/responses/ValidationError"
809
+ "401":
810
+ $ref: "#/components/responses/Unauthorized"
811
+ "403":
812
+ $ref: "#/components/responses/Forbidden"
813
+ "404":
814
+ $ref: "#/components/responses/NotFound"
815
+ "409":
816
+ $ref: "#/components/responses/Conflict"
839
817
  /api/v1/shares/{id}/migrate/accept:
840
818
  post:
841
819
  operationId: acceptMigrationById
@@ -844,24 +822,24 @@ paths:
844
822
  summary: Accept an ownership transfer (in-app)
845
823
  description: In-app counterpart to POST /shares/migrate/accept — accepts a pending ownership transfer addressed to the caller by id.
846
824
  parameters:
847
- - $ref: '#/components/parameters/ShareId'
825
+ - $ref: "#/components/parameters/ShareId"
848
826
  responses:
849
- '200':
827
+ "200":
850
828
  description: Ownership transferred
851
829
  content:
852
830
  application/json:
853
831
  schema:
854
- $ref: '#/components/schemas/MigrationStatusResponse'
855
- '400':
832
+ $ref: "#/components/schemas/MigrationStatusResponse"
833
+ "400":
856
834
  description: Migration invitation no longer active or expired
857
835
  content:
858
836
  application/json:
859
837
  schema:
860
- $ref: '#/components/schemas/Error'
861
- '401':
862
- $ref: '#/components/responses/Unauthorized'
863
- '404':
864
- $ref: '#/components/responses/NotFound'
838
+ $ref: "#/components/schemas/Error"
839
+ "401":
840
+ $ref: "#/components/responses/Unauthorized"
841
+ "404":
842
+ $ref: "#/components/responses/NotFound"
865
843
  /api/v1/shares/{id}/migrate/reject:
866
844
  post:
867
845
  operationId: rejectMigration
@@ -870,20 +848,20 @@ paths:
870
848
  summary: Reject an ownership transfer
871
849
  description: Recipient-only. Declines a pending ownership transfer; the underlying share keeps its existing permission.
872
850
  parameters:
873
- - $ref: '#/components/parameters/ShareId'
851
+ - $ref: "#/components/parameters/ShareId"
874
852
  responses:
875
- '200':
853
+ "200":
876
854
  description: Migration rejected
877
855
  content:
878
856
  application/json:
879
857
  schema:
880
- $ref: '#/components/schemas/MigrationStatusResponse'
881
- '400':
882
- $ref: '#/components/responses/ValidationError'
883
- '401':
884
- $ref: '#/components/responses/Unauthorized'
885
- '404':
886
- $ref: '#/components/responses/NotFound'
858
+ $ref: "#/components/schemas/MigrationStatusResponse"
859
+ "400":
860
+ $ref: "#/components/responses/ValidationError"
861
+ "401":
862
+ $ref: "#/components/responses/Unauthorized"
863
+ "404":
864
+ $ref: "#/components/responses/NotFound"
887
865
  /api/v1/shares/{id}/migrate/cancel:
888
866
  post:
889
867
  operationId: cancelMigration
@@ -892,9 +870,9 @@ paths:
892
870
  summary: Cancel an ownership transfer
893
871
  description: Owner-only. Cancels an outstanding ownership-transfer invitation before the recipient acts.
894
872
  parameters:
895
- - $ref: '#/components/parameters/ShareId'
873
+ - $ref: "#/components/parameters/ShareId"
896
874
  responses:
897
- '200':
875
+ "200":
898
876
  description: Migration cancelled
899
877
  content:
900
878
  application/json:
@@ -906,7 +884,8 @@ paths:
906
884
  properties:
907
885
  success:
908
886
  type: boolean
909
- enum: [true]
887
+ enum:
888
+ - true
910
889
  data:
911
890
  type: object
912
891
  required:
@@ -918,14 +897,15 @@ paths:
918
897
  migration_status:
919
898
  type: string
920
899
  nullable: true
921
- enum: [null]
900
+ enum:
901
+ - null
922
902
  description: Always null after a cancel — the in-flight migration is cleared.
923
- '400':
924
- $ref: '#/components/responses/ValidationError'
925
- '401':
926
- $ref: '#/components/responses/Unauthorized'
927
- '404':
928
- $ref: '#/components/responses/NotFound'
903
+ "400":
904
+ $ref: "#/components/responses/ValidationError"
905
+ "401":
906
+ $ref: "#/components/responses/Unauthorized"
907
+ "404":
908
+ $ref: "#/components/responses/NotFound"
929
909
  components:
930
910
  securitySchemes:
931
911
  BearerAuth:
@@ -1001,9 +981,10 @@ components:
1001
981
  properties:
1002
982
  success:
1003
983
  type: boolean
1004
- enum: [true]
984
+ enum:
985
+ - true
1005
986
  data:
1006
- $ref: '#/components/schemas/User'
987
+ $ref: "#/components/schemas/User"
1007
988
  Target:
1008
989
  type: object
1009
990
  properties:
@@ -1020,14 +1001,11 @@ components:
1020
1001
  organization_id:
1021
1002
  type: integer
1022
1003
  nullable: true
1023
- description: >-
1024
- Organization namespace. NULL = personal data. Non-null = created under an Enterprise org context; the org
1025
- admin can read it and the member-creator owns it day-to-day but cannot transfer or delete it.
1004
+ description: Organization namespace. NULL = personal data. Non-null = created under an Enterprise org context; the org admin can read it and the member-creator owns it day-to-day but cannot transfer or delete it.
1026
1005
  parent_target_id:
1027
1006
  type: string
1028
1007
  nullable: true
1029
- description: >-
1030
- Direct parent reference (migration 0017+). Authoritative source of tree structure. NULL = root target.
1008
+ description: Direct parent reference (migration 0017+). Authoritative source of tree structure. NULL = root target.
1031
1009
  title:
1032
1010
  type: string
1033
1011
  description: Goal title
@@ -1041,14 +1019,15 @@ components:
1041
1019
  recorder_tag:
1042
1020
  type: string
1043
1021
  nullable: true
1044
- description: Optional tag linking to the Recorder app
1022
+ description: Name of the linked Recorder tag, or a derived series key such as `Body Weight/BMI~` (a name, not a tag row, so it has no id). Kept alongside `recorder_tag_id` for derived keys and for clients that predate it.
1023
+ recorder_tag_id:
1024
+ type: integer
1025
+ nullable: true
1026
+ description: Id of the linked Recorder tag, for a real tag (never for a derived series key). Unlike the name it stays valid when the tag is renamed or its ownership is transferred, and it tells apart same-named tags of different owners. NULL for a target linked only by name; clients prefer the id when it is set and fall back to `recorder_tag`.
1045
1027
  recorder_goal_id:
1046
1028
  type: integer
1047
1029
  nullable: true
1048
- description: >-
1049
- Recorder Goal id pinned at the moment the tag was bound. Progress for this target is computed against this
1050
- specific goal so that later Goal period changes in Recorder do not silently re-route which goal is being
1051
- tracked.
1030
+ description: Recorder Goal id pinned at the moment the tag was bound. Progress for this target is computed against this specific goal so that later Goal period changes in Recorder do not silently re-route which goal is being tracked.
1052
1031
  created_at:
1053
1032
  type: string
1054
1033
  format: date-time
@@ -1061,26 +1040,17 @@ components:
1061
1040
  description: Resolved owner email (present in response payloads).
1062
1041
  owner_name:
1063
1042
  type: string
1064
- description: >-
1065
- Display name the owner set in their profile. Absent when they set
1066
- none. Clients name the owner by this, falling back to a masked email.
1043
+ description: Display name the owner set in their profile. Absent when they set none. Clients name the owner by this, falling back to a masked email.
1067
1044
  created_by_email:
1068
1045
  type: string
1069
1046
  format: email
1070
- description: >-
1071
- Resolved creator email (present in response payloads). Absent when `created_by_deleted` is true — there is no
1072
- creator left to name, and the owner must NOT be substituted.
1047
+ description: Resolved creator email (present in response payloads). Absent when `created_by_deleted` is true — there is no creator left to name, and the owner must NOT be substituted.
1073
1048
  created_by_name:
1074
1049
  type: string
1075
- description: >-
1076
- Display name the creator set in their profile. Absent when they set
1077
- none, or when `created_by_deleted` is true.
1050
+ description: Display name the creator set in their profile. Absent when they set none, or when `created_by_deleted` is true.
1078
1051
  created_by_deleted:
1079
1052
  type: boolean
1080
- description: >-
1081
- True when the author deleted their NASEBANAL account. The row itself survives because it belongs to this
1082
- target's owner; only the authorship is gone. Clients render a "deleted user" label (JA: 退会済ユーザー) rather
1083
- than falling back to `owner_email`, which would show the owner as the author of an edit they never made.
1053
+ description: "True when the author deleted their NASEBANAL account. The row itself survives because it belongs to this target's owner; only the authorship is gone. Clients render a \"deleted user\" label (JA: 退会済ユーザー) rather than falling back to `owner_email`, which would show the owner as the author of an edit they never made."
1084
1054
  TargetCell:
1085
1055
  type: object
1086
1056
  properties:
@@ -1113,7 +1083,7 @@ components:
1113
1083
  format: date-time
1114
1084
  TargetWithCells:
1115
1085
  allOf:
1116
- - $ref: '#/components/schemas/Target'
1086
+ - $ref: "#/components/schemas/Target"
1117
1087
  - type: object
1118
1088
  required:
1119
1089
  - progress
@@ -1122,30 +1092,18 @@ components:
1122
1092
  cells:
1123
1093
  type: array
1124
1094
  items:
1125
- $ref: '#/components/schemas/TargetCell'
1126
- description: >-
1127
- All storage cells ordered by position. Present when the list was requested without `fields`, or with
1128
- `fields=full` (the default); omitted when requested with `fields=summary` — see `progress` and
1129
- `own_progress` instead.
1095
+ $ref: "#/components/schemas/TargetCell"
1096
+ description: All storage cells ordered by position. Present when the list was requested without `fields`, or with `fields=full` (the default); omitted when requested with `fields=summary` — see `progress` and `own_progress` instead.
1130
1097
  progress:
1131
1098
  type: integer
1132
1099
  minimum: 0
1133
1100
  maximum: 100
1134
- description: >-
1135
- A target's own roll-up progress, computed server-side: the average of its children's (recursively
1136
- rolled-up) progress when it has sub-goals, or its own storage cell (position 40, `own_progress`)
1137
- when it's a leaf. Always present, regardless of `fields`.
1101
+ description: "A target's own roll-up progress, computed server-side: the average of its children's (recursively rolled-up) progress when it has sub-goals, or its own storage cell (position 40, `own_progress`) when it's a leaf. Always present, regardless of `fields`."
1138
1102
  own_progress:
1139
1103
  type: integer
1140
1104
  minimum: 0
1141
1105
  maximum: 100
1142
- description: >-
1143
- The target's own storage cell (position 40) value, unrolled — what the "clear" toggle sets directly
1144
- to 0 or 100, independent of any sub-goals. Distinct from `progress`: a target with sub-goals can
1145
- have `progress = 100` (every child rolled up to 100) while `own_progress` stays whatever it was
1146
- last explicitly set to, since a parent's own cell is never averaged into its own `progress`. Always
1147
- present, regardless of `fields` — use this, not `progress`, to tell whether a target itself has
1148
- been marked cleared.
1106
+ description: "The target's own storage cell (position 40) value, unrolled — what the \"clear\" toggle sets directly to 0 or 100, independent of any sub-goals. Distinct from `progress`: a target with sub-goals can have `progress = 100` (every child rolled up to 100) while `own_progress` stays whatever it was last explicitly set to, since a parent's own cell is never averaged into its own `progress`. Always present, regardless of `fields` — use this, not `progress`, to tell whether a target itself has been marked cleared."
1149
1107
  TargetWithCellsResponse:
1150
1108
  type: object
1151
1109
  required:
@@ -1154,12 +1112,13 @@ components:
1154
1112
  properties:
1155
1113
  success:
1156
1114
  type: boolean
1157
- enum: [true]
1115
+ enum:
1116
+ - true
1158
1117
  data:
1159
- $ref: '#/components/schemas/TargetWithCells'
1118
+ $ref: "#/components/schemas/TargetWithCells"
1160
1119
  SharedTarget:
1161
1120
  allOf:
1162
- - $ref: '#/components/schemas/TargetWithCells'
1121
+ - $ref: "#/components/schemas/TargetWithCells"
1163
1122
  - type: object
1164
1123
  properties:
1165
1124
  shared_by_user_id:
@@ -1173,13 +1132,17 @@ components:
1173
1132
  description: Display name the sharing owner set in their profile. Absent when they set none.
1174
1133
  share_permission:
1175
1134
  type: string
1176
- enum: [read, write]
1135
+ enum:
1136
+ - read
1137
+ - write
1177
1138
  share_root_target_id:
1178
1139
  type: string
1179
1140
  description: The root target id of the share that grants access to this row
1180
1141
  share_show_embed:
1181
1142
  type: integer
1182
- enum: [0, 1]
1143
+ enum:
1144
+ - 0
1145
+ - 1
1183
1146
  description: Whether the share permits embedding the linked Recorder graph
1184
1147
  Share:
1185
1148
  type: object
@@ -1194,17 +1157,24 @@ components:
1194
1157
  type: string
1195
1158
  permission:
1196
1159
  type: string
1197
- enum: [read, write]
1160
+ enum:
1161
+ - read
1162
+ - write
1198
1163
  status:
1199
1164
  type: string
1200
- enum: [pending, accepted, rejected]
1165
+ enum:
1166
+ - pending
1167
+ - accepted
1168
+ - rejected
1201
1169
  expires_at:
1202
1170
  type: string
1203
1171
  format: date-time
1204
1172
  nullable: true
1205
1173
  migration_status:
1206
1174
  type: string
1207
- enum: [pending, null]
1175
+ enum:
1176
+ - pending
1177
+ - null
1208
1178
  nullable: true
1209
1179
  description: Ownership-transfer state. NULL = no migration in flight.
1210
1180
  migration_expires_at:
@@ -1213,19 +1183,29 @@ components:
1213
1183
  nullable: true
1214
1184
  is_hidden:
1215
1185
  type: integer
1216
- enum: [0, 1]
1186
+ enum:
1187
+ - 0
1188
+ - 1
1217
1189
  is_paused:
1218
1190
  type: integer
1219
- enum: [0, 1]
1191
+ enum:
1192
+ - 0
1193
+ - 1
1220
1194
  show_embed:
1221
1195
  type: integer
1222
- enum: [0, 1]
1196
+ enum:
1197
+ - 0
1198
+ - 1
1223
1199
  include_descendants:
1224
1200
  type: integer
1225
- enum: [0, 1]
1201
+ enum:
1202
+ - 0
1203
+ - 1
1226
1204
  include_data:
1227
1205
  type: integer
1228
- enum: [0, 1]
1206
+ enum:
1207
+ - 0
1208
+ - 1
1229
1209
  parent_share_id:
1230
1210
  type: integer
1231
1211
  nullable: true
@@ -1247,17 +1227,14 @@ components:
1247
1227
  description: Enriched — present when listing shares addressed to the caller.
1248
1228
  owner_name:
1249
1229
  type: string
1250
- description: >-
1251
- Display name the sharing owner set in their profile. Absent when they set none.
1230
+ description: Display name the sharing owner set in their profile. Absent when they set none.
1252
1231
  shared_with_email:
1253
1232
  type: string
1254
1233
  format: email
1255
1234
  description: Enriched — present when listing shares the caller owns.
1256
1235
  shared_with_name:
1257
1236
  type: string
1258
- description: >-
1259
- Display name the recipient set in their profile. Set on shares the caller owns, and only once the share is
1260
- `accepted`, so an invitation does not reveal the profile of someone who has not accepted it.
1237
+ description: Display name the recipient set in their profile. Set on shares the caller owns, and only once the share is `accepted`, so an invitation does not reveal the profile of someone who has not accepted it.
1261
1238
  owner_plan:
1262
1239
  type: string
1263
1240
  description: Enriched — the owner's plan, present when listing shares the caller owns.
@@ -1269,7 +1246,8 @@ components:
1269
1246
  properties:
1270
1247
  success:
1271
1248
  type: boolean
1272
- enum: [true]
1249
+ enum:
1250
+ - true
1273
1251
  data:
1274
1252
  type: object
1275
1253
  required:
@@ -1281,7 +1259,7 @@ components:
1281
1259
  data:
1282
1260
  type: array
1283
1261
  items:
1284
- $ref: '#/components/schemas/Share'
1262
+ $ref: "#/components/schemas/Share"
1285
1263
  total:
1286
1264
  type: integer
1287
1265
  limit:
@@ -1296,7 +1274,8 @@ components:
1296
1274
  properties:
1297
1275
  success:
1298
1276
  type: boolean
1299
- enum: [true]
1277
+ enum:
1278
+ - true
1300
1279
  data:
1301
1280
  type: object
1302
1281
  required:
@@ -1307,7 +1286,10 @@ components:
1307
1286
  type: integer
1308
1287
  status:
1309
1288
  type: string
1310
- enum: [pending, accepted, rejected]
1289
+ enum:
1290
+ - pending
1291
+ - accepted
1292
+ - rejected
1311
1293
  already:
1312
1294
  type: boolean
1313
1295
  description: True when the share was already in the requested state.
@@ -1319,7 +1301,8 @@ components:
1319
1301
  properties:
1320
1302
  success:
1321
1303
  type: boolean
1322
- enum: [true]
1304
+ enum:
1305
+ - true
1323
1306
  data:
1324
1307
  type: object
1325
1308
  required:
@@ -1330,7 +1313,9 @@ components:
1330
1313
  type: integer
1331
1314
  migration_status:
1332
1315
  type: string
1333
- enum: [accepted, rejected]
1316
+ enum:
1317
+ - accepted
1318
+ - rejected
1334
1319
  SuccessFlagResponse:
1335
1320
  type: object
1336
1321
  required:
@@ -1339,13 +1324,15 @@ components:
1339
1324
  properties:
1340
1325
  success:
1341
1326
  type: boolean
1342
- enum: [true]
1327
+ enum:
1328
+ - true
1343
1329
  data:
1344
1330
  type: object
1345
1331
  properties:
1346
1332
  success:
1347
1333
  type: boolean
1348
- enum: [true]
1334
+ enum:
1335
+ - true
1349
1336
  CreateTargetInput:
1350
1337
  type: object
1351
1338
  required:
@@ -1379,13 +1366,15 @@ components:
1379
1366
  recorder_tag:
1380
1367
  type: string
1381
1368
  nullable: true
1382
- description: Tag to link with Recorder app
1369
+ description: Tag to link with Recorder app, by name. Send the name together with `recorder_tag_id` for a real tag; for a derived series key (`Body Weight/BMI~`) this is the only field.
1370
+ recorder_tag_id:
1371
+ type: integer
1372
+ nullable: true
1373
+ description: Id of the Recorder tag to link, for a real tag. Send it together with `recorder_tag`; send `null` for both to unlink.
1383
1374
  recorder_goal_id:
1384
1375
  type: integer
1385
1376
  nullable: true
1386
- description: >-
1387
- Pin a specific Recorder Goal to this target. Typically resolved by the client at bind time from the active
1388
- goal for the selected tag.
1377
+ description: Pin a specific Recorder Goal to this target. Typically resolved by the client at bind time from the active goal for the selected tag.
1389
1378
  UpdateTargetCellInput:
1390
1379
  type: object
1391
1380
  properties:
@@ -1419,7 +1408,9 @@ components:
1419
1408
  type: string
1420
1409
  permission:
1421
1410
  type: string
1422
- enum: [read, write]
1411
+ enum:
1412
+ - read
1413
+ - write
1423
1414
  default: read
1424
1415
  include_descendants:
1425
1416
  type: boolean
@@ -1431,11 +1422,11 @@ components:
1431
1422
  description: Also cascade-share the linked Recorder tag data so the recipient can view embedded graphs.
1432
1423
  share_context:
1433
1424
  type: string
1434
- enum: [personal, organization]
1425
+ enum:
1426
+ - personal
1427
+ - organization
1435
1428
  default: personal
1436
- description: >-
1437
- `organization` routes the share into the caller's active organization view; requires the recipient to be a
1438
- member of that organization.
1429
+ description: "`organization` routes the share into the caller's active organization view; requires the recipient to be a member of that organization."
1439
1430
  extra_tag_names:
1440
1431
  type: array
1441
1432
  items:
@@ -1457,7 +1448,8 @@ components:
1457
1448
  properties:
1458
1449
  success:
1459
1450
  type: boolean
1460
- enum: [false]
1451
+ enum:
1452
+ - false
1461
1453
  error:
1462
1454
  type: object
1463
1455
  required:
@@ -1477,7 +1469,7 @@ components:
1477
1469
  content:
1478
1470
  application/json:
1479
1471
  schema:
1480
- $ref: '#/components/schemas/Error'
1472
+ $ref: "#/components/schemas/Error"
1481
1473
  example:
1482
1474
  success: false
1483
1475
  error:
@@ -1488,7 +1480,7 @@ components:
1488
1480
  content:
1489
1481
  application/json:
1490
1482
  schema:
1491
- $ref: '#/components/schemas/Error'
1483
+ $ref: "#/components/schemas/Error"
1492
1484
  example:
1493
1485
  success: false
1494
1486
  error:
@@ -1499,7 +1491,7 @@ components:
1499
1491
  content:
1500
1492
  application/json:
1501
1493
  schema:
1502
- $ref: '#/components/schemas/Error'
1494
+ $ref: "#/components/schemas/Error"
1503
1495
  example:
1504
1496
  success: false
1505
1497
  error:
@@ -1510,18 +1502,18 @@ components:
1510
1502
  content:
1511
1503
  application/json:
1512
1504
  schema:
1513
- $ref: '#/components/schemas/Error'
1505
+ $ref: "#/components/schemas/Error"
1514
1506
  example:
1515
1507
  success: false
1516
1508
  error:
1517
1509
  code: CONFLICT
1518
- message: 'Share already exists (status: pending)'
1510
+ message: "Share already exists (status: pending)"
1519
1511
  ValidationError:
1520
1512
  description: Validation error
1521
1513
  content:
1522
1514
  application/json:
1523
1515
  schema:
1524
- $ref: '#/components/schemas/Error'
1516
+ $ref: "#/components/schemas/Error"
1525
1517
  example:
1526
1518
  success: false
1527
1519
  error: