diff --git a/apps/studio/components/interfaces/Billing/ChargeBreakdown.tsx b/apps/studio/components/interfaces/Billing/ChargeBreakdown.tsx
new file mode 100644
index 00000000000..38ce73ec9b6
--- /dev/null
+++ b/apps/studio/components/interfaces/Billing/ChargeBreakdown.tsx
@@ -0,0 +1,58 @@
+import { cn } from 'ui'
+
+import { formatCurrency } from '@/lib/helpers'
+
+export interface ChargeBreakdownProps {
+ subtotal: number
+ total: number
+ tax?: { amount: number; percentage: number }
+ taxStatus?: 'calculated' | 'failed' | 'not_applicable'
+ isFetching: boolean
+}
+
+export const ChargeBreakdown = ({
+ subtotal,
+ total,
+ tax,
+ taxStatus,
+ isFetching,
+}: ChargeBreakdownProps) => {
+ return (
+
+ {total !== subtotal && (
+
+
Subtotal
+
+ {formatCurrency(subtotal)}
+
+
+ )}
+
+ {taxStatus === 'calculated' && tax && tax.amount > 0 && (
+
+
Tax ({tax.percentage}%)
+
+ {formatCurrency(tax.amount)}
+
+
+ )}
+
+ {taxStatus === 'failed' && (
+
+
+ Tax could not be estimated and may be applied separately
+
+
+ )}
+
+
+
Total due today
+
+ {formatCurrency(total)}
+
+
+
+ )
+}
diff --git a/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx b/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx
index 6b8f1843e7e..ae7c6050744 100644
--- a/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx
+++ b/apps/studio/components/interfaces/Organization/BillingSettings/CreditTopUp.tsx
@@ -4,6 +4,7 @@ import { Elements } from '@stripe/react-stripe-js'
import { loadStripe, PaymentIntentResult } from '@stripe/stripe-js'
import { PermissionAction, SupportCategories } from '@supabase/shared-types/out/constants'
import { useQueryClient } from '@tanstack/react-query'
+import { useDebounce } from '@uidotdev/usehooks'
import { AlertCircle, Info } from 'lucide-react'
import { useTheme } from 'next-themes'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
@@ -32,12 +33,15 @@ import { z } from 'zod'
import type { PaymentMethodElementRef } from '../../Billing/Payment/PaymentMethods/NewPaymentMethodElement'
import PaymentMethodSelection from './Subscription/PaymentMethodSelection'
+import { ChargeBreakdown } from '@/components/interfaces/Billing/ChargeBreakdown'
import { getStripeElementsAppearanceOptions } from '@/components/interfaces/Billing/Payment/Payment.utils'
import { PaymentConfirmation } from '@/components/interfaces/Billing/Payment/PaymentConfirmation'
import { NO_PROJECT_MARKER } from '@/components/interfaces/Support/SupportForm.utils'
import { SupportLink } from '@/components/interfaces/Support/SupportLink'
import { ButtonTooltip } from '@/components/ui/ButtonTooltip'
import { useOrganizationCreditTopUpMutation } from '@/data/organizations/organization-credit-top-up-mutation'
+import { useCreditTopUpPreview } from '@/data/organizations/organization-credit-top-up-preview'
+import type { CustomerAddress, CustomerTaxId } from '@/data/organizations/types'
import { subscriptionKeys } from '@/data/subscriptions/keys'
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
import { STRIPE_PUBLIC_KEY } from '@/lib/constants'
@@ -45,12 +49,14 @@ import { STRIPE_PUBLIC_KEY } from '@/lib/constants'
const stripePromise = loadStripe(STRIPE_PUBLIC_KEY)
const FORM_ID = 'credit-top-up'
+const MIN_TOP_UP_AMOUNT = 300
+const MAX_TOP_UP_AMOUNT = 2000
const FormSchema = z.object({
amount: z.coerce
.number()
- .gte(300, 'Amount must be between $300 - $2000.')
- .lte(2000, 'Amount must be between $300 - $2000.')
+ .gte(MIN_TOP_UP_AMOUNT, `Amount must be between $${MIN_TOP_UP_AMOUNT} - $${MAX_TOP_UP_AMOUNT}.`)
+ .lte(MAX_TOP_UP_AMOUNT, `Amount must be between $${MIN_TOP_UP_AMOUNT} - $${MAX_TOP_UP_AMOUNT}.`)
.int('Amount must be a whole number.'),
paymentMethod: z.string(),
})
@@ -87,6 +93,52 @@ export const CreditTopUp = ({ slug }: { slug: string | undefined }) => {
const [topUpModalVisible, setTopUpModalVisible] = useState(false)
const [useAsDefaultBillingAddress, setUseAsDefaultBillingAddress] = useState(true)
const [paymentConfirmationLoading, setPaymentConfirmationLoading] = useState(false)
+
+ const [latestAddress, setLatestAddress] = useState()
+ const [latestTaxId, setLatestTaxId] = useState()
+
+ const billingAddress = useAsDefaultBillingAddress ? latestAddress : undefined
+ const billingTaxId = useAsDefaultBillingAddress ? latestTaxId : null
+ const debouncedAddress = useDebounce(billingAddress, 1000)
+ const debouncedTaxId = useDebounce(billingTaxId, 1000)
+
+ const watchedAmount = form.watch('amount')
+ const debouncedAmount = useDebounce(watchedAmount, 1000)
+ const parsedAmount = Number(debouncedAmount)
+ const validAmount =
+ !Number.isNaN(parsedAmount) &&
+ Number.isInteger(parsedAmount) &&
+ parsedAmount >= MIN_TOP_UP_AMOUNT &&
+ parsedAmount <= MAX_TOP_UP_AMOUNT
+ ? parsedAmount
+ : undefined
+
+ const isPreviewStale =
+ watchedAmount !== debouncedAmount ||
+ billingAddress !== debouncedAddress ||
+ billingTaxId !== debouncedTaxId
+
+ const handleAddressChange = useCallback((address: CustomerAddress) => {
+ setLatestAddress(address)
+ }, [])
+
+ const handleTaxIdChange = useCallback((taxId: CustomerTaxId | null) => {
+ setLatestTaxId(taxId)
+ }, [])
+
+ const {
+ data: creditPreview,
+ isFetching: creditPreviewIsFetching,
+ isSuccess: creditPreviewInitialized,
+ } = useCreditTopUpPreview(
+ {
+ slug,
+ amount: validAmount,
+ address: debouncedAddress,
+ taxId: debouncedTaxId ?? undefined,
+ },
+ { enabled: topUpModalVisible && !!validAmount }
+ )
const [captchaToken, setCaptchaToken] = useState(null)
const [captchaRef, setCaptchaRef] = useState(null)
@@ -175,6 +227,8 @@ export const CreditTopUp = ({ slug }: { slug: string | undefined }) => {
setCaptchaRef(null)
setPaymentIntentConfirmation(undefined)
setPaymentIntentSecret('')
+ setLatestAddress(undefined)
+ setLatestTaxId(null)
}
}
@@ -288,6 +342,8 @@ export const CreditTopUp = ({ slug }: { slug: string | undefined }) => {
readOnly={executingTopUp || paymentConfirmationLoading}
useAsDefaultBillingAddress={useAsDefaultBillingAddress}
onUseAsDefaultBillingAddressChange={setUseAsDefaultBillingAddress}
+ onAddressChange={handleAddressChange}
+ onTaxIdChange={handleTaxIdChange}
/>
)}
/>
@@ -324,6 +380,25 @@ export const CreditTopUp = ({ slug }: { slug: string | undefined }) => {
)}
+
+ {creditPreviewInitialized && !!validAmount && (
+
+
+
+ )}
{!paymentIntentConfirmation?.paymentIntent && (
@@ -332,6 +407,7 @@ export const CreditTopUp = ({ slug }: { slug: string | undefined }) => {
htmlType="submit"
type="primary"
loading={executingTopUp || paymentConfirmationLoading}
+ disabled={isPreviewStale || creditPreviewIsFetching}
>
Top Up
diff --git a/apps/studio/data/organizations/keys.ts b/apps/studio/data/organizations/keys.ts
index d41cec69d64..62d4ff7a1df 100644
--- a/apps/studio/data/organizations/keys.ts
+++ b/apps/studio/data/organizations/keys.ts
@@ -32,4 +32,8 @@ export const organizationKeys = {
) => ['organizations', 'creation-preview', tier, params] as const,
previewCreditCode: (slug: string | undefined, code: string) =>
['organizations', slug, 'preview-credit-code', code] as const,
+ creditTopUpPreview: (
+ slug: string | undefined,
+ params?: { amount?: number; address?: Record; taxId?: Record }
+ ) => ['organizations', slug, 'credits', 'preview', params] as const,
}
diff --git a/apps/studio/data/organizations/organization-credit-top-up-preview.ts b/apps/studio/data/organizations/organization-credit-top-up-preview.ts
new file mode 100644
index 00000000000..4cea861e5be
--- /dev/null
+++ b/apps/studio/data/organizations/organization-credit-top-up-preview.ts
@@ -0,0 +1,57 @@
+import { keepPreviousData, useQuery } from '@tanstack/react-query'
+
+import { organizationKeys } from './keys'
+import type { CustomerAddress, CustomerTaxId } from './types'
+import { handleError, post } from '@/data/fetchers'
+import type { ResponseError, UseCustomQueryOptions } from '@/types'
+
+export type CreditTopUpPreviewVariables = {
+ slug?: string
+ amount?: number
+ address?: CustomerAddress
+ taxId?: CustomerTaxId
+}
+
+export async function previewCreditTopUp({
+ slug,
+ amount,
+ address,
+ taxId,
+}: CreditTopUpPreviewVariables) {
+ if (!slug) throw new Error('slug is required')
+ if (!amount) throw new Error('amount is required')
+
+ const { data, error } = await post(`/platform/organizations/{slug}/billing/credits/preview`, {
+ params: { path: { slug } },
+ body: {
+ amount,
+ ...(address && { address }),
+ ...(taxId && { tax_id: taxId }),
+ },
+ })
+
+ if (error) handleError(error)
+
+ return data
+}
+
+export type CreditTopUpPreviewData = Awaited>
+
+export const useCreditTopUpPreview = (
+ { slug, amount, address, taxId }: CreditTopUpPreviewVariables,
+ {
+ enabled = true,
+ ...options
+ }: UseCustomQueryOptions = {}
+) =>
+ useQuery({
+ queryKey: organizationKeys.creditTopUpPreview(slug, {
+ amount,
+ address: address as Record | undefined,
+ taxId: taxId as Record | undefined,
+ }),
+ queryFn: () => previewCreditTopUp({ slug, amount, address, taxId }),
+ enabled: enabled && typeof slug !== 'undefined' && typeof amount !== 'undefined',
+ placeholderData: keepPreviousData,
+ ...options,
+ })
diff --git a/packages/api-types/types/api.d.ts b/packages/api-types/types/api.d.ts
index 4f84a15c31c..3163eb5c0db 100644
--- a/packages/api-types/types/api.d.ts
+++ b/packages/api-types/types/api.d.ts
@@ -5625,6 +5625,27 @@ export interface operations {
}
content?: never
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
'v1-revoke-token': {
@@ -5688,6 +5709,27 @@ export interface operations {
'application/json': components['schemas']['OrganizationResponseV1'][]
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
/** @description Unexpected error listing organizations */
500: {
headers: {
@@ -5718,6 +5760,27 @@ export interface operations {
'application/json': components['schemas']['OrganizationResponseV1']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
/** @description Unexpected error creating an organization */
500: {
headers: {
@@ -5954,6 +6017,27 @@ export interface operations {
'application/json': components['schemas']['OrganizationProjectsResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
/** @description Failed to retrieve projects */
500: {
headers: {
@@ -5999,6 +6083,27 @@ export interface operations {
'application/json': components['schemas']['V1ProjectWithDatabaseResponse'][]
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
'v1-create-a-project': {
@@ -6022,6 +6127,27 @@ export interface operations {
'application/json': components['schemas']['V1ProjectResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
'v1-get-project': {
@@ -7252,27 +7378,6 @@ export interface operations {
'application/json': components['schemas']['BranchResponse'][]
}
}
- /** @description Unauthorized */
- 401: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
- /** @description Forbidden action */
- 403: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
- /** @description Rate limit exceeded */
- 429: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
/** @description Failed to retrieve database branches */
500: {
headers: {
@@ -7306,27 +7411,6 @@ export interface operations {
'application/json': components['schemas']['BranchResponse']
}
}
- /** @description Unauthorized */
- 401: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
- /** @description Forbidden action */
- 403: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
- /** @description Rate limit exceeded */
- 429: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
/** @description Failed to create database branch */
500: {
headers: {
@@ -7405,27 +7489,6 @@ export interface operations {
'application/json': components['schemas']['BranchResponse']
}
}
- /** @description Unauthorized */
- 401: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
- /** @description Forbidden action */
- 403: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
- /** @description Rate limit exceeded */
- 429: {
- headers: {
- [name: string]: unknown
- }
- content?: never
- }
/** @description Failed to fetch database branch */
500: {
headers: {
@@ -12898,6 +12961,27 @@ export interface operations {
'application/json': components['schemas']['SnippetList']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
/** @description Failed to list user's SQL snippets */
500: {
headers: {
@@ -12926,6 +13010,27 @@ export interface operations {
'application/json': components['schemas']['SnippetResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
/** @description Failed to retrieve SQL snippet */
500: {
headers: {
diff --git a/packages/api-types/types/platform.d.ts b/packages/api-types/types/platform.d.ts
index 8961dec7e87..d2501aff841 100644
--- a/packages/api-types/types/platform.d.ts
+++ b/packages/api-types/types/platform.d.ts
@@ -1077,6 +1077,23 @@ export interface paths {
patch?: never
trace?: never
}
+ '/platform/organizations/{slug}/billing/credits/preview': {
+ parameters: {
+ query?: never
+ header?: never
+ path?: never
+ cookie?: never
+ }
+ get?: never
+ put?: never
+ /** Preview for credit top-up */
+ post: operations['OrgCreditsController_previewTopUp']
+ delete?: never
+ options?: never
+ head?: never
+ patch?: never
+ trace?: never
+ }
'/platform/organizations/{slug}/billing/credits/redeem': {
parameters: {
query?: never
@@ -1888,6 +1905,23 @@ export interface paths {
patch?: never
trace?: never
}
+ '/platform/organizations/onboarding-survey': {
+ parameters: {
+ query?: never
+ header?: never
+ path?: never
+ cookie?: never
+ }
+ get?: never
+ put?: never
+ /** Submit onboarding survey for a newly created organization */
+ post: operations['OrganizationsController_handleOnboardingSurvey']
+ delete?: never
+ options?: never
+ head?: never
+ patch?: never
+ trace?: never
+ }
'/platform/organizations/preview-creation': {
parameters: {
query?: never
@@ -4988,11 +5022,24 @@ export interface components {
workdir: string
}
CreateInvitationBody: {
- email: string
+ /**
+ * Format: email
+ * @deprecated
+ */
+ email?: string
+ emails?: string[]
require_sso?: boolean
role_id: number
role_scoped_projects?: string[]
}
+ CreateInvitationResponse: {
+ failed: {
+ /** Format: email */
+ email: string
+ error: string
+ }[]
+ succeeded: string[]
+ } | null
CreateNamespaceBody: {
namespace: string
}
@@ -5222,6 +5269,8 @@ export interface components {
| 'action_runs_read'
| 'action_runs_write'
| 'advisors_read'
+ | 'analytics_config_read'
+ | 'analytics_config_write'
| 'analytics_logs_read'
| 'analytics_usage_read'
| 'api_gateway_keys_read'
@@ -5685,6 +5734,8 @@ export interface components {
| 'action_runs_read'
| 'action_runs_write'
| 'advisors_read'
+ | 'analytics_config_read'
+ | 'analytics_config_write'
| 'analytics_logs_read'
| 'analytics_usage_read'
| 'api_gateway_keys_read'
@@ -7631,6 +7682,13 @@ export interface components {
)[]
website: string
}
+ OnboardingSurveyBody: {
+ building?: string
+ heard_from?: string
+ kind?: string
+ size?: string
+ slug: string
+ }
OrganizationProjectsResponse: {
pagination: {
/** @description Total number of projects. Use this to calculate the total number of pages. */
@@ -8271,6 +8329,36 @@ export interface components {
name: string
schema: string
}
+ PreviewCreditTopUpRequest: {
+ address?: {
+ city?: string | null
+ country: string
+ line1: string
+ line2?: string | null
+ postal_code?: string | null
+ state?: string | null
+ }
+ amount: number
+ tax_id?: {
+ country: string
+ type: string
+ value: string
+ }
+ }
+ PreviewCreditTopUpResponse: {
+ amount: number
+ currency: string
+ tax: {
+ currency: string
+ tax_amount: number
+ tax_rate_percentage: number
+ total_amount_excluding_tax: number
+ total_amount_including_tax: number
+ } | null
+ /** @enum {string} */
+ tax_status: 'calculated' | 'not_applicable' | 'failed'
+ total: number
+ }
PreviewOrganizationCreationBody: {
address?: {
city?: string | null
@@ -8648,7 +8736,7 @@ export interface components {
| '48xlarge_optimized_cpu'
| '48xlarge_high_memory'
inserted_at: string
- integration_source?: string | null
+ integration_source: string | null
is_branch_enabled: boolean
is_physical_backups_enabled: boolean
lastDatabaseResizeAt?: string
@@ -10591,6 +10679,8 @@ export interface components {
| 'action_runs_read'
| 'action_runs_write'
| 'advisors_read'
+ | 'analytics_config_read'
+ | 'analytics_config_write'
| 'analytics_logs_read'
| 'analytics_usage_read'
| 'api_gateway_keys_read'
@@ -14002,6 +14092,27 @@ export interface operations {
'application/json': components['schemas']['ListPlatformAppsResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppsController_createPlatformApp: {
@@ -14028,6 +14139,27 @@ export interface operations {
'application/json': components['schemas']['CreatePlatformAppResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppsController_getPlatformApp: {
@@ -14051,6 +14183,27 @@ export interface operations {
'application/json': components['schemas']['GetPlatformAppResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppsController_deletePlatformApp: {
@@ -14072,6 +14225,27 @@ export interface operations {
}
content?: never
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppsController_updatePlatformApp: {
@@ -14099,6 +14273,27 @@ export interface operations {
'application/json': components['schemas']['GetPlatformAppResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppSigningKeysController_listPlatformAppSigningKeys: {
@@ -14122,6 +14317,27 @@ export interface operations {
'application/json': components['schemas']['ListPlatformAppSigningKeysResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppSigningKeysController_createPlatformAppSigningKey: {
@@ -14145,6 +14361,27 @@ export interface operations {
'application/json': components['schemas']['CreatePlatformAppSigningKeyResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppSigningKeysController_deletePlatformAppSigningKey: {
@@ -14167,6 +14404,27 @@ export interface operations {
}
content?: never
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppInstallationsController_listPlatformAppInstallations: {
@@ -14189,6 +14447,27 @@ export interface operations {
'application/json': components['schemas']['ListPlatformAppInstallationsResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppInstallationsController_installPlatformApp: {
@@ -14215,6 +14494,27 @@ export interface operations {
'application/json': components['schemas']['InstallPlatformAppResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppInstallationsController_getPlatformAppInstallation: {
@@ -14238,6 +14538,27 @@ export interface operations {
'application/json': components['schemas']['GetPlatformAppInstallationResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppInstallationsController_uninstallPlatformInstallation: {
@@ -14259,6 +14580,27 @@ export interface operations {
}
content?: never
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
PlatformAppInstallationsController_updatePlatformAppInstallation: {
@@ -14282,6 +14624,27 @@ export interface operations {
'application/json': components['schemas']['UpdatePlatformAppInstallationResponse']
}
}
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
}
}
OrgAuditLogsController_getAuditLogs: {
@@ -14393,6 +14756,54 @@ export interface operations {
}
}
}
+ OrgCreditsController_previewTopUp: {
+ parameters: {
+ query?: never
+ header?: never
+ path: {
+ /** @description Organization slug */
+ slug: string
+ }
+ cookie?: never
+ }
+ requestBody: {
+ content: {
+ 'application/json': components['schemas']['PreviewCreditTopUpRequest']
+ }
+ }
+ responses: {
+ /** @description Credit top-up preview with tax calculation. */
+ 200: {
+ headers: {
+ [name: string]: unknown
+ }
+ content: {
+ 'application/json': components['schemas']['PreviewCreditTopUpResponse']
+ }
+ }
+ /** @description Unauthorized */
+ 401: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Forbidden action */
+ 403: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ /** @description Rate limit exceeded */
+ 429: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ }
+ }
OrgCreditsController_redeemCode: {
parameters: {
query?: never
@@ -15910,11 +16321,14 @@ export interface operations {
}
}
responses: {
+ /** @description Batch invitations result when using "emails" field. null/no body when using legacy "email" field. */
201: {
headers: {
[name: string]: unknown
}
- content?: never
+ content: {
+ 'application/json': components['schemas']['CreateInvitationResponse']
+ }
}
/** @description Unauthorized */
401: {
@@ -17462,6 +17876,27 @@ export interface operations {
}
}
}
+ OrganizationsController_handleOnboardingSurvey: {
+ parameters: {
+ query?: never
+ header?: never
+ path?: never
+ cookie?: never
+ }
+ requestBody: {
+ content: {
+ 'application/json': components['schemas']['OnboardingSurveyBody']
+ }
+ }
+ responses: {
+ 204: {
+ headers: {
+ [name: string]: unknown
+ }
+ content?: never
+ }
+ }
+ }
OrganizationsController_previewOrganizationCreation: {
parameters: {
query?: never