@djangocfg/api 2.1.360 → 2.1.361

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.
@@ -0,0 +1,2789 @@
1
+ {
2
+ "openapi": "3.1.0",
3
+ "info": {
4
+ "title": "Django CFG API",
5
+ "version": "1.0.0",
6
+ "description": "RESTful API with modern architecture"
7
+ },
8
+ "paths": {
9
+ "/cfg/accounts/api-key/": {
10
+ "get": {
11
+ "operationId": "cfg_accounts_api_key_retrieve",
12
+ "description": "Retrieve the current user's API key (masked) and metadata.",
13
+ "summary": "Get API key details",
14
+ "tags": [
15
+ "cfg_accounts_api_key"
16
+ ],
17
+ "security": [
18
+ {
19
+ "jwtAuth": []
20
+ },
21
+ {
22
+ "cookieAuth": []
23
+ }
24
+ ],
25
+ "responses": {
26
+ "200": {
27
+ "content": {
28
+ "application/json": {
29
+ "schema": {
30
+ "$ref": "#/components/schemas/APIKey"
31
+ }
32
+ }
33
+ },
34
+ "description": ""
35
+ },
36
+ "401": {
37
+ "content": {
38
+ "application/json": {
39
+ "schema": {
40
+ "description": "Authentication credentials were not provided."
41
+ }
42
+ }
43
+ },
44
+ "description": ""
45
+ }
46
+ },
47
+ "x-async-capable": false
48
+ }
49
+ },
50
+ "/cfg/accounts/api-key/regenerate/": {
51
+ "post": {
52
+ "operationId": "cfg_accounts_api_key_regenerate_create",
53
+ "description": "Generate a new API key. The full key is returned only once.",
54
+ "summary": "Regenerate API key",
55
+ "tags": [
56
+ "cfg_accounts_api_key"
57
+ ],
58
+ "requestBody": {
59
+ "content": {
60
+ "application/json": {
61
+ "schema": {
62
+ "$ref": "#/components/schemas/APIKeyRequest"
63
+ }
64
+ }
65
+ },
66
+ "required": true
67
+ },
68
+ "security": [
69
+ {
70
+ "jwtAuth": []
71
+ },
72
+ {
73
+ "cookieAuth": []
74
+ }
75
+ ],
76
+ "responses": {
77
+ "200": {
78
+ "content": {
79
+ "application/json": {
80
+ "schema": {
81
+ "$ref": "#/components/schemas/APIKeyRegenerate"
82
+ },
83
+ "examples": {
84
+ "RegenerateResponse": {
85
+ "value": {
86
+ "key": "d0b45e78-1234-5678-9abc-def012345678",
87
+ "reissued_at": "2024-01-15T10:30:00Z"
88
+ },
89
+ "summary": "Regenerate Response"
90
+ }
91
+ }
92
+ }
93
+ },
94
+ "description": ""
95
+ },
96
+ "401": {
97
+ "content": {
98
+ "application/json": {
99
+ "schema": {
100
+ "description": "Authentication credentials were not provided."
101
+ }
102
+ }
103
+ },
104
+ "description": ""
105
+ }
106
+ },
107
+ "x-async-capable": false
108
+ }
109
+ },
110
+ "/cfg/accounts/api-key/test/": {
111
+ "post": {
112
+ "operationId": "cfg_accounts_api_key_test_create",
113
+ "description": "Test whether an API key is valid without consuming it.",
114
+ "summary": "Test API key",
115
+ "tags": [
116
+ "cfg_accounts_api_key"
117
+ ],
118
+ "requestBody": {
119
+ "content": {
120
+ "application/json": {
121
+ "schema": {
122
+ "$ref": "#/components/schemas/APIKeyTestRequest"
123
+ }
124
+ }
125
+ },
126
+ "required": true
127
+ },
128
+ "security": [
129
+ {
130
+ "jwtAuth": []
131
+ },
132
+ {
133
+ "cookieAuth": []
134
+ }
135
+ ],
136
+ "responses": {
137
+ "200": {
138
+ "content": {
139
+ "application/json": {
140
+ "schema": {
141
+ "$ref": "#/components/schemas/APIKeyTestResult"
142
+ },
143
+ "examples": {
144
+ "ValidKey": {
145
+ "value": {
146
+ "valid": true,
147
+ "user_id": "42"
148
+ },
149
+ "summary": "Valid Key"
150
+ },
151
+ "InvalidKey": {
152
+ "value": {
153
+ "valid": false,
154
+ "user_id": null
155
+ },
156
+ "summary": "Invalid Key"
157
+ }
158
+ }
159
+ }
160
+ },
161
+ "description": ""
162
+ }
163
+ },
164
+ "x-async-capable": false
165
+ }
166
+ },
167
+ "/cfg/accounts/oauth/connections/": {
168
+ "get": {
169
+ "operationId": "cfg_accounts_oauth_connections_list",
170
+ "description": "Get all OAuth connections for the current user.",
171
+ "summary": "List OAuth connections",
172
+ "tags": [
173
+ "cfg_accounts_oauth"
174
+ ],
175
+ "security": [
176
+ {
177
+ "apiKeyAuth": []
178
+ },
179
+ {
180
+ "jwtAuthWithLastLogin": []
181
+ }
182
+ ],
183
+ "responses": {
184
+ "200": {
185
+ "content": {
186
+ "application/json": {
187
+ "schema": {
188
+ "$ref": "#/components/schemas/cfg_accounts_oauth_connections_response_200_AutoRef"
189
+ }
190
+ }
191
+ },
192
+ "description": ""
193
+ }
194
+ },
195
+ "x-async-capable": false
196
+ }
197
+ },
198
+ "/cfg/accounts/oauth/disconnect/": {
199
+ "post": {
200
+ "operationId": "cfg_accounts_oauth_disconnect_create",
201
+ "description": "Remove OAuth connection for the specified provider.",
202
+ "summary": "Disconnect OAuth provider",
203
+ "tags": [
204
+ "cfg_accounts_oauth"
205
+ ],
206
+ "requestBody": {
207
+ "content": {
208
+ "application/json": {
209
+ "schema": {
210
+ "$ref": "#/components/schemas/OAuthDisconnectRequestRequest"
211
+ }
212
+ }
213
+ },
214
+ "required": true
215
+ },
216
+ "security": [
217
+ {
218
+ "apiKeyAuth": []
219
+ },
220
+ {
221
+ "jwtAuthWithLastLogin": []
222
+ }
223
+ ],
224
+ "responses": {
225
+ "200": {
226
+ "content": {
227
+ "application/json": {
228
+ "schema": {
229
+ "$ref": "#/components/schemas/cfg_accounts_oauth_disconnect_response_200_AutoRef"
230
+ }
231
+ }
232
+ },
233
+ "description": ""
234
+ },
235
+ "400": {
236
+ "content": {
237
+ "application/json": {
238
+ "schema": {
239
+ "$ref": "#/components/schemas/OAuthError"
240
+ }
241
+ }
242
+ },
243
+ "description": ""
244
+ },
245
+ "404": {
246
+ "content": {
247
+ "application/json": {
248
+ "schema": {
249
+ "$ref": "#/components/schemas/OAuthError"
250
+ }
251
+ }
252
+ },
253
+ "description": ""
254
+ }
255
+ },
256
+ "x-async-capable": false
257
+ }
258
+ },
259
+ "/cfg/accounts/oauth/github/authorize/": {
260
+ "post": {
261
+ "operationId": "cfg_accounts_oauth_github_authorize_create",
262
+ "description": "Generate GitHub OAuth authorization URL. Redirect user to this URL to start authentication.",
263
+ "summary": "Start GitHub OAuth",
264
+ "tags": [
265
+ "cfg_accounts_oauth"
266
+ ],
267
+ "requestBody": {
268
+ "content": {
269
+ "application/json": {
270
+ "schema": {
271
+ "$ref": "#/components/schemas/OAuthAuthorizeRequestRequest"
272
+ }
273
+ }
274
+ }
275
+ },
276
+ "security": [
277
+ {}
278
+ ],
279
+ "responses": {
280
+ "200": {
281
+ "content": {
282
+ "application/json": {
283
+ "schema": {
284
+ "$ref": "#/components/schemas/OAuthAuthorizeResponse"
285
+ }
286
+ }
287
+ },
288
+ "description": ""
289
+ },
290
+ "503": {
291
+ "content": {
292
+ "application/json": {
293
+ "schema": {
294
+ "$ref": "#/components/schemas/OAuthError"
295
+ }
296
+ }
297
+ },
298
+ "description": ""
299
+ }
300
+ },
301
+ "x-async-capable": false
302
+ }
303
+ },
304
+ "/cfg/accounts/oauth/github/callback/": {
305
+ "post": {
306
+ "operationId": "cfg_accounts_oauth_github_callback_create",
307
+ "description": "Exchange authorization code for JWT tokens. Call this after GitHub redirects back with code.",
308
+ "summary": "Complete GitHub OAuth",
309
+ "tags": [
310
+ "cfg_accounts_oauth"
311
+ ],
312
+ "requestBody": {
313
+ "content": {
314
+ "application/json": {
315
+ "schema": {
316
+ "$ref": "#/components/schemas/OAuthCallbackRequestRequest"
317
+ }
318
+ }
319
+ },
320
+ "required": true
321
+ },
322
+ "security": [
323
+ {}
324
+ ],
325
+ "responses": {
326
+ "200": {
327
+ "content": {
328
+ "application/json": {
329
+ "schema": {
330
+ "$ref": "#/components/schemas/OAuthTokenResponse"
331
+ }
332
+ }
333
+ },
334
+ "description": ""
335
+ },
336
+ "400": {
337
+ "content": {
338
+ "application/json": {
339
+ "schema": {
340
+ "$ref": "#/components/schemas/OAuthError"
341
+ }
342
+ }
343
+ },
344
+ "description": ""
345
+ }
346
+ },
347
+ "x-async-capable": false
348
+ }
349
+ },
350
+ "/cfg/accounts/oauth/providers/": {
351
+ "get": {
352
+ "operationId": "cfg_accounts_oauth_providers_retrieve",
353
+ "description": "Get list of available OAuth providers for authentication.",
354
+ "summary": "List OAuth providers",
355
+ "tags": [
356
+ "cfg_accounts_oauth"
357
+ ],
358
+ "security": [
359
+ {}
360
+ ],
361
+ "responses": {
362
+ "200": {
363
+ "content": {
364
+ "application/json": {
365
+ "schema": {
366
+ "$ref": "#/components/schemas/OAuthProvidersResponse"
367
+ }
368
+ }
369
+ },
370
+ "description": ""
371
+ }
372
+ },
373
+ "x-async-capable": false
374
+ }
375
+ },
376
+ "/cfg/accounts/otp/request/": {
377
+ "post": {
378
+ "operationId": "cfg_accounts_otp_request_create",
379
+ "description": "Request OTP code to email.",
380
+ "tags": [
381
+ "cfg_accounts"
382
+ ],
383
+ "requestBody": {
384
+ "content": {
385
+ "application/json": {
386
+ "schema": {
387
+ "$ref": "#/components/schemas/OTPRequestRequest"
388
+ }
389
+ }
390
+ },
391
+ "required": true
392
+ },
393
+ "security": [
394
+ {
395
+ "apiKeyAuth": []
396
+ },
397
+ {
398
+ "jwtAuthWithLastLogin": []
399
+ },
400
+ {}
401
+ ],
402
+ "responses": {
403
+ "200": {
404
+ "content": {
405
+ "application/json": {
406
+ "schema": {
407
+ "$ref": "#/components/schemas/OTPRequestResponse"
408
+ }
409
+ }
410
+ },
411
+ "description": ""
412
+ },
413
+ "400": {
414
+ "content": {
415
+ "application/json": {
416
+ "schema": {
417
+ "$ref": "#/components/schemas/OTPErrorResponse"
418
+ }
419
+ }
420
+ },
421
+ "description": ""
422
+ },
423
+ "429": {
424
+ "content": {
425
+ "application/json": {
426
+ "schema": {
427
+ "$ref": "#/components/schemas/OTPErrorResponse"
428
+ }
429
+ }
430
+ },
431
+ "description": ""
432
+ },
433
+ "500": {
434
+ "content": {
435
+ "application/json": {
436
+ "schema": {
437
+ "$ref": "#/components/schemas/OTPErrorResponse"
438
+ }
439
+ }
440
+ },
441
+ "description": ""
442
+ }
443
+ },
444
+ "x-async-capable": false
445
+ }
446
+ },
447
+ "/cfg/accounts/otp/verify/": {
448
+ "post": {
449
+ "operationId": "cfg_accounts_otp_verify_create",
450
+ "description": "Verify OTP code and return JWT tokens or 2FA session.\n\nIf user has 2FA enabled:\n- Returns requires_2fa=True with session_id\n- Client must complete 2FA verification at /cfg/totp/verify/\n\nIf user has no 2FA:\n- Returns JWT tokens and user data directly",
451
+ "tags": [
452
+ "cfg_accounts"
453
+ ],
454
+ "requestBody": {
455
+ "content": {
456
+ "application/json": {
457
+ "schema": {
458
+ "$ref": "#/components/schemas/OTPVerifyRequest"
459
+ }
460
+ }
461
+ },
462
+ "required": true
463
+ },
464
+ "security": [
465
+ {
466
+ "apiKeyAuth": []
467
+ },
468
+ {
469
+ "jwtAuthWithLastLogin": []
470
+ },
471
+ {}
472
+ ],
473
+ "responses": {
474
+ "200": {
475
+ "content": {
476
+ "application/json": {
477
+ "schema": {
478
+ "$ref": "#/components/schemas/OTPVerifyResponse"
479
+ }
480
+ }
481
+ },
482
+ "description": ""
483
+ },
484
+ "401": {
485
+ "content": {
486
+ "application/json": {
487
+ "schema": {
488
+ "$ref": "#/components/schemas/OTPErrorResponse"
489
+ }
490
+ }
491
+ },
492
+ "description": ""
493
+ },
494
+ "429": {
495
+ "content": {
496
+ "application/json": {
497
+ "schema": {
498
+ "$ref": "#/components/schemas/OTPErrorResponse"
499
+ }
500
+ }
501
+ },
502
+ "description": ""
503
+ }
504
+ },
505
+ "x-async-capable": false
506
+ }
507
+ },
508
+ "/cfg/accounts/profile/": {
509
+ "get": {
510
+ "operationId": "cfg_accounts_profile_retrieve",
511
+ "description": "Retrieve the current authenticated user's profile information.",
512
+ "summary": "Get current user profile",
513
+ "tags": [
514
+ "cfg_accounts_profile"
515
+ ],
516
+ "security": [
517
+ {
518
+ "jwtAuth": []
519
+ },
520
+ {
521
+ "cookieAuth": []
522
+ }
523
+ ],
524
+ "responses": {
525
+ "200": {
526
+ "content": {
527
+ "application/json": {
528
+ "schema": {
529
+ "$ref": "#/components/schemas/User"
530
+ }
531
+ }
532
+ },
533
+ "description": ""
534
+ },
535
+ "401": {
536
+ "content": {
537
+ "application/json": {
538
+ "schema": {
539
+ "description": "Authentication credentials were not provided."
540
+ }
541
+ }
542
+ },
543
+ "description": ""
544
+ }
545
+ },
546
+ "x-async-capable": false
547
+ }
548
+ },
549
+ "/cfg/accounts/profile/avatar/": {
550
+ "post": {
551
+ "operationId": "cfg_accounts_profile_avatar_create",
552
+ "description": "Upload avatar image for the current authenticated user. Accepts multipart/form-data with 'avatar' field.",
553
+ "summary": "Upload user avatar",
554
+ "tags": [
555
+ "cfg_accounts_profile"
556
+ ],
557
+ "requestBody": {
558
+ "content": {
559
+ "multipart/form-data": {
560
+ "schema": {
561
+ "type": "object",
562
+ "properties": {
563
+ "avatar": {
564
+ "type": "string",
565
+ "format": "binary",
566
+ "description": "Avatar image file (JPEG, PNG, GIF, WebP, max 5MB)"
567
+ }
568
+ },
569
+ "required": [
570
+ "avatar"
571
+ ]
572
+ }
573
+ }
574
+ }
575
+ },
576
+ "security": [
577
+ {
578
+ "apiKeyAuth": []
579
+ },
580
+ {
581
+ "jwtAuthWithLastLogin": []
582
+ }
583
+ ],
584
+ "responses": {
585
+ "200": {
586
+ "content": {
587
+ "application/json": {
588
+ "schema": {
589
+ "$ref": "#/components/schemas/User"
590
+ }
591
+ }
592
+ },
593
+ "description": ""
594
+ },
595
+ "400": {
596
+ "content": {
597
+ "application/json": {
598
+ "schema": {
599
+ "description": "Invalid file or validation error."
600
+ }
601
+ }
602
+ },
603
+ "description": ""
604
+ },
605
+ "401": {
606
+ "content": {
607
+ "application/json": {
608
+ "schema": {
609
+ "description": "Authentication credentials were not provided."
610
+ }
611
+ }
612
+ },
613
+ "description": ""
614
+ }
615
+ },
616
+ "x-async-capable": false
617
+ }
618
+ },
619
+ "/cfg/accounts/profile/delete/": {
620
+ "post": {
621
+ "operationId": "cfg_accounts_profile_delete_create",
622
+ "description": "\n Permanently delete the current user's account.\n\n This operation:\n - Deactivates the account (user cannot log in)\n - Anonymizes personal data (GDPR compliance)\n - Frees up the email address for re-registration\n - Preserves audit trail\n\n The account can be restored by an administrator if needed.\n ",
623
+ "summary": "Delete user account",
624
+ "tags": [
625
+ "cfg_accounts_profile"
626
+ ],
627
+ "security": [
628
+ {
629
+ "jwtAuth": []
630
+ },
631
+ {
632
+ "cookieAuth": []
633
+ }
634
+ ],
635
+ "responses": {
636
+ "200": {
637
+ "content": {
638
+ "application/json": {
639
+ "schema": {
640
+ "$ref": "#/components/schemas/AccountDeleteResponse"
641
+ }
642
+ }
643
+ },
644
+ "description": ""
645
+ },
646
+ "401": {
647
+ "content": {
648
+ "application/json": {
649
+ "schema": {
650
+ "description": "Authentication credentials were not provided."
651
+ }
652
+ }
653
+ },
654
+ "description": ""
655
+ },
656
+ "400": {
657
+ "content": {
658
+ "application/json": {
659
+ "schema": {
660
+ "description": "Account is already deleted."
661
+ }
662
+ }
663
+ },
664
+ "description": ""
665
+ }
666
+ },
667
+ "x-async-capable": false
668
+ }
669
+ },
670
+ "/cfg/accounts/profile/partial/": {
671
+ "put": {
672
+ "operationId": "cfg_accounts_profile_partial_update",
673
+ "description": "Partially update the current authenticated user's profile information. Supports avatar upload.",
674
+ "summary": "Partial update user profile",
675
+ "tags": [
676
+ "cfg_accounts_profile"
677
+ ],
678
+ "requestBody": {
679
+ "content": {
680
+ "application/json": {
681
+ "schema": {
682
+ "$ref": "#/components/schemas/CfgUserUpdateRequest"
683
+ },
684
+ "examples": {
685
+ "ProfileUpdateWithAvatar": {
686
+ "value": {
687
+ "first_name": "John",
688
+ "last_name": "Doe",
689
+ "company": "Tech Corp",
690
+ "phone": "+1 (555) 123-4567",
691
+ "position": "Software Engineer"
692
+ },
693
+ "summary": "Profile Update with Avatar"
694
+ }
695
+ }
696
+ }
697
+ }
698
+ },
699
+ "security": [
700
+ {
701
+ "jwtAuth": []
702
+ },
703
+ {
704
+ "cookieAuth": []
705
+ }
706
+ ],
707
+ "responses": {
708
+ "200": {
709
+ "content": {
710
+ "application/json": {
711
+ "schema": {
712
+ "$ref": "#/components/schemas/User"
713
+ }
714
+ }
715
+ },
716
+ "description": ""
717
+ },
718
+ "400": {
719
+ "content": {
720
+ "application/json": {
721
+ "schema": {
722
+ "description": "Invalid data provided."
723
+ }
724
+ }
725
+ },
726
+ "description": ""
727
+ },
728
+ "401": {
729
+ "content": {
730
+ "application/json": {
731
+ "schema": {
732
+ "description": "Authentication credentials were not provided."
733
+ }
734
+ }
735
+ },
736
+ "description": ""
737
+ }
738
+ },
739
+ "x-async-capable": false
740
+ },
741
+ "patch": {
742
+ "operationId": "cfg_accounts_profile_partial_partial_update",
743
+ "description": "Partially update the current authenticated user's profile information. Supports avatar upload.",
744
+ "summary": "Partial update user profile",
745
+ "tags": [
746
+ "cfg_accounts_profile"
747
+ ],
748
+ "requestBody": {
749
+ "content": {
750
+ "application/json": {
751
+ "schema": {
752
+ "$ref": "#/components/schemas/PatchedCfgUserUpdateRequest"
753
+ },
754
+ "examples": {
755
+ "ProfileUpdateWithAvatar": {
756
+ "value": {
757
+ "first_name": "John",
758
+ "last_name": "Doe",
759
+ "company": "Tech Corp",
760
+ "phone": "+1 (555) 123-4567",
761
+ "position": "Software Engineer"
762
+ },
763
+ "summary": "Profile Update with Avatar"
764
+ }
765
+ }
766
+ }
767
+ }
768
+ },
769
+ "security": [
770
+ {
771
+ "jwtAuth": []
772
+ },
773
+ {
774
+ "cookieAuth": []
775
+ }
776
+ ],
777
+ "responses": {
778
+ "200": {
779
+ "content": {
780
+ "application/json": {
781
+ "schema": {
782
+ "$ref": "#/components/schemas/User"
783
+ }
784
+ }
785
+ },
786
+ "description": ""
787
+ },
788
+ "400": {
789
+ "content": {
790
+ "application/json": {
791
+ "schema": {
792
+ "description": "Invalid data provided."
793
+ }
794
+ }
795
+ },
796
+ "description": ""
797
+ },
798
+ "401": {
799
+ "content": {
800
+ "application/json": {
801
+ "schema": {
802
+ "description": "Authentication credentials were not provided."
803
+ }
804
+ }
805
+ },
806
+ "description": ""
807
+ }
808
+ },
809
+ "x-async-capable": false
810
+ }
811
+ },
812
+ "/cfg/accounts/profile/update/": {
813
+ "put": {
814
+ "operationId": "cfg_accounts_profile_update_update",
815
+ "description": "Update the current authenticated user's profile information.",
816
+ "summary": "Update user profile",
817
+ "tags": [
818
+ "cfg_accounts_profile"
819
+ ],
820
+ "requestBody": {
821
+ "content": {
822
+ "application/json": {
823
+ "schema": {
824
+ "$ref": "#/components/schemas/CfgUserUpdateRequest"
825
+ },
826
+ "examples": {
827
+ "ValidProfileUpdate": {
828
+ "value": {
829
+ "first_name": "John",
830
+ "last_name": "Doe",
831
+ "company": "Tech Corp",
832
+ "phone": "+1 (555) 123-4567",
833
+ "position": "Software Engineer"
834
+ },
835
+ "summary": "Valid Profile Update"
836
+ }
837
+ }
838
+ }
839
+ }
840
+ },
841
+ "security": [
842
+ {
843
+ "jwtAuth": []
844
+ },
845
+ {
846
+ "cookieAuth": []
847
+ }
848
+ ],
849
+ "responses": {
850
+ "200": {
851
+ "content": {
852
+ "application/json": {
853
+ "schema": {
854
+ "$ref": "#/components/schemas/User"
855
+ }
856
+ }
857
+ },
858
+ "description": ""
859
+ },
860
+ "400": {
861
+ "content": {
862
+ "application/json": {
863
+ "schema": {
864
+ "description": "Invalid data provided."
865
+ }
866
+ }
867
+ },
868
+ "description": ""
869
+ },
870
+ "401": {
871
+ "content": {
872
+ "application/json": {
873
+ "schema": {
874
+ "description": "Authentication credentials were not provided."
875
+ }
876
+ }
877
+ },
878
+ "description": ""
879
+ }
880
+ },
881
+ "x-async-capable": false
882
+ },
883
+ "patch": {
884
+ "operationId": "cfg_accounts_profile_update_partial_update",
885
+ "description": "Update the current authenticated user's profile information.",
886
+ "summary": "Update user profile",
887
+ "tags": [
888
+ "cfg_accounts_profile"
889
+ ],
890
+ "requestBody": {
891
+ "content": {
892
+ "application/json": {
893
+ "schema": {
894
+ "$ref": "#/components/schemas/PatchedCfgUserUpdateRequest"
895
+ },
896
+ "examples": {
897
+ "ValidProfileUpdate": {
898
+ "value": {
899
+ "first_name": "John",
900
+ "last_name": "Doe",
901
+ "company": "Tech Corp",
902
+ "phone": "+1 (555) 123-4567",
903
+ "position": "Software Engineer"
904
+ },
905
+ "summary": "Valid Profile Update"
906
+ }
907
+ }
908
+ }
909
+ }
910
+ },
911
+ "security": [
912
+ {
913
+ "jwtAuth": []
914
+ },
915
+ {
916
+ "cookieAuth": []
917
+ }
918
+ ],
919
+ "responses": {
920
+ "200": {
921
+ "content": {
922
+ "application/json": {
923
+ "schema": {
924
+ "$ref": "#/components/schemas/User"
925
+ }
926
+ }
927
+ },
928
+ "description": ""
929
+ },
930
+ "400": {
931
+ "content": {
932
+ "application/json": {
933
+ "schema": {
934
+ "description": "Invalid data provided."
935
+ }
936
+ }
937
+ },
938
+ "description": ""
939
+ },
940
+ "401": {
941
+ "content": {
942
+ "application/json": {
943
+ "schema": {
944
+ "description": "Authentication credentials were not provided."
945
+ }
946
+ }
947
+ },
948
+ "description": ""
949
+ }
950
+ },
951
+ "x-async-capable": false
952
+ }
953
+ },
954
+ "/cfg/accounts/token/refresh/": {
955
+ "post": {
956
+ "operationId": "cfg_accounts_token_refresh_create",
957
+ "description": "Refresh JWT token.",
958
+ "tags": [
959
+ "cfg_accounts_auth"
960
+ ],
961
+ "requestBody": {
962
+ "content": {
963
+ "application/json": {
964
+ "schema": {
965
+ "$ref": "#/components/schemas/TokenRefreshRequest"
966
+ }
967
+ }
968
+ },
969
+ "required": true
970
+ },
971
+ "responses": {
972
+ "200": {
973
+ "content": {
974
+ "application/json": {
975
+ "schema": {
976
+ "$ref": "#/components/schemas/TokenRefresh"
977
+ }
978
+ }
979
+ },
980
+ "description": ""
981
+ }
982
+ },
983
+ "x-async-capable": false
984
+ }
985
+ },
986
+ "/cfg/centrifugo/auth/token/": {
987
+ "get": {
988
+ "operationId": "cfg_centrifugo_auth_token_retrieve",
989
+ "description": "Generate JWT token for WebSocket connection to Centrifugo. Token includes user's allowed channels based on their permissions. Requires authentication.",
990
+ "summary": "Get Centrifugo connection token",
991
+ "tags": [
992
+ "cfg_centrifugo"
993
+ ],
994
+ "security": [
995
+ {
996
+ "apiKeyAuth": []
997
+ },
998
+ {
999
+ "jwtAuthWithLastLogin": []
1000
+ }
1001
+ ],
1002
+ "responses": {
1003
+ "200": {
1004
+ "content": {
1005
+ "application/json": {
1006
+ "schema": {
1007
+ "$ref": "#/components/schemas/ConnectionTokenResponse"
1008
+ }
1009
+ }
1010
+ },
1011
+ "description": ""
1012
+ },
1013
+ "401": {
1014
+ "content": {
1015
+ "application/json": {
1016
+ "schema": {
1017
+ "description": "Unauthorized - authentication required"
1018
+ }
1019
+ }
1020
+ },
1021
+ "description": ""
1022
+ },
1023
+ "500": {
1024
+ "content": {
1025
+ "application/json": {
1026
+ "schema": {
1027
+ "description": "Server error"
1028
+ }
1029
+ }
1030
+ },
1031
+ "description": ""
1032
+ }
1033
+ },
1034
+ "x-async-capable": false
1035
+ }
1036
+ },
1037
+ "/cfg/totp/backup-codes/": {
1038
+ "get": {
1039
+ "operationId": "cfg_totp_backup_codes_retrieve",
1040
+ "description": "Get backup codes status for user.",
1041
+ "tags": [
1042
+ "cfg_totp_backup_codes"
1043
+ ],
1044
+ "security": [
1045
+ {
1046
+ "apiKeyAuth": []
1047
+ },
1048
+ {
1049
+ "jwtAuthWithLastLogin": []
1050
+ }
1051
+ ],
1052
+ "responses": {
1053
+ "200": {
1054
+ "content": {
1055
+ "application/json": {
1056
+ "schema": {
1057
+ "$ref": "#/components/schemas/BackupCodesStatus"
1058
+ }
1059
+ }
1060
+ },
1061
+ "description": ""
1062
+ }
1063
+ },
1064
+ "x-async-capable": false
1065
+ }
1066
+ },
1067
+ "/cfg/totp/backup-codes/regenerate/": {
1068
+ "post": {
1069
+ "operationId": "cfg_totp_backup_codes_regenerate_create",
1070
+ "description": "Regenerate backup codes.\n\nRequires TOTP code for verification.\nInvalidates all existing codes.",
1071
+ "tags": [
1072
+ "cfg_totp_backup_codes"
1073
+ ],
1074
+ "requestBody": {
1075
+ "content": {
1076
+ "application/json": {
1077
+ "schema": {
1078
+ "$ref": "#/components/schemas/BackupCodesRegenerateRequest"
1079
+ }
1080
+ }
1081
+ },
1082
+ "required": true
1083
+ },
1084
+ "security": [
1085
+ {
1086
+ "apiKeyAuth": []
1087
+ },
1088
+ {
1089
+ "jwtAuthWithLastLogin": []
1090
+ }
1091
+ ],
1092
+ "responses": {
1093
+ "200": {
1094
+ "content": {
1095
+ "application/json": {
1096
+ "schema": {
1097
+ "$ref": "#/components/schemas/BackupCodesRegenerateResponse"
1098
+ }
1099
+ }
1100
+ },
1101
+ "description": ""
1102
+ },
1103
+ "400": {
1104
+ "content": {
1105
+ "application/json": {
1106
+ "schema": {
1107
+ "description": "Invalid code or 2FA not enabled"
1108
+ }
1109
+ }
1110
+ },
1111
+ "description": ""
1112
+ }
1113
+ },
1114
+ "x-async-capable": false
1115
+ }
1116
+ },
1117
+ "/cfg/totp/devices/": {
1118
+ "get": {
1119
+ "operationId": "cfg_totp_devices_retrieve",
1120
+ "description": "List all TOTP devices for user.",
1121
+ "tags": [
1122
+ "cfg_totp"
1123
+ ],
1124
+ "security": [
1125
+ {
1126
+ "apiKeyAuth": []
1127
+ },
1128
+ {
1129
+ "jwtAuthWithLastLogin": []
1130
+ }
1131
+ ],
1132
+ "responses": {
1133
+ "200": {
1134
+ "content": {
1135
+ "application/json": {
1136
+ "schema": {
1137
+ "$ref": "#/components/schemas/DeviceListResponse"
1138
+ }
1139
+ }
1140
+ },
1141
+ "description": ""
1142
+ }
1143
+ },
1144
+ "x-async-capable": false
1145
+ }
1146
+ },
1147
+ "/cfg/totp/devices/{id}/": {
1148
+ "delete": {
1149
+ "operationId": "cfg_totp_devices_destroy",
1150
+ "description": "Delete a TOTP device.\n\nRequires verification code if removing the last/primary device.",
1151
+ "parameters": [
1152
+ {
1153
+ "in": "path",
1154
+ "name": "id",
1155
+ "schema": {
1156
+ "type": "string",
1157
+ "format": "uuid"
1158
+ },
1159
+ "required": true
1160
+ }
1161
+ ],
1162
+ "tags": [
1163
+ "cfg_totp"
1164
+ ],
1165
+ "security": [
1166
+ {
1167
+ "apiKeyAuth": []
1168
+ },
1169
+ {
1170
+ "jwtAuthWithLastLogin": []
1171
+ }
1172
+ ],
1173
+ "responses": {
1174
+ "204": {
1175
+ "description": "No response body"
1176
+ }
1177
+ },
1178
+ "x-async-capable": false
1179
+ }
1180
+ },
1181
+ "/cfg/totp/disable/": {
1182
+ "post": {
1183
+ "operationId": "cfg_totp_disable_create",
1184
+ "description": "Completely disable 2FA for account.\n\nRequires verification code.",
1185
+ "tags": [
1186
+ "cfg_totp"
1187
+ ],
1188
+ "requestBody": {
1189
+ "content": {
1190
+ "application/json": {
1191
+ "schema": {
1192
+ "$ref": "#/components/schemas/DisableRequest"
1193
+ }
1194
+ }
1195
+ },
1196
+ "required": true
1197
+ },
1198
+ "security": [
1199
+ {
1200
+ "apiKeyAuth": []
1201
+ },
1202
+ {
1203
+ "jwtAuthWithLastLogin": []
1204
+ }
1205
+ ],
1206
+ "responses": {
1207
+ "200": {
1208
+ "content": {
1209
+ "application/json": {
1210
+ "schema": {
1211
+ "$ref": "#/components/schemas/cfg_totp_disable_response_200_AutoRef"
1212
+ }
1213
+ }
1214
+ },
1215
+ "description": ""
1216
+ },
1217
+ "400": {
1218
+ "content": {
1219
+ "application/json": {
1220
+ "schema": {
1221
+ "description": "Invalid code"
1222
+ }
1223
+ }
1224
+ },
1225
+ "description": ""
1226
+ }
1227
+ },
1228
+ "x-async-capable": false
1229
+ }
1230
+ },
1231
+ "/cfg/totp/setup/": {
1232
+ "post": {
1233
+ "operationId": "cfg_totp_setup_create",
1234
+ "description": "Start 2FA setup process.\n\nCreates a new TOTP device and returns QR code for scanning.",
1235
+ "tags": [
1236
+ "cfg_totp_setup"
1237
+ ],
1238
+ "requestBody": {
1239
+ "content": {
1240
+ "application/json": {
1241
+ "schema": {
1242
+ "$ref": "#/components/schemas/SetupRequest"
1243
+ }
1244
+ }
1245
+ }
1246
+ },
1247
+ "security": [
1248
+ {
1249
+ "apiKeyAuth": []
1250
+ },
1251
+ {
1252
+ "jwtAuthWithLastLogin": []
1253
+ }
1254
+ ],
1255
+ "responses": {
1256
+ "200": {
1257
+ "content": {
1258
+ "application/json": {
1259
+ "schema": {
1260
+ "$ref": "#/components/schemas/SetupResponse"
1261
+ }
1262
+ }
1263
+ },
1264
+ "description": ""
1265
+ },
1266
+ "400": {
1267
+ "content": {
1268
+ "application/json": {
1269
+ "schema": {
1270
+ "description": "2FA already enabled or invalid request"
1271
+ }
1272
+ }
1273
+ },
1274
+ "description": ""
1275
+ }
1276
+ },
1277
+ "x-async-capable": false
1278
+ }
1279
+ },
1280
+ "/cfg/totp/setup/confirm/": {
1281
+ "post": {
1282
+ "operationId": "cfg_totp_setup_confirm_create",
1283
+ "description": "Confirm 2FA setup with first valid code.\n\nActivates the device and generates backup codes.",
1284
+ "tags": [
1285
+ "cfg_totp_setup"
1286
+ ],
1287
+ "requestBody": {
1288
+ "content": {
1289
+ "application/json": {
1290
+ "schema": {
1291
+ "$ref": "#/components/schemas/ConfirmSetupRequest"
1292
+ }
1293
+ }
1294
+ },
1295
+ "required": true
1296
+ },
1297
+ "security": [
1298
+ {
1299
+ "apiKeyAuth": []
1300
+ },
1301
+ {
1302
+ "jwtAuthWithLastLogin": []
1303
+ }
1304
+ ],
1305
+ "responses": {
1306
+ "200": {
1307
+ "content": {
1308
+ "application/json": {
1309
+ "schema": {
1310
+ "$ref": "#/components/schemas/ConfirmSetupResponse"
1311
+ }
1312
+ }
1313
+ },
1314
+ "description": ""
1315
+ },
1316
+ "400": {
1317
+ "content": {
1318
+ "application/json": {
1319
+ "schema": {
1320
+ "description": "Invalid code or setup expired"
1321
+ }
1322
+ }
1323
+ },
1324
+ "description": ""
1325
+ }
1326
+ },
1327
+ "x-async-capable": false
1328
+ }
1329
+ },
1330
+ "/cfg/totp/verify/": {
1331
+ "post": {
1332
+ "operationId": "cfg_totp_verify_create",
1333
+ "description": "Verify TOTP code for 2FA session.\n\nCompletes authentication and returns JWT tokens on success.",
1334
+ "tags": [
1335
+ "cfg_totp_verify"
1336
+ ],
1337
+ "requestBody": {
1338
+ "content": {
1339
+ "application/json": {
1340
+ "schema": {
1341
+ "$ref": "#/components/schemas/VerifyRequest"
1342
+ }
1343
+ }
1344
+ },
1345
+ "required": true
1346
+ },
1347
+ "security": [
1348
+ {
1349
+ "apiKeyAuth": []
1350
+ },
1351
+ {
1352
+ "jwtAuthWithLastLogin": []
1353
+ },
1354
+ {}
1355
+ ],
1356
+ "responses": {
1357
+ "200": {
1358
+ "content": {
1359
+ "application/json": {
1360
+ "schema": {
1361
+ "$ref": "#/components/schemas/VerifyResponse"
1362
+ }
1363
+ }
1364
+ },
1365
+ "description": ""
1366
+ },
1367
+ "400": {
1368
+ "content": {
1369
+ "application/json": {
1370
+ "schema": {
1371
+ "description": "Invalid code or session"
1372
+ }
1373
+ }
1374
+ },
1375
+ "description": ""
1376
+ },
1377
+ "403": {
1378
+ "content": {
1379
+ "application/json": {
1380
+ "schema": {
1381
+ "description": "Too many attempts"
1382
+ }
1383
+ }
1384
+ },
1385
+ "description": ""
1386
+ }
1387
+ },
1388
+ "x-async-capable": false
1389
+ }
1390
+ },
1391
+ "/cfg/totp/verify/backup/": {
1392
+ "post": {
1393
+ "operationId": "cfg_totp_verify_backup_create",
1394
+ "description": "Verify backup recovery code for 2FA session.\n\nAlternative verification method when TOTP device unavailable.",
1395
+ "tags": [
1396
+ "cfg_totp_verify"
1397
+ ],
1398
+ "requestBody": {
1399
+ "content": {
1400
+ "application/json": {
1401
+ "schema": {
1402
+ "$ref": "#/components/schemas/VerifyBackupRequest"
1403
+ }
1404
+ }
1405
+ },
1406
+ "required": true
1407
+ },
1408
+ "security": [
1409
+ {
1410
+ "apiKeyAuth": []
1411
+ },
1412
+ {
1413
+ "jwtAuthWithLastLogin": []
1414
+ },
1415
+ {}
1416
+ ],
1417
+ "responses": {
1418
+ "200": {
1419
+ "content": {
1420
+ "application/json": {
1421
+ "schema": {
1422
+ "$ref": "#/components/schemas/VerifyResponse"
1423
+ }
1424
+ }
1425
+ },
1426
+ "description": ""
1427
+ },
1428
+ "400": {
1429
+ "content": {
1430
+ "application/json": {
1431
+ "schema": {
1432
+ "description": "Invalid backup code or session"
1433
+ }
1434
+ }
1435
+ },
1436
+ "description": ""
1437
+ }
1438
+ },
1439
+ "x-async-capable": false
1440
+ }
1441
+ }
1442
+ },
1443
+ "components": {
1444
+ "schemas": {
1445
+ "APIKey": {
1446
+ "type": "object",
1447
+ "description": "Serializer for API key response (masked).",
1448
+ "properties": {
1449
+ "key": {
1450
+ "type": "string",
1451
+ "description": "Masked API key"
1452
+ },
1453
+ "reissued_at": {
1454
+ "type": [
1455
+ "string",
1456
+ "null"
1457
+ ],
1458
+ "format": "date-time",
1459
+ "description": "When the key was last regenerated"
1460
+ },
1461
+ "created_at": {
1462
+ "type": "string",
1463
+ "format": "date-time",
1464
+ "description": "When the key was created"
1465
+ }
1466
+ },
1467
+ "required": [
1468
+ "created_at",
1469
+ "key",
1470
+ "reissued_at"
1471
+ ]
1472
+ },
1473
+ "APIKeyRegenerate": {
1474
+ "type": "object",
1475
+ "description": "Serializer for API key regeneration response (full key shown once).",
1476
+ "properties": {
1477
+ "key": {
1478
+ "type": "string",
1479
+ "description": "New API key (shown only once)"
1480
+ },
1481
+ "reissued_at": {
1482
+ "type": "string",
1483
+ "format": "date-time",
1484
+ "description": "When the key was regenerated"
1485
+ }
1486
+ },
1487
+ "required": [
1488
+ "key",
1489
+ "reissued_at"
1490
+ ]
1491
+ },
1492
+ "APIKeyRequest": {
1493
+ "type": "object",
1494
+ "description": "Serializer for API key response (masked).",
1495
+ "properties": {
1496
+ "key": {
1497
+ "type": "string",
1498
+ "minLength": 1,
1499
+ "description": "Masked API key"
1500
+ },
1501
+ "reissued_at": {
1502
+ "type": [
1503
+ "string",
1504
+ "null"
1505
+ ],
1506
+ "format": "date-time",
1507
+ "description": "When the key was last regenerated"
1508
+ },
1509
+ "created_at": {
1510
+ "type": "string",
1511
+ "format": "date-time",
1512
+ "description": "When the key was created"
1513
+ }
1514
+ },
1515
+ "required": [
1516
+ "created_at",
1517
+ "key",
1518
+ "reissued_at"
1519
+ ]
1520
+ },
1521
+ "APIKeyTestRequest": {
1522
+ "type": "object",
1523
+ "description": "Serializer for testing an API key.",
1524
+ "properties": {
1525
+ "key": {
1526
+ "type": "string",
1527
+ "minLength": 1,
1528
+ "description": "API key to test"
1529
+ }
1530
+ },
1531
+ "required": [
1532
+ "key"
1533
+ ]
1534
+ },
1535
+ "APIKeyTestResult": {
1536
+ "type": "object",
1537
+ "description": "Serializer for API key test result.",
1538
+ "properties": {
1539
+ "valid": {
1540
+ "type": "boolean",
1541
+ "description": "Whether the key is valid"
1542
+ },
1543
+ "user_id": {
1544
+ "type": [
1545
+ "string",
1546
+ "null"
1547
+ ],
1548
+ "description": "User ID if valid, null otherwise"
1549
+ }
1550
+ },
1551
+ "required": [
1552
+ "user_id",
1553
+ "valid"
1554
+ ]
1555
+ },
1556
+ "AccountDeleteResponse": {
1557
+ "type": "object",
1558
+ "description": "Response serializer for account deletion.",
1559
+ "properties": {
1560
+ "success": {
1561
+ "type": "boolean",
1562
+ "description": "Whether the account was successfully deleted"
1563
+ },
1564
+ "message": {
1565
+ "type": "string",
1566
+ "description": "Human-readable message about the deletion"
1567
+ }
1568
+ },
1569
+ "required": [
1570
+ "message",
1571
+ "success"
1572
+ ]
1573
+ },
1574
+ "BackupCodesRegenerateRequest": {
1575
+ "type": "object",
1576
+ "description": "Serializer for regenerating backup codes.",
1577
+ "properties": {
1578
+ "code": {
1579
+ "type": "string",
1580
+ "minLength": 6,
1581
+ "description": "TOTP code for verification",
1582
+ "maxLength": 6
1583
+ }
1584
+ },
1585
+ "required": [
1586
+ "code"
1587
+ ]
1588
+ },
1589
+ "BackupCodesRegenerateResponse": {
1590
+ "type": "object",
1591
+ "description": "Response serializer for backup codes regeneration.",
1592
+ "properties": {
1593
+ "backup_codes": {
1594
+ "type": "array",
1595
+ "items": {
1596
+ "type": "string"
1597
+ },
1598
+ "description": "List of new backup codes (save these!)"
1599
+ },
1600
+ "warning": {
1601
+ "type": "string",
1602
+ "description": "Warning about previous codes being invalidated"
1603
+ }
1604
+ },
1605
+ "required": [
1606
+ "backup_codes",
1607
+ "warning"
1608
+ ]
1609
+ },
1610
+ "BackupCodesStatus": {
1611
+ "type": "object",
1612
+ "description": "Serializer for backup codes status.",
1613
+ "properties": {
1614
+ "remaining_count": {
1615
+ "type": "integer",
1616
+ "description": "Number of unused backup codes"
1617
+ },
1618
+ "total_generated": {
1619
+ "type": "integer",
1620
+ "description": "Total number of codes generated"
1621
+ },
1622
+ "warning": {
1623
+ "type": [
1624
+ "string",
1625
+ "null"
1626
+ ],
1627
+ "description": "Warning if running low on codes"
1628
+ }
1629
+ },
1630
+ "required": [
1631
+ "remaining_count",
1632
+ "total_generated"
1633
+ ]
1634
+ },
1635
+ "CentrifugoToken": {
1636
+ "type": "object",
1637
+ "description": "Nested serializer for Centrifugo WebSocket connection token.",
1638
+ "properties": {
1639
+ "token": {
1640
+ "type": "string",
1641
+ "description": "JWT token for Centrifugo WebSocket connection"
1642
+ },
1643
+ "centrifugo_url": {
1644
+ "type": "string",
1645
+ "format": "uri",
1646
+ "description": "Centrifugo WebSocket URL"
1647
+ },
1648
+ "expires_at": {
1649
+ "type": "string",
1650
+ "format": "date-time",
1651
+ "description": "Token expiration time (ISO 8601)"
1652
+ },
1653
+ "channels": {
1654
+ "type": "array",
1655
+ "items": {
1656
+ "type": "string"
1657
+ },
1658
+ "description": "List of allowed channels for this user"
1659
+ }
1660
+ },
1661
+ "required": [
1662
+ "centrifugo_url",
1663
+ "channels",
1664
+ "expires_at",
1665
+ "token"
1666
+ ]
1667
+ },
1668
+ "CfgUserUpdateRequest": {
1669
+ "type": "object",
1670
+ "description": "Serializer for updating user profile.",
1671
+ "properties": {
1672
+ "first_name": {
1673
+ "type": "string",
1674
+ "maxLength": 50
1675
+ },
1676
+ "last_name": {
1677
+ "type": "string",
1678
+ "maxLength": 50
1679
+ },
1680
+ "company": {
1681
+ "type": "string",
1682
+ "maxLength": 100
1683
+ },
1684
+ "phone": {
1685
+ "type": "string",
1686
+ "maxLength": 20
1687
+ },
1688
+ "position": {
1689
+ "type": "string",
1690
+ "maxLength": 100
1691
+ },
1692
+ "language": {
1693
+ "type": "string",
1694
+ "maxLength": 10
1695
+ },
1696
+ "timezone": {
1697
+ "type": "string",
1698
+ "description": "IANA timezone name (e.g. 'Asia/Seoul'). Auto-detected from browser via X-Timezone header.",
1699
+ "maxLength": 64
1700
+ }
1701
+ }
1702
+ },
1703
+ "ConfirmSetupRequest": {
1704
+ "type": "object",
1705
+ "description": "Serializer for confirming 2FA setup with first code.",
1706
+ "properties": {
1707
+ "device_id": {
1708
+ "type": "string",
1709
+ "format": "uuid",
1710
+ "description": "Device ID from setup response"
1711
+ },
1712
+ "code": {
1713
+ "type": "string",
1714
+ "minLength": 6,
1715
+ "description": "6-digit TOTP code from authenticator app",
1716
+ "maxLength": 6
1717
+ }
1718
+ },
1719
+ "required": [
1720
+ "code",
1721
+ "device_id"
1722
+ ]
1723
+ },
1724
+ "ConfirmSetupResponse": {
1725
+ "type": "object",
1726
+ "description": "Response serializer for setup confirmation.",
1727
+ "properties": {
1728
+ "message": {
1729
+ "type": "string"
1730
+ },
1731
+ "backup_codes": {
1732
+ "type": "array",
1733
+ "items": {
1734
+ "type": "string"
1735
+ },
1736
+ "description": "List of backup recovery codes (save these!)"
1737
+ },
1738
+ "backup_codes_warning": {
1739
+ "type": "string",
1740
+ "description": "Warning message about backup codes"
1741
+ }
1742
+ },
1743
+ "required": [
1744
+ "backup_codes",
1745
+ "backup_codes_warning",
1746
+ "message"
1747
+ ]
1748
+ },
1749
+ "ConnectionTokenResponse": {
1750
+ "description": "Response model for Centrifugo connection token.",
1751
+ "properties": {
1752
+ "token": {
1753
+ "description": "JWT token for Centrifugo connection",
1754
+ "title": "Token",
1755
+ "type": "string"
1756
+ },
1757
+ "centrifugo_url": {
1758
+ "description": "Centrifugo WebSocket URL",
1759
+ "title": "Centrifugo Url",
1760
+ "type": "string"
1761
+ },
1762
+ "expires_at": {
1763
+ "description": "Token expiration time (ISO 8601)",
1764
+ "title": "Expires At",
1765
+ "type": "string"
1766
+ },
1767
+ "channels": {
1768
+ "description": "List of allowed channels",
1769
+ "items": {
1770
+ "type": "string"
1771
+ },
1772
+ "title": "Channels",
1773
+ "type": "array"
1774
+ }
1775
+ },
1776
+ "required": [
1777
+ "token",
1778
+ "centrifugo_url",
1779
+ "expires_at",
1780
+ "channels"
1781
+ ],
1782
+ "title": "ConnectionTokenResponse",
1783
+ "type": "object"
1784
+ },
1785
+ "DeviceList": {
1786
+ "type": "object",
1787
+ "description": "Serializer for listing TOTP devices.",
1788
+ "properties": {
1789
+ "id": {
1790
+ "type": "string",
1791
+ "format": "uuid",
1792
+ "readOnly": true
1793
+ },
1794
+ "name": {
1795
+ "type": "string",
1796
+ "readOnly": true,
1797
+ "description": "Device name for identification"
1798
+ },
1799
+ "is_primary": {
1800
+ "type": "boolean",
1801
+ "readOnly": true,
1802
+ "description": "Primary device used for verification"
1803
+ },
1804
+ "status": {
1805
+ "allOf": [
1806
+ {
1807
+ "$ref": "#/components/schemas/DeviceStatusEnum"
1808
+ }
1809
+ ],
1810
+ "readOnly": true
1811
+ },
1812
+ "created_at": {
1813
+ "type": "string",
1814
+ "format": "date-time",
1815
+ "readOnly": true
1816
+ },
1817
+ "confirmed_at": {
1818
+ "type": [
1819
+ "string",
1820
+ "null"
1821
+ ],
1822
+ "format": "date-time",
1823
+ "readOnly": true,
1824
+ "description": "When device setup was confirmed"
1825
+ },
1826
+ "last_used_at": {
1827
+ "type": [
1828
+ "string",
1829
+ "null"
1830
+ ],
1831
+ "format": "date-time",
1832
+ "readOnly": true,
1833
+ "description": "Last successful verification"
1834
+ }
1835
+ },
1836
+ "required": [
1837
+ "confirmed_at",
1838
+ "created_at",
1839
+ "id",
1840
+ "is_primary",
1841
+ "last_used_at",
1842
+ "name",
1843
+ "status"
1844
+ ]
1845
+ },
1846
+ "DeviceListResponse": {
1847
+ "type": "object",
1848
+ "description": "Response serializer for device list endpoint.",
1849
+ "properties": {
1850
+ "devices": {
1851
+ "type": "array",
1852
+ "items": {
1853
+ "$ref": "#/components/schemas/DeviceList"
1854
+ }
1855
+ },
1856
+ "has_2fa_enabled": {
1857
+ "type": "boolean"
1858
+ }
1859
+ },
1860
+ "required": [
1861
+ "devices",
1862
+ "has_2fa_enabled"
1863
+ ]
1864
+ },
1865
+ "DeviceStatusEnum": {
1866
+ "enum": [
1867
+ "pending",
1868
+ "active",
1869
+ "disabled"
1870
+ ],
1871
+ "type": "string",
1872
+ "description": "* `pending` - Pending Confirmation\n* `active` - Active\n* `disabled` - Disabled"
1873
+ },
1874
+ "DisableRequest": {
1875
+ "type": "object",
1876
+ "description": "Serializer for completely disabling 2FA.",
1877
+ "properties": {
1878
+ "code": {
1879
+ "type": "string",
1880
+ "minLength": 6,
1881
+ "description": "TOTP code for verification",
1882
+ "maxLength": 6
1883
+ }
1884
+ },
1885
+ "required": [
1886
+ "code"
1887
+ ]
1888
+ },
1889
+ "OAuthAuthorizeRequestRequest": {
1890
+ "type": "object",
1891
+ "description": "Request to start OAuth flow.",
1892
+ "properties": {
1893
+ "redirect_uri": {
1894
+ "type": "string",
1895
+ "format": "uri",
1896
+ "description": "URL to redirect after OAuth authorization. If not provided, uses config's site_url + callback_path"
1897
+ },
1898
+ "source_url": {
1899
+ "type": "string",
1900
+ "format": "uri",
1901
+ "description": "Optional source URL for registration tracking"
1902
+ }
1903
+ }
1904
+ },
1905
+ "OAuthAuthorizeResponse": {
1906
+ "type": "object",
1907
+ "description": "Response with OAuth authorization URL.",
1908
+ "properties": {
1909
+ "authorization_url": {
1910
+ "type": "string",
1911
+ "format": "uri",
1912
+ "description": "Full URL to redirect user to OAuth provider"
1913
+ },
1914
+ "state": {
1915
+ "type": "string",
1916
+ "description": "State token for CSRF protection. Store this and verify on callback."
1917
+ }
1918
+ },
1919
+ "required": [
1920
+ "authorization_url",
1921
+ "state"
1922
+ ]
1923
+ },
1924
+ "OAuthCallbackRequestRequest": {
1925
+ "type": "object",
1926
+ "description": "Request to complete OAuth flow (callback handler).",
1927
+ "properties": {
1928
+ "code": {
1929
+ "type": "string",
1930
+ "minLength": 10,
1931
+ "description": "Authorization code from OAuth provider callback",
1932
+ "maxLength": 500
1933
+ },
1934
+ "state": {
1935
+ "type": "string",
1936
+ "minLength": 20,
1937
+ "description": "State token for CSRF verification (from authorize response)",
1938
+ "maxLength": 100
1939
+ },
1940
+ "redirect_uri": {
1941
+ "type": "string",
1942
+ "format": "uri",
1943
+ "description": "Same redirect_uri used in authorize request. If not provided, uses config's site_url + callback_path"
1944
+ }
1945
+ },
1946
+ "required": [
1947
+ "code",
1948
+ "state"
1949
+ ]
1950
+ },
1951
+ "OAuthConnection": {
1952
+ "type": "object",
1953
+ "description": "Serializer for OAuth connection info (user-facing).",
1954
+ "properties": {
1955
+ "id": {
1956
+ "type": "integer",
1957
+ "readOnly": true
1958
+ },
1959
+ "provider": {
1960
+ "allOf": [
1961
+ {
1962
+ "$ref": "#/components/schemas/OAuthProviderEnum"
1963
+ }
1964
+ ],
1965
+ "readOnly": true,
1966
+ "description": "OAuth provider name (github, google, etc.)\n\n* `github` - GitHub"
1967
+ },
1968
+ "provider_display": {
1969
+ "type": "string",
1970
+ "readOnly": true
1971
+ },
1972
+ "provider_username": {
1973
+ "type": "string",
1974
+ "readOnly": true,
1975
+ "description": "Username on the OAuth provider platform"
1976
+ },
1977
+ "provider_email": {
1978
+ "type": "string",
1979
+ "format": "email",
1980
+ "readOnly": true,
1981
+ "description": "Email from OAuth provider (may differ from user.email)"
1982
+ },
1983
+ "provider_avatar_url": {
1984
+ "type": "string",
1985
+ "format": "uri",
1986
+ "readOnly": true,
1987
+ "description": "Avatar URL from OAuth provider"
1988
+ },
1989
+ "connected_at": {
1990
+ "type": "string",
1991
+ "format": "date-time",
1992
+ "readOnly": true,
1993
+ "description": "When this OAuth connection was created"
1994
+ },
1995
+ "last_login_at": {
1996
+ "type": "string",
1997
+ "format": "date-time",
1998
+ "readOnly": true,
1999
+ "description": "Last time this OAuth connection was used for login"
2000
+ }
2001
+ },
2002
+ "required": [
2003
+ "connected_at",
2004
+ "id",
2005
+ "last_login_at",
2006
+ "provider",
2007
+ "provider_avatar_url",
2008
+ "provider_display",
2009
+ "provider_email",
2010
+ "provider_username"
2011
+ ]
2012
+ },
2013
+ "OAuthDisconnectRequestRequest": {
2014
+ "type": "object",
2015
+ "description": "Request to disconnect OAuth provider.",
2016
+ "properties": {
2017
+ "provider": {
2018
+ "allOf": [
2019
+ {
2020
+ "$ref": "#/components/schemas/OAuthProviderEnum"
2021
+ }
2022
+ ],
2023
+ "description": "OAuth provider to disconnect\n\n* `github` - GitHub"
2024
+ }
2025
+ },
2026
+ "required": [
2027
+ "provider"
2028
+ ]
2029
+ },
2030
+ "OAuthError": {
2031
+ "type": "object",
2032
+ "description": "Error response for OAuth endpoints.",
2033
+ "properties": {
2034
+ "error": {
2035
+ "type": "string",
2036
+ "description": "Error code"
2037
+ },
2038
+ "error_description": {
2039
+ "type": "string",
2040
+ "description": "Human-readable error description"
2041
+ }
2042
+ },
2043
+ "required": [
2044
+ "error"
2045
+ ]
2046
+ },
2047
+ "OAuthProviderEnum": {
2048
+ "enum": [
2049
+ "github"
2050
+ ],
2051
+ "type": "string",
2052
+ "description": "* `github` - GitHub"
2053
+ },
2054
+ "OAuthProvidersResponse": {
2055
+ "type": "object",
2056
+ "description": "Response with available OAuth providers.",
2057
+ "properties": {
2058
+ "providers": {
2059
+ "type": "array",
2060
+ "items": {
2061
+ "type": "object",
2062
+ "additionalProperties": {}
2063
+ },
2064
+ "description": "List of available OAuth providers"
2065
+ }
2066
+ },
2067
+ "required": [
2068
+ "providers"
2069
+ ]
2070
+ },
2071
+ "OAuthTokenResponse": {
2072
+ "type": "object",
2073
+ "description": "Response with JWT tokens after OAuth authentication.\n\nWhen 2FA is required:\n- requires_2fa: True\n- session_id: UUID of 2FA verification session\n- access/refresh/user: null\n\nWhen 2FA is not required:\n- requires_2fa: False\n- session_id: null\n- access/refresh/user: populated",
2074
+ "properties": {
2075
+ "requires_2fa": {
2076
+ "type": "boolean",
2077
+ "default": false,
2078
+ "description": "True if 2FA verification is required"
2079
+ },
2080
+ "session_id": {
2081
+ "type": [
2082
+ "string",
2083
+ "null"
2084
+ ],
2085
+ "format": "uuid",
2086
+ "description": "2FA session ID (only when requires_2fa=True)"
2087
+ },
2088
+ "access": {
2089
+ "type": [
2090
+ "string",
2091
+ "null"
2092
+ ],
2093
+ "description": "JWT access token (null when requires_2fa=True)"
2094
+ },
2095
+ "refresh": {
2096
+ "type": [
2097
+ "string",
2098
+ "null"
2099
+ ],
2100
+ "description": "JWT refresh token (null when requires_2fa=True)"
2101
+ },
2102
+ "user": {
2103
+ "type": [
2104
+ "object",
2105
+ "null"
2106
+ ],
2107
+ "additionalProperties": {},
2108
+ "description": "Authenticated user info (null when requires_2fa=True)"
2109
+ },
2110
+ "is_new_user": {
2111
+ "type": "boolean",
2112
+ "description": "True if a new user was created during this OAuth flow"
2113
+ },
2114
+ "is_new_connection": {
2115
+ "type": "boolean",
2116
+ "description": "True if a new OAuth connection was created"
2117
+ },
2118
+ "should_prompt_2fa": {
2119
+ "type": "boolean",
2120
+ "description": "True if user should be prompted to enable 2FA"
2121
+ }
2122
+ },
2123
+ "required": [
2124
+ "is_new_connection",
2125
+ "is_new_user"
2126
+ ]
2127
+ },
2128
+ "OTPErrorResponse": {
2129
+ "type": "object",
2130
+ "description": "Typed error response for OTP operations.\n\nerror_code values:\n - invalid_identifier — malformed email\n - cooldown — too soon after last request (retry_after = seconds)\n - hourly_limit — hourly quota exceeded (retry_after = seconds until reset)\n - daily_limit — daily quota exceeded (retry_after = seconds until reset)\n - rate_limited — IP-level rate limit hit (no retry_after)\n - user_creation_failed — internal error creating account\n - send_failed — transport error (email / SMS)\n - internal_error — unexpected server error",
2131
+ "properties": {
2132
+ "error": {
2133
+ "type": "string",
2134
+ "description": "Human-readable error message"
2135
+ },
2136
+ "error_code": {
2137
+ "type": [
2138
+ "string",
2139
+ "null"
2140
+ ],
2141
+ "description": "Machine-readable error code"
2142
+ },
2143
+ "retry_after": {
2144
+ "type": [
2145
+ "integer",
2146
+ "null"
2147
+ ],
2148
+ "description": "Seconds until the client may retry (present only for rate-limit errors)"
2149
+ }
2150
+ },
2151
+ "required": [
2152
+ "error"
2153
+ ]
2154
+ },
2155
+ "OTPRequestRequest": {
2156
+ "type": "object",
2157
+ "description": "Serializer for OTP request.",
2158
+ "properties": {
2159
+ "identifier": {
2160
+ "type": "string",
2161
+ "minLength": 1,
2162
+ "description": "Email address for OTP delivery"
2163
+ },
2164
+ "source_url": {
2165
+ "type": "string",
2166
+ "format": "uri",
2167
+ "description": "Source URL for tracking registration (e.g., https://my.djangocfg.com)"
2168
+ }
2169
+ },
2170
+ "required": [
2171
+ "identifier"
2172
+ ]
2173
+ },
2174
+ "OTPRequestResponse": {
2175
+ "type": "object",
2176
+ "description": "OTP request response.",
2177
+ "properties": {
2178
+ "message": {
2179
+ "type": "string",
2180
+ "description": "Success message"
2181
+ }
2182
+ },
2183
+ "required": [
2184
+ "message"
2185
+ ]
2186
+ },
2187
+ "OTPVerifyRequest": {
2188
+ "type": "object",
2189
+ "description": "Serializer for OTP verification.",
2190
+ "properties": {
2191
+ "identifier": {
2192
+ "type": "string",
2193
+ "minLength": 1,
2194
+ "description": "Email address used for OTP request"
2195
+ },
2196
+ "otp": {
2197
+ "type": "string",
2198
+ "minLength": 4,
2199
+ "maxLength": 4
2200
+ },
2201
+ "source_url": {
2202
+ "type": "string",
2203
+ "format": "uri",
2204
+ "description": "Source URL for tracking login (e.g., https://my.djangocfg.com)"
2205
+ }
2206
+ },
2207
+ "required": [
2208
+ "identifier",
2209
+ "otp"
2210
+ ]
2211
+ },
2212
+ "OTPVerifyResponse": {
2213
+ "type": "object",
2214
+ "description": "OTP verification response.\n\nWhen 2FA is required:\n- requires_2fa: True\n- session_id: UUID of 2FA verification session\n- refresh/access/user: null\n\nWhen 2FA is not required:\n- requires_2fa: False\n- session_id: null\n- refresh/access/user: populated",
2215
+ "properties": {
2216
+ "requires_2fa": {
2217
+ "type": "boolean",
2218
+ "default": false,
2219
+ "description": "Whether 2FA verification is required"
2220
+ },
2221
+ "session_id": {
2222
+ "type": [
2223
+ "string",
2224
+ "null"
2225
+ ],
2226
+ "format": "uuid",
2227
+ "description": "2FA session ID (if requires_2fa is True)"
2228
+ },
2229
+ "refresh": {
2230
+ "type": [
2231
+ "string",
2232
+ "null"
2233
+ ],
2234
+ "description": "JWT refresh token (if requires_2fa is False)"
2235
+ },
2236
+ "access": {
2237
+ "type": [
2238
+ "string",
2239
+ "null"
2240
+ ],
2241
+ "description": "JWT access token (if requires_2fa is False)"
2242
+ },
2243
+ "user": {
2244
+ "oneOf": [
2245
+ {
2246
+ "$ref": "#/components/schemas/User"
2247
+ },
2248
+ {
2249
+ "type": "null"
2250
+ }
2251
+ ],
2252
+ "description": "User information (if requires_2fa is False)"
2253
+ },
2254
+ "should_prompt_2fa": {
2255
+ "type": "boolean",
2256
+ "description": "Whether user should be prompted to enable 2FA"
2257
+ }
2258
+ }
2259
+ },
2260
+ "PatchedCfgUserUpdateRequest": {
2261
+ "type": "object",
2262
+ "description": "Serializer for updating user profile.",
2263
+ "properties": {
2264
+ "first_name": {
2265
+ "type": "string",
2266
+ "maxLength": 50
2267
+ },
2268
+ "last_name": {
2269
+ "type": "string",
2270
+ "maxLength": 50
2271
+ },
2272
+ "company": {
2273
+ "type": "string",
2274
+ "maxLength": 100
2275
+ },
2276
+ "phone": {
2277
+ "type": "string",
2278
+ "maxLength": 20
2279
+ },
2280
+ "position": {
2281
+ "type": "string",
2282
+ "maxLength": 100
2283
+ },
2284
+ "language": {
2285
+ "type": "string",
2286
+ "maxLength": 10
2287
+ },
2288
+ "timezone": {
2289
+ "type": "string",
2290
+ "description": "IANA timezone name (e.g. 'Asia/Seoul'). Auto-detected from browser via X-Timezone header.",
2291
+ "maxLength": 64
2292
+ }
2293
+ }
2294
+ },
2295
+ "SetupRequest": {
2296
+ "type": "object",
2297
+ "description": "Serializer for starting 2FA setup.",
2298
+ "properties": {
2299
+ "device_name": {
2300
+ "type": "string",
2301
+ "minLength": 1,
2302
+ "default": "Authenticator",
2303
+ "description": "Device name for identification (e.g., 'My iPhone')",
2304
+ "maxLength": 100
2305
+ }
2306
+ }
2307
+ },
2308
+ "SetupResponse": {
2309
+ "type": "object",
2310
+ "description": "Response serializer for setup initiation.",
2311
+ "properties": {
2312
+ "device_id": {
2313
+ "type": "string",
2314
+ "format": "uuid",
2315
+ "description": "Device ID to use for confirmation"
2316
+ },
2317
+ "secret": {
2318
+ "type": "string",
2319
+ "description": "Base32-encoded TOTP secret (for manual entry)"
2320
+ },
2321
+ "provisioning_uri": {
2322
+ "type": "string",
2323
+ "description": "otpauth:// URI for QR code generation"
2324
+ },
2325
+ "qr_code_base64": {
2326
+ "type": "string",
2327
+ "description": "Base64-encoded QR code image (data URI)"
2328
+ },
2329
+ "expires_in": {
2330
+ "type": "integer",
2331
+ "description": "Seconds until setup expires (typically 600 = 10 minutes)"
2332
+ }
2333
+ },
2334
+ "required": [
2335
+ "device_id",
2336
+ "expires_in",
2337
+ "provisioning_uri",
2338
+ "qr_code_base64",
2339
+ "secret"
2340
+ ]
2341
+ },
2342
+ "TokenRefresh": {
2343
+ "type": "object",
2344
+ "properties": {
2345
+ "access": {
2346
+ "type": "string",
2347
+ "readOnly": true
2348
+ },
2349
+ "refresh": {
2350
+ "type": "string"
2351
+ }
2352
+ },
2353
+ "required": [
2354
+ "access",
2355
+ "refresh"
2356
+ ]
2357
+ },
2358
+ "TokenRefreshRequest": {
2359
+ "type": "object",
2360
+ "properties": {
2361
+ "refresh": {
2362
+ "type": "string",
2363
+ "minLength": 1
2364
+ }
2365
+ },
2366
+ "required": [
2367
+ "refresh"
2368
+ ]
2369
+ },
2370
+ "TotpVerifyUser": {
2371
+ "type": "object",
2372
+ "description": "User data returned after 2FA verification.",
2373
+ "properties": {
2374
+ "id": {
2375
+ "type": "integer",
2376
+ "readOnly": true
2377
+ },
2378
+ "email": {
2379
+ "type": "string",
2380
+ "format": "email",
2381
+ "readOnly": true
2382
+ },
2383
+ "first_name": {
2384
+ "type": [
2385
+ "string",
2386
+ "null"
2387
+ ],
2388
+ "maxLength": 50
2389
+ },
2390
+ "last_name": {
2391
+ "type": [
2392
+ "string",
2393
+ "null"
2394
+ ],
2395
+ "maxLength": 50
2396
+ },
2397
+ "full_name": {
2398
+ "type": "string",
2399
+ "description": "Get user's full name.",
2400
+ "readOnly": true
2401
+ },
2402
+ "initials": {
2403
+ "type": "string",
2404
+ "description": "Get user's initials for avatar fallback.",
2405
+ "readOnly": true
2406
+ },
2407
+ "display_username": {
2408
+ "type": "string",
2409
+ "description": "Get formatted username for display.",
2410
+ "readOnly": true
2411
+ },
2412
+ "company": {
2413
+ "type": [
2414
+ "string",
2415
+ "null"
2416
+ ],
2417
+ "maxLength": 100
2418
+ },
2419
+ "phone": {
2420
+ "type": [
2421
+ "string",
2422
+ "null"
2423
+ ],
2424
+ "maxLength": 20
2425
+ },
2426
+ "position": {
2427
+ "type": [
2428
+ "string",
2429
+ "null"
2430
+ ],
2431
+ "maxLength": 100
2432
+ },
2433
+ "language": {
2434
+ "type": [
2435
+ "string",
2436
+ "null"
2437
+ ],
2438
+ "maxLength": 10
2439
+ },
2440
+ "timezone": {
2441
+ "type": [
2442
+ "string",
2443
+ "null"
2444
+ ],
2445
+ "maxLength": 64
2446
+ },
2447
+ "avatar": {
2448
+ "type": [
2449
+ "string",
2450
+ "null"
2451
+ ],
2452
+ "format": "uri",
2453
+ "readOnly": true
2454
+ },
2455
+ "is_staff": {
2456
+ "type": "boolean",
2457
+ "readOnly": true,
2458
+ "title": "Staff status",
2459
+ "description": "Designates whether the user can log into this admin site."
2460
+ },
2461
+ "is_superuser": {
2462
+ "type": "boolean",
2463
+ "readOnly": true,
2464
+ "title": "Superuser status",
2465
+ "description": "Designates that this user has all permissions without explicitly assigning them."
2466
+ },
2467
+ "date_joined": {
2468
+ "type": "string",
2469
+ "format": "date-time",
2470
+ "readOnly": true
2471
+ },
2472
+ "last_login": {
2473
+ "type": [
2474
+ "string",
2475
+ "null"
2476
+ ],
2477
+ "format": "date-time",
2478
+ "readOnly": true
2479
+ },
2480
+ "unanswered_messages_count": {
2481
+ "type": "integer",
2482
+ "readOnly": true,
2483
+ "default": 0
2484
+ },
2485
+ "api_key": {
2486
+ "type": [
2487
+ "string",
2488
+ "null"
2489
+ ],
2490
+ "readOnly": true
2491
+ }
2492
+ },
2493
+ "required": [
2494
+ "api_key",
2495
+ "avatar",
2496
+ "date_joined",
2497
+ "display_username",
2498
+ "email",
2499
+ "full_name",
2500
+ "id",
2501
+ "initials",
2502
+ "is_staff",
2503
+ "is_superuser",
2504
+ "last_login",
2505
+ "unanswered_messages_count"
2506
+ ]
2507
+ },
2508
+ "User": {
2509
+ "type": "object",
2510
+ "description": "Serializer for user details.",
2511
+ "properties": {
2512
+ "id": {
2513
+ "type": "integer",
2514
+ "readOnly": true
2515
+ },
2516
+ "email": {
2517
+ "type": "string",
2518
+ "format": "email",
2519
+ "readOnly": true
2520
+ },
2521
+ "first_name": {
2522
+ "type": [
2523
+ "string",
2524
+ "null"
2525
+ ],
2526
+ "maxLength": 50
2527
+ },
2528
+ "last_name": {
2529
+ "type": [
2530
+ "string",
2531
+ "null"
2532
+ ],
2533
+ "maxLength": 50
2534
+ },
2535
+ "full_name": {
2536
+ "type": "string",
2537
+ "description": "Get user's full name.",
2538
+ "readOnly": true
2539
+ },
2540
+ "initials": {
2541
+ "type": "string",
2542
+ "description": "Get user's initials for avatar fallback.",
2543
+ "readOnly": true
2544
+ },
2545
+ "display_username": {
2546
+ "type": "string",
2547
+ "description": "Get formatted username for display.",
2548
+ "readOnly": true
2549
+ },
2550
+ "company": {
2551
+ "type": [
2552
+ "string",
2553
+ "null"
2554
+ ],
2555
+ "maxLength": 100
2556
+ },
2557
+ "phone": {
2558
+ "type": [
2559
+ "string",
2560
+ "null"
2561
+ ],
2562
+ "maxLength": 20
2563
+ },
2564
+ "position": {
2565
+ "type": [
2566
+ "string",
2567
+ "null"
2568
+ ],
2569
+ "maxLength": 100
2570
+ },
2571
+ "language": {
2572
+ "type": [
2573
+ "string",
2574
+ "null"
2575
+ ],
2576
+ "maxLength": 10
2577
+ },
2578
+ "timezone": {
2579
+ "type": [
2580
+ "string",
2581
+ "null"
2582
+ ],
2583
+ "maxLength": 64
2584
+ },
2585
+ "avatar": {
2586
+ "type": [
2587
+ "string",
2588
+ "null"
2589
+ ],
2590
+ "format": "uri",
2591
+ "readOnly": true
2592
+ },
2593
+ "is_staff": {
2594
+ "type": "boolean",
2595
+ "readOnly": true,
2596
+ "title": "Staff status",
2597
+ "description": "Designates whether the user can log into this admin site."
2598
+ },
2599
+ "is_superuser": {
2600
+ "type": "boolean",
2601
+ "readOnly": true,
2602
+ "title": "Superuser status",
2603
+ "description": "Designates that this user has all permissions without explicitly assigning them."
2604
+ },
2605
+ "date_joined": {
2606
+ "type": "string",
2607
+ "format": "date-time",
2608
+ "readOnly": true
2609
+ },
2610
+ "last_login": {
2611
+ "type": [
2612
+ "string",
2613
+ "null"
2614
+ ],
2615
+ "format": "date-time",
2616
+ "readOnly": true
2617
+ },
2618
+ "unanswered_messages_count": {
2619
+ "type": "integer",
2620
+ "readOnly": true,
2621
+ "default": 0
2622
+ },
2623
+ "centrifugo": {
2624
+ "oneOf": [
2625
+ {
2626
+ "$ref": "#/components/schemas/CentrifugoToken"
2627
+ },
2628
+ {
2629
+ "type": "null"
2630
+ }
2631
+ ],
2632
+ "readOnly": true
2633
+ },
2634
+ "api_key": {
2635
+ "type": [
2636
+ "string",
2637
+ "null"
2638
+ ],
2639
+ "readOnly": true
2640
+ }
2641
+ },
2642
+ "required": [
2643
+ "api_key",
2644
+ "avatar",
2645
+ "centrifugo",
2646
+ "date_joined",
2647
+ "display_username",
2648
+ "email",
2649
+ "full_name",
2650
+ "id",
2651
+ "initials",
2652
+ "is_staff",
2653
+ "is_superuser",
2654
+ "last_login",
2655
+ "unanswered_messages_count"
2656
+ ]
2657
+ },
2658
+ "VerifyBackupRequest": {
2659
+ "type": "object",
2660
+ "description": "Serializer for backup code verification during login.",
2661
+ "properties": {
2662
+ "session_id": {
2663
+ "type": "string",
2664
+ "format": "uuid",
2665
+ "description": "2FA session ID from login response"
2666
+ },
2667
+ "backup_code": {
2668
+ "type": "string",
2669
+ "minLength": 8,
2670
+ "description": "8-character backup recovery code",
2671
+ "maxLength": 8
2672
+ }
2673
+ },
2674
+ "required": [
2675
+ "backup_code",
2676
+ "session_id"
2677
+ ]
2678
+ },
2679
+ "VerifyRequest": {
2680
+ "type": "object",
2681
+ "description": "Serializer for TOTP code verification during login.",
2682
+ "properties": {
2683
+ "session_id": {
2684
+ "type": "string",
2685
+ "format": "uuid",
2686
+ "description": "2FA session ID from login response"
2687
+ },
2688
+ "code": {
2689
+ "type": "string",
2690
+ "minLength": 6,
2691
+ "description": "6-digit TOTP code from authenticator app",
2692
+ "maxLength": 6
2693
+ }
2694
+ },
2695
+ "required": [
2696
+ "code",
2697
+ "session_id"
2698
+ ]
2699
+ },
2700
+ "VerifyResponse": {
2701
+ "type": "object",
2702
+ "description": "Response serializer for successful 2FA verification.",
2703
+ "properties": {
2704
+ "message": {
2705
+ "type": "string"
2706
+ },
2707
+ "access_token": {
2708
+ "type": "string",
2709
+ "description": "JWT access token"
2710
+ },
2711
+ "refresh_token": {
2712
+ "type": "string",
2713
+ "description": "JWT refresh token"
2714
+ },
2715
+ "user": {
2716
+ "allOf": [
2717
+ {
2718
+ "$ref": "#/components/schemas/TotpVerifyUser"
2719
+ }
2720
+ ],
2721
+ "description": "User profile data"
2722
+ },
2723
+ "remaining_backup_codes": {
2724
+ "type": "integer",
2725
+ "description": "Number of remaining backup codes (if backup code was used)"
2726
+ },
2727
+ "warning": {
2728
+ "type": "string",
2729
+ "description": "Warning message (e.g., low backup codes)"
2730
+ }
2731
+ },
2732
+ "required": [
2733
+ "access_token",
2734
+ "message",
2735
+ "refresh_token",
2736
+ "user"
2737
+ ]
2738
+ },
2739
+ "cfg_accounts_oauth_connections_response_200_AutoRef": {
2740
+ "type": "array",
2741
+ "items": {
2742
+ "$ref": "#/components/schemas/OAuthConnection"
2743
+ }
2744
+ },
2745
+ "cfg_accounts_oauth_disconnect_response_200_AutoRef": {
2746
+ "type": "object",
2747
+ "properties": {
2748
+ "message": {
2749
+ "type": "string"
2750
+ }
2751
+ }
2752
+ },
2753
+ "cfg_totp_disable_response_200_AutoRef": {
2754
+ "description": "2FA disabled successfully"
2755
+ }
2756
+ },
2757
+ "securitySchemes": {
2758
+ "apiKeyAuth": {
2759
+ "type": "apiKey",
2760
+ "in": "header",
2761
+ "name": "X-API-Key"
2762
+ },
2763
+ "basicAuth": {
2764
+ "type": "http",
2765
+ "scheme": "basic"
2766
+ },
2767
+ "cookieAuth": {
2768
+ "type": "apiKey",
2769
+ "in": "cookie",
2770
+ "name": "sessionid"
2771
+ },
2772
+ "jwtAuth": {
2773
+ "type": "http",
2774
+ "scheme": "bearer",
2775
+ "bearerFormat": "JWT"
2776
+ },
2777
+ "jwtAuthWithLastLogin": {
2778
+ "type": "http",
2779
+ "scheme": "bearer",
2780
+ "bearerFormat": "JWT"
2781
+ }
2782
+ }
2783
+ },
2784
+ "servers": [
2785
+ {
2786
+ "url": "http://localhost:8000"
2787
+ }
2788
+ ]
2789
+ }