@idelio/contracts 0.1.0-beta.0 → 0.1.0-beta.1

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.
@@ -22,7 +22,9 @@ paths:
22
22
  /me:
23
23
  get:
24
24
  operationId: getMe
25
- summary: Return the authenticated user, their workspace and effective role.
25
+ summary: Get the current user
26
+ description: >-
27
+ Return the authenticated user, their workspace and effective role.
26
28
  responses:
27
29
  "200":
28
30
  description: User + workspace context
@@ -32,8 +34,10 @@ paths:
32
34
  /me/onboarding:
33
35
  post:
34
36
  operationId: completeOnboarding
35
- summary: Record that the authenticated membership finished onboarding.
37
+ summary: Complete onboarding
36
38
  description: >-
39
+ Record that the authenticated membership finished onboarding.
40
+
37
41
  Idempotent. A repeat returns the stored timestamp rather than moving it,
38
42
  so a retry or a second tab cannot rewrite when a user was onboarded.
39
43
  Takes no request body - the only fact is that it happened, and the
@@ -53,11 +57,11 @@ paths:
53
57
  description: Authenticated with an API key, which has no membership.
54
58
  content:
55
59
  application/json:
56
- schema: { $ref: "#/components/schemas/Error" }
60
+ schema: { $ref: "#/components/schemas/ErrorEnvelope" }
57
61
  /workspace:
58
62
  get:
59
63
  operationId: getWorkspace
60
- summary: Retrieve the current workspace.
64
+ summary: Get the workspace
61
65
  responses:
62
66
  "200":
63
67
  description: Workspace object
@@ -74,9 +78,12 @@ paths:
74
78
  "429": { $ref: "#/components/responses/RateLimited" }
75
79
  patch:
76
80
  operationId: updateWorkspace
77
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
78
81
  security: [{ bearerAuth: [] }]
79
- summary: Update workspace name and settings.
82
+ summary: Update the workspace
83
+ description: >-
84
+ Update workspace name and settings.
85
+
86
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
80
87
  parameters:
81
88
  - name: Idempotency-Key
82
89
  in: header
@@ -105,7 +112,7 @@ paths:
105
112
  /workspace/members:
106
113
  get:
107
114
  operationId: listMembers
108
- summary: List members and their roles.
115
+ summary: List members
109
116
  parameters:
110
117
  - { name: cursor, in: query, schema: { type: string } }
111
118
  - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 20 } }
@@ -130,9 +137,15 @@ paths:
130
137
  /workspace/invitations:
131
138
  post:
132
139
  operationId: inviteMember
133
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
140
+ # Team workspaces are phase 6: kept out of the published reference
141
+ # until the app can manage members (apps/docs drops x-internal).
142
+ x-internal: true
134
143
  security: [{ bearerAuth: [] }]
135
- summary: Invite a user by email with a role.
144
+ summary: Invite a member
145
+ description: >-
146
+ Invite a user by email with a role.
147
+
148
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
136
149
  parameters:
137
150
  - name: Idempotency-Key
138
151
  in: header
@@ -167,9 +180,12 @@ paths:
167
180
  /workspace/members/{userId}:
168
181
  patch:
169
182
  operationId: changeMemberRole
183
+ # Team workspaces are phase 6: kept out of the published reference
184
+ # until the app can manage members (apps/docs drops x-internal).
185
+ x-internal: true
170
186
  description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
171
187
  security: [{ bearerAuth: [] }]
172
- summary: Change a member's role.
188
+ summary: Change a member's role
173
189
  parameters:
174
190
  - { name: userId, in: path, required: true, schema: { type: string } }
175
191
  requestBody:
@@ -196,9 +212,12 @@ paths:
196
212
  "429": { $ref: "#/components/responses/RateLimited" }
197
213
  delete:
198
214
  operationId: removeMember
215
+ # Team workspaces are phase 6: kept out of the published reference
216
+ # until the app can manage members (apps/docs drops x-internal).
217
+ x-internal: true
199
218
  description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
200
219
  security: [{ bearerAuth: [] }]
201
- summary: Remove a member from the workspace.
220
+ summary: Remove a member
202
221
  parameters:
203
222
  - { name: userId, in: path, required: true, schema: { type: string } }
204
223
  responses:
@@ -209,7 +228,7 @@ paths:
209
228
  /brands:
210
229
  get:
211
230
  operationId: listBrands
212
- summary: List brands in the workspace.
231
+ summary: List brands
213
232
  parameters:
214
233
  - { name: status, in: query, schema: { type: string, enum: [draft, generating, ready, failed] } }
215
234
  - { name: q, in: query, schema: { type: string } }
@@ -235,7 +254,10 @@ paths:
235
254
  "429": { $ref: "#/components/responses/RateLimited" }
236
255
  post:
237
256
  operationId: createBrand
238
- summary: Generate a new brand from a prompt or template (reserves credits, starts a durable workflow).
257
+ summary: Create a brand
258
+ description: >-
259
+ Generate a new brand from a prompt or template (reserves credits, starts
260
+ a durable workflow).
239
261
  parameters:
240
262
  - name: Idempotency-Key
241
263
  in: header
@@ -268,7 +290,10 @@ paths:
268
290
  /brands/surprise:
269
291
  post:
270
292
  operationId: surpriseBrief
271
- summary: Generate a random brand idea to seed the creator's Describe step ("Surprise me") - free, not persisted.
293
+ summary: Generate a random brand idea
294
+ description: >-
295
+ Generate a random brand idea to seed the creator's Describe step
296
+ ("Surprise me") - free, not persisted.
272
297
  responses:
273
298
  "200":
274
299
  description: A freshly generated random brief
@@ -279,8 +304,10 @@ paths:
279
304
  /brands/directions:
280
305
  post:
281
306
  operationId: brandCreativeDirections
282
- summary: Shortlist creative directions against a brief - free, not persisted.
307
+ summary: Shortlist creative directions
283
308
  description: >-
309
+ Shortlist creative directions against a brief - free, not persisted.
310
+
284
311
  Ranks the palette, typography and logo catalogs against the founder's
285
312
  own description so the Customize step suggests directions that suit
286
313
  their brand instead of a fixed order. Returns catalog ids only, never
@@ -306,8 +333,11 @@ paths:
306
333
  /brands/names:
307
334
  post:
308
335
  operationId: brandNameIdeas
309
- summary: Generate brand name ideas for the creator's name generator - free, not persisted.
336
+ summary: Generate brand name ideas
310
337
  description: >-
338
+ Generate brand name ideas for the creator's name generator - free, not
339
+ persisted.
340
+
311
341
  Returns six brand name candidates in the requested style, each with a
312
342
  one-line hint explaining why it works. Pass the founder's own keyword
313
343
  and description to keep the ideas about their actual business. Free
@@ -330,7 +360,9 @@ paths:
330
360
  /brands/{id}:
331
361
  get:
332
362
  operationId: getBrand
333
- summary: Retrieve a brand with its head version summary.
363
+ summary: Get a brand
364
+ description: >-
365
+ Retrieve a brand with its head version summary.
334
366
  parameters:
335
367
  - { name: id, in: path, required: true, schema: { type: string } }
336
368
  responses:
@@ -350,7 +382,9 @@ paths:
350
382
  "429": { $ref: "#/components/responses/RateLimited" }
351
383
  patch:
352
384
  operationId: updateBrand
353
- summary: Rename a brand, change its slug, or update generation locks.
385
+ summary: Update a brand
386
+ description: >-
387
+ Rename a brand, change its slug, or update generation locks.
354
388
  parameters:
355
389
  - { name: id, in: path, required: true, schema: { type: string } }
356
390
  requestBody:
@@ -377,7 +411,9 @@ paths:
377
411
  "429": { $ref: "#/components/responses/RateLimited" }
378
412
  delete:
379
413
  operationId: deleteBrand
380
- summary: Soft-delete a brand (never hard-deleted).
414
+ summary: Delete a brand
415
+ description: >-
416
+ Soft-delete a brand (never hard-deleted).
381
417
  parameters:
382
418
  - { name: id, in: path, required: true, schema: { type: string } }
383
419
  responses:
@@ -387,7 +423,7 @@ paths:
387
423
  /brands/{id}/assets:
388
424
  get:
389
425
  operationId: listBrandAssets
390
- summary: List assets belonging to a brand.
426
+ summary: List a brand's assets
391
427
  parameters:
392
428
  - { name: id, in: path, required: true, schema: { type: string } }
393
429
  - { name: kind, in: query, schema: { type: string } }
@@ -419,7 +455,14 @@ paths:
419
455
  "429": { $ref: "#/components/responses/RateLimited" }
420
456
  post:
421
457
  operationId: expandBrand
422
- summary: Expand a brand - generate additional assets from its frozen head DNA (every asset kind except logo, which has its own generate/approve path). custom_image requires custom_image_prompt and is never combined with other kinds in the same request; color_palette/font_pairing are likewise never combined with any other kind. mockup and hero_image are studio/elite only - flash has no model route for them.
458
+ summary: Expand a brand
459
+ description: >-
460
+ Expand a brand - generate additional assets from its frozen head DNA
461
+ (every asset kind except logo, which has its own generate/approve path).
462
+ custom_image requires custom_image_prompt and is never combined with
463
+ other kinds in the same request; color_palette/font_pairing are likewise
464
+ never combined with any other kind. mockup and hero_image are
465
+ studio/elite only - flash has no model route for them.
423
466
  parameters:
424
467
  - { name: id, in: path, required: true, schema: { type: string } }
425
468
  - { name: Idempotency-Key, in: header, required: true, schema: { type: string } }
@@ -446,7 +489,10 @@ paths:
446
489
  /brands/{id}/refine:
447
490
  post:
448
491
  operationId: refineBrandDna
449
- summary: Free-text Creative Director chat edit to the brand's DNA (strategy/palette/typography); forks a new BrandVersion.
492
+ summary: Refine a brand's DNA
493
+ description: >-
494
+ Free-text Creative Director chat edit to the brand's DNA
495
+ (strategy/palette/typography); forks a new BrandVersion.
450
496
  parameters:
451
497
  - { name: id, in: path, required: true, schema: { type: string } }
452
498
  - { name: Idempotency-Key, in: header, required: true, schema: { type: string } }
@@ -473,7 +519,9 @@ paths:
473
519
  /brands/{id}/logo:
474
520
  get:
475
521
  operationId: getBrandLogo
476
- summary: Redirect to the brand's logo file, as PNG or SVG.
522
+ summary: Get a brand's logo
523
+ description: >-
524
+ Redirect to the brand's logo file, as PNG or SVG.
477
525
  parameters:
478
526
  - { name: id, in: path, required: true, schema: { type: string } }
479
527
  - { name: format, in: query, schema: { type: string, enum: [png, svg], default: png } }
@@ -506,7 +554,9 @@ paths:
506
554
  /brands/{id}/palette:
507
555
  get:
508
556
  operationId: getBrandPalette
509
- summary: Export the palette as design tokens (inline).
557
+ summary: Get a brand's palette
558
+ description: >-
559
+ Export the palette as design tokens (inline).
510
560
  parameters:
511
561
  - { name: id, in: path, required: true, schema: { type: string } }
512
562
  - { name: format, in: query, schema: { type: string, enum: [json, css], default: json } }
@@ -526,7 +576,9 @@ paths:
526
576
  /brands/{id}/tokens:
527
577
  get:
528
578
  operationId: getBrandTokens
529
- summary: Full W3C design-token document (inline).
579
+ summary: Get a brand's design tokens
580
+ description: >-
581
+ Full W3C design-token document (inline).
530
582
  parameters:
531
583
  - { name: id, in: path, required: true, schema: { type: string } }
532
584
  responses:
@@ -543,7 +595,9 @@ paths:
543
595
  /brands/{id}/dna:
544
596
  get:
545
597
  operationId: getBrandDna
546
- summary: The frozen creative genome (brief + strategy) the brand reads from.
598
+ summary: Get a brand's DNA
599
+ description: >-
600
+ The frozen creative genome (brief + strategy) the brand reads from.
547
601
  parameters:
548
602
  - { name: id, in: path, required: true, schema: { type: string } }
549
603
  responses:
@@ -560,7 +614,9 @@ paths:
560
614
  /brands/{id}/versions:
561
615
  get:
562
616
  operationId: listBrandVersions
563
- summary: Version history (git-commit semantics) for the brand, newest first.
617
+ summary: List a brand's versions
618
+ description: >-
619
+ Version history (git-commit semantics) for the brand, newest first.
564
620
  parameters:
565
621
  - { name: id, in: path, required: true, schema: { type: string } }
566
622
  responses:
@@ -578,7 +634,10 @@ paths:
578
634
  /brands/{id}/suggestions:
579
635
  get:
580
636
  operationId: getBrandSuggestions
581
- summary: This week's Creative-Director suggestions for the dashboard - computed weekly per brand, cached.
637
+ summary: List a brand's suggestions
638
+ description: >-
639
+ This week's Creative-Director suggestions for the dashboard - computed
640
+ weekly per brand, cached.
582
641
  parameters:
583
642
  - { name: id, in: path, required: true, schema: { type: string } }
584
643
  responses:
@@ -597,7 +656,10 @@ paths:
597
656
  /brands/{id}/suggestions/{kind}/generate:
598
657
  post:
599
658
  operationId: generateBrandSuggestion
600
- summary: Start generating one of this week's suggestions - delegates entirely to POST /brands/{id}/assets.
659
+ summary: Generate a suggestion
660
+ description: >-
661
+ Start generating one of this week's suggestions - delegates entirely to
662
+ POST /brands/{id}/assets.
601
663
  parameters:
602
664
  - { name: id, in: path, required: true, schema: { type: string } }
603
665
  - { name: kind, in: path, required: true, schema: { type: string } }
@@ -616,7 +678,13 @@ paths:
616
678
  /suggestions:
617
679
  get:
618
680
  operationId: listSuggestions
619
- summary: The dashboard's cross-brand suggestions - up to 3 items from the 3 most recently active ready brands, mixed round-robin. Never 404/409; a workspace with nothing to suggest gets an empty list. A brand that owns every catalogue kind it can be offered contributes custom asset ideas (kind custom_image) instead.
681
+ summary: List suggestions
682
+ description: >-
683
+ The dashboard's cross-brand suggestions - up to 3 items from the 3 most
684
+ recently active ready brands, mixed round-robin. Never 404/409; a
685
+ workspace with nothing to suggest gets an empty list. A brand that owns
686
+ every catalogue kind it can be offered contributes custom asset ideas
687
+ (kind custom_image) instead.
620
688
  responses:
621
689
  "200":
622
690
  description: Suggestions
@@ -633,7 +701,11 @@ paths:
633
701
  /brands/{id}/versions/restore:
634
702
  post:
635
703
  operationId: restoreBrandVersion
636
- summary: Restore a prior brand DNA version as the current version (creates a new version, like git revert - nothing is edited in place). Asset versions are untouched.
704
+ summary: Restore a brand version
705
+ description: >-
706
+ Restore a prior brand DNA version as the current version (creates a new
707
+ version, like git revert - nothing is edited in place). Asset versions
708
+ are untouched.
637
709
  parameters:
638
710
  - { name: id, in: path, required: true, schema: { type: string } }
639
711
  - { name: Idempotency-Key, in: header, required: true, schema: { type: string } }
@@ -655,7 +727,9 @@ paths:
655
727
  /brands/{id}/export:
656
728
  get:
657
729
  operationId: exportBrandKit
658
- summary: Package the full brand kit as a ZIP (async, always repackaged fresh).
730
+ summary: Export a brand kit
731
+ description: >-
732
+ Package the full brand kit as a ZIP (async, always repackaged fresh).
659
733
  parameters:
660
734
  - { name: id, in: path, required: true, schema: { type: string } }
661
735
  - { name: include, in: query, schema: { type: string }, description: "Comma-separated asset kinds, e.g. logo,color_palette. Omit for all." }
@@ -670,7 +744,11 @@ paths:
670
744
  /brands/{id}/bundle:
671
745
  get:
672
746
  operationId: getBrandBundle
673
- summary: Repo-ready package (tokens, CSS/framework config, logo/favicon) for a target toolchain - deterministic per brand+target; 302 if already built, 202 otherwise.
747
+ summary: Get a brand bundle
748
+ description: >-
749
+ Repo-ready package (tokens, CSS/framework config, logo/favicon) for a
750
+ target toolchain - deterministic per brand+target; 302 if already built,
751
+ 202 otherwise.
674
752
  parameters:
675
753
  - { name: id, in: path, required: true, schema: { type: string } }
676
754
  - { name: target, in: query, schema: { type: string, enum: [tokens, next, vite, expo], default: tokens } }
@@ -697,7 +775,7 @@ paths:
697
775
  /brands/{id}/guidelines:
698
776
  get:
699
777
  operationId: getBrandGuidelines
700
- summary: Download the brand guidelines PDF.
778
+ summary: Get the brand guidelines PDF
701
779
  parameters:
702
780
  - { name: id, in: path, required: true, schema: { type: string } }
703
781
  responses:
@@ -707,7 +785,7 @@ paths:
707
785
  /jobs:
708
786
  get:
709
787
  operationId: listJobs
710
- summary: List generation jobs in the workspace.
788
+ summary: List jobs
711
789
  parameters:
712
790
  - { name: status, in: query, schema: { type: string, enum: [queued, running, completed, failed, canceled] } }
713
791
  - { name: brand_id, in: query, schema: { type: string } }
@@ -733,7 +811,9 @@ paths:
733
811
  /jobs/{id}:
734
812
  get:
735
813
  operationId: getJob
736
- summary: Get job status and per-step progress.
814
+ summary: Get a job
815
+ description: >-
816
+ Get job status and per-step progress.
737
817
  parameters:
738
818
  - { name: id, in: path, required: true, schema: { type: string } }
739
819
  responses:
@@ -751,8 +831,10 @@ paths:
751
831
  /jobs/{id}/events:
752
832
  get:
753
833
  operationId: streamJobEvents
754
- summary: Subscribe to the job's SSE event stream (text/event-stream).
834
+ summary: Stream job events
755
835
  description: >-
836
+ Subscribe to the job's SSE event stream (text/event-stream).
837
+
756
838
  Emits `stream.connected`, then `job.step.started`/`job.step.completed`
757
839
  (skipped steps carry `"skipped": true`), interleaved with `asset.ready`
758
840
  (payload `{asset_id, kind}`) whenever a generated asset becomes
@@ -775,12 +857,18 @@ paths:
775
857
  - { name: id, in: path, required: true, schema: { type: string } }
776
858
  - { name: Last-Event-ID, in: header, schema: { type: string } }
777
859
  responses:
778
- "200": { description: text/event-stream }
860
+ "200":
861
+ description: Server-sent events stream of job progress (asset.ready, job.step.*, job.completed, job.failed).
862
+ content:
863
+ text/event-stream:
864
+ schema: { type: string }
779
865
  "404": { description: Not found }
780
866
  /jobs/{id}/cancel:
781
867
  post:
782
868
  operationId: cancelJob
783
- summary: Cancel a running job; the reservation is refunded on the ledger.
869
+ summary: Cancel a job
870
+ description: >-
871
+ Cancel a running job; the reservation is refunded on the ledger.
784
872
  parameters:
785
873
  - { name: id, in: path, required: true, schema: { type: string } }
786
874
  responses:
@@ -799,7 +887,9 @@ paths:
799
887
  /jobs/{id}/logo-selection:
800
888
  post:
801
889
  operationId: selectLogoConcept
802
- summary: Approve one of the generated logo concepts; resumes the paused workflow.
890
+ summary: Select a logo concept
891
+ description: >-
892
+ Approve one of the generated logo concepts; resumes the paused workflow.
803
893
  parameters:
804
894
  - { name: id, in: path, required: true, schema: { type: string } }
805
895
  requestBody:
@@ -826,11 +916,12 @@ paths:
826
916
  /jobs/{id}/logo-concepts/{assetVersionId}/preview:
827
917
  get:
828
918
  operationId: previewLogoConceptLockup
829
- summary: >-
919
+ summary: Preview a logo concept lockup
920
+ description: >-
830
921
  A free, instant redirect to a preview render of one logo concept in a
831
- different arrangement and/or font - never persisted, never charged,
832
- no Idempotency-Key. Query params are both optional; omitting one
833
- previews with that concept's own current value.
922
+ different arrangement and/or font - never persisted, never charged, no
923
+ Idempotency-Key. Query params are both optional; omitting one previews
924
+ with that concept's own current value.
834
925
  parameters:
835
926
  - { name: id, in: path, required: true, schema: { type: string } }
836
927
  - { name: assetVersionId, in: path, required: true, schema: { type: string } }
@@ -856,7 +947,8 @@ paths:
856
947
  /jobs/{id}/logo-concepts/{assetVersionId}/palette:
857
948
  get:
858
949
  operationId: getLogoConceptPalette
859
- summary: >-
950
+ summary: Get a logo concept's palette
951
+ description: >-
860
952
  The brand's generated DNA palette tokens, for the picker's colour
861
953
  override swatches - free, read-only.
862
954
  parameters:
@@ -872,7 +964,11 @@ paths:
872
964
  /jobs/{id}/assets/{kind}/retry:
873
965
  post:
874
966
  operationId: retryJobAsset
875
- summary: Retry one failed or credit-blocked asset within an in-progress generation job, for free.
967
+ summary: Retry a failed asset
968
+ description: >-
969
+ Retry one failed or credit-blocked asset within an in-progress
970
+ generation job. The failed attempt was already refunded, so the
971
+ asset's price is charged once, and only if the retry succeeds.
876
972
  parameters:
877
973
  - { name: id, in: path, required: true, schema: { type: string } }
878
974
  - { name: kind, in: path, required: true, schema: { type: string } }
@@ -893,7 +989,9 @@ paths:
893
989
  /assets/{id}:
894
990
  get:
895
991
  operationId: getAsset
896
- summary: Retrieve a single asset with its current version.
992
+ summary: Get an asset
993
+ description: >-
994
+ Retrieve a single asset with its current version.
897
995
  parameters:
898
996
  - { name: id, in: path, required: true, schema: { type: string } }
899
997
  responses:
@@ -913,7 +1011,9 @@ paths:
913
1011
  "429": { $ref: "#/components/responses/RateLimited" }
914
1012
  delete:
915
1013
  operationId: deleteAsset
916
- summary: Remove an asset from the brand library.
1014
+ summary: Delete an asset
1015
+ description: >-
1016
+ Remove an asset from the brand library.
917
1017
  parameters:
918
1018
  - { name: id, in: path, required: true, schema: { type: string } }
919
1019
  responses:
@@ -923,8 +1023,10 @@ paths:
923
1023
  /assets/{id}/qa:
924
1024
  get:
925
1025
  operationId: getAssetQaReport
926
- summary: Get the Pixel Check QA report (per-dimension scores).
1026
+ summary: Get an asset's QA report
927
1027
  description: >-
1028
+ Get the Pixel Check QA report (per-dimension scores).
1029
+
928
1030
  Supported for API consumers regardless of what the Idelio app UI
929
1031
  currently renders. No in-app screen shows this report today - see
930
1032
  QaReport's own description for why - but the endpoint and the data
@@ -953,9 +1055,10 @@ paths:
953
1055
  /assets/{id}/download:
954
1056
  get:
955
1057
  operationId: downloadAsset
956
- summary: Redirect to a time-limited signed CDN URL, or return it as JSON
957
- with `redirect=false`.
1058
+ summary: Download an asset
958
1059
  description: |
1060
+ Redirect to a time-limited signed CDN URL, or return it as JSON
1061
+
959
1062
  `redirect=false` returns `{ url }` as JSON instead of a 302. A
960
1063
  browser `fetch()` that then requests that URL directly - rather than
961
1064
  following our own 302 to it - keeps its real Origin header on the
@@ -1000,10 +1103,10 @@ paths:
1000
1103
  /assets/{id}/versions/{versionId}/download:
1001
1104
  get:
1002
1105
  operationId: downloadAssetVersion
1003
- summary: Redirect to a time-limited signed CDN URL for a SPECIFIC version - unlike
1004
- /assets/{id}/download (always the current version), this previews any version of
1005
- this asset, selected or not (e.g. a logo concept awaiting the human pick).
1006
- `redirect=false` returns it as JSON instead - see /assets/{id}/download.
1106
+ summary: Download an asset version
1107
+ description: >-
1108
+ Redirect to a time-limited signed CDN URL for a SPECIFIC version -
1109
+ unlike
1007
1110
  parameters:
1008
1111
  - { name: id, in: path, required: true, schema: { type: string } }
1009
1112
  - { name: versionId, in: path, required: true, schema: { type: string } }
@@ -1040,11 +1143,9 @@ paths:
1040
1143
  /assets/{id}/download-all:
1041
1144
  get:
1042
1145
  operationId: downloadAllAssetFiles
1043
- summary: Zip every file of the current version together and redirect to a
1044
- time-limited signed CDN URL for the ZIP - unlike /assets/{id}/download
1045
- (one file, chosen by `format`), this bundles all of them, one entry
1046
- per file, so "Download all files" stops silently picking one.
1047
- `redirect=false` returns it as JSON instead - see /assets/{id}/download.
1146
+ summary: Download all asset files
1147
+ description: >-
1148
+ Zip every file of the current version together and redirect to a
1048
1149
  parameters:
1049
1150
  - { name: id, in: path, required: true, schema: { type: string } }
1050
1151
  - { name: redirect, in: query, schema: { type: boolean, default: true } }
@@ -1064,7 +1165,10 @@ paths:
1064
1165
  /assets/{id}/versions:
1065
1166
  get:
1066
1167
  operationId: listAssetVersions
1067
- summary: List an asset's versions (e.g. logo concepts awaiting selection, or version history).
1168
+ summary: List an asset's versions
1169
+ description: >-
1170
+ List an asset's versions (e.g. logo concepts awaiting selection, or
1171
+ version history).
1068
1172
  parameters:
1069
1173
  - { name: id, in: path, required: true, schema: { type: string } }
1070
1174
  responses:
@@ -1089,7 +1193,10 @@ paths:
1089
1193
  /assets/{id}/regenerate:
1090
1194
  post:
1091
1195
  operationId: regenerateAsset
1092
- summary: Regenerate an asset's concepts (2 free per asset, then 25% of its base price).
1196
+ summary: Regenerate an asset
1197
+ description: >-
1198
+ Regenerate an asset's concepts (2 free per asset, then 25% of its base
1199
+ price).
1093
1200
  parameters:
1094
1201
  - { name: id, in: path, required: true, schema: { type: string } }
1095
1202
  - { name: Idempotency-Key, in: header, required: true, schema: { type: string } }
@@ -1112,8 +1219,11 @@ paths:
1112
1219
  /assets/{id}/refine:
1113
1220
  post:
1114
1221
  operationId: refineAsset
1115
- summary: Refine an asset - a free-text instruction, or font/accent/style overrides for `logo_wordmark`.
1222
+ summary: Refine an asset
1116
1223
  description: >-
1224
+ Refine an asset - a free-text instruction, or font/accent/style
1225
+ overrides for `logo_wordmark`.
1226
+
1117
1227
  For `logo`, sends a free-text instruction. For `logo_wordmark`, sends
1118
1228
  either a free-text instruction or structured treatment overrides (font
1119
1229
  family, accent color, style seed) - an instruction is resolved to
@@ -1152,7 +1262,9 @@ paths:
1152
1262
  /assets/{id}/logo-treatment:
1153
1263
  get:
1154
1264
  operationId: getLogoTreatment
1155
- summary: Read a wordmark/logo's current treatment (font, accent, style).
1265
+ summary: Get a logo treatment
1266
+ description: >-
1267
+ Read a wordmark/logo's current treatment (font, accent, style).
1156
1268
  tags: [Assets]
1157
1269
  security: [{ bearerAuth: [] }, { apiKeyAuth: [] }]
1158
1270
  parameters:
@@ -1164,11 +1276,12 @@ paths:
1164
1276
  application/json:
1165
1277
  schema: { $ref: "#/components/schemas/LogoTreatment" }
1166
1278
  "404":
1167
- $ref: "#/components/responses/NotFound"
1279
+ description: Not found
1168
1280
  /assets/{id}/logo-treatment/preview:
1169
1281
  get:
1170
1282
  operationId: previewLogoTreatment
1171
- summary: >-
1283
+ summary: Preview a logo treatment
1284
+ description: >-
1172
1285
  A free, instant redirect to a preview render of a wordmark with
1173
1286
  different font/accent/style - never persisted, never charged, no
1174
1287
  Idempotency-Key. Query params are optional; omitting one previews with
@@ -1196,7 +1309,7 @@ paths:
1196
1309
  "302":
1197
1310
  description: Redirect to a signed CDN URL for the rendered preview (default).
1198
1311
  "404":
1199
- $ref: "#/components/responses/NotFound"
1312
+ description: Not found
1200
1313
  "422":
1201
1314
  description: Invalid query parameters.
1202
1315
  "503":
@@ -1204,7 +1317,10 @@ paths:
1204
1317
  /assets/{id}/variations:
1205
1318
  post:
1206
1319
  operationId: variationsAsset
1207
- summary: Generate a curated preset variation of a logo (always logo-kind, counts against the 2-free-regens budget).
1320
+ summary: Generate a logo variation
1321
+ description: >-
1322
+ Generate a curated preset variation of a logo (always logo-kind, counts
1323
+ against the 2-free-regens budget).
1208
1324
  parameters:
1209
1325
  - { name: id, in: path, required: true, schema: { type: string } }
1210
1326
  - { name: Idempotency-Key, in: header, required: true, schema: { type: string } }
@@ -1232,7 +1348,10 @@ paths:
1232
1348
  /assets/{id}/restore:
1233
1349
  post:
1234
1350
  operationId: restoreAsset
1235
- summary: Restore a prior asset version as the current version (creates a new version, like git revert - nothing is edited in place).
1351
+ summary: Restore an asset version
1352
+ description: >-
1353
+ Restore a prior asset version as the current version (creates a new
1354
+ version, like git revert - nothing is edited in place).
1236
1355
  parameters:
1237
1356
  - { name: id, in: path, required: true, schema: { type: string } }
1238
1357
  - { name: Idempotency-Key, in: header, required: true, schema: { type: string } }
@@ -1257,7 +1376,9 @@ paths:
1257
1376
  /credits/balance:
1258
1377
  get:
1259
1378
  operationId: getCreditBalance
1260
- summary: Get the current balance, plan and renewal date.
1379
+ summary: Get the credit balance
1380
+ description: >-
1381
+ Get the current balance, plan and renewal date.
1261
1382
  responses:
1262
1383
  "200":
1263
1384
  description: Balance summary
@@ -1267,7 +1388,9 @@ paths:
1267
1388
  /credits/ledger:
1268
1389
  get:
1269
1390
  operationId: listCreditLedger
1270
- summary: List the workspace's append-only credit ledger entries.
1391
+ summary: List ledger entries
1392
+ description: >-
1393
+ List the workspace's append-only credit ledger entries.
1271
1394
  parameters:
1272
1395
  - { name: reason, in: query, schema: { type: string, enum: [grant, purchase, reserve, settle, refund, clawback] } }
1273
1396
  - { name: cursor, in: query, schema: { type: string } }
@@ -1281,7 +1404,9 @@ paths:
1281
1404
  /ai-teams:
1282
1405
  get:
1283
1406
  operationId: listAiTeams
1284
- summary: List the AI team tiers and their credit multipliers.
1407
+ summary: List AI teams
1408
+ description: >-
1409
+ List the AI team tiers and their credit multipliers.
1285
1410
  responses:
1286
1411
  "200":
1287
1412
  description: AI team tiers
@@ -1296,7 +1421,9 @@ paths:
1296
1421
  /healthz:
1297
1422
  get:
1298
1423
  operationId: healthz
1299
- summary: Liveness and dependency health probe (unversioned in prod routing).
1424
+ summary: Check health
1425
+ description: >-
1426
+ Liveness and dependency health probe (unversioned in prod routing).
1300
1427
  security: []
1301
1428
  responses:
1302
1429
  "200": { description: Healthy }
@@ -1304,7 +1431,9 @@ paths:
1304
1431
  /waitlist:
1305
1432
  post:
1306
1433
  operationId: joinWaitlist
1307
- summary: Join the public waitlist. No authentication required.
1434
+ summary: Join the waitlist
1435
+ description: >-
1436
+ Join the public waitlist. No authentication required.
1308
1437
  security: []
1309
1438
  requestBody:
1310
1439
  required: true
@@ -1327,14 +1456,15 @@ paths:
1327
1456
  /consent:
1328
1457
  post:
1329
1458
  operationId: recordConsent
1330
- summary: >-
1459
+ summary: Record consent
1460
+ description: >-
1331
1461
  Record proof of cookie/privacy/Terms consent, or of what a checkout
1332
1462
  confirmation step disclosed. Cookie and privacy records need no
1333
- authentication (client_id is the caller's anonymous/session
1334
- identifier), and a purchase disclosure is sent with a session so it
1335
- attributes to the workspace. A terms_acceptance REQUIRES a session and
1336
- is refused with 401 without one: a record scoped to no workspace could
1337
- never be read back, so an anonymous one would evidence nothing.
1463
+ authentication (client_id is the caller's anonymous/session identifier),
1464
+ and a purchase disclosure is sent with a session so it attributes to the
1465
+ workspace. A terms_acceptance REQUIRES a session and is refused with 401
1466
+ without one: a record scoped to no workspace could never be read back,
1467
+ so an anonymous one would evidence nothing.
1338
1468
  security: []
1339
1469
  requestBody:
1340
1470
  required: true
@@ -1371,7 +1501,9 @@ paths:
1371
1501
  /api-keys:
1372
1502
  get:
1373
1503
  operationId: listApiKeys
1374
- summary: List the workspace's API keys (non-revoked only).
1504
+ summary: List API keys
1505
+ description: >-
1506
+ List the workspace's API keys (non-revoked only).
1375
1507
  responses:
1376
1508
  "200":
1377
1509
  description: API keys
@@ -1390,9 +1522,12 @@ paths:
1390
1522
  "429": { $ref: "#/components/responses/RateLimited" }
1391
1523
  post:
1392
1524
  operationId: createApiKey
1393
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1394
1525
  security: [{ bearerAuth: [] }]
1395
- summary: Mint a new API key. The secret is shown only in this response.
1526
+ summary: Create an API key
1527
+ description: >-
1528
+ Mint a new API key. The secret is shown only in this response.
1529
+
1530
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1396
1531
  requestBody:
1397
1532
  required: true
1398
1533
  content:
@@ -1414,9 +1549,12 @@ paths:
1414
1549
  /api-keys/{id}:
1415
1550
  delete:
1416
1551
  operationId: revokeApiKey
1417
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1418
1552
  security: [{ bearerAuth: [] }]
1419
- summary: Revoke an API key immediately.
1553
+ summary: Revoke an API key
1554
+ description: >-
1555
+ Revoke an API key immediately.
1556
+
1557
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1420
1558
  parameters:
1421
1559
  - { name: id, in: path, required: true, schema: { type: string } }
1422
1560
  responses:
@@ -1427,7 +1565,9 @@ paths:
1427
1565
  /usage:
1428
1566
  get:
1429
1567
  operationId: getUsage
1430
- summary: Aggregate API-key usage for the workspace, bucketed by time.
1568
+ summary: Get API usage
1569
+ description: >-
1570
+ Aggregate API-key usage for the workspace, bucketed by time.
1431
1571
  parameters:
1432
1572
  - { name: from, in: query, schema: { type: string, format: date-time } }
1433
1573
  - { name: to, in: query, schema: { type: string, format: date-time } }
@@ -1441,7 +1581,10 @@ paths:
1441
1581
  /webhook-endpoints:
1442
1582
  get:
1443
1583
  operationId: listWebhookEndpoints
1444
- summary: List the workspace's outbound webhook endpoints (secrets never included).
1584
+ summary: List webhook endpoints
1585
+ description: >-
1586
+ List the workspace's outbound webhook endpoints (secrets never
1587
+ included).
1445
1588
  responses:
1446
1589
  "200":
1447
1590
  description: Webhook endpoints
@@ -1460,8 +1603,12 @@ paths:
1460
1603
  "429": { $ref: "#/components/responses/RateLimited" }
1461
1604
  post:
1462
1605
  operationId: createWebhookEndpoint
1463
- description: A session needs at least the admin role; an API key needs the `webhooks:write` scope.
1464
- summary: Register a new outbound webhook endpoint. The signing secret is shown only in this response.
1606
+ summary: Create a webhook endpoint
1607
+ description: >-
1608
+ Register a new outbound webhook endpoint. The signing secret is shown
1609
+ only in this response.
1610
+
1611
+ A session needs at least the admin role; an API key needs the `webhooks:write` scope.
1465
1612
  requestBody:
1466
1613
  required: true
1467
1614
  content:
@@ -1483,8 +1630,11 @@ paths:
1483
1630
  /webhook-endpoints/{id}:
1484
1631
  patch:
1485
1632
  operationId: updateWebhookEndpoint
1486
- description: A session needs at least the admin role; an API key needs the `webhooks:write` scope.
1487
- summary: Update an endpoint's subscribed events, or enable/disable it.
1633
+ summary: Update a webhook endpoint
1634
+ description: >-
1635
+ Update an endpoint's subscribed events, or enable/disable it.
1636
+
1637
+ A session needs at least the admin role; an API key needs the `webhooks:write` scope.
1488
1638
  parameters:
1489
1639
  - { name: id, in: path, required: true, schema: { type: string } }
1490
1640
  requestBody:
@@ -1513,9 +1663,9 @@ paths:
1513
1663
  operationId: deleteWebhookEndpoint
1514
1664
  description: >-
1515
1665
  A session needs at least the admin role; an API key needs the `webhooks:write` scope.
1516
- The endpoint stops receiving events at once, including retries of a delivery already in
1517
- flight, and every later call naming it answers 404.
1518
- summary: Remove a webhook endpoint.
1666
+ The endpoint stops receiving new events at once. A delivery already waiting on its retry
1667
+ schedule makes at most one more attempt, then stops. Every later call naming it answers 404.
1668
+ summary: Delete a webhook endpoint
1519
1669
  parameters:
1520
1670
  - { name: id, in: path, required: true, schema: { type: string } }
1521
1671
  responses:
@@ -1526,8 +1676,11 @@ paths:
1526
1676
  /webhook-endpoints/{id}/test:
1527
1677
  post:
1528
1678
  operationId: testWebhookEndpoint
1529
- description: A session needs at least the admin role; an API key needs the `webhooks:write` scope.
1530
- summary: Dispatch a synthetic test.ping event to the endpoint.
1679
+ summary: Test a webhook endpoint
1680
+ description: >-
1681
+ Dispatch a synthetic test.ping event to the endpoint.
1682
+
1683
+ A session needs at least the admin role; an API key needs the `webhooks:write` scope.
1531
1684
  parameters:
1532
1685
  - { name: id, in: path, required: true, schema: { type: string } }
1533
1686
  responses:
@@ -1546,15 +1699,47 @@ paths:
1546
1699
  "403": { description: Caller's role is below admin }
1547
1700
  "404": { description: No webhook endpoint with that id }
1548
1701
  "429": { $ref: "#/components/responses/RateLimited" }
1702
+ /webhook-endpoints/{id}/deliveries:
1703
+ get:
1704
+ operationId: listWebhookDeliveries
1705
+ summary: List an endpoint's deliveries
1706
+ description: >-
1707
+ The endpoint's recent deliveries, newest first, including test pings: what was
1708
+ sent, how many attempts it took, and the last HTTP status or error.
1709
+ parameters:
1710
+ - { name: id, in: path, required: true, schema: { type: string } }
1711
+ - { name: cursor, in: query, schema: { type: string } }
1712
+ - { name: limit, in: query, schema: { type: integer, minimum: 1, maximum: 100, default: 20 } }
1713
+ responses:
1714
+ "200":
1715
+ description: A page of deliveries
1716
+ headers:
1717
+ X-RateLimit-Limit: { $ref: "#/components/headers/RateLimitLimit" }
1718
+ X-RateLimit-Remaining: { $ref: "#/components/headers/RateLimitRemaining" }
1719
+ X-RateLimit-Reset: { $ref: "#/components/headers/RateLimitReset" }
1720
+ content:
1721
+ application/json:
1722
+ schema:
1723
+ type: object
1724
+ required: [data, next_cursor, has_more]
1725
+ properties:
1726
+ data:
1727
+ type: array
1728
+ items: { $ref: "#/components/schemas/WebhookDelivery" }
1729
+ next_cursor: { type: [string, "null"] }
1730
+ has_more: { type: boolean }
1731
+ "404": { description: No webhook endpoint with that id }
1732
+ "429": { $ref: "#/components/responses/RateLimited" }
1549
1733
  /webhooks/stripe:
1550
1734
  post:
1551
1735
  operationId: receiveStripeWebhook
1552
- summary: >-
1553
- Inbound Stripe event (checkout/invoice/subscription). HMAC-SHA256
1554
- signed via the Stripe-Signature header - not the same auth as the rest
1555
- of the API. Drives the credit ledger and workspace plan/entitlements.
1556
- Stripe is not Merchant of Record: SFER LABS LLC is the seller, so tax
1557
- and invoicing responsibility sits with us.
1736
+ summary: Receive a Stripe event
1737
+ description: >-
1738
+ Inbound Stripe event (checkout/invoice/subscription). HMAC-SHA256 signed
1739
+ via the Stripe-Signature header - not the same auth as the rest of the
1740
+ API. Drives the credit ledger and workspace plan/entitlements. Stripe is
1741
+ not Merchant of Record: SFER LABS LLC is the seller, so tax and
1742
+ invoicing responsibility sits with us.
1558
1743
  security: []
1559
1744
  requestBody:
1560
1745
  required: true
@@ -1579,11 +1764,12 @@ paths:
1579
1764
  /webhooks/clerk:
1580
1765
  post:
1581
1766
  operationId: receiveClerkWebhook
1582
- summary: >-
1767
+ summary: Receive a Clerk event
1768
+ description: >-
1583
1769
  Inbound Clerk lifecycle event (organization.deleted,
1584
- organizationMembership.deleted, ...). Verified via svix
1585
- (svix-id/svix-timestamp/svix-signature headers) - not the same auth
1586
- as the rest of the API.
1770
+ organizationMembership.deleted, ...). Verified via svix (svix-id/svix-
1771
+ timestamp/svix-signature headers) - not the same auth as the rest of the
1772
+ API.
1587
1773
  security: []
1588
1774
  requestBody:
1589
1775
  required: true
@@ -1607,9 +1793,12 @@ paths:
1607
1793
  /billing/subscription:
1608
1794
  get:
1609
1795
  operationId: getSubscription
1610
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1611
1796
  security: [{ bearerAuth: [] }]
1612
- summary: Get the active subscription and entitlements.
1797
+ summary: Get the subscription
1798
+ description: >-
1799
+ Get the active subscription and entitlements.
1800
+
1801
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1613
1802
  responses:
1614
1803
  "200":
1615
1804
  description: Subscription object
@@ -1630,9 +1819,12 @@ paths:
1630
1819
  /billing/checkout:
1631
1820
  post:
1632
1821
  operationId: createCheckout
1633
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1634
1822
  security: [{ bearerAuth: [] }]
1635
- summary: Create a checkout session for a plan or credit pack.
1823
+ summary: Create a checkout session
1824
+ description: >-
1825
+ Create a checkout session for a plan or credit pack.
1826
+
1827
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1636
1828
  parameters:
1637
1829
  - name: Idempotency-Key
1638
1830
  in: header
@@ -1668,8 +1860,10 @@ paths:
1668
1860
  get:
1669
1861
  operationId: getCheckoutSession
1670
1862
  security: [{ bearerAuth: [] }]
1671
- summary: Read whether a checkout has been applied to this workspace yet.
1863
+ summary: Get a checkout session
1672
1864
  description: >
1865
+ Read whether a checkout has been applied to this workspace yet.
1866
+
1673
1867
  Available to a signed-in app session with at least the admin role; an
1674
1868
  API key receives 403 `session_required`.
1675
1869
  Reports settlement in Idelio, not at the payment provider. A plan
@@ -1698,13 +1892,15 @@ paths:
1698
1892
  /billing/subscription/change-plan:
1699
1893
  post:
1700
1894
  operationId: changeSubscriptionPlan
1701
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1702
1895
  security: [{ bearerAuth: [] }]
1703
- summary: >-
1896
+ summary: Change the subscription plan
1897
+ description: >-
1704
1898
  Switch an existing subscription to a different plan. Upgrades apply
1705
- immediately (prorated credits granted right away); downgrades are
1706
- queued for the end of the current billing period and reported back
1707
- via pending_plan/plan_change_effective_at.
1899
+ immediately (prorated credits granted right away); downgrades are queued
1900
+ for the end of the current billing period and reported back via
1901
+ pending_plan/plan_change_effective_at.
1902
+
1903
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1708
1904
  parameters:
1709
1905
  - name: Idempotency-Key
1710
1906
  in: header
@@ -1734,9 +1930,12 @@ paths:
1734
1930
  /billing/catalog:
1735
1931
  get:
1736
1932
  operationId: getBillingCatalog
1737
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1738
1933
  security: [{ bearerAuth: [] }]
1739
- summary: Resolve the active provider's price_id for every plan and top-up pack.
1934
+ summary: Get the billing catalog
1935
+ description: >-
1936
+ Resolve the active provider's price_id for every plan and top-up pack.
1937
+
1938
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1740
1939
  responses:
1741
1940
  "200":
1742
1941
  description: Provider-agnostic price catalog
@@ -1751,9 +1950,12 @@ paths:
1751
1950
  /billing/portal:
1752
1951
  post:
1753
1952
  operationId: createPortalSession
1754
- description: Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1755
1953
  security: [{ bearerAuth: [] }]
1756
- summary: Create a Stripe customer-portal session.
1954
+ summary: Create a portal session
1955
+ description: >-
1956
+ Create a Stripe customer-portal session.
1957
+
1958
+ Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1757
1959
  parameters:
1758
1960
  - name: Idempotency-Key
1759
1961
  in: header
@@ -1781,8 +1983,10 @@ paths:
1781
1983
  get:
1782
1984
  operationId: getPaymentMethod
1783
1985
  security: [{ bearerAuth: [] }]
1784
- summary: The card this workspace's charges land on.
1986
+ summary: Get the payment method
1785
1987
  description: >
1988
+ The card this workspace's charges land on.
1989
+
1786
1990
  Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1787
1991
  Returns null when there is no card on file - which is the normal state for a workspace
1788
1992
  that has never paid, and for a saved method that is not a card (PayPal, a bank debit).
@@ -1809,8 +2013,10 @@ paths:
1809
2013
  get:
1810
2014
  operationId: listInvoices
1811
2015
  security: [{ bearerAuth: [] }]
1812
- summary: List the workspace's invoices from Stripe.
2016
+ summary: List invoices
1813
2017
  description: >
2018
+ List the workspace's invoices from Stripe.
2019
+
1814
2020
  Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1815
2021
  Results are newest first. That order is inherited rather than pinned: Stripe's invoice
1816
2022
  list exposes no ordering parameter and orders by creation date, which is already newest
@@ -1843,8 +2049,10 @@ paths:
1843
2049
  get:
1844
2050
  operationId: getAutoTopup
1845
2051
  security: [{ bearerAuth: [] }]
1846
- summary: Get the workspace's auto top-up preference.
2052
+ summary: Get auto top-up
1847
2053
  description: >-
2054
+ Get the workspace's auto top-up preference.
2055
+
1848
2056
  Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1849
2057
  The stored preference only. Nothing acts on it yet: no automatic
1850
2058
  purchase is made when the balance runs low, for any workspace (#426).
@@ -1865,8 +2073,10 @@ paths:
1865
2073
  patch:
1866
2074
  operationId: updateAutoTopup
1867
2075
  security: [{ bearerAuth: [] }]
1868
- summary: Store the workspace's auto top-up preference.
2076
+ summary: Update auto top-up
1869
2077
  description: >-
2078
+ Store the workspace's auto top-up preference.
2079
+
1870
2080
  Available to a signed-in app session with at least the admin role. An API key receives 403 `session_required`.
1871
2081
  Records the preference and the pack it names. It does NOT arrange a
1872
2082
  purchase: nothing reads these values, and no credits are ever bought
@@ -1895,7 +2105,7 @@ paths:
1895
2105
  /templates:
1896
2106
  get:
1897
2107
  operationId: listTemplates
1898
- summary: List available brand templates.
2108
+ summary: List templates
1899
2109
  parameters:
1900
2110
  - { name: category, in: query, schema: { type: string } }
1901
2111
  - { name: cursor, in: query, schema: { type: string } }
@@ -1920,7 +2130,9 @@ paths:
1920
2130
  /templates/{id}:
1921
2131
  get:
1922
2132
  operationId: getTemplate
1923
- summary: Retrieve a template definition.
2133
+ summary: Get a template
2134
+ description: >-
2135
+ Retrieve a template definition.
1924
2136
  parameters:
1925
2137
  - { name: id, in: path, required: true, schema: { type: string } }
1926
2138
  responses:
@@ -2989,6 +3201,13 @@ components:
2989
3201
  type: array
2990
3202
  items: { $ref: "#/components/schemas/WebhookEventType" }
2991
3203
  disabled: { type: boolean }
3204
+ disabled_reason:
3205
+ type: [string, "null"]
3206
+ enum: [manual, failures, null]
3207
+ description: >-
3208
+ Why the endpoint is disabled. `failures` means 3 fully failed deliveries in a
3209
+ row disabled it; re-enabling it with PATCH resets the count.
3210
+ consecutive_failures: { type: integer }
2992
3211
  created_at: { type: string, format: date-time }
2993
3212
  WebhookEndpointWithSecret:
2994
3213
  allOf:
@@ -3017,10 +3236,22 @@ components:
3017
3236
  type: string
3018
3237
  enum:
3019
3238
  - brand.completed
3020
- - brand.updated
3021
3239
  - asset.ready
3022
3240
  - asset.regenerated
3023
3241
  - job.failed
3024
3242
  - credits.low
3025
- - credits.settled
3026
- - subscription.changed
3243
+ WebhookDelivery:
3244
+ type: object
3245
+ properties:
3246
+ id: { type: string }
3247
+ event_id: { type: string }
3248
+ event_type: { type: string }
3249
+ status:
3250
+ type: string
3251
+ enum: [pending, delivered, failed]
3252
+ attempt_count: { type: integer }
3253
+ last_status_code: { type: [integer, "null"] }
3254
+ last_error: { type: [string, "null"] }
3255
+ payload: { type: object, additionalProperties: true }
3256
+ created_at: { type: string, format: date-time }
3257
+ delivered_at: { type: [string, "null"], format: date-time }