@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,990 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
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
|
|
8
|
+
contact:
|
|
9
|
+
name: NASEBANAL
|
|
10
|
+
url: https://www.nasebanal.com
|
|
11
|
+
servers:
|
|
12
|
+
- url: http://localhost:8788
|
|
13
|
+
description: Local dev (wrangler dev)
|
|
14
|
+
- url: https://api.account.nasebanal.com
|
|
15
|
+
description: Production
|
|
16
|
+
security:
|
|
17
|
+
- BearerAuth: []
|
|
18
|
+
paths:
|
|
19
|
+
/health:
|
|
20
|
+
get:
|
|
21
|
+
tags:
|
|
22
|
+
- Health
|
|
23
|
+
summary: Health check
|
|
24
|
+
description: Returns the health status of the API.
|
|
25
|
+
security: []
|
|
26
|
+
responses:
|
|
27
|
+
'200':
|
|
28
|
+
description: API is healthy
|
|
29
|
+
content:
|
|
30
|
+
application/json:
|
|
31
|
+
schema:
|
|
32
|
+
type: object
|
|
33
|
+
properties:
|
|
34
|
+
status:
|
|
35
|
+
type: string
|
|
36
|
+
example: ok
|
|
37
|
+
timestamp:
|
|
38
|
+
type: string
|
|
39
|
+
format: date-time
|
|
40
|
+
/api/v1/me:
|
|
41
|
+
get:
|
|
42
|
+
tags:
|
|
43
|
+
- User
|
|
44
|
+
summary: Get current user profile
|
|
45
|
+
description: Returns the authenticated user's profile information including subscription details.
|
|
46
|
+
responses:
|
|
47
|
+
'200':
|
|
48
|
+
description: User profile
|
|
49
|
+
content:
|
|
50
|
+
application/json:
|
|
51
|
+
schema:
|
|
52
|
+
$ref: '#/components/schemas/UserResponse'
|
|
53
|
+
'401':
|
|
54
|
+
$ref: '#/components/responses/Unauthorized'
|
|
55
|
+
delete:
|
|
56
|
+
tags:
|
|
57
|
+
- User
|
|
58
|
+
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.
|
|
63
|
+
|
|
64
|
+
|
|
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.
|
|
73
|
+
responses:
|
|
74
|
+
'200':
|
|
75
|
+
description: Account deleted
|
|
76
|
+
content:
|
|
77
|
+
application/json:
|
|
78
|
+
schema:
|
|
79
|
+
type: object
|
|
80
|
+
required:
|
|
81
|
+
- success
|
|
82
|
+
- data
|
|
83
|
+
properties:
|
|
84
|
+
success:
|
|
85
|
+
type: boolean
|
|
86
|
+
enum: [true]
|
|
87
|
+
data:
|
|
88
|
+
type: object
|
|
89
|
+
required:
|
|
90
|
+
- deleted
|
|
91
|
+
- user_id
|
|
92
|
+
properties:
|
|
93
|
+
deleted:
|
|
94
|
+
type: boolean
|
|
95
|
+
enum: [true]
|
|
96
|
+
user_id:
|
|
97
|
+
type: integer
|
|
98
|
+
organizations_deleted:
|
|
99
|
+
type: integer
|
|
100
|
+
description: Organizations removed because the deleted user was their only member.
|
|
101
|
+
subscriptions_cancelled:
|
|
102
|
+
type: integer
|
|
103
|
+
auth0_identity_deleted:
|
|
104
|
+
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':
|
|
112
|
+
description: Service accounts cannot be deleted through this endpoint
|
|
113
|
+
content:
|
|
114
|
+
application/json:
|
|
115
|
+
schema:
|
|
116
|
+
$ref: '#/components/schemas/Error'
|
|
117
|
+
'409':
|
|
118
|
+
description: The caller is the last administrator of an organization that still has members
|
|
119
|
+
content:
|
|
120
|
+
application/json:
|
|
121
|
+
schema:
|
|
122
|
+
$ref: '#/components/schemas/Error'
|
|
123
|
+
'502':
|
|
124
|
+
description: A downstream service could not be purged — nothing was deleted
|
|
125
|
+
content:
|
|
126
|
+
application/json:
|
|
127
|
+
schema:
|
|
128
|
+
$ref: '#/components/schemas/Error'
|
|
129
|
+
/api/v1/me/profile:
|
|
130
|
+
put:
|
|
131
|
+
tags:
|
|
132
|
+
- User
|
|
133
|
+
summary: Update profile
|
|
134
|
+
description: Updates the authenticated user's profile information.
|
|
135
|
+
requestBody:
|
|
136
|
+
required: true
|
|
137
|
+
content:
|
|
138
|
+
application/json:
|
|
139
|
+
schema:
|
|
140
|
+
$ref: '#/components/schemas/UpdateProfileInput'
|
|
141
|
+
responses:
|
|
142
|
+
'200':
|
|
143
|
+
description: Profile updated
|
|
144
|
+
content:
|
|
145
|
+
application/json:
|
|
146
|
+
schema:
|
|
147
|
+
$ref: '#/components/schemas/UserResponse'
|
|
148
|
+
'401':
|
|
149
|
+
$ref: '#/components/responses/Unauthorized'
|
|
150
|
+
/api/v1/me/accept-terms:
|
|
151
|
+
post:
|
|
152
|
+
tags:
|
|
153
|
+
- User
|
|
154
|
+
summary: Accept terms of service
|
|
155
|
+
description: Records the user's acceptance of the terms of service.
|
|
156
|
+
responses:
|
|
157
|
+
'200':
|
|
158
|
+
description: Terms accepted
|
|
159
|
+
content:
|
|
160
|
+
application/json:
|
|
161
|
+
schema:
|
|
162
|
+
type: object
|
|
163
|
+
properties:
|
|
164
|
+
data:
|
|
165
|
+
type: object
|
|
166
|
+
properties:
|
|
167
|
+
tos_accepted_at:
|
|
168
|
+
type: string
|
|
169
|
+
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'
|
|
211
|
+
/api/v1/me/subscriptions:
|
|
212
|
+
get:
|
|
213
|
+
tags:
|
|
214
|
+
- Subscriptions
|
|
215
|
+
summary: Get all per-service subscriptions
|
|
216
|
+
description: Returns all per-service subscriptions for the authenticated user.
|
|
217
|
+
responses:
|
|
218
|
+
'200':
|
|
219
|
+
description: List of service subscriptions
|
|
220
|
+
content:
|
|
221
|
+
application/json:
|
|
222
|
+
schema:
|
|
223
|
+
type: object
|
|
224
|
+
properties:
|
|
225
|
+
data:
|
|
226
|
+
type: array
|
|
227
|
+
items:
|
|
228
|
+
$ref: '#/components/schemas/ServiceSubscription'
|
|
229
|
+
'401':
|
|
230
|
+
$ref: '#/components/responses/Unauthorized'
|
|
231
|
+
/api/v1/me/subscriptions/{serviceId}:
|
|
232
|
+
get:
|
|
233
|
+
tags:
|
|
234
|
+
- Subscriptions
|
|
235
|
+
summary: Get subscription for a service
|
|
236
|
+
description: Returns the subscription for a specific service.
|
|
237
|
+
parameters:
|
|
238
|
+
- name: serviceId
|
|
239
|
+
in: path
|
|
240
|
+
required: true
|
|
241
|
+
schema:
|
|
242
|
+
type: string
|
|
243
|
+
responses:
|
|
244
|
+
'200':
|
|
245
|
+
description: Service subscription
|
|
246
|
+
content:
|
|
247
|
+
application/json:
|
|
248
|
+
schema:
|
|
249
|
+
type: object
|
|
250
|
+
properties:
|
|
251
|
+
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'
|
|
352
|
+
/api/v1/me/tokens:
|
|
353
|
+
get:
|
|
354
|
+
tags:
|
|
355
|
+
- API Tokens
|
|
356
|
+
summary: List API tokens
|
|
357
|
+
description: Returns all Personal Access Tokens for the authenticated user.
|
|
358
|
+
responses:
|
|
359
|
+
'200':
|
|
360
|
+
description: List of API tokens
|
|
361
|
+
content:
|
|
362
|
+
application/json:
|
|
363
|
+
schema:
|
|
364
|
+
type: object
|
|
365
|
+
properties:
|
|
366
|
+
data:
|
|
367
|
+
type: object
|
|
368
|
+
properties:
|
|
369
|
+
data:
|
|
370
|
+
type: array
|
|
371
|
+
items:
|
|
372
|
+
$ref: '#/components/schemas/ApiToken'
|
|
373
|
+
total:
|
|
374
|
+
type: integer
|
|
375
|
+
'401':
|
|
376
|
+
$ref: '#/components/responses/Unauthorized'
|
|
377
|
+
post:
|
|
378
|
+
tags:
|
|
379
|
+
- API Tokens
|
|
380
|
+
summary: Create API token
|
|
381
|
+
description: Creates a new Personal Access Token. The raw token is returned only once in the response.
|
|
382
|
+
requestBody:
|
|
383
|
+
required: true
|
|
384
|
+
content:
|
|
385
|
+
application/json:
|
|
386
|
+
schema:
|
|
387
|
+
$ref: '#/components/schemas/CreateApiTokenInput'
|
|
388
|
+
responses:
|
|
389
|
+
'201':
|
|
390
|
+
description: Token created
|
|
391
|
+
content:
|
|
392
|
+
application/json:
|
|
393
|
+
schema:
|
|
394
|
+
type: object
|
|
395
|
+
properties:
|
|
396
|
+
data:
|
|
397
|
+
allOf:
|
|
398
|
+
- $ref: '#/components/schemas/ApiToken'
|
|
399
|
+
- type: object
|
|
400
|
+
properties:
|
|
401
|
+
token:
|
|
402
|
+
type: string
|
|
403
|
+
description: The raw token (only returned on creation)
|
|
404
|
+
example: nbpat_a1b2c3d4e5f6g7h8i9j0...
|
|
405
|
+
'401':
|
|
406
|
+
$ref: '#/components/responses/Unauthorized'
|
|
407
|
+
/api/v1/me/tokens/{id}:
|
|
408
|
+
delete:
|
|
409
|
+
tags:
|
|
410
|
+
- API Tokens
|
|
411
|
+
summary: Delete API token
|
|
412
|
+
description: Deletes a Personal Access Token by ID.
|
|
413
|
+
parameters:
|
|
414
|
+
- name: id
|
|
415
|
+
in: path
|
|
416
|
+
required: true
|
|
417
|
+
schema:
|
|
418
|
+
type: integer
|
|
419
|
+
responses:
|
|
420
|
+
'200':
|
|
421
|
+
description: Token deleted
|
|
422
|
+
content:
|
|
423
|
+
application/json:
|
|
424
|
+
schema:
|
|
425
|
+
type: object
|
|
426
|
+
properties:
|
|
427
|
+
data:
|
|
428
|
+
type: object
|
|
429
|
+
properties:
|
|
430
|
+
success:
|
|
431
|
+
type: boolean
|
|
432
|
+
example: true
|
|
433
|
+
'401':
|
|
434
|
+
$ref: '#/components/responses/Unauthorized'
|
|
435
|
+
'404':
|
|
436
|
+
$ref: '#/components/responses/NotFound'
|
|
437
|
+
/api/v1/organizations/{orgId}/service-accounts:
|
|
438
|
+
get:
|
|
439
|
+
tags:
|
|
440
|
+
- Service Accounts
|
|
441
|
+
summary: List service accounts
|
|
442
|
+
description: Returns all service accounts owned by the given organization. Requires the caller to be an Org Admin.
|
|
443
|
+
parameters:
|
|
444
|
+
- name: orgId
|
|
445
|
+
in: path
|
|
446
|
+
required: true
|
|
447
|
+
schema:
|
|
448
|
+
type: integer
|
|
449
|
+
responses:
|
|
450
|
+
'200':
|
|
451
|
+
description: List of service accounts
|
|
452
|
+
content:
|
|
453
|
+
application/json:
|
|
454
|
+
schema:
|
|
455
|
+
type: object
|
|
456
|
+
properties:
|
|
457
|
+
data:
|
|
458
|
+
type: object
|
|
459
|
+
properties:
|
|
460
|
+
data:
|
|
461
|
+
type: array
|
|
462
|
+
items:
|
|
463
|
+
$ref: '#/components/schemas/ServiceAccount'
|
|
464
|
+
total:
|
|
465
|
+
type: integer
|
|
466
|
+
'401':
|
|
467
|
+
$ref: '#/components/responses/Unauthorized'
|
|
468
|
+
'403':
|
|
469
|
+
$ref: '#/components/responses/Forbidden'
|
|
470
|
+
'404':
|
|
471
|
+
$ref: '#/components/responses/NotFound'
|
|
472
|
+
post:
|
|
473
|
+
tags:
|
|
474
|
+
- Service Accounts
|
|
475
|
+
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.
|
|
479
|
+
parameters:
|
|
480
|
+
- name: orgId
|
|
481
|
+
in: path
|
|
482
|
+
required: true
|
|
483
|
+
schema:
|
|
484
|
+
type: integer
|
|
485
|
+
requestBody:
|
|
486
|
+
required: true
|
|
487
|
+
content:
|
|
488
|
+
application/json:
|
|
489
|
+
schema:
|
|
490
|
+
$ref: '#/components/schemas/CreateServiceAccountInput'
|
|
491
|
+
responses:
|
|
492
|
+
'201':
|
|
493
|
+
description: Service account created
|
|
494
|
+
content:
|
|
495
|
+
application/json:
|
|
496
|
+
schema:
|
|
497
|
+
type: object
|
|
498
|
+
properties:
|
|
499
|
+
data:
|
|
500
|
+
$ref: '#/components/schemas/ServiceAccount'
|
|
501
|
+
'401':
|
|
502
|
+
$ref: '#/components/responses/Unauthorized'
|
|
503
|
+
'403':
|
|
504
|
+
$ref: '#/components/responses/Forbidden'
|
|
505
|
+
/api/v1/organizations/{orgId}/service-accounts/{saId}:
|
|
506
|
+
put:
|
|
507
|
+
tags:
|
|
508
|
+
- Service Accounts
|
|
509
|
+
summary: Rename a service account
|
|
510
|
+
parameters:
|
|
511
|
+
- name: orgId
|
|
512
|
+
in: path
|
|
513
|
+
required: true
|
|
514
|
+
schema:
|
|
515
|
+
type: integer
|
|
516
|
+
- name: saId
|
|
517
|
+
in: path
|
|
518
|
+
required: true
|
|
519
|
+
schema:
|
|
520
|
+
type: integer
|
|
521
|
+
requestBody:
|
|
522
|
+
required: true
|
|
523
|
+
content:
|
|
524
|
+
application/json:
|
|
525
|
+
schema:
|
|
526
|
+
$ref: '#/components/schemas/CreateServiceAccountInput'
|
|
527
|
+
responses:
|
|
528
|
+
'200':
|
|
529
|
+
description: Service account updated
|
|
530
|
+
content:
|
|
531
|
+
application/json:
|
|
532
|
+
schema:
|
|
533
|
+
type: object
|
|
534
|
+
properties:
|
|
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'
|
|
543
|
+
delete:
|
|
544
|
+
tags:
|
|
545
|
+
- Service Accounts
|
|
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.
|
|
550
|
+
parameters:
|
|
551
|
+
- name: orgId
|
|
552
|
+
in: path
|
|
553
|
+
required: true
|
|
554
|
+
schema:
|
|
555
|
+
type: integer
|
|
556
|
+
- name: saId
|
|
557
|
+
in: path
|
|
558
|
+
required: true
|
|
559
|
+
schema:
|
|
560
|
+
type: integer
|
|
561
|
+
responses:
|
|
562
|
+
'200':
|
|
563
|
+
description: Service account deleted
|
|
564
|
+
content:
|
|
565
|
+
application/json:
|
|
566
|
+
schema:
|
|
567
|
+
type: object
|
|
568
|
+
properties:
|
|
569
|
+
data:
|
|
570
|
+
type: object
|
|
571
|
+
properties:
|
|
572
|
+
success:
|
|
573
|
+
type: boolean
|
|
574
|
+
cascade_token_count:
|
|
575
|
+
type: integer
|
|
576
|
+
'401':
|
|
577
|
+
$ref: '#/components/responses/Unauthorized'
|
|
578
|
+
'403':
|
|
579
|
+
$ref: '#/components/responses/Forbidden'
|
|
580
|
+
'404':
|
|
581
|
+
$ref: '#/components/responses/NotFound'
|
|
582
|
+
/api/v1/organizations/{orgId}/service-accounts/{saId}/tokens:
|
|
583
|
+
get:
|
|
584
|
+
tags:
|
|
585
|
+
- Service Accounts
|
|
586
|
+
summary: List service-account tokens
|
|
587
|
+
parameters:
|
|
588
|
+
- name: orgId
|
|
589
|
+
in: path
|
|
590
|
+
required: true
|
|
591
|
+
schema:
|
|
592
|
+
type: integer
|
|
593
|
+
- name: saId
|
|
594
|
+
in: path
|
|
595
|
+
required: true
|
|
596
|
+
schema:
|
|
597
|
+
type: integer
|
|
598
|
+
responses:
|
|
599
|
+
'200':
|
|
600
|
+
description: List of tokens
|
|
601
|
+
content:
|
|
602
|
+
application/json:
|
|
603
|
+
schema:
|
|
604
|
+
type: object
|
|
605
|
+
properties:
|
|
606
|
+
data:
|
|
607
|
+
type: object
|
|
608
|
+
properties:
|
|
609
|
+
data:
|
|
610
|
+
type: array
|
|
611
|
+
items:
|
|
612
|
+
$ref: '#/components/schemas/ApiToken'
|
|
613
|
+
total:
|
|
614
|
+
type: integer
|
|
615
|
+
'401':
|
|
616
|
+
$ref: '#/components/responses/Unauthorized'
|
|
617
|
+
'403':
|
|
618
|
+
$ref: '#/components/responses/Forbidden'
|
|
619
|
+
'404':
|
|
620
|
+
$ref: '#/components/responses/NotFound'
|
|
621
|
+
post:
|
|
622
|
+
tags:
|
|
623
|
+
- Service Accounts
|
|
624
|
+
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.
|
|
628
|
+
parameters:
|
|
629
|
+
- name: orgId
|
|
630
|
+
in: path
|
|
631
|
+
required: true
|
|
632
|
+
schema:
|
|
633
|
+
type: integer
|
|
634
|
+
- name: saId
|
|
635
|
+
in: path
|
|
636
|
+
required: true
|
|
637
|
+
schema:
|
|
638
|
+
type: integer
|
|
639
|
+
requestBody:
|
|
640
|
+
required: true
|
|
641
|
+
content:
|
|
642
|
+
application/json:
|
|
643
|
+
schema:
|
|
644
|
+
$ref: '#/components/schemas/CreateApiTokenInput'
|
|
645
|
+
responses:
|
|
646
|
+
'201':
|
|
647
|
+
description: Token issued
|
|
648
|
+
content:
|
|
649
|
+
application/json:
|
|
650
|
+
schema:
|
|
651
|
+
type: object
|
|
652
|
+
properties:
|
|
653
|
+
data:
|
|
654
|
+
allOf:
|
|
655
|
+
- $ref: '#/components/schemas/ApiToken'
|
|
656
|
+
- type: object
|
|
657
|
+
properties:
|
|
658
|
+
token:
|
|
659
|
+
type: string
|
|
660
|
+
description: The raw token value (returned once on creation)
|
|
661
|
+
example: nbpat_a1b2c3d4...
|
|
662
|
+
'401':
|
|
663
|
+
$ref: '#/components/responses/Unauthorized'
|
|
664
|
+
'403':
|
|
665
|
+
$ref: '#/components/responses/Forbidden'
|
|
666
|
+
'404':
|
|
667
|
+
$ref: '#/components/responses/NotFound'
|
|
668
|
+
/api/v1/organizations/{orgId}/service-accounts/{saId}/tokens/{tokenId}:
|
|
669
|
+
delete:
|
|
670
|
+
tags:
|
|
671
|
+
- Service Accounts
|
|
672
|
+
summary: Revoke a service-account token
|
|
673
|
+
parameters:
|
|
674
|
+
- name: orgId
|
|
675
|
+
in: path
|
|
676
|
+
required: true
|
|
677
|
+
schema:
|
|
678
|
+
type: integer
|
|
679
|
+
- name: saId
|
|
680
|
+
in: path
|
|
681
|
+
required: true
|
|
682
|
+
schema:
|
|
683
|
+
type: integer
|
|
684
|
+
- name: tokenId
|
|
685
|
+
in: path
|
|
686
|
+
required: true
|
|
687
|
+
schema:
|
|
688
|
+
type: integer
|
|
689
|
+
responses:
|
|
690
|
+
'200':
|
|
691
|
+
description: Token revoked
|
|
692
|
+
content:
|
|
693
|
+
application/json:
|
|
694
|
+
schema:
|
|
695
|
+
type: object
|
|
696
|
+
properties:
|
|
697
|
+
data:
|
|
698
|
+
type: object
|
|
699
|
+
properties:
|
|
700
|
+
success:
|
|
701
|
+
type: boolean
|
|
702
|
+
'401':
|
|
703
|
+
$ref: '#/components/responses/Unauthorized'
|
|
704
|
+
'403':
|
|
705
|
+
$ref: '#/components/responses/Forbidden'
|
|
706
|
+
'404':
|
|
707
|
+
$ref: '#/components/responses/NotFound'
|
|
708
|
+
components:
|
|
709
|
+
securitySchemes:
|
|
710
|
+
BearerAuth:
|
|
711
|
+
type: http
|
|
712
|
+
scheme: bearer
|
|
713
|
+
bearerFormat: JWT or PAT
|
|
714
|
+
description: Use either an Auth0 JWT token or a Personal Access Token (PAT) starting with `nbpat_`.
|
|
715
|
+
schemas:
|
|
716
|
+
User:
|
|
717
|
+
type: object
|
|
718
|
+
properties:
|
|
719
|
+
id:
|
|
720
|
+
type: integer
|
|
721
|
+
email:
|
|
722
|
+
type: string
|
|
723
|
+
format: email
|
|
724
|
+
name:
|
|
725
|
+
type: string
|
|
726
|
+
language:
|
|
727
|
+
type: string
|
|
728
|
+
enum:
|
|
729
|
+
- ja
|
|
730
|
+
- en
|
|
731
|
+
timezone:
|
|
732
|
+
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`.
|
|
736
|
+
example: auto
|
|
737
|
+
plan:
|
|
738
|
+
type: string
|
|
739
|
+
enum:
|
|
740
|
+
- free
|
|
741
|
+
- pro
|
|
742
|
+
- family
|
|
743
|
+
- enterprise
|
|
744
|
+
subscription_status:
|
|
745
|
+
type: string
|
|
746
|
+
enum:
|
|
747
|
+
- active
|
|
748
|
+
- canceled
|
|
749
|
+
- past_due
|
|
750
|
+
- trialing
|
|
751
|
+
- null
|
|
752
|
+
nullable: true
|
|
753
|
+
subscription_expires_at:
|
|
754
|
+
type: string
|
|
755
|
+
format: date-time
|
|
756
|
+
nullable: true
|
|
757
|
+
subscriptions:
|
|
758
|
+
type: array
|
|
759
|
+
items:
|
|
760
|
+
$ref: '#/components/schemas/ServiceSubscription'
|
|
761
|
+
tos_accepted_at:
|
|
762
|
+
type: string
|
|
763
|
+
format: date-time
|
|
764
|
+
nullable: true
|
|
765
|
+
created_at:
|
|
766
|
+
type: string
|
|
767
|
+
format: date-time
|
|
768
|
+
UserResponse:
|
|
769
|
+
type: object
|
|
770
|
+
properties:
|
|
771
|
+
data:
|
|
772
|
+
$ref: '#/components/schemas/User'
|
|
773
|
+
UpdateProfileInput:
|
|
774
|
+
type: object
|
|
775
|
+
properties:
|
|
776
|
+
name:
|
|
777
|
+
type: string
|
|
778
|
+
language:
|
|
779
|
+
type: string
|
|
780
|
+
enum:
|
|
781
|
+
- ja
|
|
782
|
+
- en
|
|
783
|
+
timezone:
|
|
784
|
+
type: string
|
|
785
|
+
description: IANA time zone name, or `auto` to follow the device.
|
|
786
|
+
ServiceSubscription:
|
|
787
|
+
type: object
|
|
788
|
+
properties:
|
|
789
|
+
id:
|
|
790
|
+
type: integer
|
|
791
|
+
user_id:
|
|
792
|
+
type: integer
|
|
793
|
+
service_id:
|
|
794
|
+
type: string
|
|
795
|
+
plan:
|
|
796
|
+
type: string
|
|
797
|
+
enum:
|
|
798
|
+
- free
|
|
799
|
+
- pro
|
|
800
|
+
- family
|
|
801
|
+
- enterprise
|
|
802
|
+
subscription_id:
|
|
803
|
+
type: string
|
|
804
|
+
nullable: true
|
|
805
|
+
subscription_status:
|
|
806
|
+
type: string
|
|
807
|
+
enum:
|
|
808
|
+
- active
|
|
809
|
+
- canceled
|
|
810
|
+
- past_due
|
|
811
|
+
- trialing
|
|
812
|
+
- null
|
|
813
|
+
nullable: true
|
|
814
|
+
subscription_expires_at:
|
|
815
|
+
type: string
|
|
816
|
+
format: date-time
|
|
817
|
+
nullable: true
|
|
818
|
+
created_at:
|
|
819
|
+
type: string
|
|
820
|
+
format: date-time
|
|
821
|
+
updated_at:
|
|
822
|
+
type: string
|
|
823
|
+
format: date-time
|
|
824
|
+
ApiToken:
|
|
825
|
+
type: object
|
|
826
|
+
properties:
|
|
827
|
+
id:
|
|
828
|
+
type: integer
|
|
829
|
+
user_id:
|
|
830
|
+
type: integer
|
|
831
|
+
name:
|
|
832
|
+
type: string
|
|
833
|
+
last_used_at:
|
|
834
|
+
type: string
|
|
835
|
+
format: date-time
|
|
836
|
+
nullable: true
|
|
837
|
+
expires_at:
|
|
838
|
+
type: string
|
|
839
|
+
format: date-time
|
|
840
|
+
nullable: true
|
|
841
|
+
created_at:
|
|
842
|
+
type: string
|
|
843
|
+
format: date-time
|
|
844
|
+
updated_at:
|
|
845
|
+
type: string
|
|
846
|
+
format: date-time
|
|
847
|
+
CreateApiTokenInput:
|
|
848
|
+
type: object
|
|
849
|
+
required:
|
|
850
|
+
- name
|
|
851
|
+
properties:
|
|
852
|
+
name:
|
|
853
|
+
type: string
|
|
854
|
+
minLength: 1
|
|
855
|
+
maxLength: 100
|
|
856
|
+
example: My API Token
|
|
857
|
+
expires_at:
|
|
858
|
+
type: string
|
|
859
|
+
format: date-time
|
|
860
|
+
description: Optional expiration date for the token.
|
|
861
|
+
ServiceAccount:
|
|
862
|
+
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.
|
|
867
|
+
properties:
|
|
868
|
+
id:
|
|
869
|
+
type: integer
|
|
870
|
+
name:
|
|
871
|
+
type: string
|
|
872
|
+
organization_id:
|
|
873
|
+
type: integer
|
|
874
|
+
is_service_account:
|
|
875
|
+
type: integer
|
|
876
|
+
enum:
|
|
877
|
+
- 1
|
|
878
|
+
description: Always 1 for SA rows; included for parity with the underlying users schema.
|
|
879
|
+
auth0_sub:
|
|
880
|
+
type: string
|
|
881
|
+
description: Synthetic, prefixed 'service-account|' followed by a UUID. Has no real Auth0 identity behind it.
|
|
882
|
+
email:
|
|
883
|
+
type: string
|
|
884
|
+
nullable: true
|
|
885
|
+
description: Auto-generated 'sa-<uuid>@nasebanal.com'. Not a real mailbox.
|
|
886
|
+
token_count:
|
|
887
|
+
type: integer
|
|
888
|
+
description: Number of api_tokens currently owned by this SA. Returned only on list and create responses.
|
|
889
|
+
created_at:
|
|
890
|
+
type: string
|
|
891
|
+
format: date-time
|
|
892
|
+
updated_at:
|
|
893
|
+
type: string
|
|
894
|
+
format: date-time
|
|
895
|
+
CreateServiceAccountInput:
|
|
896
|
+
type: object
|
|
897
|
+
required:
|
|
898
|
+
- name
|
|
899
|
+
properties:
|
|
900
|
+
name:
|
|
901
|
+
type: string
|
|
902
|
+
minLength: 1
|
|
903
|
+
maxLength: 200
|
|
904
|
+
example: Acme Metrics Bot
|
|
905
|
+
Error:
|
|
906
|
+
type: object
|
|
907
|
+
required:
|
|
908
|
+
- success
|
|
909
|
+
- error
|
|
910
|
+
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
|
+
success:
|
|
925
|
+
type: boolean
|
|
926
|
+
enum: [false]
|
|
927
|
+
error:
|
|
928
|
+
type: object
|
|
929
|
+
required:
|
|
930
|
+
- code
|
|
931
|
+
- message
|
|
932
|
+
properties:
|
|
933
|
+
code:
|
|
934
|
+
type: string
|
|
935
|
+
message:
|
|
936
|
+
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
|
+
details:
|
|
942
|
+
type: object
|
|
943
|
+
additionalProperties: true
|
|
944
|
+
responses:
|
|
945
|
+
Unauthorized:
|
|
946
|
+
description: Authentication required or invalid token
|
|
947
|
+
content:
|
|
948
|
+
application/json:
|
|
949
|
+
schema:
|
|
950
|
+
$ref: '#/components/schemas/Error'
|
|
951
|
+
example:
|
|
952
|
+
success: false
|
|
953
|
+
error:
|
|
954
|
+
code: AUTH_ERROR
|
|
955
|
+
message: No authentication token provided
|
|
956
|
+
NotFound:
|
|
957
|
+
description: Resource not found
|
|
958
|
+
content:
|
|
959
|
+
application/json:
|
|
960
|
+
schema:
|
|
961
|
+
$ref: '#/components/schemas/Error'
|
|
962
|
+
example:
|
|
963
|
+
success: false
|
|
964
|
+
error:
|
|
965
|
+
code: NOT_FOUND
|
|
966
|
+
message: Resource not found
|
|
967
|
+
Forbidden:
|
|
968
|
+
description: Caller is authenticated but lacks the required role or plan
|
|
969
|
+
content:
|
|
970
|
+
application/json:
|
|
971
|
+
schema:
|
|
972
|
+
$ref: '#/components/schemas/Error'
|
|
973
|
+
example:
|
|
974
|
+
success: false
|
|
975
|
+
error:
|
|
976
|
+
code: PLAN_LIMIT_EXCEEDED
|
|
977
|
+
message: Service Accounts require an Enterprise plan for this organization.
|
|
978
|
+
tags:
|
|
979
|
+
- name: Health
|
|
980
|
+
description: Health check endpoints
|
|
981
|
+
- name: User
|
|
982
|
+
description: User profile endpoints
|
|
983
|
+
- name: Subscriptions
|
|
984
|
+
description: Subscription management endpoints
|
|
985
|
+
- name: Stripe
|
|
986
|
+
description: Stripe billing and payment endpoints
|
|
987
|
+
- name: API Tokens
|
|
988
|
+
description: Personal Access Token management
|
|
989
|
+
- name: Service Accounts
|
|
990
|
+
description: Org-scoped service accounts for Enterprise organizations and their API tokens. Org Admin only.
|