b5212dcdc2
Add traceable ledger filtering and permanent referral codes so operators can investigate credit activity without weakening immutable accounting guarantees.
1975 lines
73 KiB
YAML
1975 lines
73 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: OSG Account Server API
|
|
version: 0.1.0
|
|
description: |
|
|
Account, credit, referral, integrity, and managed AI APIs for OSGKeyboard.
|
|
Local features and user-owned API keys remain independent of this service.
|
|
servers:
|
|
- url: https://account.osglab.com
|
|
security:
|
|
- bearerAuth: []
|
|
paths:
|
|
/health:
|
|
get:
|
|
security: []
|
|
summary: Compatibility health check
|
|
responses:
|
|
"200": { $ref: "#/components/responses/HealthUp" }
|
|
/health/live:
|
|
get:
|
|
security: []
|
|
summary: Process liveness
|
|
responses:
|
|
"200": { $ref: "#/components/responses/HealthUp" }
|
|
/health/ready:
|
|
get:
|
|
security: []
|
|
summary: Database and migration readiness
|
|
responses:
|
|
"200": { $ref: "#/components/responses/HealthUp" }
|
|
"503":
|
|
description: Database is unavailable or migrations failed.
|
|
/v1/auth/apple:
|
|
post:
|
|
security: []
|
|
summary: Exchange Sign in with Apple credentials for an OSG session
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AppleSignInRequest" }
|
|
responses:
|
|
"200":
|
|
description: Authenticated session
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/SessionTokenEnvelope" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/auth/refresh:
|
|
post:
|
|
security: []
|
|
summary: Rotate a refresh token
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [refreshToken]
|
|
properties:
|
|
refreshToken: { type: string, minLength: 32 }
|
|
responses:
|
|
"200":
|
|
description: Rotated session
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/SessionTokenEnvelope" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/auth/logout:
|
|
post:
|
|
summary: Revoke the current session family
|
|
responses:
|
|
"204": { description: Session revoked }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/analytics/events:
|
|
post:
|
|
security:
|
|
- {}
|
|
- bearerAuth: []
|
|
summary: Idempotently accept privacy-minimized product events
|
|
description: |
|
|
Accepts pre-login or authenticated client events. The random
|
|
installation UUID is stored only as a digest. When a valid bearer
|
|
session is supplied, the installation is linked to the account and is
|
|
deleted with that account. Audio, user text, prompts, transcripts,
|
|
model output, credentials and arbitrary properties are never accepted.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ProductAnalyticsBatchRequest" }
|
|
responses:
|
|
"200":
|
|
description: Atomic batch acceptance and replay counts
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ProductAnalyticsBatchResponse" }
|
|
"400": { $ref: "#/components/responses/Error" }
|
|
"409": { $ref: "#/components/responses/Error" }
|
|
"422": { $ref: "#/components/responses/Error" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/account:
|
|
get:
|
|
summary: Return the account profile
|
|
responses:
|
|
"200":
|
|
description: Account profile
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AccountEnvelope" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
patch:
|
|
summary: Update the current account nickname
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/UpdateAccountProfileRequest" }
|
|
responses:
|
|
"200":
|
|
description: Updated account profile
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AccountEnvelope" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
delete:
|
|
summary: Reauthenticate with Apple, delete the account, and revoke authorization
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/DeleteAccountRequest" }
|
|
responses:
|
|
"204": { description: Account deleted }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/apple/events:
|
|
post:
|
|
security: []
|
|
summary: Receive a signed Apple server-to-server account event
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [payload]
|
|
properties:
|
|
payload: { type: string }
|
|
responses:
|
|
"204": { description: Event accepted }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/credits/balance:
|
|
get:
|
|
summary: Return available and consumed integer credits
|
|
responses:
|
|
"200":
|
|
description: Credit account
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CreditAccount" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/credits/ledger:
|
|
get:
|
|
summary: Return immutable credit history
|
|
parameters:
|
|
- $ref: "#/components/parameters/Limit"
|
|
responses:
|
|
"200":
|
|
description: Ledger entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/LedgerEntry" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/credits/rates:
|
|
get:
|
|
summary: Return effective managed-provider rate cards
|
|
responses:
|
|
"200":
|
|
description: Effective rate cards
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items: { type: object, additionalProperties: true }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/storekit/products:
|
|
get:
|
|
summary: Return enabled consumable credit products
|
|
description: |
|
|
Current catalog: `500tks` grants 500 credits, `1500tks` grants 1,500
|
|
credits, and `3000tks` grants 3,000 credits. Localized prices are
|
|
supplied by StoreKit.
|
|
responses:
|
|
"200":
|
|
description: StoreKit credit product catalog
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/StoreKitProduct" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/storekit/transactions:
|
|
get:
|
|
summary: Return credited StoreKit purchase history for the current account
|
|
description: |
|
|
Returns only App Store transactions that were previously verified and
|
|
committed with their immutable credit-ledger entries. Results include
|
|
purchases credited before this endpoint was introduced and never call
|
|
the App Store at query time. The opaque cursor follows the stable
|
|
descending order of `purchasedAt` and `transactionId`.
|
|
parameters:
|
|
- $ref: "#/components/parameters/Limit"
|
|
- name: cursor
|
|
in: query
|
|
description: Opaque cursor returned by the preceding page.
|
|
schema: { type: string, minLength: 1, maxLength: 256 }
|
|
responses:
|
|
"200":
|
|
description: Credited StoreKit purchases for the authenticated account
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/StoreKitTransactionHistory" }
|
|
"400": { $ref: "#/components/responses/Error" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
post:
|
|
summary: Verify an App Store transaction and idempotently grant credits
|
|
description: |
|
|
Submit the StoreKit 2 `VerificationResult.jwsRepresentation` before
|
|
finishing the consumable transaction. The purchase must include an
|
|
`appAccountToken` equal to the authenticated account UUID. Replaying
|
|
the same App Store transaction returns the original grant.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/StoreKitTransactionRequest" }
|
|
responses:
|
|
"200":
|
|
description: Verified purchase grant or idempotent replay
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/StoreKitPurchase" }
|
|
"409": { $ref: "#/components/responses/Error" }
|
|
"422": { $ref: "#/components/responses/Error" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/referrals:
|
|
get:
|
|
summary: List invitees without exposing their Apple identity
|
|
parameters:
|
|
- $ref: "#/components/parameters/Limit"
|
|
responses:
|
|
"200":
|
|
description: Referral bindings
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items: { type: object, additionalProperties: true }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/referrals/me:
|
|
get:
|
|
summary: Return the referral profile and provision its permanent account invite code
|
|
responses:
|
|
"200":
|
|
description: Referral profile
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ReferralProfile" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/referrals/code:
|
|
post:
|
|
deprecated: true
|
|
summary: Compatibility endpoint for the permanent account invite code
|
|
responses:
|
|
"200":
|
|
description: Invite code
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ReferralCode" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/referrals/redeem:
|
|
post:
|
|
summary: Bind the account to an inviter during the eligibility window
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/RedeemReferralRequest" }
|
|
responses:
|
|
"200": { description: Referral binding }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/referrals/bind:
|
|
post:
|
|
deprecated: true
|
|
summary: Compatibility alias for referral redemption
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/RedeemReferralRequest" }
|
|
responses:
|
|
"200": { description: Referral binding }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/referrals/campaigns:
|
|
get:
|
|
summary: Return active referral campaigns
|
|
responses:
|
|
"200": { description: Active campaigns }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/integrity/challenges:
|
|
post:
|
|
security: []
|
|
summary: Issue a single-use App Attest challenge
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AppAttestChallengeRequest" }
|
|
responses:
|
|
"201":
|
|
description: Challenge issued
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AppAttestChallengeResponse" }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/integrity/attest:
|
|
post:
|
|
security: []
|
|
summary: Register a validated App Attest key
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AppAttestationRequest" }
|
|
responses:
|
|
"204": { description: Key registered }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/integrity/assert:
|
|
post:
|
|
security: []
|
|
summary: Validate a challenge-only App Attest assertion
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AppAssertionRequest" }
|
|
responses:
|
|
"200": { description: Assertion counter advanced }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/gateway/catalog:
|
|
get:
|
|
summary: Return configured managed-provider capabilities
|
|
responses:
|
|
"200": { description: Provider catalog }
|
|
default: { $ref: "#/components/responses/Error" }
|
|
/v1/gateway/grants:
|
|
post:
|
|
summary: Create an idempotent managed-provider grant
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CreateGatewayGrantRequest" }
|
|
responses:
|
|
"201":
|
|
description: Gateway grant and rotating credentials
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/GatewayGrantTokens" }
|
|
default: { $ref: "#/components/responses/GatewayError" }
|
|
/v1/gateway/grants/refresh:
|
|
post:
|
|
security: []
|
|
summary: Rotate a gateway refresh token
|
|
parameters:
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/RefreshGatewayGrantRequest" }
|
|
responses:
|
|
"200":
|
|
description: Rotated gateway credentials
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/GatewayGrantTokens" }
|
|
default: { $ref: "#/components/responses/GatewayError" }
|
|
/v1/gateway/grants/{grantId}:
|
|
delete:
|
|
summary: Revoke a gateway grant
|
|
parameters:
|
|
- name: grantId
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
responses:
|
|
"204": { description: Gateway grant revoked }
|
|
default: { $ref: "#/components/responses/GatewayError" }
|
|
/v1/gateway/llm/{capability}:
|
|
post:
|
|
summary: Run a metered polish, AI, or agent request
|
|
description: |
|
|
The server deterministically selects model, thinking, search, tools, retry,
|
|
and output-budget policy from `capability` plus optional `taskKind`. It
|
|
never infers task type from `input` or `context`, and clients cannot
|
|
supply provider parameters. Search and tools are currently disabled.
|
|
An authenticated `oobe` purpose is accepted only for dictation polish.
|
|
The first successful request per account is complimentary; later attempts
|
|
fail without falling through to paid billing.
|
|
parameters:
|
|
- $ref: "#/components/parameters/RequestId"
|
|
- name: capability
|
|
in: path
|
|
required: true
|
|
schema: { type: string, enum: [polish, ai, agent] }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/TextGatewayRequest" }
|
|
responses:
|
|
"200":
|
|
description: JSON response, or SSE when stream is true
|
|
default: { $ref: "#/components/responses/GatewayError" }
|
|
/v1/gateway/asr:
|
|
post:
|
|
summary: Run buffered metered ASR
|
|
parameters:
|
|
- $ref: "#/components/parameters/RequestId"
|
|
- { name: X-Audio-Duration-Ms, in: header, required: true, schema: { type: integer, minimum: 1, maximum: 600000 } }
|
|
- { name: X-Audio-Format, in: header, schema: { type: string, enum: [pcm, wav, ogg, mp3], default: pcm } }
|
|
- { name: X-Audio-Codec, in: header, schema: { type: string, enum: [raw, opus], default: raw } }
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/octet-stream:
|
|
schema: { type: string, contentEncoding: binary }
|
|
responses:
|
|
"200": { description: Newline-delimited Volcengine ASR result frames }
|
|
default: { $ref: "#/components/responses/GatewayError" }
|
|
/v1/gateway/asr/sessions:
|
|
post:
|
|
summary: Reserve credits and create a one-shot streaming ASR session
|
|
parameters:
|
|
- $ref: "#/components/parameters/RequestId"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CreateAsrSessionRequest" }
|
|
responses:
|
|
"201":
|
|
description: Session created
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/CreateAsrSessionResponse" }
|
|
default: { $ref: "#/components/responses/GatewayError" }
|
|
/v1/gateway/asr/sessions/{sessionId}/stream:
|
|
get:
|
|
summary: Upgrade to WebSocket and stream binary audio frames
|
|
description: |
|
|
Send authenticated binary audio frames, then the exact text frame
|
|
`{"type":"end"}`. The server forwards binary provider-result frames and
|
|
closes the one-shot session after settlement.
|
|
parameters:
|
|
- name: sessionId
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
responses:
|
|
"101": { description: WebSocket upgrade }
|
|
default: { $ref: "#/components/responses/GatewayError" }
|
|
/.well-known/apple-app-site-association:
|
|
get:
|
|
servers:
|
|
- url: https://osglab.com
|
|
security: []
|
|
summary: Return the Apple Universal Links association document
|
|
responses:
|
|
"200":
|
|
description: AASA JSON without a redirect
|
|
headers:
|
|
Cache-Control:
|
|
schema: { type: string, const: "no-store, max-age=0" }
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AppleAppSiteAssociation" }
|
|
/apple-app-site-association:
|
|
get:
|
|
servers:
|
|
- url: https://osglab.com
|
|
security: []
|
|
summary: Return the root compatibility AASA document
|
|
responses:
|
|
"200":
|
|
description: AASA JSON without a redirect
|
|
headers:
|
|
Cache-Control:
|
|
schema: { type: string, const: "no-store, max-age=0" }
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AppleAppSiteAssociation" }
|
|
/i/{code}:
|
|
get:
|
|
servers:
|
|
- url: https://osglab.com
|
|
security: []
|
|
summary: Privacy-preserving invitation landing page
|
|
parameters:
|
|
- name: code
|
|
in: path
|
|
required: true
|
|
schema: { type: string, pattern: "^[A-Za-z0-9_-]{22}$" }
|
|
responses:
|
|
"200": { description: Bilingual HTML landing page }
|
|
"404": { description: Invalid, unknown, or expired invitation }
|
|
"503": { description: Invitation lookup is temporarily unavailable }
|
|
/v1/admin/auth/session:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
summary: Check the current administrator session
|
|
responses:
|
|
"200":
|
|
description: Authenticated or anonymous session state
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminSessionState" }
|
|
"404": { description: Verified administrator client certificate is absent while mTLS is required }
|
|
/v1/admin/auth/login:
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
summary: Authenticate an administrator with password and TOTP
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [username, password, totpCode]
|
|
properties:
|
|
username: { type: string, minLength: 3, maxLength: 64 }
|
|
password: { type: string, minLength: 1, maxLength: 1024 }
|
|
totpCode: { type: string, pattern: "^[0-9]{6}$" }
|
|
responses:
|
|
"200":
|
|
description: Secure session and CSRF cookies created
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminLoginResponse" }
|
|
"401": { description: Credentials are invalid }
|
|
"429": { description: Login is locked or rate limited }
|
|
/v1/admin/auth/logout:
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Revoke the current administrator session
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminCsrf"
|
|
responses:
|
|
"204": { description: Session revoked }
|
|
"401": { description: Session is invalid }
|
|
/v1/admin/overview:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Return registration, activity, and credit overview statistics
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminRange"
|
|
responses:
|
|
"200":
|
|
description: Overview statistics
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminOverview" }
|
|
"400": { description: Range is invalid }
|
|
"401": { description: Session is invalid }
|
|
/v1/admin/referrals:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Return referral funnel and ranking statistics
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminRange"
|
|
- name: sort
|
|
in: query
|
|
schema: { type: string, enum: [invited, qualified, creditsEarned] }
|
|
- $ref: "#/components/parameters/AdminSortOrder"
|
|
- name: limit
|
|
in: query
|
|
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
|
|
responses:
|
|
"200":
|
|
description: Referral statistics
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminReferralOverview" }
|
|
"400": { description: Range, sort, order, or limit is invalid }
|
|
"401": { description: Session is invalid }
|
|
/v1/admin/analytics:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Return product growth, retention, usage and monetization analytics
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminRange"
|
|
responses:
|
|
"200":
|
|
description: Privacy-minimized product analytics aggregates
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminProductAnalytics" }
|
|
"400": { description: Range is invalid }
|
|
"401": { description: Session is invalid }
|
|
/v1/admin/users:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: List users or search by full or 8-character internal user ID suffix
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
schema: { type: string, maxLength: 36 }
|
|
- name: cursor
|
|
in: query
|
|
schema: { type: string, maxLength: 256 }
|
|
- $ref: "#/components/parameters/Limit"
|
|
- $ref: "#/components/parameters/AdminFrom"
|
|
- $ref: "#/components/parameters/AdminUntil"
|
|
- name: status
|
|
in: query
|
|
schema: { type: string, enum: [active, suspended] }
|
|
- $ref: "#/components/parameters/AdminCreatedAtSort"
|
|
- $ref: "#/components/parameters/AdminSortOrder"
|
|
responses:
|
|
"200":
|
|
description: Privacy-minimized user summaries
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminUserPage" }
|
|
"400": { description: Query, filter, sort, limit, or cursor is malformed }
|
|
"401": { description: Session is invalid }
|
|
"403": { description: ANALYST role cannot access user records }
|
|
/v1/admin/users/{userId}:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Return privacy-minimized user details
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminUserId"
|
|
responses:
|
|
"200":
|
|
description: User details
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminUserDetail" }
|
|
"403": { description: ANALYST role cannot access user records }
|
|
"404": { description: User was not found }
|
|
/v1/admin/users/{userId}/ledger:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Return the immutable credit ledger for a user
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminUserId"
|
|
- name: cursor
|
|
in: query
|
|
schema: { type: string, maxLength: 256 }
|
|
- $ref: "#/components/parameters/AdminLedgerLimit"
|
|
- $ref: "#/components/parameters/AdminFrom"
|
|
- $ref: "#/components/parameters/AdminUntil"
|
|
- $ref: "#/components/parameters/AdminLedgerType"
|
|
- $ref: "#/components/parameters/AdminLedgerEntryType"
|
|
- $ref: "#/components/parameters/AdminLedgerUsageType"
|
|
- $ref: "#/components/parameters/AdminLedgerReferenceId"
|
|
- $ref: "#/components/parameters/AdminLedgerSort"
|
|
- $ref: "#/components/parameters/AdminSortOrder"
|
|
responses:
|
|
"200":
|
|
description: Credit ledger entries ordered by the requested field and unique entry ID
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminLedgerPage" }
|
|
"400": { description: Filter, sort, limit, or cursor is malformed }
|
|
"403": { description: ANALYST role cannot access credit ledger records }
|
|
"404": { description: User was not found }
|
|
/v1/admin/credits/ledger:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Return the latest immutable credit ledger entries across users
|
|
parameters:
|
|
- name: cursor
|
|
in: query
|
|
schema: { type: string, maxLength: 256 }
|
|
- $ref: "#/components/parameters/AdminLedgerLimit"
|
|
- $ref: "#/components/parameters/AdminFrom"
|
|
- $ref: "#/components/parameters/AdminUntil"
|
|
- $ref: "#/components/parameters/AdminLedgerType"
|
|
- $ref: "#/components/parameters/AdminLedgerEntryType"
|
|
- $ref: "#/components/parameters/AdminLedgerUsageType"
|
|
- $ref: "#/components/parameters/AdminLedgerReferenceId"
|
|
- $ref: "#/components/parameters/AdminLedgerSort"
|
|
- $ref: "#/components/parameters/AdminSortOrder"
|
|
responses:
|
|
"200":
|
|
description: Latest credit ledger entries ordered by the requested field and unique entry ID
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminLedgerPage" }
|
|
"400": { description: Filter, sort, limit, or cursor is malformed }
|
|
"403": { description: ANALYST role cannot access credit ledger records }
|
|
/v1/admin/credits/grants:
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Grant integer credits through an idempotent ledger transaction
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminCsrf"
|
|
- $ref: "#/components/parameters/IdempotencyKey"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [userId, amount, reason]
|
|
properties:
|
|
userId: { type: string, format: uuid }
|
|
amount: { type: integer, format: int64, minimum: 1 }
|
|
reason: { type: string, minLength: 4, maxLength: 200 }
|
|
responses:
|
|
"200":
|
|
description: Grant applied or replayed
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminGrantResponse" }
|
|
"400": { description: Grant input or idempotency key is invalid }
|
|
"403": { description: CSRF or role authorization failed }
|
|
"404": { description: Target user was not found }
|
|
"409": { description: Idempotency key conflicts with another grant }
|
|
/v1/admin/operators/summary:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Return administrator and active-session security indicators
|
|
responses:
|
|
"200":
|
|
description: Security indicators
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [enabledOperators, lockedOperators, activeSessions]
|
|
properties:
|
|
enabledOperators: { type: integer, minimum: 0 }
|
|
lockedOperators: { type: integer, minimum: 0 }
|
|
activeSessions: { type: integer, format: int64, minimum: 0 }
|
|
"403": { description: INSUFFICIENT_PERMISSION; SUPER_ADMIN is required }
|
|
/v1/admin/operators:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: List administrator operators
|
|
parameters:
|
|
- name: cursor
|
|
in: query
|
|
schema: { type: string, maxLength: 256 }
|
|
- $ref: "#/components/parameters/Limit"
|
|
- $ref: "#/components/parameters/AdminFrom"
|
|
- $ref: "#/components/parameters/AdminUntil"
|
|
- name: role
|
|
in: query
|
|
schema: { type: string, enum: [SUPER_ADMIN, SUPPORT, ANALYST] }
|
|
- name: enabled
|
|
in: query
|
|
schema: { type: boolean }
|
|
- name: locked
|
|
in: query
|
|
description: Whether locked_until is later than the request time.
|
|
schema: { type: boolean }
|
|
- name: sort
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [createdAt, username, lastLoginAt]
|
|
default: createdAt
|
|
- $ref: "#/components/parameters/AdminSortOrder"
|
|
responses:
|
|
"200":
|
|
description: Operators ordered by the requested stable sort and operator ID; null lastLoginAt values are last
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminOperatorPage" }
|
|
"403": { description: INSUFFICIENT_PERMISSION; SUPER_ADMIN is required }
|
|
"400": { description: Filter, sort, limit, or cursor is malformed }
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Create an operator and return TOTP provisioning data once
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminCsrf"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminOperatorCreateRequest" }
|
|
responses:
|
|
"201":
|
|
description: Operator created; plaintext TOTP material is returned only here
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminOperatorProvisioning" }
|
|
"400": { description: VALIDATION_ERROR }
|
|
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
|
"409": { description: ADMIN_USERNAME_CONFLICT }
|
|
/v1/admin/operators/{operatorId}/enable:
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Enable an operator
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminOperatorId"
|
|
- $ref: "#/components/parameters/AdminCsrf"
|
|
responses:
|
|
"204": { description: Operator enabled and action audited }
|
|
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
|
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
|
/v1/admin/operators/{operatorId}/disable:
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Disable an operator and atomically revoke all active sessions
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminOperatorId"
|
|
- $ref: "#/components/parameters/AdminCsrf"
|
|
responses:
|
|
"204": { description: Operator disabled and sessions revoked }
|
|
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
|
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
|
"409": { description: CANNOT_DISABLE_SELF or LAST_SUPER_ADMIN_REQUIRED }
|
|
/v1/admin/operators/{operatorId}/unlock:
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Clear an operator login lock
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminOperatorId"
|
|
- $ref: "#/components/parameters/AdminCsrf"
|
|
responses:
|
|
"204": { description: Operator unlocked }
|
|
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
|
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
|
/v1/admin/operators/{operatorId}/credentials/reset:
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Reset password and TOTP, atomically revoking all active sessions
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminOperatorId"
|
|
- $ref: "#/components/parameters/AdminCsrf"
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminOperatorPasswordRequest" }
|
|
responses:
|
|
"200":
|
|
description: Credentials reset; plaintext TOTP material is returned only here
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminOperatorProvisioning" }
|
|
"400": { description: VALIDATION_ERROR }
|
|
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
|
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
|
/v1/admin/operators/{operatorId}/sessions/revoke:
|
|
post:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Revoke every active session for an operator
|
|
parameters:
|
|
- $ref: "#/components/parameters/AdminOperatorId"
|
|
- $ref: "#/components/parameters/AdminCsrf"
|
|
responses:
|
|
"204": { description: All active sessions revoked }
|
|
"403": { description: CSRF_INVALID, ORIGIN_INVALID, or INSUFFICIENT_PERMISSION }
|
|
"404": { description: ADMIN_OPERATOR_NOT_FOUND }
|
|
/v1/admin/audit:
|
|
get:
|
|
security:
|
|
- adminMtls: []
|
|
adminSession: []
|
|
summary: Return append-only administrator audit events
|
|
parameters:
|
|
- name: cursor
|
|
in: query
|
|
schema: { type: string, maxLength: 256 }
|
|
- $ref: "#/components/parameters/Limit"
|
|
- $ref: "#/components/parameters/AdminFrom"
|
|
- $ref: "#/components/parameters/AdminUntil"
|
|
- name: action
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum:
|
|
- LOGIN_SUCCEEDED
|
|
- LOGIN_FAILED
|
|
- SESSION_REVOKED
|
|
- OPERATOR_CREATED
|
|
- OPERATOR_ENABLED
|
|
- OPERATOR_DISABLED
|
|
- OPERATOR_UNLOCKED
|
|
- OPERATOR_CREDENTIALS_RESET
|
|
- OPERATOR_SESSIONS_REVOKED
|
|
- MANUAL_CREDIT_GRANTED
|
|
- name: result
|
|
in: query
|
|
schema: { type: string, enum: [success, rejected] }
|
|
- $ref: "#/components/parameters/AdminCreatedAtSort"
|
|
- $ref: "#/components/parameters/AdminSortOrder"
|
|
responses:
|
|
"200":
|
|
description: Recent audit events
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/AdminAuditPage" }
|
|
"400": { description: Filter, sort, limit, or cursor is malformed }
|
|
"403": { description: Super-administrator role is required }
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
adminMtls:
|
|
type: mutualTLS
|
|
description: Client certificate issued by the dedicated administrator CA; required when ADMIN_MTLS_REQUIRED is true.
|
|
adminSession:
|
|
type: apiKey
|
|
in: cookie
|
|
name: osg_admin_session
|
|
parameters:
|
|
Limit:
|
|
name: limit
|
|
in: query
|
|
schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
|
|
RequestId:
|
|
name: X-Request-ID
|
|
in: header
|
|
required: true
|
|
schema: { type: string, pattern: "^[A-Za-z0-9_-]{8,64}$" }
|
|
IdempotencyKey:
|
|
name: Idempotency-Key
|
|
in: header
|
|
required: true
|
|
schema: { type: string, minLength: 8, maxLength: 128 }
|
|
AdminCsrf:
|
|
name: X-CSRF-Token
|
|
in: header
|
|
required: true
|
|
schema: { type: string, minLength: 32, maxLength: 512 }
|
|
AdminRange:
|
|
name: range
|
|
in: query
|
|
schema: { type: string, enum: [7d, 30d, 90d], default: 30d }
|
|
AdminFrom:
|
|
name: from
|
|
in: query
|
|
description: Inclusive UTC lower bound. When both bounds are present, from must be earlier than until.
|
|
schema: { type: string, format: date-time }
|
|
AdminUntil:
|
|
name: until
|
|
in: query
|
|
description: Exclusive UTC upper bound.
|
|
schema: { type: string, format: date-time }
|
|
AdminCreatedAtSort:
|
|
name: sort
|
|
in: query
|
|
schema: { type: string, enum: [createdAt], default: createdAt }
|
|
AdminSortOrder:
|
|
name: order
|
|
in: query
|
|
schema: { type: string, enum: [asc, desc] }
|
|
AdminLedgerType:
|
|
name: type
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [grant, reserve, settle, refund]
|
|
AdminLedgerEntryType:
|
|
name: entryType
|
|
in: query
|
|
description: Exact immutable ledger entry type. This filter is ANDed with all other filters.
|
|
schema:
|
|
$ref: "#/components/schemas/LedgerEntryType"
|
|
AdminLedgerUsageType:
|
|
name: usageType
|
|
in: query
|
|
description: Product usage associated with the reservation. HOTWORD request source takes precedence over capability.
|
|
schema: { type: string, enum: [polish, asr, ai, agent, hotword] }
|
|
AdminLedgerReferenceId:
|
|
name: referenceId
|
|
in: query
|
|
schema: { type: string, format: uuid }
|
|
AdminLedgerSort:
|
|
name: sort
|
|
in: query
|
|
schema: { type: string, enum: [createdAt, amount], default: createdAt }
|
|
AdminLedgerLimit:
|
|
name: limit
|
|
in: query
|
|
schema: { type: integer, minimum: 1, maximum: 100, default: 100 }
|
|
AdminUserId:
|
|
name: userId
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
AdminOperatorId:
|
|
name: operatorId
|
|
in: path
|
|
required: true
|
|
schema: { type: string, format: uuid }
|
|
responses:
|
|
HealthUp:
|
|
description: Service is healthy
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [status]
|
|
properties:
|
|
status: { type: string, const: UP }
|
|
Error:
|
|
description: API error
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/ApiErrorEnvelope" }
|
|
GatewayError:
|
|
description: Managed-provider error
|
|
content:
|
|
application/json:
|
|
schema: { $ref: "#/components/schemas/GatewayError" }
|
|
schemas:
|
|
ProductAnalyticsEvent:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [clientEventId, eventType, occurredAt, surface]
|
|
properties:
|
|
clientEventId: { type: string, format: uuid }
|
|
eventType:
|
|
type: string
|
|
enum:
|
|
- FIRST_OPEN
|
|
- SESSION_STARTED
|
|
- KEYBOARD_ACTIVATED
|
|
- AI_FEATURE_STARTED
|
|
- AI_FEATURE_SUCCEEDED
|
|
- AI_FEATURE_FAILED
|
|
- PURCHASE_VIEWED
|
|
- PURCHASE_STARTED
|
|
- PURCHASE_CANCELLED
|
|
- REFERRAL_SHARED
|
|
- INVITE_OPENED
|
|
occurredAt: { type: string, format: date-time }
|
|
surface: { type: string, enum: [APP, KEYBOARD, INVITE_WEB] }
|
|
acquisitionChannel:
|
|
type: string
|
|
enum: [APP_STORE_ORGANIC, REFERRAL, SOCIAL_CONTENT, UNKNOWN]
|
|
feature:
|
|
type: string
|
|
enum: [TRANSCRIPTION, POLISH, AI_ASSISTANT, AGENT, HOTWORD, OTHER]
|
|
executionMode: { type: string, enum: [MANAGED, LOCAL, BYOK] }
|
|
failureCategory:
|
|
type: string
|
|
enum: [NETWORK, PROVIDER, TIMEOUT, CANCELLED, INSUFFICIENT_CREDITS, VALIDATION, UNKNOWN]
|
|
durationBucket:
|
|
type: string
|
|
enum: [LT_1S, S1_TO_3, S3_TO_10, S10_TO_30, GTE_30S]
|
|
appVersion:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 32
|
|
pattern: "^[A-Za-z0-9._+-]+$"
|
|
osVersion:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 32
|
|
pattern: "^[A-Za-z0-9._+-]+$"
|
|
ProductAnalyticsBatchRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [installationId, events]
|
|
properties:
|
|
installationId: { type: string, format: uuid }
|
|
events:
|
|
type: array
|
|
minItems: 1
|
|
maxItems: 50
|
|
items: { $ref: "#/components/schemas/ProductAnalyticsEvent" }
|
|
ProductAnalyticsBatchResponse:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [accepted, replayed]
|
|
properties:
|
|
accepted: { type: integer, minimum: 0, maximum: 50 }
|
|
replayed: { type: integer, minimum: 0, maximum: 50 }
|
|
AdminSessionState:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [authenticated]
|
|
properties:
|
|
authenticated: { type: boolean }
|
|
operatorName: { type: ["string", "null"], minLength: 3, maxLength: 64 }
|
|
role:
|
|
type: ["string", "null"]
|
|
enum: [SUPER_ADMIN, SUPPORT, ANALYST, null]
|
|
description: CSRF material is intentionally not reconstructed or returned by session checks.
|
|
AdminLoginResponse:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [operatorName, role, csrfToken]
|
|
properties:
|
|
operatorName: { type: string, minLength: 3, maxLength: 64 }
|
|
role: { type: string, enum: [SUPER_ADMIN, SUPPORT, ANALYST] }
|
|
csrfToken:
|
|
type: string
|
|
minLength: 32
|
|
maxLength: 512
|
|
description: Returned once for the new session; the CSRF cookie is the reload fallback.
|
|
AdminUsageAggregate:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [kind, requests, chargedCredits, asrMillis, inputTokens, outputTokens]
|
|
properties:
|
|
kind: { type: string }
|
|
requests: { type: integer, format: int64, minimum: 0 }
|
|
chargedCredits: { type: integer, format: int64, minimum: 0 }
|
|
asrMillis: { type: integer, format: int64, minimum: 0 }
|
|
inputTokens: { type: integer, format: int64, minimum: 0 }
|
|
outputTokens: { type: integer, format: int64, minimum: 0 }
|
|
AdminTrendPoint:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [date, registrations, creditsUsed]
|
|
properties:
|
|
date: { type: string, format: date }
|
|
registrations: { type: integer, format: int64, minimum: 0 }
|
|
creditsUsed: { type: integer, format: int64, minimum: 0 }
|
|
AdminOverview:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- totalUsers
|
|
- activeUsers
|
|
- newUsers
|
|
- totalCreditBalance
|
|
- creditsGranted
|
|
- creditsUsed
|
|
- trend
|
|
- usage
|
|
properties:
|
|
totalUsers: { type: integer, format: int64, minimum: 0 }
|
|
activeUsers: { type: integer, format: int64, minimum: 0 }
|
|
newUsers: { type: integer, format: int64, minimum: 0 }
|
|
totalCreditBalance: { type: integer, format: int64, minimum: 0 }
|
|
creditsGranted: { type: integer, format: int64, minimum: 0 }
|
|
creditsUsed: { type: integer, format: int64, minimum: 0 }
|
|
trend:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminTrendPoint" }
|
|
usage:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminUsageAggregate" }
|
|
AdminFunnelStep:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [label, count]
|
|
properties:
|
|
label:
|
|
type: string
|
|
enum: [邀请码创建, 成功绑定, 有效使用并奖励]
|
|
count: { type: integer, format: int64, minimum: 0 }
|
|
AdminReferralRank:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [userId, invited, qualified, creditsEarned]
|
|
properties:
|
|
userId: { type: string, format: uuid }
|
|
invited: { type: integer, format: int64, minimum: 0 }
|
|
qualified: { type: integer, format: int64, minimum: 0 }
|
|
creditsEarned: { type: integer, format: int64, minimum: 0 }
|
|
AdminReferralOverview:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [pendingBindings, ineligibleBindings, funnel, ranking]
|
|
properties:
|
|
pendingBindings: { type: integer, format: int64, minimum: 0 }
|
|
ineligibleBindings: { type: integer, format: int64, minimum: 0 }
|
|
funnel:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminFunnelStep" }
|
|
ranking:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminReferralRank" }
|
|
AdminAnalyticsRate:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [numerator, denominator]
|
|
properties:
|
|
numerator: { type: integer, format: int64, minimum: 0 }
|
|
denominator: { type: integer, format: int64, minimum: 0 }
|
|
percent: { type: ["number", "null"], minimum: 0, maximum: 100 }
|
|
AdminAnalyticsFunnelStep:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [label, count]
|
|
properties:
|
|
label: { type: string, maxLength: 64 }
|
|
count: { type: integer, format: int64, minimum: 0 }
|
|
AdminAnalyticsChannel:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [channel, installations, activated, activationRate]
|
|
properties:
|
|
channel:
|
|
type: string
|
|
enum: [APP_STORE_ORGANIC, REFERRAL, SOCIAL_CONTENT, UNKNOWN]
|
|
installations: { type: integer, format: int64, minimum: 0 }
|
|
activated: { type: integer, format: int64, minimum: 0 }
|
|
activationRate: { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
AdminAnalyticsCohort:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [cohortDate, size]
|
|
properties:
|
|
cohortDate: { type: string, format: date }
|
|
size: { type: integer, format: int64, minimum: 0 }
|
|
d1:
|
|
anyOf:
|
|
- { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
- { type: "null" }
|
|
d7:
|
|
anyOf:
|
|
- { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
- { type: "null" }
|
|
d30:
|
|
anyOf:
|
|
- { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
- { type: "null" }
|
|
AdminAnalyticsFeatureUsage:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [feature, executionMode, users, successes]
|
|
properties:
|
|
feature:
|
|
type: string
|
|
enum: [TRANSCRIPTION, POLISH, AI_ASSISTANT, AGENT, HOTWORD, OTHER]
|
|
executionMode: { type: string, enum: [MANAGED, LOCAL, BYOK] }
|
|
users: { type: integer, format: int64, minimum: 0 }
|
|
successes: { type: integer, format: int64, minimum: 0 }
|
|
AdminProductAnalytics:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- period
|
|
- northStar
|
|
- growth
|
|
- activity
|
|
- consumption
|
|
- monetization
|
|
- growthFunnel
|
|
- retention
|
|
- aiFeatures
|
|
- referralFunnel
|
|
- guardrails
|
|
properties:
|
|
period:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [from, until]
|
|
properties:
|
|
from: { type: string, format: date-time }
|
|
until: { type: string, format: date-time }
|
|
northStar:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [weeklyAiActiveUsers, previousWeeklyAiActiveUsers]
|
|
properties:
|
|
weeklyAiActiveUsers: { type: integer, format: int64, minimum: 0 }
|
|
previousWeeklyAiActiveUsers: { type: integer, format: int64, minimum: 0 }
|
|
weekOverWeekPercent: { type: ["number", "null"] }
|
|
growth:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [newInstallations, newAccounts, activation24h, channels]
|
|
properties:
|
|
newInstallations: { type: integer, format: int64, minimum: 0 }
|
|
newAccounts: { type: integer, format: int64, minimum: 0 }
|
|
activation24h: { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
medianTimeToValueMinutes: { type: ["number", "null"], minimum: 0 }
|
|
channels:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminAnalyticsChannel" }
|
|
activity:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [dau, wau, mau, successfulAiRequests]
|
|
properties:
|
|
dau: { type: integer, format: int64, minimum: 0 }
|
|
wau: { type: integer, format: int64, minimum: 0 }
|
|
mau: { type: integer, format: int64, minimum: 0 }
|
|
stickinessPercent: { type: ["number", "null"], minimum: 0, maximum: 100 }
|
|
successfulAiRequests: { type: integer, format: int64, minimum: 0 }
|
|
successfulRequestsPerActiveUser: { type: ["number", "null"], minimum: 0 }
|
|
consumption:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [totalCredits]
|
|
properties:
|
|
totalCredits: { type: integer, format: int64, minimum: 0 }
|
|
averageDailyCreditsPerActiveUser: { type: ["number", "null"], minimum: 0 }
|
|
medianUserDailyCredits: { type: ["number", "null"], minimum: 0 }
|
|
averageCreditsPerManagedRequest: { type: ["number", "null"], minimum: 0 }
|
|
monetization:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
[payingUsers, purchases, creditsPurchased, conversion7d, conversion30d, repeatPurchaseRate]
|
|
properties:
|
|
payingUsers: { type: integer, format: int64, minimum: 0 }
|
|
purchases: { type: integer, format: int64, minimum: 0 }
|
|
creditsPurchased: { type: integer, format: int64, minimum: 0 }
|
|
conversion7d: { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
conversion30d: { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
repeatPurchaseRate: { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
growthFunnel:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminAnalyticsFunnelStep" }
|
|
retention:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminAnalyticsCohort" }
|
|
aiFeatures:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminAnalyticsFeatureUsage" }
|
|
referralFunnel:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminAnalyticsFunnelStep" }
|
|
guardrails:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [clientAiSuccessRate, managedSuccessRate, creditBlockedUsers]
|
|
properties:
|
|
clientAiSuccessRate: { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
managedSuccessRate: { $ref: "#/components/schemas/AdminAnalyticsRate" }
|
|
creditBlockedUsers: { type: integer, format: int64, minimum: 0 }
|
|
AdminUserSummary:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [userId, displayName, status, creditBalance, consumedCredits, createdAt]
|
|
properties:
|
|
userId: { type: string, format: uuid }
|
|
displayName: { type: string }
|
|
status: { type: string, enum: [active, suspended, closed] }
|
|
creditBalance: { type: integer, format: int64, minimum: 0 }
|
|
consumedCredits: { type: integer, format: int64, minimum: 0 }
|
|
createdAt: { type: string, format: date-time }
|
|
AdminUserPage:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [items]
|
|
properties:
|
|
items:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminUserSummary" }
|
|
nextCursor: { type: ["string", "null"] }
|
|
AdminUserReferral:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [invitedUsers, rewardedInvites]
|
|
properties:
|
|
inviterUserId: { type: ["string", "null"], format: uuid }
|
|
invitedUsers: { type: integer, format: int64, minimum: 0 }
|
|
rewardedInvites: { type: integer, format: int64, minimum: 0 }
|
|
AdminUserDetail:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- userId
|
|
- displayName
|
|
- status
|
|
- creditBalance
|
|
- consumedCredits
|
|
- createdAt
|
|
- qualifiedUsage
|
|
- usage
|
|
- referral
|
|
properties:
|
|
userId: { type: string, format: uuid }
|
|
displayName: { type: string }
|
|
status: { type: string, enum: [active, suspended, closed] }
|
|
creditBalance: { type: integer, format: int64, minimum: 0 }
|
|
consumedCredits: { type: integer, format: int64, minimum: 0 }
|
|
createdAt: { type: string, format: date-time }
|
|
lastActiveAt: { type: ["string", "null"], format: date-time }
|
|
qualifiedUsage: { type: boolean }
|
|
referralCode: { type: ["string", "null"] }
|
|
referredByUserId: { type: ["string", "null"], format: uuid }
|
|
usage:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminUsageAggregate" }
|
|
referral: { $ref: "#/components/schemas/AdminUserReferral" }
|
|
LedgerEntryType:
|
|
type: string
|
|
enum:
|
|
- SIGNUP_TRIAL
|
|
- MANUAL_GRANT
|
|
- USAGE_RESERVE
|
|
- USAGE_SETTLE
|
|
- USAGE_RELEASE
|
|
- USAGE_REFUND
|
|
- REFERRAL_INVITER
|
|
- REFERRAL_INVITEE
|
|
- STOREKIT_PURCHASE
|
|
- SUBSCRIPTION_GRANT
|
|
AdminLedgerDetails:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [kind]
|
|
description: Privacy-minimized source metadata. Missing source associations omit the details object.
|
|
properties:
|
|
kind: { type: string, enum: [manualGrant, storeKit, referral, usage] }
|
|
reason: { type: string, description: Present for manualGrant details }
|
|
operatorName: { type: string, description: Present for manualGrant details }
|
|
productId: { type: string, description: Present for storeKit details }
|
|
transactionId: { type: string, description: Present for storeKit details }
|
|
originalTransactionId: { type: string, description: Present for storeKit details }
|
|
environment: { type: string, enum: [SANDBOX, PRODUCTION], description: Present for storeKit details }
|
|
purchasedAt: { type: string, format: date-time, description: Present for storeKit details }
|
|
role: { type: string, enum: [inviter, invitee], description: Present for referral details }
|
|
relatedUserId: { type: string, format: uuid, description: Present for referral details }
|
|
reservationId: { type: string, format: uuid, description: Present for usage details }
|
|
AdminLedgerEntry:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [entryId, userId, type, entryType, amount, balanceAfter, reasonCode, createdAt]
|
|
properties:
|
|
entryId: { type: string, format: uuid }
|
|
userId: { type: string, format: uuid }
|
|
type: { type: string, enum: [grant, reserve, settle, refund] }
|
|
entryType: { $ref: "#/components/schemas/LedgerEntryType" }
|
|
amount: { type: integer, format: int64 }
|
|
balanceAfter: { type: integer, format: int64, minimum: 0 }
|
|
reasonCode:
|
|
allOf:
|
|
- $ref: "#/components/schemas/LedgerEntryType"
|
|
deprecated: true
|
|
description: Compatibility alias for entryType
|
|
referenceId: { type: ["string", "null"], format: uuid }
|
|
usageType:
|
|
type: ["string", "null"]
|
|
enum: [polish, asr, ai, agent, hotword, null]
|
|
description: Product usage associated with this ledger operation
|
|
details: { $ref: "#/components/schemas/AdminLedgerDetails" }
|
|
createdAt: { type: string, format: date-time }
|
|
AdminLedgerPage:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [items]
|
|
properties:
|
|
items:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminLedgerEntry" }
|
|
nextCursor: { type: ["string", "null"] }
|
|
AdminGrantResponse:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [transactionId, balanceAfter]
|
|
properties:
|
|
transactionId: { type: string, format: uuid }
|
|
balanceAfter: { type: integer, format: int64, minimum: 0 }
|
|
AdminAudit:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [auditId, operatorName, action, targetType, targetId, result, createdAt]
|
|
properties:
|
|
auditId: { type: string, format: uuid }
|
|
operatorName: { type: string }
|
|
action: { type: string }
|
|
targetType: { type: string }
|
|
targetId: { type: string }
|
|
requestId: { type: ["string", "null"] }
|
|
result: { type: string, enum: [success, rejected] }
|
|
createdAt: { type: string, format: date-time }
|
|
AdminAuditPage:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [items]
|
|
properties:
|
|
items:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminAudit" }
|
|
nextCursor: { type: ["string", "null"] }
|
|
AdminOperator:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
- operatorId
|
|
- username
|
|
- role
|
|
- enabled
|
|
- failedLoginCount
|
|
- createdAt
|
|
- updatedAt
|
|
properties:
|
|
operatorId: { type: string, format: uuid }
|
|
username:
|
|
type: string
|
|
pattern: "^[a-z0-9][a-z0-9._@-]{2,63}$"
|
|
role: { type: string, enum: [SUPER_ADMIN, SUPPORT, ANALYST] }
|
|
enabled: { type: boolean }
|
|
failedLoginCount: { type: integer, minimum: 0 }
|
|
lockedUntil: { type: ["string", "null"], format: date-time }
|
|
lastLoginAt: { type: ["string", "null"], format: date-time }
|
|
createdAt: { type: string, format: date-time }
|
|
updatedAt: { type: string, format: date-time }
|
|
AdminOperatorPage:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [items]
|
|
properties:
|
|
items:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/AdminOperator" }
|
|
nextCursor: { type: ["string", "null"] }
|
|
AdminOperatorCreateRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [username, password, role]
|
|
properties:
|
|
username:
|
|
type: string
|
|
minLength: 3
|
|
maxLength: 64
|
|
pattern: "^[A-Za-z0-9][A-Za-z0-9._@-]{2,63}$"
|
|
password: { type: string, minLength: 12, maxLength: 1024 }
|
|
role: { type: string, enum: [SUPER_ADMIN, SUPPORT, ANALYST] }
|
|
AdminOperatorPasswordRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [password]
|
|
properties:
|
|
password: { type: string, minLength: 12, maxLength: 1024 }
|
|
AdminOperatorProvisioning:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [operatorId, totpSecret, otpauthUri]
|
|
properties:
|
|
operatorId: { type: string, format: uuid }
|
|
operator:
|
|
oneOf:
|
|
- $ref: "#/components/schemas/AdminOperator"
|
|
- type: "null"
|
|
totpSecret:
|
|
type: string
|
|
pattern: "^[A-Z2-7]{32}$"
|
|
description: 160-bit Base32 secret returned once; never persisted in plaintext.
|
|
otpauthUri:
|
|
type: string
|
|
pattern: "^otpauth://totp/"
|
|
description: Provisioning URI returned once; never persisted.
|
|
AppleSignInRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [identityToken, authorizationCode, nonce]
|
|
properties:
|
|
identityToken:
|
|
type: string
|
|
description: Identity token returned by Sign in with Apple.
|
|
authorizationCode:
|
|
type: string
|
|
description: Single-use authorization code returned by Sign in with Apple.
|
|
nonce:
|
|
type: string
|
|
description: Raw nonce whose lowercase SHA-256 hex digest was sent to Apple.
|
|
displayName:
|
|
type: ["string", "null"]
|
|
maxLength: 128
|
|
description: Optional first-authorization Apple name used only to seed the nickname.
|
|
deviceCheckToken:
|
|
type: ["string", "null"]
|
|
description: Ephemeral DeviceCheck token; never persisted in plaintext.
|
|
appAttest:
|
|
oneOf:
|
|
- $ref: "#/components/schemas/AppAttestAssertion"
|
|
- type: "null"
|
|
AppAttestAssertion:
|
|
type: object
|
|
description: |
|
|
For Apple sign-in, generate the assertion with `clientDataHash` equal to
|
|
SHA-256 of the exact UTF-8 payload below, including the final line feed:
|
|
|
|
```
|
|
osg-app-attest-v1
|
|
purpose=apple-sign-in
|
|
challenge=<challenge>
|
|
identity_token_sha256=<identity-token-digest>
|
|
authorization_code_sha256=<authorization-code-digest>
|
|
nonce_sha256=<raw-nonce-digest>
|
|
```
|
|
|
|
`challenge` is the Base64URL value returned by `/v1/integrity/challenges`.
|
|
Each digest is SHA-256 of the corresponding UTF-8 request value, encoded
|
|
as unpadded Base64URL. The server reconstructs this payload and never
|
|
trusts a client-supplied hash.
|
|
additionalProperties: false
|
|
required: [keyId, challengeId, challenge, assertion]
|
|
properties:
|
|
keyId: { type: string, maxLength: 128 }
|
|
challengeId: { type: string, format: uuid }
|
|
challenge: { type: string, description: Base64URL challenge returned by the server }
|
|
assertion: { type: string, contentEncoding: base64 }
|
|
SessionTokenResponse:
|
|
type: object
|
|
required: [accountId, tokenType, accessToken, accessTokenExpiresAtEpochSeconds, refreshToken, refreshTokenExpiresAtEpochSeconds]
|
|
properties:
|
|
accountId: { type: string, format: uuid }
|
|
tokenType: { type: string, const: Bearer }
|
|
accessToken: { type: string }
|
|
accessTokenExpiresAtEpochSeconds: { type: integer, format: int64 }
|
|
refreshToken: { type: string }
|
|
refreshTokenExpiresAtEpochSeconds: { type: integer, format: int64 }
|
|
SessionTokenEnvelope:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [data]
|
|
properties:
|
|
data: { $ref: "#/components/schemas/SessionTokenResponse" }
|
|
Account:
|
|
type: object
|
|
required: [id, createdAtEpochSeconds]
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
createdAtEpochSeconds: { type: integer, format: int64 }
|
|
displayName:
|
|
type: ["string", "null"]
|
|
maxLength: 64
|
|
AccountEnvelope:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [data]
|
|
properties:
|
|
data: { $ref: "#/components/schemas/Account" }
|
|
UpdateAccountProfileRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [displayName]
|
|
properties:
|
|
displayName:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 64
|
|
DeleteAccountRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [identityToken, authorizationCode, nonce]
|
|
properties:
|
|
identityToken: { type: string, maxLength: 16384 }
|
|
authorizationCode: { type: string, maxLength: 4096 }
|
|
nonce: { type: string, maxLength: 512 }
|
|
CreditAccount:
|
|
type: object
|
|
additionalProperties: true
|
|
required: [userId, balance, lifetimeUsed]
|
|
properties:
|
|
userId: { type: string, format: uuid }
|
|
balance: { type: integer, format: int64, minimum: 0 }
|
|
lifetimeUsed:
|
|
type: integer
|
|
format: int64
|
|
minimum: 0
|
|
description: Settled usage minus credits returned by refunds
|
|
LedgerEntry:
|
|
type: object
|
|
additionalProperties: true
|
|
required: [id, amountDelta, balanceAfter]
|
|
properties:
|
|
id: { type: string, format: uuid }
|
|
amountDelta: { type: integer, format: int64 }
|
|
balanceAfter: { type: integer, format: int64, minimum: 0 }
|
|
StoreKitProduct:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [productId, credits]
|
|
properties:
|
|
productId:
|
|
type: string
|
|
enum: [500tks, 1500tks, 3000tks]
|
|
credits: { type: integer, format: int64, minimum: 1 }
|
|
StoreKitTransactionRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [signedTransaction]
|
|
properties:
|
|
signedTransaction:
|
|
type: string
|
|
minLength: 100
|
|
maxLength: 32768
|
|
description: StoreKit 2 VerificationResult.jwsRepresentation
|
|
StoreKitPurchase:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [transactionId, productId, creditsGranted, balanceAfter, replayed]
|
|
properties:
|
|
transactionId: { type: string, pattern: "^[0-9]{1,64}$" }
|
|
productId: { type: string, minLength: 3, maxLength: 128 }
|
|
creditsGranted: { type: integer, format: int64, minimum: 1 }
|
|
balanceAfter: { type: integer, format: int64, minimum: 0 }
|
|
replayed: { type: boolean }
|
|
StoreKitTransactionHistoryItem:
|
|
type: object
|
|
additionalProperties: false
|
|
required:
|
|
[transactionId, productId, creditsGranted, balanceAfter, purchasedAt, status]
|
|
properties:
|
|
transactionId: { type: string, pattern: "^[0-9]{1,64}$" }
|
|
productId: { type: string, minLength: 3, maxLength: 128 }
|
|
creditsGranted: { type: integer, format: int64, minimum: 1 }
|
|
balanceAfter: { type: integer, format: int64, minimum: 0 }
|
|
purchasedAt: { type: string, format: date-time }
|
|
status: { type: string, enum: [credited] }
|
|
StoreKitTransactionHistory:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [items, nextCursor]
|
|
properties:
|
|
items:
|
|
type: array
|
|
items: { $ref: "#/components/schemas/StoreKitTransactionHistoryItem" }
|
|
nextCursor:
|
|
type: ["string", "null"]
|
|
maxLength: 256
|
|
AppleAppSiteAssociation:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [applinks]
|
|
properties:
|
|
applinks:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [details]
|
|
properties:
|
|
details:
|
|
type: array
|
|
items:
|
|
type: object
|
|
required: [appIDs, components]
|
|
properties:
|
|
appIDs:
|
|
type: array
|
|
items: { type: string }
|
|
components:
|
|
type: array
|
|
items: { type: object, additionalProperties: true }
|
|
ReferralCode:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [code, inviteUrl, createdAt]
|
|
properties:
|
|
code:
|
|
type: string
|
|
pattern: "^[A-Za-z0-9_-]{22}$"
|
|
description: Permanent opaque identifier assigned once to the account.
|
|
inviteUrl:
|
|
type: string
|
|
format: uri
|
|
description: Stable first-party invitation URL containing the permanent code.
|
|
campaignId:
|
|
type: ["string", "null"]
|
|
format: uuid
|
|
description: Legacy creation metadata; it does not limit the invitation lifetime.
|
|
createdAt: { type: string, format: date-time }
|
|
ReferralProfile:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [code]
|
|
properties:
|
|
code: { $ref: "#/components/schemas/ReferralCode" }
|
|
binding:
|
|
type: ["object", "null"]
|
|
additionalProperties: true
|
|
RedeemReferralRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [code]
|
|
properties:
|
|
code: { type: string, pattern: "^[A-Za-z0-9_-]{22}$" }
|
|
AppAttestChallengeRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [purpose, keyId]
|
|
properties:
|
|
purpose: { type: string, enum: [attestation, assertion] }
|
|
keyId: { type: string, maxLength: 128 }
|
|
AppAttestChallengeResponse:
|
|
type: object
|
|
required: [challengeId, challenge, expiresAtEpochSeconds]
|
|
properties:
|
|
challengeId: { type: string, format: uuid }
|
|
challenge: { type: string }
|
|
expiresAtEpochSeconds: { type: integer, format: int64 }
|
|
AppAttestationRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [challengeId, challenge, keyId, attestationObject]
|
|
properties:
|
|
challengeId: { type: string, format: uuid }
|
|
challenge: { type: string }
|
|
keyId: { type: string }
|
|
attestationObject: { type: string, contentEncoding: base64 }
|
|
AppAssertionRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [challengeId, challenge, keyId, assertion, clientDataHash]
|
|
properties:
|
|
challengeId: { type: string, format: uuid }
|
|
challenge: { type: string }
|
|
keyId: { type: string }
|
|
assertion: { type: string, contentEncoding: base64 }
|
|
clientDataHash: { type: string, description: Base64URL SHA-256 of the echoed challenge }
|
|
TextGatewayRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [input]
|
|
properties:
|
|
input: { type: string, minLength: 1, maxLength: 32000 }
|
|
context: { type: ["string", "null"], maxLength: 32000 }
|
|
maxOutputTokens:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 4096
|
|
default: 512
|
|
description: |
|
|
Requested output budget. The server clamps dictation polish and
|
|
edit-last-input to 512 tokens; translation, clipboard transform,
|
|
and custom skill to 2,048; and reasoning tasks to 4,096.
|
|
temperature: { type: number, minimum: 0, maximum: 1, default: 0.2 }
|
|
stream: { type: boolean, default: false }
|
|
taskKind:
|
|
type: ["string", "null"]
|
|
enum:
|
|
- dictation_polish
|
|
- translation
|
|
- edit_last_input
|
|
- ai_question
|
|
- clipboard_transform
|
|
- custom_skill
|
|
- agent_planning
|
|
- null
|
|
description: |
|
|
Optional deterministic task selector. Allowed combinations are:
|
|
`polish` with `dictation_polish`, `translation`, or `edit_last_input`;
|
|
`ai` with `ai_question`, `clipboard_transform`, or `custom_skill`;
|
|
and `agent` with `agent_planning`. Omission defaults respectively to
|
|
`dictation_polish`, `ai_question`, and `agent_planning`. A mismatch
|
|
returns `400 invalid_request`.
|
|
requestSource:
|
|
type: ["string", "null"]
|
|
enum: [hotword, null]
|
|
description: Optional product entry point; hotword is accepted only for AI requests
|
|
requestPurpose:
|
|
type: ["string", "null"]
|
|
enum: [oobe, null]
|
|
description: |
|
|
Optional server-audited billing purpose. `oobe` is valid only with
|
|
`polish` and `dictation_polish`, and is complimentary once per account.
|
|
CreateGatewayGrantRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [scopes]
|
|
properties:
|
|
scopes:
|
|
type: array
|
|
uniqueItems: true
|
|
minItems: 1
|
|
items: { type: string, enum: [polish, ai, agent, asr] }
|
|
lifetimeSeconds: { type: ["integer", "null"], format: int64, minimum: 1 }
|
|
RefreshGatewayGrantRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [refreshToken]
|
|
properties:
|
|
refreshToken: { type: string, minLength: 32 }
|
|
GatewayGrantTokens:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [grantId, scopes, accessToken, accessExpiresAt, refreshToken, refreshExpiresAt]
|
|
properties:
|
|
grantId: { type: string, format: uuid }
|
|
scopes:
|
|
type: array
|
|
uniqueItems: true
|
|
items: { type: string, enum: [polish, ai, agent, asr] }
|
|
accessToken: { type: string }
|
|
accessExpiresAt: { type: string, format: date-time }
|
|
refreshToken: { type: string }
|
|
refreshExpiresAt: { type: string, format: date-time }
|
|
CreateAsrSessionRequest:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [estimatedDurationMillis]
|
|
properties:
|
|
format: { type: string, enum: [pcm, wav, ogg, mp3], default: pcm }
|
|
codec: { type: string, enum: [raw, opus], default: raw }
|
|
sampleRate: { type: integer, const: 16000 }
|
|
bits: { type: integer, const: 16 }
|
|
channels: { type: integer, minimum: 1, maximum: 2, default: 1 }
|
|
language: { type: ["string", "null"], maxLength: 32 }
|
|
estimatedDurationMillis: { type: integer, minimum: 1, maximum: 600000 }
|
|
CreateAsrSessionResponse:
|
|
type: object
|
|
required: [sessionId, websocketPath, maxFrameBytes, idleTimeoutMillis]
|
|
properties:
|
|
sessionId: { type: string, format: uuid }
|
|
websocketPath: { type: string }
|
|
maxFrameBytes: { type: integer }
|
|
idleTimeoutMillis: { type: integer, format: int64 }
|
|
ApiError:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [code, message]
|
|
properties:
|
|
code: { type: string }
|
|
message: { type: string }
|
|
ApiErrorEnvelope:
|
|
type: object
|
|
additionalProperties: false
|
|
required: [error]
|
|
properties:
|
|
error: { $ref: "#/components/schemas/ApiError" }
|
|
GatewayError:
|
|
type: object
|
|
required: [code, message, requestId]
|
|
properties:
|
|
code: { type: string }
|
|
message: { type: string }
|
|
requestId: { type: string }
|