@nasebanal/cli 0.1.0 → 0.2.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.
@@ -1,10 +1,8 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: NASEBANAL Account API
4
- description: >-
5
- Centralized user and billing management API for NASEBANAL applications. Manages user profiles, per-service
6
- subscriptions, Stripe billing, and Personal Access Tokens (PAT).
7
- version: 1.4.0
4
+ description: Centralized user and billing management API for NASEBANAL applications. Manages user profiles, per-service subscriptions, Stripe billing, and Personal Access Tokens (PAT).
5
+ version: 1.5.0
8
6
  contact:
9
7
  name: NASEBANAL
10
8
  url: https://www.nasebanal.com
@@ -24,7 +22,7 @@ paths:
24
22
  description: Returns the health status of the API.
25
23
  security: []
26
24
  responses:
27
- '200':
25
+ "200":
28
26
  description: API is healthy
29
27
  content:
30
28
  application/json:
@@ -44,34 +42,26 @@ paths:
44
42
  summary: Get current user profile
45
43
  description: Returns the authenticated user's profile information including subscription details.
46
44
  responses:
47
- '200':
45
+ "200":
48
46
  description: User profile
49
47
  content:
50
48
  application/json:
51
49
  schema:
52
- $ref: '#/components/schemas/UserResponse'
53
- '401':
54
- $ref: '#/components/responses/Unauthorized'
50
+ $ref: "#/components/schemas/UserResponse"
51
+ "401":
52
+ $ref: "#/components/responses/Unauthorized"
55
53
  delete:
56
54
  tags:
57
55
  - User
58
56
  summary: Delete account
59
- description: >-
60
- Permanently deletes the authenticated user's account and every service's data for it: Recorder records, tags and
61
- media, Target goals, shares on both sides, organization memberships, and API tokens. An active personal
62
- subscription is cancelled at Stripe as part of the same call.
57
+ description: |-
58
+ Permanently deletes the authenticated user's account and every service's data for it: Recorder records, tags and media, Target goals, shares on both sides, organization memberships, and API tokens. An active personal subscription is cancelled at Stripe as part of the same call.
63
59
 
60
+ Irreversible — there is no soft-delete or reactivation. Callers must confirm intent before invoking, and must send the user through logout afterwards: their access token stays cryptographically valid but no longer resolves to an account, so a subsequent authenticated request would provision a brand-new empty user.
64
61
 
65
- Irreversible — there is no soft-delete or reactivation. Callers must confirm intent before invoking, and must
66
- send the user through logout afterwards: their access token stays cryptographically valid but no longer resolves
67
- to an account, so a subsequent authenticated request would provision a brand-new empty user.
68
-
69
-
70
- Refused with `409` while the caller is the only administrator of an organization that still has other members;
71
- the organization must be handed over or deleted first. `502` means nothing was deleted (a downstream service
72
- could not be purged) and the request can safely be retried.
62
+ Refused with `409` while the caller is the only administrator of an organization that still has other members; the organization must be handed over or deleted first. `502` means nothing was deleted (a downstream service could not be purged) and the request can safely be retried.
73
63
  responses:
74
- '200':
64
+ "200":
75
65
  description: Account deleted
76
66
  content:
77
67
  application/json:
@@ -83,7 +73,8 @@ paths:
83
73
  properties:
84
74
  success:
85
75
  type: boolean
86
- enum: [true]
76
+ enum:
77
+ - true
87
78
  data:
88
79
  type: object
89
80
  required:
@@ -92,7 +83,8 @@ paths:
92
83
  properties:
93
84
  deleted:
94
85
  type: boolean
95
- enum: [true]
86
+ enum:
87
+ - true
96
88
  user_id:
97
89
  type: integer
98
90
  organizations_deleted:
@@ -102,30 +94,27 @@ paths:
102
94
  type: integer
103
95
  auth0_identity_deleted:
104
96
  type: boolean
105
- description: >-
106
- Whether the Auth0 identity was removed as well. False when the API has no Management API
107
- credentials configured — the account data is still fully deleted, but signing in again creates
108
- a new empty account.
109
- '401':
110
- $ref: '#/components/responses/Unauthorized'
111
- '403':
97
+ description: Whether the Auth0 identity was removed as well. False when the API has no Management API credentials configured — the account data is still fully deleted, but signing in again creates a new empty account.
98
+ "401":
99
+ $ref: "#/components/responses/Unauthorized"
100
+ "403":
112
101
  description: Service accounts cannot be deleted through this endpoint
113
102
  content:
114
103
  application/json:
115
104
  schema:
116
- $ref: '#/components/schemas/Error'
117
- '409':
105
+ $ref: "#/components/schemas/Error"
106
+ "409":
118
107
  description: The caller is the last administrator of an organization that still has members
119
108
  content:
120
109
  application/json:
121
110
  schema:
122
- $ref: '#/components/schemas/Error'
123
- '502':
111
+ $ref: "#/components/schemas/Error"
112
+ "502":
124
113
  description: A downstream service could not be purged — nothing was deleted
125
114
  content:
126
115
  application/json:
127
116
  schema:
128
- $ref: '#/components/schemas/Error'
117
+ $ref: "#/components/schemas/Error"
129
118
  /api/v1/me/profile:
130
119
  put:
131
120
  tags:
@@ -137,16 +126,16 @@ paths:
137
126
  content:
138
127
  application/json:
139
128
  schema:
140
- $ref: '#/components/schemas/UpdateProfileInput'
129
+ $ref: "#/components/schemas/UpdateProfileInput"
141
130
  responses:
142
- '200':
131
+ "200":
143
132
  description: Profile updated
144
133
  content:
145
134
  application/json:
146
135
  schema:
147
- $ref: '#/components/schemas/UserResponse'
148
- '401':
149
- $ref: '#/components/responses/Unauthorized'
136
+ $ref: "#/components/schemas/UserResponse"
137
+ "401":
138
+ $ref: "#/components/responses/Unauthorized"
150
139
  /api/v1/me/accept-terms:
151
140
  post:
152
141
  tags:
@@ -154,7 +143,7 @@ paths:
154
143
  summary: Accept terms of service
155
144
  description: Records the user's acceptance of the terms of service.
156
145
  responses:
157
- '200':
146
+ "200":
158
147
  description: Terms accepted
159
148
  content:
160
149
  application/json:
@@ -167,47 +156,8 @@ paths:
167
156
  tos_accepted_at:
168
157
  type: string
169
158
  format: date-time
170
- '401':
171
- $ref: '#/components/responses/Unauthorized'
172
- /api/v1/me/subscription:
173
- x-internal: true
174
- get:
175
- tags:
176
- - Subscriptions
177
- summary: Get subscription info (legacy)
178
- description: Returns the authenticated user's legacy subscription information.
179
- responses:
180
- '200':
181
- description: Subscription info
182
- content:
183
- application/json:
184
- schema:
185
- type: object
186
- properties:
187
- data:
188
- type: object
189
- properties:
190
- plan:
191
- type: string
192
- enum:
193
- - free
194
- - pro
195
- - family
196
- - enterprise
197
- subscription_id:
198
- type: string
199
- subscription_status:
200
- type: string
201
- enum:
202
- - active
203
- - canceled
204
- - past_due
205
- - trialing
206
- subscription_expires_at:
207
- type: string
208
- format: date-time
209
- '401':
210
- $ref: '#/components/responses/Unauthorized'
159
+ "401":
160
+ $ref: "#/components/responses/Unauthorized"
211
161
  /api/v1/me/subscriptions:
212
162
  get:
213
163
  tags:
@@ -215,7 +165,7 @@ paths:
215
165
  summary: Get all per-service subscriptions
216
166
  description: Returns all per-service subscriptions for the authenticated user.
217
167
  responses:
218
- '200':
168
+ "200":
219
169
  description: List of service subscriptions
220
170
  content:
221
171
  application/json:
@@ -225,9 +175,9 @@ paths:
225
175
  data:
226
176
  type: array
227
177
  items:
228
- $ref: '#/components/schemas/ServiceSubscription'
229
- '401':
230
- $ref: '#/components/responses/Unauthorized'
178
+ $ref: "#/components/schemas/ServiceSubscription"
179
+ "401":
180
+ $ref: "#/components/responses/Unauthorized"
231
181
  /api/v1/me/subscriptions/{serviceId}:
232
182
  get:
233
183
  tags:
@@ -241,7 +191,7 @@ paths:
241
191
  schema:
242
192
  type: string
243
193
  responses:
244
- '200':
194
+ "200":
245
195
  description: Service subscription
246
196
  content:
247
197
  application/json:
@@ -249,106 +199,11 @@ paths:
249
199
  type: object
250
200
  properties:
251
201
  data:
252
- $ref: '#/components/schemas/ServiceSubscription'
253
- '401':
254
- $ref: '#/components/responses/Unauthorized'
255
- '404':
256
- $ref: '#/components/responses/NotFound'
257
- /api/v1/stripe/checkout:
258
- x-internal: true
259
- post:
260
- tags:
261
- - Stripe
262
- summary: Create Stripe checkout session
263
- description: Creates a new Stripe checkout session for subscription purchase.
264
- requestBody:
265
- required: true
266
- content:
267
- application/json:
268
- schema:
269
- type: object
270
- required:
271
- - plan
272
- properties:
273
- plan:
274
- type: string
275
- enum: [pro, family]
276
- description: Target subscription plan.
277
- serviceId:
278
- type: string
279
- description: Service the subscription applies to (defaults to "default").
280
- currency:
281
- type: string
282
- enum: [jpy, usd]
283
- default: jpy
284
- description: >-
285
- Billing currency for the new subscription; selects the matching
286
- per-currency Stripe Price. Defaults to jpy when omitted. Stripe
287
- locks a customer to this currency on first payment, so it only
288
- applies to the initial checkout.
289
- returnUrl:
290
- type: string
291
- description: >-
292
- Locale-aware URL Stripe returns the user to; the result query
293
- string (?upgrade=success&plan=…&serviceId=…) is appended by the API.
294
- responses:
295
- '200':
296
- description: Checkout session created
297
- content:
298
- application/json:
299
- schema:
300
- type: object
301
- properties:
302
- data:
303
- type: object
304
- properties:
305
- url:
306
- type: string
307
- description: Stripe checkout session URL
308
- '401':
309
- $ref: '#/components/responses/Unauthorized'
310
- /api/v1/stripe/change-plan:
311
- x-internal: true
312
- post:
313
- tags:
314
- - Stripe
315
- summary: Change subscription plan
316
- description: Changes the authenticated user's subscription plan.
317
- responses:
318
- '200':
319
- description: Plan changed
320
- content:
321
- application/json:
322
- schema:
323
- type: object
324
- properties:
325
- data:
326
- type: object
327
- '401':
328
- $ref: '#/components/responses/Unauthorized'
329
- /api/v1/stripe/portal:
330
- x-internal: true
331
- post:
332
- tags:
333
- - Stripe
334
- summary: Create customer portal session
335
- description: Creates a Stripe customer portal session for subscription management.
336
- responses:
337
- '200':
338
- description: Portal session created
339
- content:
340
- application/json:
341
- schema:
342
- type: object
343
- properties:
344
- data:
345
- type: object
346
- properties:
347
- url:
348
- type: string
349
- description: Stripe customer portal URL
350
- '401':
351
- $ref: '#/components/responses/Unauthorized'
202
+ $ref: "#/components/schemas/ServiceSubscription"
203
+ "401":
204
+ $ref: "#/components/responses/Unauthorized"
205
+ "404":
206
+ $ref: "#/components/responses/NotFound"
352
207
  /api/v1/me/tokens:
353
208
  get:
354
209
  tags:
@@ -356,7 +211,7 @@ paths:
356
211
  summary: List API tokens
357
212
  description: Returns all Personal Access Tokens for the authenticated user.
358
213
  responses:
359
- '200':
214
+ "200":
360
215
  description: List of API tokens
361
216
  content:
362
217
  application/json:
@@ -369,11 +224,11 @@ paths:
369
224
  data:
370
225
  type: array
371
226
  items:
372
- $ref: '#/components/schemas/ApiToken'
227
+ $ref: "#/components/schemas/ApiToken"
373
228
  total:
374
229
  type: integer
375
- '401':
376
- $ref: '#/components/responses/Unauthorized'
230
+ "401":
231
+ $ref: "#/components/responses/Unauthorized"
377
232
  post:
378
233
  tags:
379
234
  - API Tokens
@@ -384,9 +239,9 @@ paths:
384
239
  content:
385
240
  application/json:
386
241
  schema:
387
- $ref: '#/components/schemas/CreateApiTokenInput'
242
+ $ref: "#/components/schemas/CreateApiTokenInput"
388
243
  responses:
389
- '201':
244
+ "201":
390
245
  description: Token created
391
246
  content:
392
247
  application/json:
@@ -395,15 +250,15 @@ paths:
395
250
  properties:
396
251
  data:
397
252
  allOf:
398
- - $ref: '#/components/schemas/ApiToken'
253
+ - $ref: "#/components/schemas/ApiToken"
399
254
  - type: object
400
255
  properties:
401
256
  token:
402
257
  type: string
403
258
  description: The raw token (only returned on creation)
404
259
  example: nbpat_a1b2c3d4e5f6g7h8i9j0...
405
- '401':
406
- $ref: '#/components/responses/Unauthorized'
260
+ "401":
261
+ $ref: "#/components/responses/Unauthorized"
407
262
  /api/v1/me/tokens/{id}:
408
263
  delete:
409
264
  tags:
@@ -417,7 +272,7 @@ paths:
417
272
  schema:
418
273
  type: integer
419
274
  responses:
420
- '200':
275
+ "200":
421
276
  description: Token deleted
422
277
  content:
423
278
  application/json:
@@ -430,10 +285,157 @@ paths:
430
285
  success:
431
286
  type: boolean
432
287
  example: true
433
- '401':
434
- $ref: '#/components/responses/Unauthorized'
435
- '404':
436
- $ref: '#/components/responses/NotFound'
288
+ "401":
289
+ $ref: "#/components/responses/Unauthorized"
290
+ "404":
291
+ $ref: "#/components/responses/NotFound"
292
+ /api/v1/me/notifications:
293
+ get:
294
+ tags:
295
+ - Notifications
296
+ summary: List notifications
297
+ description: Returns the caller's in-app notifications, newest first, with the total unread count. Read rows are deleted 30 days after they were read and unread rows 90 days after their last update.
298
+ parameters:
299
+ - name: limit
300
+ in: query
301
+ required: false
302
+ description: Maximum rows to return.
303
+ schema:
304
+ type: integer
305
+ minimum: 1
306
+ maximum: 100
307
+ default: 30
308
+ - name: unread_only
309
+ in: query
310
+ required: false
311
+ description: Return only unread rows.
312
+ schema:
313
+ type: boolean
314
+ default: false
315
+ responses:
316
+ "200":
317
+ description: Notifications and the unread count
318
+ content:
319
+ application/json:
320
+ schema:
321
+ type: object
322
+ properties:
323
+ data:
324
+ $ref: "#/components/schemas/NotificationInbox"
325
+ "401":
326
+ $ref: "#/components/responses/Unauthorized"
327
+ /api/v1/me/notifications/unread-count:
328
+ get:
329
+ tags:
330
+ - Notifications
331
+ summary: Unread notification count
332
+ description: Returns only the number of unread notifications. Cheap enough to poll for a badge; use the list endpoint to read the rows.
333
+ responses:
334
+ "200":
335
+ description: Unread count
336
+ content:
337
+ application/json:
338
+ schema:
339
+ type: object
340
+ properties:
341
+ data:
342
+ type: object
343
+ properties:
344
+ unread_count:
345
+ type: integer
346
+ minimum: 0
347
+ example: 3
348
+ "401":
349
+ $ref: "#/components/responses/Unauthorized"
350
+ /api/v1/me/notifications/read:
351
+ post:
352
+ tags:
353
+ - Notifications
354
+ summary: Mark notifications as read
355
+ description: "Marks the given rows (`ids`, at most 100) or every unread row (`all: true`) as read. Ids that do not exist or belong to someone else are ignored."
356
+ requestBody:
357
+ required: true
358
+ content:
359
+ application/json:
360
+ schema:
361
+ $ref: "#/components/schemas/MarkNotificationsReadInput"
362
+ responses:
363
+ "200":
364
+ description: Marked as read
365
+ content:
366
+ application/json:
367
+ schema:
368
+ type: object
369
+ properties:
370
+ data:
371
+ type: object
372
+ properties:
373
+ updated:
374
+ type: boolean
375
+ example: true
376
+ "401":
377
+ $ref: "#/components/responses/Unauthorized"
378
+ /api/v1/me/device-tokens:
379
+ post:
380
+ tags:
381
+ - Notifications
382
+ summary: Register a device for push
383
+ description: Sends this device's Expo push token to the signed-in account. Registering a token that belongs to another account moves it to the caller, so a shared phone follows whoever is signed in. At most a handful of devices are kept per user (the newest).
384
+ requestBody:
385
+ required: true
386
+ content:
387
+ application/json:
388
+ schema:
389
+ $ref: "#/components/schemas/RegisterDeviceTokenInput"
390
+ responses:
391
+ "200":
392
+ description: Registered
393
+ content:
394
+ application/json:
395
+ schema:
396
+ type: object
397
+ properties:
398
+ data:
399
+ type: object
400
+ properties:
401
+ registered:
402
+ type: boolean
403
+ example: true
404
+ "401":
405
+ $ref: "#/components/responses/Unauthorized"
406
+ delete:
407
+ tags:
408
+ - Notifications
409
+ summary: Unregister a device
410
+ description: "Detaches a push token from the caller (on sign-out). Scoped to the caller: another account's token is left alone."
411
+ requestBody:
412
+ required: true
413
+ content:
414
+ application/json:
415
+ schema:
416
+ type: object
417
+ required:
418
+ - token
419
+ properties:
420
+ token:
421
+ type: string
422
+ example: ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]
423
+ responses:
424
+ "200":
425
+ description: Unregistered
426
+ content:
427
+ application/json:
428
+ schema:
429
+ type: object
430
+ properties:
431
+ data:
432
+ type: object
433
+ properties:
434
+ unregistered:
435
+ type: boolean
436
+ example: true
437
+ "401":
438
+ $ref: "#/components/responses/Unauthorized"
437
439
  /api/v1/organizations/{orgId}/service-accounts:
438
440
  get:
439
441
  tags:
@@ -447,7 +449,7 @@ paths:
447
449
  schema:
448
450
  type: integer
449
451
  responses:
450
- '200':
452
+ "200":
451
453
  description: List of service accounts
452
454
  content:
453
455
  application/json:
@@ -460,22 +462,20 @@ paths:
460
462
  data:
461
463
  type: array
462
464
  items:
463
- $ref: '#/components/schemas/ServiceAccount'
465
+ $ref: "#/components/schemas/ServiceAccount"
464
466
  total:
465
467
  type: integer
466
- '401':
467
- $ref: '#/components/responses/Unauthorized'
468
- '403':
469
- $ref: '#/components/responses/Forbidden'
470
- '404':
471
- $ref: '#/components/responses/NotFound'
468
+ "401":
469
+ $ref: "#/components/responses/Unauthorized"
470
+ "403":
471
+ $ref: "#/components/responses/Forbidden"
472
+ "404":
473
+ $ref: "#/components/responses/NotFound"
472
474
  post:
473
475
  tags:
474
476
  - Service Accounts
475
477
  summary: Create a service account
476
- description: >-
477
- Creates a new service account in the organization. Requires the caller to be an Org Admin AND the organization
478
- to hold an active Enterprise subscription.
478
+ description: Creates a new service account in the organization. Requires the caller to be an Org Admin AND the organization to hold an active Enterprise subscription.
479
479
  parameters:
480
480
  - name: orgId
481
481
  in: path
@@ -487,9 +487,9 @@ paths:
487
487
  content:
488
488
  application/json:
489
489
  schema:
490
- $ref: '#/components/schemas/CreateServiceAccountInput'
490
+ $ref: "#/components/schemas/CreateServiceAccountInput"
491
491
  responses:
492
- '201':
492
+ "201":
493
493
  description: Service account created
494
494
  content:
495
495
  application/json:
@@ -497,11 +497,11 @@ paths:
497
497
  type: object
498
498
  properties:
499
499
  data:
500
- $ref: '#/components/schemas/ServiceAccount'
501
- '401':
502
- $ref: '#/components/responses/Unauthorized'
503
- '403':
504
- $ref: '#/components/responses/Forbidden'
500
+ $ref: "#/components/schemas/ServiceAccount"
501
+ "401":
502
+ $ref: "#/components/responses/Unauthorized"
503
+ "403":
504
+ $ref: "#/components/responses/Forbidden"
505
505
  /api/v1/organizations/{orgId}/service-accounts/{saId}:
506
506
  put:
507
507
  tags:
@@ -523,9 +523,9 @@ paths:
523
523
  content:
524
524
  application/json:
525
525
  schema:
526
- $ref: '#/components/schemas/CreateServiceAccountInput'
526
+ $ref: "#/components/schemas/CreateServiceAccountInput"
527
527
  responses:
528
- '200':
528
+ "200":
529
529
  description: Service account updated
530
530
  content:
531
531
  application/json:
@@ -533,20 +533,18 @@ paths:
533
533
  type: object
534
534
  properties:
535
535
  data:
536
- $ref: '#/components/schemas/ServiceAccount'
537
- '401':
538
- $ref: '#/components/responses/Unauthorized'
539
- '403':
540
- $ref: '#/components/responses/Forbidden'
541
- '404':
542
- $ref: '#/components/responses/NotFound'
536
+ $ref: "#/components/schemas/ServiceAccount"
537
+ "401":
538
+ $ref: "#/components/responses/Unauthorized"
539
+ "403":
540
+ $ref: "#/components/responses/Forbidden"
541
+ "404":
542
+ $ref: "#/components/responses/NotFound"
543
543
  delete:
544
544
  tags:
545
545
  - Service Accounts
546
546
  summary: Delete a service account
547
- description: >-
548
- Deletes the service account and cascades to all of its API tokens. Returns the cascade count for audit
549
- reference.
547
+ description: Deletes the service account and cascades to all of its API tokens. Returns the cascade count for audit reference.
550
548
  parameters:
551
549
  - name: orgId
552
550
  in: path
@@ -559,7 +557,7 @@ paths:
559
557
  schema:
560
558
  type: integer
561
559
  responses:
562
- '200':
560
+ "200":
563
561
  description: Service account deleted
564
562
  content:
565
563
  application/json:
@@ -573,12 +571,12 @@ paths:
573
571
  type: boolean
574
572
  cascade_token_count:
575
573
  type: integer
576
- '401':
577
- $ref: '#/components/responses/Unauthorized'
578
- '403':
579
- $ref: '#/components/responses/Forbidden'
580
- '404':
581
- $ref: '#/components/responses/NotFound'
574
+ "401":
575
+ $ref: "#/components/responses/Unauthorized"
576
+ "403":
577
+ $ref: "#/components/responses/Forbidden"
578
+ "404":
579
+ $ref: "#/components/responses/NotFound"
582
580
  /api/v1/organizations/{orgId}/service-accounts/{saId}/tokens:
583
581
  get:
584
582
  tags:
@@ -596,7 +594,7 @@ paths:
596
594
  schema:
597
595
  type: integer
598
596
  responses:
599
- '200':
597
+ "200":
600
598
  description: List of tokens
601
599
  content:
602
600
  application/json:
@@ -609,22 +607,20 @@ paths:
609
607
  data:
610
608
  type: array
611
609
  items:
612
- $ref: '#/components/schemas/ApiToken'
610
+ $ref: "#/components/schemas/ApiToken"
613
611
  total:
614
612
  type: integer
615
- '401':
616
- $ref: '#/components/responses/Unauthorized'
617
- '403':
618
- $ref: '#/components/responses/Forbidden'
619
- '404':
620
- $ref: '#/components/responses/NotFound'
613
+ "401":
614
+ $ref: "#/components/responses/Unauthorized"
615
+ "403":
616
+ $ref: "#/components/responses/Forbidden"
617
+ "404":
618
+ $ref: "#/components/responses/NotFound"
621
619
  post:
622
620
  tags:
623
621
  - Service Accounts
624
622
  summary: Issue a new token for a service account
625
- description: >-
626
- Creates a new API token under the service account. The raw `nbpat_...` token is returned exactly once; it is not
627
- stored in plaintext and cannot be retrieved later.
623
+ description: Creates a new API token under the service account. The raw `nbpat_...` token is returned exactly once; it is not stored in plaintext and cannot be retrieved later.
628
624
  parameters:
629
625
  - name: orgId
630
626
  in: path
@@ -641,9 +637,9 @@ paths:
641
637
  content:
642
638
  application/json:
643
639
  schema:
644
- $ref: '#/components/schemas/CreateApiTokenInput'
640
+ $ref: "#/components/schemas/CreateApiTokenInput"
645
641
  responses:
646
- '201':
642
+ "201":
647
643
  description: Token issued
648
644
  content:
649
645
  application/json:
@@ -652,19 +648,19 @@ paths:
652
648
  properties:
653
649
  data:
654
650
  allOf:
655
- - $ref: '#/components/schemas/ApiToken'
651
+ - $ref: "#/components/schemas/ApiToken"
656
652
  - type: object
657
653
  properties:
658
654
  token:
659
655
  type: string
660
656
  description: The raw token value (returned once on creation)
661
657
  example: nbpat_a1b2c3d4...
662
- '401':
663
- $ref: '#/components/responses/Unauthorized'
664
- '403':
665
- $ref: '#/components/responses/Forbidden'
666
- '404':
667
- $ref: '#/components/responses/NotFound'
658
+ "401":
659
+ $ref: "#/components/responses/Unauthorized"
660
+ "403":
661
+ $ref: "#/components/responses/Forbidden"
662
+ "404":
663
+ $ref: "#/components/responses/NotFound"
668
664
  /api/v1/organizations/{orgId}/service-accounts/{saId}/tokens/{tokenId}:
669
665
  delete:
670
666
  tags:
@@ -687,7 +683,7 @@ paths:
687
683
  schema:
688
684
  type: integer
689
685
  responses:
690
- '200':
686
+ "200":
691
687
  description: Token revoked
692
688
  content:
693
689
  application/json:
@@ -699,12 +695,12 @@ paths:
699
695
  properties:
700
696
  success:
701
697
  type: boolean
702
- '401':
703
- $ref: '#/components/responses/Unauthorized'
704
- '403':
705
- $ref: '#/components/responses/Forbidden'
706
- '404':
707
- $ref: '#/components/responses/NotFound'
698
+ "401":
699
+ $ref: "#/components/responses/Unauthorized"
700
+ "403":
701
+ $ref: "#/components/responses/Forbidden"
702
+ "404":
703
+ $ref: "#/components/responses/NotFound"
708
704
  components:
709
705
  securitySchemes:
710
706
  BearerAuth:
@@ -730,9 +726,7 @@ components:
730
726
  - en
731
727
  timezone:
732
728
  type: string
733
- description: >-
734
- IANA time zone name (e.g. `Asia/Tokyo`), or `auto` to follow the
735
- device the client runs on. Defaults to `auto`.
729
+ description: IANA time zone name (e.g. `Asia/Tokyo`), or `auto` to follow the device the client runs on. Defaults to `auto`.
736
730
  example: auto
737
731
  plan:
738
732
  type: string
@@ -757,7 +751,7 @@ components:
757
751
  subscriptions:
758
752
  type: array
759
753
  items:
760
- $ref: '#/components/schemas/ServiceSubscription'
754
+ $ref: "#/components/schemas/ServiceSubscription"
761
755
  tos_accepted_at:
762
756
  type: string
763
757
  format: date-time
@@ -769,7 +763,7 @@ components:
769
763
  type: object
770
764
  properties:
771
765
  data:
772
- $ref: '#/components/schemas/User'
766
+ $ref: "#/components/schemas/User"
773
767
  UpdateProfileInput:
774
768
  type: object
775
769
  properties:
@@ -858,12 +852,87 @@ components:
858
852
  type: string
859
853
  format: date-time
860
854
  description: Optional expiration date for the token.
855
+ Notification:
856
+ type: object
857
+ description: One inbox row. Repeats of the same event on the same entity collapse into a single unread row (`count` says how many).
858
+ properties:
859
+ id:
860
+ type: integer
861
+ type:
862
+ type: string
863
+ description: Event kind, e.g. `share.invited`, `share.accepted`, `share.rejected`, `share.revoked`, `ownership.transfer_requested`, `target.updated`, `target.deleted`, `recorder.tag_updated`. New kinds may appear; clients should fall back to a generic sentence for one they do not know.
864
+ example: recorder.tag_updated
865
+ service_id:
866
+ type: string
867
+ description: Which API raised it (`target`, `recorder`, `account`); tells a client which app the reference belongs to.
868
+ example: recorder
869
+ ref_id:
870
+ type: string
871
+ nullable: true
872
+ description: "The entity to open: a target id, a tag id or a share id, depending on `type`."
873
+ params:
874
+ type: object
875
+ additionalProperties: true
876
+ description: "Display data, never rendered into a push: `actor_name`, `owner_name`, `recipient_name`, `target_title`, `tag_name`, and for `recorder.tag_updated` the latest `change` plus up to five `changes` (newest first), each with `action`, `record_id`, `value`, `unit`, `recorded_at`, `comment`, `media_type` (kind only, never a URL) and for goal edits `kind: goal`, `goal_value`, `direction`."
877
+ count:
878
+ type: integer
879
+ minimum: 1
880
+ read_at:
881
+ type: string
882
+ nullable: true
883
+ description: UTC, `YYYY-MM-DD HH:MM:SS`. Null while unread.
884
+ created_at:
885
+ type: string
886
+ description: UTC, `YYYY-MM-DD HH:MM:SS`.
887
+ updated_at:
888
+ type: string
889
+ description: UTC, `YYYY-MM-DD HH:MM:SS`. Moves forward when a repeat collapses into the row.
890
+ NotificationInbox:
891
+ type: object
892
+ properties:
893
+ notifications:
894
+ type: array
895
+ items:
896
+ $ref: "#/components/schemas/Notification"
897
+ unread_count:
898
+ type: integer
899
+ minimum: 0
900
+ description: Total unread rows, not just those in this page.
901
+ MarkNotificationsReadInput:
902
+ type: object
903
+ description: "Send either `all: true` or a non-empty `ids` array."
904
+ properties:
905
+ all:
906
+ type: boolean
907
+ enum:
908
+ - true
909
+ ids:
910
+ type: array
911
+ minItems: 1
912
+ maxItems: 100
913
+ items:
914
+ type: integer
915
+ example:
916
+ - 12
917
+ - 13
918
+ RegisterDeviceTokenInput:
919
+ type: object
920
+ required:
921
+ - token
922
+ - platform
923
+ properties:
924
+ token:
925
+ type: string
926
+ description: An Expo push token.
927
+ example: ExponentPushToken[xxxxxxxxxxxxxxxxxxxxxx]
928
+ platform:
929
+ type: string
930
+ enum:
931
+ - ios
932
+ - android
861
933
  ServiceAccount:
862
934
  type: object
863
- description: >-
864
- A non-human users row scoped to a single organization. SAs hold API tokens via the existing api_tokens table
865
- (user_id = SA.id). They never appear in member lists; verifyToken rejects any JWT bearing the synthetic
866
- 'service-account|' sub.
935
+ description: A non-human users row scoped to a single organization. SAs hold API tokens via the existing api_tokens table (user_id = SA.id). They never appear in member lists; verifyToken rejects any JWT bearing the synthetic 'service-account|' sub.
867
936
  properties:
868
937
  id:
869
938
  type: integer
@@ -908,22 +977,10 @@ components:
908
977
  - success
909
978
  - error
910
979
  properties:
911
- # The implementation has always answered with the same two-field
912
- # envelope as a success response, `{ success, error }` — see
913
- # errorResponse() in nb-account-api/src/utils/errors.ts. Only the
914
- # success half of the envelope was ever described here, so every error
915
- # response carried an undeclared `success` property. Specmatic reports
916
- # it as R2003 "Unknown property", which is how this was found: the
917
- # provider contract test covered only /health until the scope was
918
- # widened to GET /api/v1/me -> 401.
919
- #
920
- # Pinned with `enum` for the same reason the success envelope pins it
921
- # to [true] — a plain boolean lets a stub answer `success: true`
922
- # alongside an error body, which is a state the implementation cannot
923
- # produce.
924
980
  success:
925
981
  type: boolean
926
- enum: [false]
982
+ enum:
983
+ - false
927
984
  error:
928
985
  type: object
929
986
  required:
@@ -934,10 +991,6 @@ components:
934
991
  type: string
935
992
  message:
936
993
  type: string
937
- # Optional, and omitted entirely when absent: AppError carries
938
- # `details?: Record<string, unknown>` and JSON.stringify drops the
939
- # key when it is undefined. Declared so a response that does carry
940
- # it is not reported as another unknown property.
941
994
  details:
942
995
  type: object
943
996
  additionalProperties: true
@@ -947,7 +1000,7 @@ components:
947
1000
  content:
948
1001
  application/json:
949
1002
  schema:
950
- $ref: '#/components/schemas/Error'
1003
+ $ref: "#/components/schemas/Error"
951
1004
  example:
952
1005
  success: false
953
1006
  error:
@@ -958,7 +1011,7 @@ components:
958
1011
  content:
959
1012
  application/json:
960
1013
  schema:
961
- $ref: '#/components/schemas/Error'
1014
+ $ref: "#/components/schemas/Error"
962
1015
  example:
963
1016
  success: false
964
1017
  error:
@@ -969,7 +1022,7 @@ components:
969
1022
  content:
970
1023
  application/json:
971
1024
  schema:
972
- $ref: '#/components/schemas/Error'
1025
+ $ref: "#/components/schemas/Error"
973
1026
  example:
974
1027
  success: false
975
1028
  error:
@@ -982,9 +1035,9 @@ tags:
982
1035
  description: User profile endpoints
983
1036
  - name: Subscriptions
984
1037
  description: Subscription management endpoints
985
- - name: Stripe
986
- description: Stripe billing and payment endpoints
987
1038
  - name: API Tokens
988
1039
  description: Personal Access Token management
989
1040
  - name: Service Accounts
990
1041
  description: Org-scoped service accounts for Enterprise organizations and their API tokens. Org Admin only.
1042
+ - name: Notifications
1043
+ description: In-app notification inbox and mobile push device registration