@nasebanal/cli 0.1.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/LICENSE +21 -0
- package/README.md +237 -0
- package/dist/apis.js +6 -0
- package/dist/auth.js +98 -0
- package/dist/config.js +97 -0
- package/dist/http.js +55 -0
- package/dist/index.js +53 -0
- package/dist/oauth.js +265 -0
- package/dist/output.js +26 -0
- package/dist/spec/build.js +185 -0
- package/dist/spec/loader.js +23 -0
- package/package.json +59 -0
- package/specs/account.yaml +990 -0
- package/specs/app-template.yaml +486 -0
- package/specs/recorder.yaml +2774 -0
- package/specs/target.yaml +1540 -0
|
@@ -0,0 +1,1540 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
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
|
|
12
|
+
contact:
|
|
13
|
+
name: NASEBANAL
|
|
14
|
+
url: https://www.nasebanal.com
|
|
15
|
+
servers:
|
|
16
|
+
- url: http://localhost:8790
|
|
17
|
+
description: Local dev (wrangler dev)
|
|
18
|
+
- url: https://api.target.nasebanal.com
|
|
19
|
+
description: Production
|
|
20
|
+
security:
|
|
21
|
+
- BearerAuth: []
|
|
22
|
+
paths:
|
|
23
|
+
/api/v1/health:
|
|
24
|
+
get:
|
|
25
|
+
operationId: getHealth
|
|
26
|
+
tags:
|
|
27
|
+
- Health
|
|
28
|
+
summary: Health check
|
|
29
|
+
description: Returns the health status of the API.
|
|
30
|
+
security: []
|
|
31
|
+
responses:
|
|
32
|
+
'200':
|
|
33
|
+
description: API is healthy
|
|
34
|
+
content:
|
|
35
|
+
application/json:
|
|
36
|
+
schema:
|
|
37
|
+
type: object
|
|
38
|
+
required:
|
|
39
|
+
- success
|
|
40
|
+
- data
|
|
41
|
+
properties:
|
|
42
|
+
success:
|
|
43
|
+
type: boolean
|
|
44
|
+
enum: [true]
|
|
45
|
+
data:
|
|
46
|
+
type: object
|
|
47
|
+
properties:
|
|
48
|
+
status:
|
|
49
|
+
type: string
|
|
50
|
+
example: ok
|
|
51
|
+
timestamp:
|
|
52
|
+
type: string
|
|
53
|
+
format: date-time
|
|
54
|
+
/api/v1/me:
|
|
55
|
+
get:
|
|
56
|
+
operationId: getCurrentUser
|
|
57
|
+
tags:
|
|
58
|
+
- User
|
|
59
|
+
summary: Get current user profile
|
|
60
|
+
description: Returns the authenticated user's profile information (resolved from the Account API).
|
|
61
|
+
responses:
|
|
62
|
+
'200':
|
|
63
|
+
description: User profile
|
|
64
|
+
content:
|
|
65
|
+
application/json:
|
|
66
|
+
schema:
|
|
67
|
+
$ref: '#/components/schemas/UserResponse'
|
|
68
|
+
'401':
|
|
69
|
+
$ref: '#/components/responses/Unauthorized'
|
|
70
|
+
/api/v1/targets:
|
|
71
|
+
get:
|
|
72
|
+
operationId: listTargets
|
|
73
|
+
tags:
|
|
74
|
+
- Targets
|
|
75
|
+
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}.
|
|
82
|
+
parameters:
|
|
83
|
+
- name: fields
|
|
84
|
+
in: query
|
|
85
|
+
required: false
|
|
86
|
+
schema:
|
|
87
|
+
type: string
|
|
88
|
+
enum:
|
|
89
|
+
- full
|
|
90
|
+
- summary
|
|
91
|
+
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.
|
|
95
|
+
responses:
|
|
96
|
+
'200':
|
|
97
|
+
description: List of targets with cells (or, with fields=summary, without cells)
|
|
98
|
+
content:
|
|
99
|
+
application/json:
|
|
100
|
+
schema:
|
|
101
|
+
type: object
|
|
102
|
+
required:
|
|
103
|
+
- success
|
|
104
|
+
- data
|
|
105
|
+
properties:
|
|
106
|
+
success:
|
|
107
|
+
type: boolean
|
|
108
|
+
enum: [true]
|
|
109
|
+
data:
|
|
110
|
+
type: object
|
|
111
|
+
required:
|
|
112
|
+
- data
|
|
113
|
+
- total
|
|
114
|
+
properties:
|
|
115
|
+
data:
|
|
116
|
+
type: array
|
|
117
|
+
items:
|
|
118
|
+
$ref: '#/components/schemas/TargetWithCells'
|
|
119
|
+
total:
|
|
120
|
+
type: integer
|
|
121
|
+
examples:
|
|
122
|
+
full:
|
|
123
|
+
summary: Default (fields omitted or fields=full)
|
|
124
|
+
value:
|
|
125
|
+
success: true
|
|
126
|
+
data:
|
|
127
|
+
data:
|
|
128
|
+
- id: tgt_a1b2c3d4
|
|
129
|
+
user_id: 42
|
|
130
|
+
created_by_user_id: 42
|
|
131
|
+
organization_id: null
|
|
132
|
+
parent_target_id: null
|
|
133
|
+
title: Learn Japanese
|
|
134
|
+
description: null
|
|
135
|
+
memo: null
|
|
136
|
+
recorder_tag: null
|
|
137
|
+
recorder_goal_id: null
|
|
138
|
+
progress: 40
|
|
139
|
+
own_progress: 40
|
|
140
|
+
created_at: '2026-05-14T12:00:00Z'
|
|
141
|
+
updated_at: '2026-05-14T12:00:00Z'
|
|
142
|
+
owner_email: user@example.com
|
|
143
|
+
owner_name: Sample User
|
|
144
|
+
created_by_email: user@example.com
|
|
145
|
+
created_by_name: Sample User
|
|
146
|
+
created_by_deleted: false
|
|
147
|
+
cells:
|
|
148
|
+
- id: 1
|
|
149
|
+
target_id: tgt_a1b2c3d4
|
|
150
|
+
position: 40
|
|
151
|
+
text: Learn Japanese
|
|
152
|
+
progress: 40
|
|
153
|
+
created_by_user_id: 42
|
|
154
|
+
created_at: '2026-05-14T12:00:00Z'
|
|
155
|
+
updated_at: '2026-05-14T12:00:00Z'
|
|
156
|
+
total: 1
|
|
157
|
+
summary:
|
|
158
|
+
summary: fields=summary
|
|
159
|
+
value:
|
|
160
|
+
success: true
|
|
161
|
+
data:
|
|
162
|
+
data:
|
|
163
|
+
- id: tgt_a1b2c3d4
|
|
164
|
+
user_id: 42
|
|
165
|
+
created_by_user_id: 42
|
|
166
|
+
organization_id: null
|
|
167
|
+
parent_target_id: null
|
|
168
|
+
title: Learn Japanese
|
|
169
|
+
description: null
|
|
170
|
+
memo: null
|
|
171
|
+
recorder_tag: null
|
|
172
|
+
recorder_goal_id: null
|
|
173
|
+
progress: 40
|
|
174
|
+
own_progress: 40
|
|
175
|
+
created_at: '2026-05-14T12:00:00Z'
|
|
176
|
+
updated_at: '2026-05-14T12:00:00Z'
|
|
177
|
+
owner_email: user@example.com
|
|
178
|
+
owner_name: Sample User
|
|
179
|
+
created_by_email: user@example.com
|
|
180
|
+
created_by_name: Sample User
|
|
181
|
+
created_by_deleted: false
|
|
182
|
+
total: 1
|
|
183
|
+
'401':
|
|
184
|
+
$ref: '#/components/responses/Unauthorized'
|
|
185
|
+
post:
|
|
186
|
+
operationId: createTarget
|
|
187
|
+
tags:
|
|
188
|
+
- Targets
|
|
189
|
+
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.
|
|
193
|
+
requestBody:
|
|
194
|
+
required: true
|
|
195
|
+
content:
|
|
196
|
+
application/json:
|
|
197
|
+
schema:
|
|
198
|
+
$ref: '#/components/schemas/CreateTargetInput'
|
|
199
|
+
responses:
|
|
200
|
+
'201':
|
|
201
|
+
description: Target created with its storage cells
|
|
202
|
+
content:
|
|
203
|
+
application/json:
|
|
204
|
+
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'
|
|
214
|
+
/api/v1/targets/{id}:
|
|
215
|
+
get:
|
|
216
|
+
operationId: getTarget
|
|
217
|
+
tags:
|
|
218
|
+
- Targets
|
|
219
|
+
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.
|
|
223
|
+
parameters:
|
|
224
|
+
- $ref: '#/components/parameters/TargetId'
|
|
225
|
+
responses:
|
|
226
|
+
'200':
|
|
227
|
+
description: Target with cells
|
|
228
|
+
content:
|
|
229
|
+
application/json:
|
|
230
|
+
schema:
|
|
231
|
+
$ref: '#/components/schemas/TargetWithCellsResponse'
|
|
232
|
+
'401':
|
|
233
|
+
$ref: '#/components/responses/Unauthorized'
|
|
234
|
+
'404':
|
|
235
|
+
$ref: '#/components/responses/NotFound'
|
|
236
|
+
put:
|
|
237
|
+
operationId: updateTarget
|
|
238
|
+
tags:
|
|
239
|
+
- Targets
|
|
240
|
+
summary: Update target
|
|
241
|
+
description: Updates a target's title, description, memo, and/or its Recorder tag binding.
|
|
242
|
+
parameters:
|
|
243
|
+
- $ref: '#/components/parameters/TargetId'
|
|
244
|
+
requestBody:
|
|
245
|
+
required: true
|
|
246
|
+
content:
|
|
247
|
+
application/json:
|
|
248
|
+
schema:
|
|
249
|
+
$ref: '#/components/schemas/UpdateTargetInput'
|
|
250
|
+
responses:
|
|
251
|
+
'200':
|
|
252
|
+
description: Target updated
|
|
253
|
+
content:
|
|
254
|
+
application/json:
|
|
255
|
+
schema:
|
|
256
|
+
type: object
|
|
257
|
+
required:
|
|
258
|
+
- success
|
|
259
|
+
- data
|
|
260
|
+
properties:
|
|
261
|
+
success:
|
|
262
|
+
type: boolean
|
|
263
|
+
enum: [true]
|
|
264
|
+
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'
|
|
272
|
+
delete:
|
|
273
|
+
operationId: deleteTarget
|
|
274
|
+
tags:
|
|
275
|
+
- Targets
|
|
276
|
+
summary: Delete target
|
|
277
|
+
description: Deletes a target and all its cells.
|
|
278
|
+
parameters:
|
|
279
|
+
- $ref: '#/components/parameters/TargetId'
|
|
280
|
+
responses:
|
|
281
|
+
'200':
|
|
282
|
+
description: Target deleted
|
|
283
|
+
content:
|
|
284
|
+
application/json:
|
|
285
|
+
schema:
|
|
286
|
+
$ref: '#/components/schemas/SuccessFlagResponse'
|
|
287
|
+
'401':
|
|
288
|
+
$ref: '#/components/responses/Unauthorized'
|
|
289
|
+
'404':
|
|
290
|
+
$ref: '#/components/responses/NotFound'
|
|
291
|
+
/api/v1/targets/{id}/cells/{position}:
|
|
292
|
+
put:
|
|
293
|
+
operationId: updateTargetCell
|
|
294
|
+
tags:
|
|
295
|
+
- Target Cells
|
|
296
|
+
summary: Update target cell
|
|
297
|
+
description: Updates the text and/or progress of a specific storage cell on a target.
|
|
298
|
+
parameters:
|
|
299
|
+
- $ref: '#/components/parameters/TargetId'
|
|
300
|
+
- name: position
|
|
301
|
+
in: path
|
|
302
|
+
required: true
|
|
303
|
+
schema:
|
|
304
|
+
type: integer
|
|
305
|
+
minimum: 0
|
|
306
|
+
maximum: 80
|
|
307
|
+
description: Cell position in the storage layout (0-80; position 40 is reserved for the target title)
|
|
308
|
+
requestBody:
|
|
309
|
+
required: true
|
|
310
|
+
content:
|
|
311
|
+
application/json:
|
|
312
|
+
schema:
|
|
313
|
+
$ref: '#/components/schemas/UpdateTargetCellInput'
|
|
314
|
+
responses:
|
|
315
|
+
'200':
|
|
316
|
+
description: Cell updated
|
|
317
|
+
content:
|
|
318
|
+
application/json:
|
|
319
|
+
schema:
|
|
320
|
+
type: object
|
|
321
|
+
required:
|
|
322
|
+
- success
|
|
323
|
+
- data
|
|
324
|
+
properties:
|
|
325
|
+
success:
|
|
326
|
+
type: boolean
|
|
327
|
+
enum: [true]
|
|
328
|
+
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'
|
|
336
|
+
/api/v1/targets/{id}/parent:
|
|
337
|
+
put:
|
|
338
|
+
operationId: setTargetParent
|
|
339
|
+
tags:
|
|
340
|
+
- Targets
|
|
341
|
+
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.
|
|
346
|
+
parameters:
|
|
347
|
+
- $ref: '#/components/parameters/TargetId'
|
|
348
|
+
requestBody:
|
|
349
|
+
required: true
|
|
350
|
+
content:
|
|
351
|
+
application/json:
|
|
352
|
+
schema:
|
|
353
|
+
$ref: '#/components/schemas/SetTargetParentInput'
|
|
354
|
+
responses:
|
|
355
|
+
'200':
|
|
356
|
+
description: Parent updated; returns the updated target
|
|
357
|
+
content:
|
|
358
|
+
application/json:
|
|
359
|
+
schema:
|
|
360
|
+
type: object
|
|
361
|
+
required:
|
|
362
|
+
- success
|
|
363
|
+
- data
|
|
364
|
+
properties:
|
|
365
|
+
success:
|
|
366
|
+
type: boolean
|
|
367
|
+
enum: [true]
|
|
368
|
+
data:
|
|
369
|
+
$ref: '#/components/schemas/Target'
|
|
370
|
+
'400':
|
|
371
|
+
description: Invalid move (self-parent, namespace mismatch, or cycle)
|
|
372
|
+
content:
|
|
373
|
+
application/json:
|
|
374
|
+
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'
|
|
382
|
+
/api/v1/shared-targets:
|
|
383
|
+
get:
|
|
384
|
+
operationId: listSharedTargets
|
|
385
|
+
tags:
|
|
386
|
+
- Sharing
|
|
387
|
+
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.
|
|
392
|
+
responses:
|
|
393
|
+
'200':
|
|
394
|
+
description: Shared targets
|
|
395
|
+
content:
|
|
396
|
+
application/json:
|
|
397
|
+
schema:
|
|
398
|
+
type: object
|
|
399
|
+
required:
|
|
400
|
+
- success
|
|
401
|
+
- data
|
|
402
|
+
properties:
|
|
403
|
+
success:
|
|
404
|
+
type: boolean
|
|
405
|
+
enum: [true]
|
|
406
|
+
data:
|
|
407
|
+
type: object
|
|
408
|
+
required:
|
|
409
|
+
- data
|
|
410
|
+
- total
|
|
411
|
+
properties:
|
|
412
|
+
data:
|
|
413
|
+
type: array
|
|
414
|
+
items:
|
|
415
|
+
$ref: '#/components/schemas/SharedTarget'
|
|
416
|
+
total:
|
|
417
|
+
type: integer
|
|
418
|
+
'401':
|
|
419
|
+
$ref: '#/components/responses/Unauthorized'
|
|
420
|
+
/api/v1/shares:
|
|
421
|
+
get:
|
|
422
|
+
operationId: listMyShares
|
|
423
|
+
tags:
|
|
424
|
+
- Sharing
|
|
425
|
+
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.
|
|
429
|
+
responses:
|
|
430
|
+
'200':
|
|
431
|
+
description: Shares owned by the caller
|
|
432
|
+
content:
|
|
433
|
+
application/json:
|
|
434
|
+
schema:
|
|
435
|
+
$ref: '#/components/schemas/ShareListResponse'
|
|
436
|
+
'401':
|
|
437
|
+
$ref: '#/components/responses/Unauthorized'
|
|
438
|
+
post:
|
|
439
|
+
operationId: createShare
|
|
440
|
+
tags:
|
|
441
|
+
- Sharing
|
|
442
|
+
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.
|
|
449
|
+
requestBody:
|
|
450
|
+
required: true
|
|
451
|
+
content:
|
|
452
|
+
application/json:
|
|
453
|
+
schema:
|
|
454
|
+
$ref: '#/components/schemas/CreateShareInput'
|
|
455
|
+
responses:
|
|
456
|
+
'201':
|
|
457
|
+
description: Share created (pending acceptance)
|
|
458
|
+
content:
|
|
459
|
+
application/json:
|
|
460
|
+
schema:
|
|
461
|
+
type: object
|
|
462
|
+
required:
|
|
463
|
+
- success
|
|
464
|
+
- data
|
|
465
|
+
properties:
|
|
466
|
+
success:
|
|
467
|
+
type: boolean
|
|
468
|
+
enum: [true]
|
|
469
|
+
data:
|
|
470
|
+
$ref: '#/components/schemas/Share'
|
|
471
|
+
'400':
|
|
472
|
+
$ref: '#/components/responses/ValidationError'
|
|
473
|
+
'401':
|
|
474
|
+
$ref: '#/components/responses/Unauthorized'
|
|
475
|
+
'403':
|
|
476
|
+
description: Sharing not permitted (plan limit, or recipient not in organization)
|
|
477
|
+
content:
|
|
478
|
+
application/json:
|
|
479
|
+
schema:
|
|
480
|
+
$ref: '#/components/schemas/Error'
|
|
481
|
+
'404':
|
|
482
|
+
description: Target not found, or recipient email not registered
|
|
483
|
+
content:
|
|
484
|
+
application/json:
|
|
485
|
+
schema:
|
|
486
|
+
$ref: '#/components/schemas/Error'
|
|
487
|
+
'409':
|
|
488
|
+
$ref: '#/components/responses/Conflict'
|
|
489
|
+
/api/v1/shares/with-me:
|
|
490
|
+
get:
|
|
491
|
+
operationId: listSharesWithMe
|
|
492
|
+
tags:
|
|
493
|
+
- Sharing
|
|
494
|
+
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.
|
|
498
|
+
parameters:
|
|
499
|
+
- name: status
|
|
500
|
+
in: query
|
|
501
|
+
required: false
|
|
502
|
+
schema:
|
|
503
|
+
type: string
|
|
504
|
+
enum: [accepted, pending, rejected, all]
|
|
505
|
+
default: accepted
|
|
506
|
+
description: Which share statuses to return (default `accepted`).
|
|
507
|
+
responses:
|
|
508
|
+
'200':
|
|
509
|
+
description: Shares addressed to the caller
|
|
510
|
+
content:
|
|
511
|
+
application/json:
|
|
512
|
+
schema:
|
|
513
|
+
$ref: '#/components/schemas/ShareListResponse'
|
|
514
|
+
'401':
|
|
515
|
+
$ref: '#/components/responses/Unauthorized'
|
|
516
|
+
/api/v1/shares/recipient-context-options:
|
|
517
|
+
get:
|
|
518
|
+
operationId: getRecipientContextOptions
|
|
519
|
+
tags:
|
|
520
|
+
- Sharing
|
|
521
|
+
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.
|
|
526
|
+
parameters:
|
|
527
|
+
- name: email
|
|
528
|
+
in: query
|
|
529
|
+
required: true
|
|
530
|
+
schema:
|
|
531
|
+
type: string
|
|
532
|
+
format: email
|
|
533
|
+
description: Recipient email to evaluate.
|
|
534
|
+
responses:
|
|
535
|
+
'200':
|
|
536
|
+
description: Available sharing contexts
|
|
537
|
+
content:
|
|
538
|
+
application/json:
|
|
539
|
+
schema:
|
|
540
|
+
type: object
|
|
541
|
+
required:
|
|
542
|
+
- success
|
|
543
|
+
- data
|
|
544
|
+
properties:
|
|
545
|
+
success:
|
|
546
|
+
type: boolean
|
|
547
|
+
enum: [true]
|
|
548
|
+
data:
|
|
549
|
+
type: object
|
|
550
|
+
required:
|
|
551
|
+
- options
|
|
552
|
+
properties:
|
|
553
|
+
options:
|
|
554
|
+
type: array
|
|
555
|
+
items:
|
|
556
|
+
type: string
|
|
557
|
+
enum: [personal, organization]
|
|
558
|
+
example: [personal, organization]
|
|
559
|
+
'400':
|
|
560
|
+
$ref: '#/components/responses/ValidationError'
|
|
561
|
+
'401':
|
|
562
|
+
$ref: '#/components/responses/Unauthorized'
|
|
563
|
+
/api/v1/shares/accept:
|
|
564
|
+
post:
|
|
565
|
+
operationId: acceptShareByToken
|
|
566
|
+
tags:
|
|
567
|
+
- Sharing
|
|
568
|
+
summary: Accept a share invitation by token
|
|
569
|
+
description: Accepts a pending share invitation using the token from the invitation email.
|
|
570
|
+
requestBody:
|
|
571
|
+
required: true
|
|
572
|
+
content:
|
|
573
|
+
application/json:
|
|
574
|
+
schema:
|
|
575
|
+
$ref: '#/components/schemas/TokenInput'
|
|
576
|
+
responses:
|
|
577
|
+
'200':
|
|
578
|
+
description: Share accepted (or already accepted)
|
|
579
|
+
content:
|
|
580
|
+
application/json:
|
|
581
|
+
schema:
|
|
582
|
+
$ref: '#/components/schemas/ShareStatusResponse'
|
|
583
|
+
'400':
|
|
584
|
+
description: Invitation expired or already declined
|
|
585
|
+
content:
|
|
586
|
+
application/json:
|
|
587
|
+
schema:
|
|
588
|
+
$ref: '#/components/schemas/Error'
|
|
589
|
+
'401':
|
|
590
|
+
$ref: '#/components/responses/Unauthorized'
|
|
591
|
+
'404':
|
|
592
|
+
$ref: '#/components/responses/NotFound'
|
|
593
|
+
/api/v1/shares/migrate/accept:
|
|
594
|
+
post:
|
|
595
|
+
operationId: acceptMigrationByToken
|
|
596
|
+
tags:
|
|
597
|
+
- Sharing
|
|
598
|
+
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.
|
|
603
|
+
requestBody:
|
|
604
|
+
required: true
|
|
605
|
+
content:
|
|
606
|
+
application/json:
|
|
607
|
+
schema:
|
|
608
|
+
$ref: '#/components/schemas/TokenInput'
|
|
609
|
+
responses:
|
|
610
|
+
'200':
|
|
611
|
+
description: Ownership transferred
|
|
612
|
+
content:
|
|
613
|
+
application/json:
|
|
614
|
+
schema:
|
|
615
|
+
$ref: '#/components/schemas/MigrationStatusResponse'
|
|
616
|
+
'400':
|
|
617
|
+
description: Migration invitation no longer active or expired
|
|
618
|
+
content:
|
|
619
|
+
application/json:
|
|
620
|
+
schema:
|
|
621
|
+
$ref: '#/components/schemas/Error'
|
|
622
|
+
'401':
|
|
623
|
+
$ref: '#/components/responses/Unauthorized'
|
|
624
|
+
'404':
|
|
625
|
+
$ref: '#/components/responses/NotFound'
|
|
626
|
+
/api/v1/shares/{id}:
|
|
627
|
+
delete:
|
|
628
|
+
operationId: deleteShare
|
|
629
|
+
tags:
|
|
630
|
+
- Sharing
|
|
631
|
+
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.
|
|
636
|
+
parameters:
|
|
637
|
+
- $ref: '#/components/parameters/ShareId'
|
|
638
|
+
- name: cascade_tag_shares
|
|
639
|
+
in: query
|
|
640
|
+
required: false
|
|
641
|
+
schema:
|
|
642
|
+
type: string
|
|
643
|
+
enum: ['true', 'false']
|
|
644
|
+
default: 'true'
|
|
645
|
+
description: Set to `false` to keep the linked Recorder tag shares when deleting.
|
|
646
|
+
responses:
|
|
647
|
+
'200':
|
|
648
|
+
description: Share deleted
|
|
649
|
+
content:
|
|
650
|
+
application/json:
|
|
651
|
+
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'
|
|
661
|
+
/api/v1/shares/{id}/accept:
|
|
662
|
+
post:
|
|
663
|
+
operationId: acceptShareById
|
|
664
|
+
tags:
|
|
665
|
+
- Sharing
|
|
666
|
+
summary: Accept a share invitation (in-app)
|
|
667
|
+
description: In-app counterpart to POST /shares/accept — accepts a pending share addressed to the caller by id.
|
|
668
|
+
parameters:
|
|
669
|
+
- $ref: '#/components/parameters/ShareId'
|
|
670
|
+
responses:
|
|
671
|
+
'200':
|
|
672
|
+
description: Share accepted (or already accepted)
|
|
673
|
+
content:
|
|
674
|
+
application/json:
|
|
675
|
+
schema:
|
|
676
|
+
$ref: '#/components/schemas/ShareStatusResponse'
|
|
677
|
+
'400':
|
|
678
|
+
description: Invitation expired or already declined
|
|
679
|
+
content:
|
|
680
|
+
application/json:
|
|
681
|
+
schema:
|
|
682
|
+
$ref: '#/components/schemas/Error'
|
|
683
|
+
'401':
|
|
684
|
+
$ref: '#/components/responses/Unauthorized'
|
|
685
|
+
'404':
|
|
686
|
+
$ref: '#/components/responses/NotFound'
|
|
687
|
+
/api/v1/shares/{id}/reject:
|
|
688
|
+
post:
|
|
689
|
+
operationId: rejectShare
|
|
690
|
+
tags:
|
|
691
|
+
- Sharing
|
|
692
|
+
summary: Reject a share invitation
|
|
693
|
+
description: Declines a pending share addressed to the caller. An already-accepted share cannot be rejected (delete it instead).
|
|
694
|
+
parameters:
|
|
695
|
+
- $ref: '#/components/parameters/ShareId'
|
|
696
|
+
responses:
|
|
697
|
+
'200':
|
|
698
|
+
description: Share rejected (or already rejected)
|
|
699
|
+
content:
|
|
700
|
+
application/json:
|
|
701
|
+
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'
|
|
709
|
+
/api/v1/shares/{id}/pause:
|
|
710
|
+
patch:
|
|
711
|
+
operationId: toggleSharePaused
|
|
712
|
+
tags:
|
|
713
|
+
- Sharing
|
|
714
|
+
summary: Pause or resume a share
|
|
715
|
+
description: Owner-only. Pauses or resumes a share without deleting it; a paused share is hidden from the recipient's shared-targets list.
|
|
716
|
+
parameters:
|
|
717
|
+
- $ref: '#/components/parameters/ShareId'
|
|
718
|
+
requestBody:
|
|
719
|
+
required: true
|
|
720
|
+
content:
|
|
721
|
+
application/json:
|
|
722
|
+
schema:
|
|
723
|
+
type: object
|
|
724
|
+
required:
|
|
725
|
+
- is_paused
|
|
726
|
+
properties:
|
|
727
|
+
is_paused:
|
|
728
|
+
type: boolean
|
|
729
|
+
responses:
|
|
730
|
+
'200':
|
|
731
|
+
description: Updated share row
|
|
732
|
+
content:
|
|
733
|
+
application/json:
|
|
734
|
+
schema:
|
|
735
|
+
type: object
|
|
736
|
+
required:
|
|
737
|
+
- success
|
|
738
|
+
- data
|
|
739
|
+
properties:
|
|
740
|
+
success:
|
|
741
|
+
type: boolean
|
|
742
|
+
enum: [true]
|
|
743
|
+
data:
|
|
744
|
+
$ref: '#/components/schemas/Share'
|
|
745
|
+
'401':
|
|
746
|
+
$ref: '#/components/responses/Unauthorized'
|
|
747
|
+
'404':
|
|
748
|
+
$ref: '#/components/responses/NotFound'
|
|
749
|
+
/api/v1/shares/{id}/visibility:
|
|
750
|
+
patch:
|
|
751
|
+
operationId: toggleShareVisibility
|
|
752
|
+
tags:
|
|
753
|
+
- Sharing
|
|
754
|
+
summary: Hide or unhide a share
|
|
755
|
+
description: Recipient-only. Hides or unhides a share from the caller's own shared-targets list.
|
|
756
|
+
parameters:
|
|
757
|
+
- $ref: '#/components/parameters/ShareId'
|
|
758
|
+
requestBody:
|
|
759
|
+
required: true
|
|
760
|
+
content:
|
|
761
|
+
application/json:
|
|
762
|
+
schema:
|
|
763
|
+
type: object
|
|
764
|
+
required:
|
|
765
|
+
- is_hidden
|
|
766
|
+
properties:
|
|
767
|
+
is_hidden:
|
|
768
|
+
type: boolean
|
|
769
|
+
responses:
|
|
770
|
+
'200':
|
|
771
|
+
description: Updated share row
|
|
772
|
+
content:
|
|
773
|
+
application/json:
|
|
774
|
+
schema:
|
|
775
|
+
type: object
|
|
776
|
+
required:
|
|
777
|
+
- success
|
|
778
|
+
- data
|
|
779
|
+
properties:
|
|
780
|
+
success:
|
|
781
|
+
type: boolean
|
|
782
|
+
enum: [true]
|
|
783
|
+
data:
|
|
784
|
+
$ref: '#/components/schemas/Share'
|
|
785
|
+
'401':
|
|
786
|
+
$ref: '#/components/responses/Unauthorized'
|
|
787
|
+
'404':
|
|
788
|
+
$ref: '#/components/responses/NotFound'
|
|
789
|
+
/api/v1/shares/{id}/transfer:
|
|
790
|
+
post:
|
|
791
|
+
operationId: transferOwnership
|
|
792
|
+
tags:
|
|
793
|
+
- Sharing
|
|
794
|
+
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.
|
|
799
|
+
parameters:
|
|
800
|
+
- $ref: '#/components/parameters/ShareId'
|
|
801
|
+
responses:
|
|
802
|
+
'200':
|
|
803
|
+
description: Migration invitation issued
|
|
804
|
+
content:
|
|
805
|
+
application/json:
|
|
806
|
+
schema:
|
|
807
|
+
type: object
|
|
808
|
+
required:
|
|
809
|
+
- success
|
|
810
|
+
- data
|
|
811
|
+
properties:
|
|
812
|
+
success:
|
|
813
|
+
type: boolean
|
|
814
|
+
enum: [true]
|
|
815
|
+
data:
|
|
816
|
+
type: object
|
|
817
|
+
required:
|
|
818
|
+
- id
|
|
819
|
+
- migration_status
|
|
820
|
+
properties:
|
|
821
|
+
id:
|
|
822
|
+
type: integer
|
|
823
|
+
migration_status:
|
|
824
|
+
type: string
|
|
825
|
+
enum: [pending]
|
|
826
|
+
expires_at:
|
|
827
|
+
type: string
|
|
828
|
+
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'
|
|
839
|
+
/api/v1/shares/{id}/migrate/accept:
|
|
840
|
+
post:
|
|
841
|
+
operationId: acceptMigrationById
|
|
842
|
+
tags:
|
|
843
|
+
- Sharing
|
|
844
|
+
summary: Accept an ownership transfer (in-app)
|
|
845
|
+
description: In-app counterpart to POST /shares/migrate/accept — accepts a pending ownership transfer addressed to the caller by id.
|
|
846
|
+
parameters:
|
|
847
|
+
- $ref: '#/components/parameters/ShareId'
|
|
848
|
+
responses:
|
|
849
|
+
'200':
|
|
850
|
+
description: Ownership transferred
|
|
851
|
+
content:
|
|
852
|
+
application/json:
|
|
853
|
+
schema:
|
|
854
|
+
$ref: '#/components/schemas/MigrationStatusResponse'
|
|
855
|
+
'400':
|
|
856
|
+
description: Migration invitation no longer active or expired
|
|
857
|
+
content:
|
|
858
|
+
application/json:
|
|
859
|
+
schema:
|
|
860
|
+
$ref: '#/components/schemas/Error'
|
|
861
|
+
'401':
|
|
862
|
+
$ref: '#/components/responses/Unauthorized'
|
|
863
|
+
'404':
|
|
864
|
+
$ref: '#/components/responses/NotFound'
|
|
865
|
+
/api/v1/shares/{id}/migrate/reject:
|
|
866
|
+
post:
|
|
867
|
+
operationId: rejectMigration
|
|
868
|
+
tags:
|
|
869
|
+
- Sharing
|
|
870
|
+
summary: Reject an ownership transfer
|
|
871
|
+
description: Recipient-only. Declines a pending ownership transfer; the underlying share keeps its existing permission.
|
|
872
|
+
parameters:
|
|
873
|
+
- $ref: '#/components/parameters/ShareId'
|
|
874
|
+
responses:
|
|
875
|
+
'200':
|
|
876
|
+
description: Migration rejected
|
|
877
|
+
content:
|
|
878
|
+
application/json:
|
|
879
|
+
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'
|
|
887
|
+
/api/v1/shares/{id}/migrate/cancel:
|
|
888
|
+
post:
|
|
889
|
+
operationId: cancelMigration
|
|
890
|
+
tags:
|
|
891
|
+
- Sharing
|
|
892
|
+
summary: Cancel an ownership transfer
|
|
893
|
+
description: Owner-only. Cancels an outstanding ownership-transfer invitation before the recipient acts.
|
|
894
|
+
parameters:
|
|
895
|
+
- $ref: '#/components/parameters/ShareId'
|
|
896
|
+
responses:
|
|
897
|
+
'200':
|
|
898
|
+
description: Migration cancelled
|
|
899
|
+
content:
|
|
900
|
+
application/json:
|
|
901
|
+
schema:
|
|
902
|
+
type: object
|
|
903
|
+
required:
|
|
904
|
+
- success
|
|
905
|
+
- data
|
|
906
|
+
properties:
|
|
907
|
+
success:
|
|
908
|
+
type: boolean
|
|
909
|
+
enum: [true]
|
|
910
|
+
data:
|
|
911
|
+
type: object
|
|
912
|
+
required:
|
|
913
|
+
- id
|
|
914
|
+
- migration_status
|
|
915
|
+
properties:
|
|
916
|
+
id:
|
|
917
|
+
type: integer
|
|
918
|
+
migration_status:
|
|
919
|
+
type: string
|
|
920
|
+
nullable: true
|
|
921
|
+
enum: [null]
|
|
922
|
+
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'
|
|
929
|
+
components:
|
|
930
|
+
securitySchemes:
|
|
931
|
+
BearerAuth:
|
|
932
|
+
type: http
|
|
933
|
+
scheme: bearer
|
|
934
|
+
bearerFormat: JWT or PAT
|
|
935
|
+
description: Use either an Auth0 JWT token or a Personal Access Token (PAT) starting with `nbpat_`.
|
|
936
|
+
parameters:
|
|
937
|
+
TargetId:
|
|
938
|
+
name: id
|
|
939
|
+
in: path
|
|
940
|
+
required: true
|
|
941
|
+
schema:
|
|
942
|
+
type: string
|
|
943
|
+
description: Target ID
|
|
944
|
+
ShareId:
|
|
945
|
+
name: id
|
|
946
|
+
in: path
|
|
947
|
+
required: true
|
|
948
|
+
schema:
|
|
949
|
+
type: integer
|
|
950
|
+
description: Share ID
|
|
951
|
+
schemas:
|
|
952
|
+
User:
|
|
953
|
+
type: object
|
|
954
|
+
required:
|
|
955
|
+
- id
|
|
956
|
+
- auth0_sub
|
|
957
|
+
- email
|
|
958
|
+
- name
|
|
959
|
+
- language
|
|
960
|
+
- plan
|
|
961
|
+
properties:
|
|
962
|
+
id:
|
|
963
|
+
type: integer
|
|
964
|
+
auth0_sub:
|
|
965
|
+
type: string
|
|
966
|
+
email:
|
|
967
|
+
type: string
|
|
968
|
+
format: email
|
|
969
|
+
name:
|
|
970
|
+
type: string
|
|
971
|
+
language:
|
|
972
|
+
type: string
|
|
973
|
+
enum:
|
|
974
|
+
- ja
|
|
975
|
+
- en
|
|
976
|
+
plan:
|
|
977
|
+
type: string
|
|
978
|
+
enum:
|
|
979
|
+
- free
|
|
980
|
+
- pro
|
|
981
|
+
- family
|
|
982
|
+
- enterprise
|
|
983
|
+
subscription_status:
|
|
984
|
+
type: string
|
|
985
|
+
enum:
|
|
986
|
+
- active
|
|
987
|
+
- canceled
|
|
988
|
+
- past_due
|
|
989
|
+
- trialing
|
|
990
|
+
- null
|
|
991
|
+
nullable: true
|
|
992
|
+
subscription_expires_at:
|
|
993
|
+
type: string
|
|
994
|
+
format: date-time
|
|
995
|
+
nullable: true
|
|
996
|
+
UserResponse:
|
|
997
|
+
type: object
|
|
998
|
+
required:
|
|
999
|
+
- success
|
|
1000
|
+
- data
|
|
1001
|
+
properties:
|
|
1002
|
+
success:
|
|
1003
|
+
type: boolean
|
|
1004
|
+
enum: [true]
|
|
1005
|
+
data:
|
|
1006
|
+
$ref: '#/components/schemas/User'
|
|
1007
|
+
Target:
|
|
1008
|
+
type: object
|
|
1009
|
+
properties:
|
|
1010
|
+
id:
|
|
1011
|
+
type: string
|
|
1012
|
+
description: Unique target ID
|
|
1013
|
+
user_id:
|
|
1014
|
+
type: integer
|
|
1015
|
+
description: Owner user id
|
|
1016
|
+
created_by_user_id:
|
|
1017
|
+
type: integer
|
|
1018
|
+
nullable: true
|
|
1019
|
+
description: User who created the target. Distinct from ownership; preserved across ownership transfer.
|
|
1020
|
+
organization_id:
|
|
1021
|
+
type: integer
|
|
1022
|
+
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.
|
|
1026
|
+
parent_target_id:
|
|
1027
|
+
type: string
|
|
1028
|
+
nullable: true
|
|
1029
|
+
description: >-
|
|
1030
|
+
Direct parent reference (migration 0017+). Authoritative source of tree structure. NULL = root target.
|
|
1031
|
+
title:
|
|
1032
|
+
type: string
|
|
1033
|
+
description: Goal title
|
|
1034
|
+
maxLength: 200
|
|
1035
|
+
description:
|
|
1036
|
+
type: string
|
|
1037
|
+
nullable: true
|
|
1038
|
+
memo:
|
|
1039
|
+
type: string
|
|
1040
|
+
nullable: true
|
|
1041
|
+
recorder_tag:
|
|
1042
|
+
type: string
|
|
1043
|
+
nullable: true
|
|
1044
|
+
description: Optional tag linking to the Recorder app
|
|
1045
|
+
recorder_goal_id:
|
|
1046
|
+
type: integer
|
|
1047
|
+
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.
|
|
1052
|
+
created_at:
|
|
1053
|
+
type: string
|
|
1054
|
+
format: date-time
|
|
1055
|
+
updated_at:
|
|
1056
|
+
type: string
|
|
1057
|
+
format: date-time
|
|
1058
|
+
owner_email:
|
|
1059
|
+
type: string
|
|
1060
|
+
format: email
|
|
1061
|
+
description: Resolved owner email (present in response payloads).
|
|
1062
|
+
owner_name:
|
|
1063
|
+
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.
|
|
1067
|
+
created_by_email:
|
|
1068
|
+
type: string
|
|
1069
|
+
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.
|
|
1073
|
+
created_by_name:
|
|
1074
|
+
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.
|
|
1078
|
+
created_by_deleted:
|
|
1079
|
+
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.
|
|
1084
|
+
TargetCell:
|
|
1085
|
+
type: object
|
|
1086
|
+
properties:
|
|
1087
|
+
id:
|
|
1088
|
+
type: integer
|
|
1089
|
+
target_id:
|
|
1090
|
+
type: string
|
|
1091
|
+
position:
|
|
1092
|
+
type: integer
|
|
1093
|
+
minimum: 0
|
|
1094
|
+
maximum: 80
|
|
1095
|
+
description: Cell position in the storage layout (0-80; position 40 is reserved for the target title)
|
|
1096
|
+
text:
|
|
1097
|
+
type: string
|
|
1098
|
+
maxLength: 500
|
|
1099
|
+
description: Cell content
|
|
1100
|
+
progress:
|
|
1101
|
+
type: integer
|
|
1102
|
+
minimum: 0
|
|
1103
|
+
maximum: 100
|
|
1104
|
+
description: Progress percentage
|
|
1105
|
+
created_by_user_id:
|
|
1106
|
+
type: integer
|
|
1107
|
+
nullable: true
|
|
1108
|
+
created_at:
|
|
1109
|
+
type: string
|
|
1110
|
+
format: date-time
|
|
1111
|
+
updated_at:
|
|
1112
|
+
type: string
|
|
1113
|
+
format: date-time
|
|
1114
|
+
TargetWithCells:
|
|
1115
|
+
allOf:
|
|
1116
|
+
- $ref: '#/components/schemas/Target'
|
|
1117
|
+
- type: object
|
|
1118
|
+
required:
|
|
1119
|
+
- progress
|
|
1120
|
+
- own_progress
|
|
1121
|
+
properties:
|
|
1122
|
+
cells:
|
|
1123
|
+
type: array
|
|
1124
|
+
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.
|
|
1130
|
+
progress:
|
|
1131
|
+
type: integer
|
|
1132
|
+
minimum: 0
|
|
1133
|
+
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`.
|
|
1138
|
+
own_progress:
|
|
1139
|
+
type: integer
|
|
1140
|
+
minimum: 0
|
|
1141
|
+
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.
|
|
1149
|
+
TargetWithCellsResponse:
|
|
1150
|
+
type: object
|
|
1151
|
+
required:
|
|
1152
|
+
- success
|
|
1153
|
+
- data
|
|
1154
|
+
properties:
|
|
1155
|
+
success:
|
|
1156
|
+
type: boolean
|
|
1157
|
+
enum: [true]
|
|
1158
|
+
data:
|
|
1159
|
+
$ref: '#/components/schemas/TargetWithCells'
|
|
1160
|
+
SharedTarget:
|
|
1161
|
+
allOf:
|
|
1162
|
+
- $ref: '#/components/schemas/TargetWithCells'
|
|
1163
|
+
- type: object
|
|
1164
|
+
properties:
|
|
1165
|
+
shared_by_user_id:
|
|
1166
|
+
type: integer
|
|
1167
|
+
description: User id of the sharing owner
|
|
1168
|
+
shared_by_email:
|
|
1169
|
+
type: string
|
|
1170
|
+
format: email
|
|
1171
|
+
shared_by_name:
|
|
1172
|
+
type: string
|
|
1173
|
+
description: Display name the sharing owner set in their profile. Absent when they set none.
|
|
1174
|
+
share_permission:
|
|
1175
|
+
type: string
|
|
1176
|
+
enum: [read, write]
|
|
1177
|
+
share_root_target_id:
|
|
1178
|
+
type: string
|
|
1179
|
+
description: The root target id of the share that grants access to this row
|
|
1180
|
+
share_show_embed:
|
|
1181
|
+
type: integer
|
|
1182
|
+
enum: [0, 1]
|
|
1183
|
+
description: Whether the share permits embedding the linked Recorder graph
|
|
1184
|
+
Share:
|
|
1185
|
+
type: object
|
|
1186
|
+
properties:
|
|
1187
|
+
id:
|
|
1188
|
+
type: integer
|
|
1189
|
+
owner_user_id:
|
|
1190
|
+
type: integer
|
|
1191
|
+
shared_with_user_id:
|
|
1192
|
+
type: integer
|
|
1193
|
+
target_id:
|
|
1194
|
+
type: string
|
|
1195
|
+
permission:
|
|
1196
|
+
type: string
|
|
1197
|
+
enum: [read, write]
|
|
1198
|
+
status:
|
|
1199
|
+
type: string
|
|
1200
|
+
enum: [pending, accepted, rejected]
|
|
1201
|
+
expires_at:
|
|
1202
|
+
type: string
|
|
1203
|
+
format: date-time
|
|
1204
|
+
nullable: true
|
|
1205
|
+
migration_status:
|
|
1206
|
+
type: string
|
|
1207
|
+
enum: [pending, null]
|
|
1208
|
+
nullable: true
|
|
1209
|
+
description: Ownership-transfer state. NULL = no migration in flight.
|
|
1210
|
+
migration_expires_at:
|
|
1211
|
+
type: string
|
|
1212
|
+
format: date-time
|
|
1213
|
+
nullable: true
|
|
1214
|
+
is_hidden:
|
|
1215
|
+
type: integer
|
|
1216
|
+
enum: [0, 1]
|
|
1217
|
+
is_paused:
|
|
1218
|
+
type: integer
|
|
1219
|
+
enum: [0, 1]
|
|
1220
|
+
show_embed:
|
|
1221
|
+
type: integer
|
|
1222
|
+
enum: [0, 1]
|
|
1223
|
+
include_descendants:
|
|
1224
|
+
type: integer
|
|
1225
|
+
enum: [0, 1]
|
|
1226
|
+
include_data:
|
|
1227
|
+
type: integer
|
|
1228
|
+
enum: [0, 1]
|
|
1229
|
+
parent_share_id:
|
|
1230
|
+
type: integer
|
|
1231
|
+
nullable: true
|
|
1232
|
+
created_at:
|
|
1233
|
+
type: string
|
|
1234
|
+
format: date-time
|
|
1235
|
+
updated_at:
|
|
1236
|
+
type: string
|
|
1237
|
+
format: date-time
|
|
1238
|
+
target_title:
|
|
1239
|
+
type: string
|
|
1240
|
+
description: Enriched — title of the shared target.
|
|
1241
|
+
target_chain:
|
|
1242
|
+
type: string
|
|
1243
|
+
description: Enriched — owner-side "Parent > Child" breadcrumb for the target.
|
|
1244
|
+
owner_email:
|
|
1245
|
+
type: string
|
|
1246
|
+
format: email
|
|
1247
|
+
description: Enriched — present when listing shares addressed to the caller.
|
|
1248
|
+
owner_name:
|
|
1249
|
+
type: string
|
|
1250
|
+
description: >-
|
|
1251
|
+
Display name the sharing owner set in their profile. Absent when they set none.
|
|
1252
|
+
shared_with_email:
|
|
1253
|
+
type: string
|
|
1254
|
+
format: email
|
|
1255
|
+
description: Enriched — present when listing shares the caller owns.
|
|
1256
|
+
shared_with_name:
|
|
1257
|
+
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.
|
|
1261
|
+
owner_plan:
|
|
1262
|
+
type: string
|
|
1263
|
+
description: Enriched — the owner's plan, present when listing shares the caller owns.
|
|
1264
|
+
ShareListResponse:
|
|
1265
|
+
type: object
|
|
1266
|
+
required:
|
|
1267
|
+
- success
|
|
1268
|
+
- data
|
|
1269
|
+
properties:
|
|
1270
|
+
success:
|
|
1271
|
+
type: boolean
|
|
1272
|
+
enum: [true]
|
|
1273
|
+
data:
|
|
1274
|
+
type: object
|
|
1275
|
+
required:
|
|
1276
|
+
- data
|
|
1277
|
+
- total
|
|
1278
|
+
- limit
|
|
1279
|
+
- offset
|
|
1280
|
+
properties:
|
|
1281
|
+
data:
|
|
1282
|
+
type: array
|
|
1283
|
+
items:
|
|
1284
|
+
$ref: '#/components/schemas/Share'
|
|
1285
|
+
total:
|
|
1286
|
+
type: integer
|
|
1287
|
+
limit:
|
|
1288
|
+
type: integer
|
|
1289
|
+
offset:
|
|
1290
|
+
type: integer
|
|
1291
|
+
ShareStatusResponse:
|
|
1292
|
+
type: object
|
|
1293
|
+
required:
|
|
1294
|
+
- success
|
|
1295
|
+
- data
|
|
1296
|
+
properties:
|
|
1297
|
+
success:
|
|
1298
|
+
type: boolean
|
|
1299
|
+
enum: [true]
|
|
1300
|
+
data:
|
|
1301
|
+
type: object
|
|
1302
|
+
required:
|
|
1303
|
+
- id
|
|
1304
|
+
- status
|
|
1305
|
+
properties:
|
|
1306
|
+
id:
|
|
1307
|
+
type: integer
|
|
1308
|
+
status:
|
|
1309
|
+
type: string
|
|
1310
|
+
enum: [pending, accepted, rejected]
|
|
1311
|
+
already:
|
|
1312
|
+
type: boolean
|
|
1313
|
+
description: True when the share was already in the requested state.
|
|
1314
|
+
MigrationStatusResponse:
|
|
1315
|
+
type: object
|
|
1316
|
+
required:
|
|
1317
|
+
- success
|
|
1318
|
+
- data
|
|
1319
|
+
properties:
|
|
1320
|
+
success:
|
|
1321
|
+
type: boolean
|
|
1322
|
+
enum: [true]
|
|
1323
|
+
data:
|
|
1324
|
+
type: object
|
|
1325
|
+
required:
|
|
1326
|
+
- id
|
|
1327
|
+
- migration_status
|
|
1328
|
+
properties:
|
|
1329
|
+
id:
|
|
1330
|
+
type: integer
|
|
1331
|
+
migration_status:
|
|
1332
|
+
type: string
|
|
1333
|
+
enum: [accepted, rejected]
|
|
1334
|
+
SuccessFlagResponse:
|
|
1335
|
+
type: object
|
|
1336
|
+
required:
|
|
1337
|
+
- success
|
|
1338
|
+
- data
|
|
1339
|
+
properties:
|
|
1340
|
+
success:
|
|
1341
|
+
type: boolean
|
|
1342
|
+
enum: [true]
|
|
1343
|
+
data:
|
|
1344
|
+
type: object
|
|
1345
|
+
properties:
|
|
1346
|
+
success:
|
|
1347
|
+
type: boolean
|
|
1348
|
+
enum: [true]
|
|
1349
|
+
CreateTargetInput:
|
|
1350
|
+
type: object
|
|
1351
|
+
required:
|
|
1352
|
+
- title
|
|
1353
|
+
properties:
|
|
1354
|
+
title:
|
|
1355
|
+
type: string
|
|
1356
|
+
minLength: 1
|
|
1357
|
+
maxLength: 200
|
|
1358
|
+
example: Become a professional athlete
|
|
1359
|
+
description:
|
|
1360
|
+
type: string
|
|
1361
|
+
memo:
|
|
1362
|
+
type: string
|
|
1363
|
+
parent_id:
|
|
1364
|
+
type: string
|
|
1365
|
+
description: Optional parent target id to nest the new target under at creation time.
|
|
1366
|
+
UpdateTargetInput:
|
|
1367
|
+
type: object
|
|
1368
|
+
properties:
|
|
1369
|
+
title:
|
|
1370
|
+
type: string
|
|
1371
|
+
minLength: 1
|
|
1372
|
+
maxLength: 200
|
|
1373
|
+
description:
|
|
1374
|
+
type: string
|
|
1375
|
+
nullable: true
|
|
1376
|
+
memo:
|
|
1377
|
+
type: string
|
|
1378
|
+
nullable: true
|
|
1379
|
+
recorder_tag:
|
|
1380
|
+
type: string
|
|
1381
|
+
nullable: true
|
|
1382
|
+
description: Tag to link with Recorder app
|
|
1383
|
+
recorder_goal_id:
|
|
1384
|
+
type: integer
|
|
1385
|
+
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.
|
|
1389
|
+
UpdateTargetCellInput:
|
|
1390
|
+
type: object
|
|
1391
|
+
properties:
|
|
1392
|
+
text:
|
|
1393
|
+
type: string
|
|
1394
|
+
maxLength: 500
|
|
1395
|
+
description: Cell content
|
|
1396
|
+
progress:
|
|
1397
|
+
type: integer
|
|
1398
|
+
minimum: 0
|
|
1399
|
+
maximum: 100
|
|
1400
|
+
description: Progress percentage
|
|
1401
|
+
SetTargetParentInput:
|
|
1402
|
+
type: object
|
|
1403
|
+
properties:
|
|
1404
|
+
parent_target_id:
|
|
1405
|
+
type: string
|
|
1406
|
+
nullable: true
|
|
1407
|
+
description: New parent target id, or null to detach to root.
|
|
1408
|
+
CreateShareInput:
|
|
1409
|
+
type: object
|
|
1410
|
+
required:
|
|
1411
|
+
- shared_with_email
|
|
1412
|
+
- target_id
|
|
1413
|
+
properties:
|
|
1414
|
+
shared_with_email:
|
|
1415
|
+
type: string
|
|
1416
|
+
format: email
|
|
1417
|
+
description: Email of the user to share with (must be a registered user).
|
|
1418
|
+
target_id:
|
|
1419
|
+
type: string
|
|
1420
|
+
permission:
|
|
1421
|
+
type: string
|
|
1422
|
+
enum: [read, write]
|
|
1423
|
+
default: read
|
|
1424
|
+
include_descendants:
|
|
1425
|
+
type: boolean
|
|
1426
|
+
default: false
|
|
1427
|
+
description: Share the whole subtree rooted at the target, not just the target itself.
|
|
1428
|
+
include_data:
|
|
1429
|
+
type: boolean
|
|
1430
|
+
default: false
|
|
1431
|
+
description: Also cascade-share the linked Recorder tag data so the recipient can view embedded graphs.
|
|
1432
|
+
share_context:
|
|
1433
|
+
type: string
|
|
1434
|
+
enum: [personal, organization]
|
|
1435
|
+
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.
|
|
1439
|
+
extra_tag_names:
|
|
1440
|
+
type: array
|
|
1441
|
+
items:
|
|
1442
|
+
type: string
|
|
1443
|
+
description: Additional real Recorder tag names to include when cascading data shares.
|
|
1444
|
+
TokenInput:
|
|
1445
|
+
type: object
|
|
1446
|
+
required:
|
|
1447
|
+
- token
|
|
1448
|
+
properties:
|
|
1449
|
+
token:
|
|
1450
|
+
type: string
|
|
1451
|
+
description: The invitation token from the email link.
|
|
1452
|
+
Error:
|
|
1453
|
+
type: object
|
|
1454
|
+
required:
|
|
1455
|
+
- success
|
|
1456
|
+
- error
|
|
1457
|
+
properties:
|
|
1458
|
+
success:
|
|
1459
|
+
type: boolean
|
|
1460
|
+
enum: [false]
|
|
1461
|
+
error:
|
|
1462
|
+
type: object
|
|
1463
|
+
required:
|
|
1464
|
+
- code
|
|
1465
|
+
- message
|
|
1466
|
+
properties:
|
|
1467
|
+
code:
|
|
1468
|
+
type: string
|
|
1469
|
+
message:
|
|
1470
|
+
type: string
|
|
1471
|
+
details:
|
|
1472
|
+
type: object
|
|
1473
|
+
additionalProperties: true
|
|
1474
|
+
responses:
|
|
1475
|
+
Unauthorized:
|
|
1476
|
+
description: Authentication required or invalid token
|
|
1477
|
+
content:
|
|
1478
|
+
application/json:
|
|
1479
|
+
schema:
|
|
1480
|
+
$ref: '#/components/schemas/Error'
|
|
1481
|
+
example:
|
|
1482
|
+
success: false
|
|
1483
|
+
error:
|
|
1484
|
+
code: AUTH_ERROR
|
|
1485
|
+
message: No authentication token provided
|
|
1486
|
+
Forbidden:
|
|
1487
|
+
description: The caller is not allowed to perform this action
|
|
1488
|
+
content:
|
|
1489
|
+
application/json:
|
|
1490
|
+
schema:
|
|
1491
|
+
$ref: '#/components/schemas/Error'
|
|
1492
|
+
example:
|
|
1493
|
+
success: false
|
|
1494
|
+
error:
|
|
1495
|
+
code: FORBIDDEN
|
|
1496
|
+
message: Cannot transfer ownership of organization-owned target. Contact the organization admin.
|
|
1497
|
+
NotFound:
|
|
1498
|
+
description: Resource not found
|
|
1499
|
+
content:
|
|
1500
|
+
application/json:
|
|
1501
|
+
schema:
|
|
1502
|
+
$ref: '#/components/schemas/Error'
|
|
1503
|
+
example:
|
|
1504
|
+
success: false
|
|
1505
|
+
error:
|
|
1506
|
+
code: NOT_FOUND
|
|
1507
|
+
message: Target not found
|
|
1508
|
+
Conflict:
|
|
1509
|
+
description: The request conflicts with the current state of the resource
|
|
1510
|
+
content:
|
|
1511
|
+
application/json:
|
|
1512
|
+
schema:
|
|
1513
|
+
$ref: '#/components/schemas/Error'
|
|
1514
|
+
example:
|
|
1515
|
+
success: false
|
|
1516
|
+
error:
|
|
1517
|
+
code: CONFLICT
|
|
1518
|
+
message: 'Share already exists (status: pending)'
|
|
1519
|
+
ValidationError:
|
|
1520
|
+
description: Validation error
|
|
1521
|
+
content:
|
|
1522
|
+
application/json:
|
|
1523
|
+
schema:
|
|
1524
|
+
$ref: '#/components/schemas/Error'
|
|
1525
|
+
example:
|
|
1526
|
+
success: false
|
|
1527
|
+
error:
|
|
1528
|
+
code: VALIDATION_ERROR
|
|
1529
|
+
message: Title is required
|
|
1530
|
+
tags:
|
|
1531
|
+
- name: Health
|
|
1532
|
+
description: Health check endpoints
|
|
1533
|
+
- name: User
|
|
1534
|
+
description: User profile endpoints
|
|
1535
|
+
- name: Targets
|
|
1536
|
+
description: Target management
|
|
1537
|
+
- name: Target Cells
|
|
1538
|
+
description: Individual storage cell management on a target
|
|
1539
|
+
- name: Sharing
|
|
1540
|
+
description: Sharing targets with other users and transferring ownership
|