Compare commits

..

5 Commits

Author SHA1 Message Date
343db1d315 openapi: fix invalid BillingStatus schema (object + enum hybrid)
The previous PR (#14070) inadvertently left BillingStatus as an
invalid hybrid: an OpenAPI object schema with both 'properties' and
'enum' — the enum is meaningless on an object type.

The object properties (subscription, balance, has_payment_method)
duplicate what's already in BillingStatusResponse, the only place
that referenced BillingStatus did so via 'billing_status' field
which clearly wants the enum value.

Cleanly converts BillingStatus to a string enum matching cloud's
runtime emission. Closes the last (1) handler reference in
Comfy-Org/cloud's TestCutoverSafe gate (BE-1106).
2026-05-22 18:31:50 -07:00
187442cca4 openapi: add enum values + FeedbackRequest schema for cloud cutover (PR E) (#14070)
* openapi: add enum values + FeedbackRequest schema for cloud cutover (PR E)

Adds missing cloud-runtime enum values to vendor schemas that the
cloud runtime emits but vendor declared as plain strings.

Changes:
  - JobEntry.status: enum [pending, in_progress, completed, failed, cancelled]
  - JobDetailResponse.status: same enum
  - BillingStatus: enum [awaiting_payment_method, pending_payment, paid,
      payment_failed, inactive]
  - FeedbackRequest schema added (with type enum)
  - /api/feedback POST: requestBody now $refs FeedbackRequest

All cloud-runtime-emitted; no impact on OSS-local semantics.

Identified via Comfy-Org/cloud's TestCutoverSafe gate (BE-1106) as
the remaining schema-level divergences after PRs A-D landed and got
synced.

* openapi: add type enum to Workspace schema (cutover follow-up)

Cloud's Workspace runtime shape includes a 'type' field with enum
[personal, team] that vendor's Workspace was missing. Cloud handlers
reference the generated ingest.WorkspaceType Go enum.

Same kind of surgical addition as JobEntry.status / BillingStatus /
JobDetailResponse.status in this PR — adds cloud-runtime field to
existing vendor schema.
2026-05-22 18:23:22 -07:00
c3c881f37b openapi: rename cloud-side response schemas to match runtime (PR D) (#14065)
* openapi: rename cloud-side response schemas to match runtime (PR D)

Follow-up to the BE-1106 stack (#14060/61/63). Cloud's Go handlers
reference response schemas by name (e.g., ingest.WorkflowResponse,
ingest.SubscribeResponse), but vendor's matching operations were
declaring those responses against differently-named vendor-side
schemas (CloudWorkflow, BillingSubscription, etc.). After the stack
landed, schemas like WorkflowResponse exist in vendor but weren't
referenced by any path, so codegen pruned the unreferenced types.

This PR:
  1. Updates 34 operation $refs in cloud-runtime paths to point to
     the schema names cloud's handlers expect (e.g., CloudWorkflow →
     WorkflowResponse on /api/workflows/{workflow_id}).
  2. Adds 12 cloud-only schemas that weren't in vendor yet but are
     referenced by these renames (e.g., SubscribeResponse,
     CancelSubscriptionResponse, BillingOpStatusResponse). Each
     copied verbatim from Comfy-Org/cloud's hand-written ingest spec
     and tagged x-runtime: [cloud] with a [cloud-only] description
     prefix.

Schema renames span the same domains as the operationId renames in
PR A: billing/subscriptions (7 schemas), workflows (5), userdata (3),
jobs (2), hub (2), history (2), auth/workspace (4), and misc cloud
endpoints (9).

Convergent safety check after this lands (against cloud's
TestCutoverSafe gate, BE-1106):
  Pre-PR D:   205 missing handler refs
  Post-PR D:  105 missing handler refs (-49%)
  Cumulative since the original 938-ref baseline: -89%

The remaining 105 are a Phase 3 follow-up (response headers,
text/plain responses, codegen-derived enum sub-types, and a small
set of inline-response-schema operations that vendor declares
inline where cloud has named-schema $refs).

* openapi: drop PR-label comment from new schemas block

PR-internal labels don't belong in committed code — future readers
won't know what 'PR D' means and the marker stops being useful the
moment this PR merges.
2026-05-22 16:34:52 -07:00
7984a6a38e openapi: rename 55 cloud-side operationIds to match runtime (PR A of 3) (#14060)
* openapi: rename 55 cloud-side operationIds to match runtime handlers

For the 55 operations below, vendor's operationId did not match the
name cloud's runtime handlers expect. Generated types from vendor
therefore had different names (e.g. CreateSubscription200JSONResponse)
than what cloud handlers reference (Subscribe200JSONResponse), which
blocks the post-cutover combined-spec codegen.

All 55 renames target the cloud-runtime-authoritative name. Several
of these endpoints are shared concepts (queue, settings, userdata,
object_info) that OSS local also serves — the rename aligns vendor
with the longstanding cloud handler-side convention to unblock the
shared codegen. No request/response *shape* changes in this PR; only
operationId labels.

Notable categories:
  - Billing/subscriptions: 7 renames (subscribe, getBillingPlans, ...)
  - Workspace + workflows: 13 renames (createWorkflow, ...)
  - Hub: 3 renames
  - Auth/users: 5 renames
  - Shared OSS surface (settings, queue, view, userdata): 12 renames
  - Misc cloud-only: 15 renames

Identified via Comfy-Org/cloud's TestCutoverSafe build-safety gate
(BE-1106), which compares handler type references against codegen
output from the combined spec.

* fix(openapi): resolve getHistory operationId collision

Spectral flagged: both /api/history (OSS local) and /api/history_v2
(cloud) had operationId 'getHistory' after the rename. Rename vendor's
/api/history to 'getPromptHistory' to disambiguate. Cloud's runtime
denies /api/history at the overlay level so combined codegen is
unaffected by this change.

* openapi: add 41 cloud-runtime schemas to components.schemas (PR B of 3) (#14061)

* openapi: add 41 cloud-runtime schemas to components.schemas (cutover prep)

Adds schemas that exist in Comfy-Org/cloud's hand-written ingest spec
but not yet in this vendored OSS spec. All tagged x-runtime: [cloud]
per the field-drift convention and prefixed with [cloud-only] in the
description.

These schemas are referenced by cloud's Go handlers via the generated
ingest.<Schema> Go type names. Codegen from the vendored spec didn't
produce those types because the schemas weren't declared here. Adding
them unblocks the post-cutover combined-spec codegen.

Schemas added (alphabetical):
  AssetDownloadResponse, AssetMetadataResponse, BillingBalanceResponse,
  BillingPlansResponse, BillingStatusResponse, GetUserDataResponseFull,
  HistoryDetailEntry, HistoryDetailResponse, HistoryResponse,
  HubLabelInfo, HubProfileSummary, HubWorkflowListResponse,
  HubWorkflowStatus, HubWorkflowSummary, HubWorkflowTemplateEntry,
  JobStatusResponse, JobsListResponse, LabelRef, LogsResponse, Member,
  OAuthRegisterBadRequestResponse, PendingInvite, Plan, PlanAvailability,
  PlanAvailabilityReason, PlanSeatSummary, PreviewPlanInfo,
  PreviewSubscribeResponse, PublishedWorkflowDetail, SecretResponse,
  SubscriptionDuration, SubscriptionTier, UserDataResponseFull,
  ValidationError, ValidationResult, WorkflowForkedFrom, WorkflowResponse,
  WorkflowVersionContentResponse, WorkspaceAPIKeyInfo, WorkspaceSummary,
  WorkspaceWithRole

Identified via Comfy-Org/cloud's TestCutoverSafe build-safety gate
(BE-1106). Companion to PR #14060 (operationId renames).

* fix(openapi): add BindingErrorResponse schema

OAuthRegisterBadRequestResponse references BindingErrorResponse but
that schema wasn't in the original add. Adding it now as a cloud-only
schema matching the cloud runtime's binding-error shape (single
'message' string field).

* openapi: add missing 4xx/5xx response bodies for cloud-emitting endpoints (#14063)

Vendor declares shared endpoints (e.g. /api/queue, /api/settings,
/api/assets/*, /api/billing/*) with success responses but is missing
many of the 4xx/5xx error response bodies that Comfy-Org/cloud's
runtime actually emits. Cloud's Go handlers reference the generated
ingest.Op<StatusCode>JSONResponse types for these missing statuses,
which currently fail to resolve when codegen runs against the
vendored spec.

This PR adds 237 response entries across 117 operations, restoring
the documented error responses that cloud emits. Bodies are copied
verbatim from Comfy-Org/cloud's hand-written ingest spec
(services/ingest/openapi.yaml) and reference a new ErrorResponse
schema also added in this PR (matches cloud's {code, message} runtime
shape, tagged x-runtime: [cloud]).

ErrorResponse is intentionally separate from the existing CloudError
schema. CloudError's shape ({error}) describes one runtime; cloud
emits a different shape ({code, message}). Existing CloudError refs
in vendor are untouched; new cloud-emitting error references use
ErrorResponse.

Identified via Comfy-Org/cloud's TestCutoverSafe build-safety gate
(BE-1106). Companion to PR #14060 (operationId renames) and PR #14061
(cloud-only schema additions).
2026-05-22 16:15:18 -07:00
e75b739c1d Delete the source branch after doing the backport. (#14062) 2026-05-22 15:47:03 -07:00
2 changed files with 404 additions and 59 deletions

View File

@ -458,6 +458,41 @@ jobs:
echo "Released ${NEW_VERSION} on ${RELEASE_BRANCH}."
- name: Delete remote source branch
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
REPO: ${{ github.repository }}
SOURCE_BRANCH: ${{ steps.resolve.outputs.source_branch }}
SOURCE_COMMIT: ${{ inputs.commit }}
RELEASE_BRANCH: ${{ steps.latest.outputs.release_branch }}
DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
run: |
set -euo pipefail
# Belt-and-braces: the resolve step already refuses the default branch,
# but never delete the default or the release branch under any
# circumstances.
if [[ "${SOURCE_BRANCH}" == "${DEFAULT_BRANCH}" || "${SOURCE_BRANCH}" == "${RELEASE_BRANCH}" ]]; then
echo "::error::Refusing to delete '${SOURCE_BRANCH}' (matches default or release branch)."
exit 1
fi
# Delete the source branch on origin, but only if its tip is still the
# SHA we released from. If someone pushed new commits to it after we
# resolved it, leave it alone — those commits would be silently lost.
current_tip="$(git ls-remote origin "refs/heads/${SOURCE_BRANCH}" | awk '{print $1}')"
if [[ -z "${current_tip}" ]]; then
echo "Source branch '${SOURCE_BRANCH}' no longer exists on origin; nothing to delete."
exit 0
fi
if [[ "${current_tip}" != "${SOURCE_COMMIT}" ]]; then
echo "::warning::Source branch '${SOURCE_BRANCH}' tip (${current_tip}) no longer matches released commit (${SOURCE_COMMIT}). Leaving it in place."
exit 0
fi
git push origin --delete "refs/heads/${SOURCE_BRANCH}"
echo "Deleted remote branch '${SOURCE_BRANCH}'."
- name: Summary
if: always()
env:

View File

@ -1200,7 +1200,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/ListUserdataResponse"
$ref: "#/components/schemas/GetUserDataResponseFull"
"404":
description: Directory not found
@ -1340,7 +1340,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/UserDataResponse"
$ref: "#/components/schemas/UserDataResponseFull"
"409":
description: File exists and overwrite not set
'400':
@ -1434,7 +1434,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/UserDataResponse"
$ref: "#/components/schemas/UserDataResponseFull"
"404":
description: Source file not found
"409":
@ -2752,7 +2752,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudJobStatus"
$ref: "#/components/schemas/JobCancelResponse"
"401":
description: Unauthorized
content:
@ -2803,7 +2803,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudJobStatus"
$ref: "#/components/schemas/JobStatusResponse"
"401":
description: Unauthorized
content:
@ -2899,7 +2899,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/HistoryV2Response"
$ref: "#/components/schemas/HistoryResponse"
"401":
description: Unauthorized
content:
@ -2938,7 +2938,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/HistoryV2Entry"
$ref: "#/components/schemas/HistoryDetailResponse"
"401":
description: Unauthorized
content:
@ -2994,7 +2994,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudLogsResponse"
$ref: "#/components/schemas/LogsResponse"
"401":
description: Unauthorized
content:
@ -3315,7 +3315,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/RemoteAssetMetadata"
$ref: "#/components/schemas/AssetMetadataResponse"
"400":
description: Bad request
content:
@ -3889,7 +3889,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/HubWorkflowList"
$ref: "#/components/schemas/HubWorkflowListResponse"
'400':
description: Bad request (e.g. malformed pagination cursor)
content:
@ -3972,7 +3972,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/HubWorkflow"
$ref: "#/components/schemas/HubWorkflowDetail"
"404":
description: Not found
content:
@ -4092,7 +4092,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudWorkflowList"
$ref: "#/components/schemas/WorkflowListResponse"
"401":
description: Unauthorized
content:
@ -4136,7 +4136,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudWorkflow"
$ref: "#/components/schemas/WorkflowResponse"
"400":
description: Bad request
content:
@ -4183,7 +4183,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudWorkflow"
$ref: "#/components/schemas/WorkflowResponse"
"401":
description: Unauthorized
content:
@ -4239,7 +4239,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudWorkflow"
$ref: "#/components/schemas/WorkflowResponse"
"400":
description: Bad request
content:
@ -4438,7 +4438,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudWorkflow"
$ref: "#/components/schemas/WorkflowResponse"
"401":
description: Unauthorized
content:
@ -4607,7 +4607,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudWorkflow"
$ref: "#/components/schemas/PublishedWorkflowDetail"
"404":
description: Not found
content:
@ -4743,7 +4743,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/AuthTokenResponse"
$ref: "#/components/schemas/ExchangeTokenResponse"
"400":
description: Bad request
content:
@ -5089,7 +5089,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/BillingBalance"
$ref: "#/components/schemas/BillingBalanceResponse"
"401":
description: Unauthorized
content:
@ -5132,7 +5132,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/BillingEventList"
$ref: "#/components/schemas/BillingEventsResponse"
"401":
description: Unauthorized
content:
@ -5166,7 +5166,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/BillingOp"
$ref: "#/components/schemas/BillingOpStatusResponse"
"401":
description: Unauthorized
content:
@ -5278,7 +5278,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/SubscriptionPreview"
$ref: "#/components/schemas/PreviewSubscribeResponse"
"400":
description: Bad request
content:
@ -5311,7 +5311,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/BillingStatus"
$ref: "#/components/schemas/BillingStatusResponse"
"401":
description: Unauthorized
content:
@ -5359,7 +5359,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/BillingSubscription"
$ref: "#/components/schemas/SubscribeResponse"
"400":
description: Bad request
content:
@ -5392,7 +5392,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/BillingSubscription"
$ref: "#/components/schemas/CancelSubscriptionResponse"
"401":
description: Unauthorized
content:
@ -5425,7 +5425,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/BillingSubscription"
$ref: "#/components/schemas/ResubscribeResponse"
"401":
description: Unauthorized
content:
@ -5470,7 +5470,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/BillingBalance"
$ref: "#/components/schemas/CreateTopupResponse"
"400":
description: Bad request
content:
@ -5555,7 +5555,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/WorkspaceApiKeyCreated"
$ref: "#/components/schemas/CreateWorkspaceAPIKeyResponse"
"400":
description: Bad request
content:
@ -5704,7 +5704,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/WorkspaceInvite"
$ref: "#/components/schemas/PendingInvite"
"400":
description: Bad request
content:
@ -6315,22 +6315,7 @@ paths:
content:
application/json:
schema:
type: object
required:
- message
properties:
message:
type: string
description: Feedback message
rating:
type: integer
minimum: 1
maximum: 5
description: Optional satisfaction rating
context:
type: object
additionalProperties: true
description: Additional context metadata
$ref: "#/components/schemas/FeedbackRequest"
responses:
"201":
description: Feedback submitted
@ -6486,7 +6471,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/Workspace"
$ref: "#/components/schemas/AcceptInviteResponse"
"400":
description: Bad request
content:
@ -6586,7 +6571,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/SecretMeta"
$ref: "#/components/schemas/SecretResponse"
"400":
description: Bad request
content:
@ -6645,7 +6630,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/SecretMeta"
$ref: "#/components/schemas/SecretResponse"
"401":
description: Unauthorized
content:
@ -6702,7 +6687,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/SecretMeta"
$ref: "#/components/schemas/SecretResponse"
"400":
description: Bad request
content:
@ -6805,7 +6790,7 @@ paths:
content:
application/json:
schema:
$ref: "#/components/schemas/CloudUser"
$ref: "#/components/schemas/UserResponse"
"401":
description: Unauthorized
content:
@ -7535,6 +7520,12 @@ components:
description: Unique job identifier (same as prompt_id)
status:
type: string
enum:
- pending
- in_progress
- completed
- failed
- cancelled
description: Current job status
create_time:
type: integer
@ -7568,6 +7559,12 @@ components:
format: uuid
status:
type: string
enum:
- pending
- in_progress
- completed
- failed
- cancelled
workflow:
type: object
additionalProperties: true
@ -9588,16 +9585,15 @@ components:
description: List of plan features
BillingStatus:
type: object
type: string
x-runtime: [cloud]
description: "[cloud-only] Overall billing and subscription status."
properties:
subscription:
$ref: "#/components/schemas/BillingSubscription"
balance:
$ref: "#/components/schemas/BillingBalance"
has_payment_method:
type: boolean
description: "[cloud-only] Overall billing/payment lifecycle status."
enum:
- awaiting_payment_method
- pending_payment
- paid
- payment_failed
- inactive
BillingSubscription:
type: object
@ -9659,6 +9655,12 @@ components:
type: string
name:
type: string
type:
type: string
enum:
- personal
- team
description: Workspace type (personal vs. team).
owner_id:
type: string
member_count:
@ -11379,3 +11381,311 @@ components:
message:
type: string
description: Human-readable error message
AcceptInviteResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Response returned after successfully accepting a workspace invitation.'
required:
- workspace_id
- workspace_name
properties:
workspace_id:
type: string
description: ID of the workspace joined
workspace_name:
type: string
description: Name of the workspace joined
BillingEventsResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Paginated list of billing events for a workspace.'
required:
- total
- events
- page
- limit
- totalPages
properties:
total:
type: integer
description: Total number of events
events:
type: array
items:
$ref: '#/components/schemas/BillingEvent'
page:
type: integer
description: Current page number (1-indexed)
limit:
type: integer
description: Items per page
totalPages:
type: integer
description: Total number of pages
BillingOpStatusResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Status of an asynchronous billing operation.'
required:
- id
- status
- started_at
properties:
id:
type: string
description: Unique identifier for the billing operation
status:
type: string
enum:
- pending
- succeeded
- failed
description: Current status of the operation
error_message:
type: string
description: Error message if status is failed
started_at:
type: string
format: date-time
description: When the operation was initiated
completed_at:
type: string
format: date-time
description: When the operation completed (success or failure)
CancelSubscriptionResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Response after successfully cancelling a subscription.'
required:
- cancel_at
- billing_op_id
properties:
billing_op_id:
type: string
description: Billing operation ID to poll for status via GET /api/billing/ops/{id}
cancel_at:
type: string
format: date-time
description: The date when the subscription will end (end of current billing period)
CreateTopupResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Response after successfully purchasing a credit top-up.'
required:
- topup_id
- status
- amount_cents
- billing_op_id
properties:
billing_op_id:
type: string
description: Billing operation ID to poll for status via GET /api/billing/ops/{id}
topup_id:
type: string
description: Unique identifier for the top-up request (same as billing_op_id, deprecated)
status:
type: string
enum:
- pending
- completed
- failed
description: Current status of the top-up
amount_cents:
type: integer
format: int64
description: Amount being charged in cents
CreateWorkspaceAPIKeyResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Response containing the newly created workspace API key.'
required:
- id
- name
- description
- key
- key_prefix
- created_at
properties:
id:
type: string
format: uuid
description: API key ID
name:
type: string
description: User-provided label
description:
type: string
description: User-provided description of the key's purpose. Limit is byte-based (UTF-8 encoding); 5000 bytes equals
5000 ASCII characters or fewer multi-byte characters.
maxLength: 5000
key:
type: string
description: The full plaintext API key (only shown once)
key_prefix:
type: string
description: First 8 chars after prefix for display
expires_at:
type: string
format: date-time
description: When the key expires (if set)
created_at:
type: string
format: date-time
description: When the key was created
ExchangeTokenResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Response containing the issued Cloud JWT and its expiry.'
required:
- token
- expires_at
- workspace
- role
- permissions
properties:
token:
type: string
description: Cloud JWT token
expires_at:
type: string
format: date-time
description: Token expiration time (RFC 3339)
workspace:
$ref: '#/components/schemas/WorkspaceSummary'
role:
type: string
enum:
- owner
- member
description: User's role in the workspace
permissions:
type: array
items:
type: string
description: Permission strings for the role
example:
- owner:*
JobCancelResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Response for POST /api/jobs/{job_id}/cancel. Returned on both fresh cancels and idempotent no-ops.'
required:
- cancelled
properties:
cancelled:
type: boolean
description: "True when a cancel event was successfully dispatched by this call.\nFalse when the job was already in\
\ a terminal or cancelling state,\nin which case the call is a no-op (still 200 \u2014 idempotent).\n"
ResubscribeResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Response after successfully resubscribing to a billing plan.'
required:
- status
- billing_op_id
properties:
billing_op_id:
type: string
description: Billing operation ID to poll for status via GET /api/billing/ops/{id}
status:
type: string
enum:
- active
description: The subscription status after resubscribing
message:
type: string
description: Human-readable confirmation message
SubscribeResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Response after successfully subscribing to a billing plan.'
required:
- status
- billing_op_id
properties:
billing_op_id:
type: string
description: Billing operation ID to poll for status via GET /api/billing/ops/{id}
status:
type: string
enum:
- subscribed
- needs_payment_method
- pending_payment
description: 'Status of the subscription operation:
- subscribed: Subscription is active immediately
- needs_payment_method: User must add payment method via payment_method_url
- pending_payment: Upgrade initiated, waiting for payment to complete
'
effective_at:
type: string
format: date-time
description: When the subscription became/becomes active (present when status=subscribed or pending_payment)
payment_method_url:
type: string
description: URL to redirect user to add payment method (present when status=needs_payment_method)
UserResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] User information response'
required:
- id
- status
properties:
id:
type: string
description: Firebase UID of the authenticated user
status:
type: string
description: User status (always "active" for authenticated users)
WorkflowListResponse:
type: object
x-runtime: [cloud]
description: '[cloud-only] Paginated list of saved workflows.'
required:
- data
- pagination
properties:
data:
type: array
items:
$ref: '#/components/schemas/WorkflowResponse'
pagination:
$ref: '#/components/schemas/PaginationInfo'
FeedbackRequest:
type: object
x-runtime: [cloud]
description: "[cloud-only] User feedback submission body."
required:
- message
properties:
type:
type: string
enum:
- missing_nodes
- general
- missing_models
description: Feedback category
category:
type: string
description: Additional category metadata
message:
type: string
description: User-provided feedback message