feat: Gemini AI integration — conversations, messages, image gen

- Fixed YAML parse error (unquoted colon in description broke @scalar/json-magic)
- Converted orval.config.ts → orval.config.cjs (fixes orval v8 TypeScript config loading)
- Codegen now works: zod schemas + React Query hooks regenerated with Gemini types
- Added Gemini tag, 4 path groups, 8 schemas to openapi.yaml
- lib/integrations-gemini-ai wired: tsconfig refs, api-server package.json dep
- Created routes/gemini.ts: CRUD conversations/messages + SSE chat stream + image gen
- Mounted /gemini router in routes/index.ts
This commit is contained in:
Replit Agent
2026-03-20 02:41:12 +00:00
parent cdb104e34f
commit e86dab0d65
54 changed files with 3620 additions and 28 deletions

View File

@@ -1,45 +1,396 @@
import { z } from "zod";
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import * as zod from "zod";
export const HealthCheckResponse = z.object({
status: z.string(),
/**
* Returns server health status
* @summary Health check
*/
export const HealthCheckResponse = zod.object({
status: zod.string(),
});
export const ErrorResponse = z.object({
error: z.string(),
/**
* Accepts a request, creates a job row, and issues an eval fee Lightning invoice.
* @summary Create a new agent job
*/
export const CreateJobBody = zod.object({
request: zod.string().min(1),
});
export const CreateJobBody = z.object({
request: z.string().min(1).max(500),
/**
* Returns current job state. Automatically advances the state machine when a pending invoice is found to be paid.
* @summary Get job status
*/
export const GetJobParams = zod.object({
id: zod.coerce.string(),
});
export const GetJobParams = z.object({
id: z.string(),
export const GetJobResponse = zod.object({
jobId: zod.string(),
state: zod.enum([
"awaiting_eval_payment",
"evaluating",
"rejected",
"awaiting_work_payment",
"executing",
"complete",
"failed",
]),
createdAt: zod
.date()
.describe("ISO 8601 timestamp of job creation (always present)"),
completedAt: zod
.date()
.nullish()
.describe(
"ISO 8601 timestamp of job completion; null when not yet complete",
),
evalInvoice: zod
.object({
paymentRequest: zod.string(),
amountSats: zod.number(),
})
.optional(),
workInvoice: zod
.object({
paymentRequest: zod.string(),
amountSats: zod.number(),
})
.optional(),
pricingBreakdown: zod
.object({
estimatedCostUsd: zod
.number()
.optional()
.describe(
"Total estimated cost in USD (token cost + DO infra + margin)",
),
marginPct: zod
.number()
.optional()
.describe("Originator margin percentage applied"),
btcPriceUsd: zod
.number()
.optional()
.describe("BTC\/USD spot price used to convert the invoice to sats"),
})
.optional()
.describe(
"Cost breakdown shown with the work invoice (estimations at invoice-creation time)",
),
reason: zod.string().optional(),
result: zod.string().optional(),
costLedger: zod
.object({
actualInputTokens: zod.number().optional(),
actualOutputTokens: zod.number().optional(),
totalTokens: zod
.number()
.optional()
.describe("Sum of actualInputTokens + actualOutputTokens"),
actualCostUsd: zod
.number()
.optional()
.describe("Raw Anthropic token cost (no infra, no margin)"),
actualChargeUsd: zod
.number()
.optional()
.describe(
"What we honestly charged in USD (actual token cost + DO infra + margin)",
),
estimatedCostUsd: zod
.number()
.optional()
.describe("Original estimate used to create the work invoice"),
actualAmountSats: zod
.number()
.optional()
.describe(
"Honest sats charge (actual cost converted at the locked BTC price)",
),
workAmountSats: zod
.number()
.optional()
.describe("Amount the user originally paid in sats"),
refundAmountSats: zod
.number()
.optional()
.describe(
"Sats owed back to the user (workAmountSats - actualAmountSats, >= 0)",
),
refundState: zod
.enum(["not_applicable", "pending", "paid"])
.optional()
.describe("Lifecycle of the refund for this job"),
marginPct: zod.number().optional(),
btcPriceUsd: zod
.number()
.optional()
.describe("BTC\/USD price locked at invoice creation time"),
})
.optional()
.describe("Honest post-work accounting stored after the job completes"),
errorMessage: zod.string().optional(),
});
export const GetJobRefundParams = z.object({
id: z.string(),
/**
* After a job completes, if the actual cost (tokens used + infra + margin) was
less than the work invoice amount, the difference is owed back to the user.
Submit a BOLT11 invoice for exactly `refundAmountSats` to receive the payment.
Idempotent: returns 409 if already paid or if no refund is owed.
* @summary Claim a refund for overpayment
*/
export const ClaimRefundParams = zod.object({
id: zod.coerce.string(),
});
export const ClaimRefundBody = z.object({
paymentRequest: z.string(),
export const ClaimRefundBody = zod.object({
invoice: zod.string().describe("BOLT11 invoice for exactly refundAmountSats"),
});
export const RunDemoQueryParams = z.object({
request: z.string().min(1),
export const ClaimRefundResponse = zod.object({
ok: zod.boolean(),
refundAmountSats: zod.number(),
paymentHash: zod.string(),
message: zod.string(),
});
export const CreateSessionBody = z.object({
amount_sats: z.number().int().min(100).max(10000),
/**
* Opens a new session. Pay the returned Lightning invoice to activate it.
Once active, use the `macaroon` from GET /sessions/:id to authenticate requests.
Deposits: 10010,000 sats. Sessions expire after 24 h of inactivity.
* @summary Create a pre-funded session
*/
export const createSessionBodyAmountSatsMin = 100;
export const createSessionBodyAmountSatsMax = 10000;
export const CreateSessionBody = zod.object({
amount_sats: zod
.number()
.min(createSessionBodyAmountSatsMin)
.max(createSessionBodyAmountSatsMax)
.describe("Deposit amount (10010,000 sats)"),
});
export const GetSessionParams = z.object({
id: z.string(),
/**
* Returns current state, balance, and pending invoice info. Auto-advances on payment.
* @summary Get session status
*/
export const GetSessionParams = zod.object({
id: zod.coerce.string(),
});
export const SubmitSessionRequestBody = z.object({
request: z.string().min(1),
export const GetSessionResponse = zod.object({
sessionId: zod.string(),
state: zod.enum(["awaiting_payment", "active", "paused", "expired"]),
balanceSats: zod.number(),
minimumBalanceSats: zod.number().optional(),
macaroon: zod
.string()
.optional()
.describe(
"Bearer token for authenticating requests; present when active or paused",
),
expiresAt: zod.date().optional(),
invoice: zod
.object({
paymentRequest: zod.string().optional(),
amountSats: zod.number().optional(),
paymentHash: zod
.string()
.optional()
.describe("Only present in stub\/dev mode"),
})
.optional()
.describe("Present when state is awaiting_payment"),
pendingTopup: zod
.object({
paymentRequest: zod.string().optional(),
amountSats: zod.number().optional(),
paymentHash: zod
.string()
.optional()
.describe("Only present in stub\/dev mode"),
})
.optional()
.describe("Present when a topup invoice is outstanding"),
});
export const TopupSessionBody = z.object({
amount_sats: z.number().int().min(100).max(10000),
/**
* Runs eval + work and debits the actual compute cost from the session balance.
Rejected requests still incur a small eval fee. Requires `Authorization: Bearer <macaroon>`.
* @summary Submit a request against a session balance
*/
export const SubmitSessionRequestParams = zod.object({
id: zod.coerce.string(),
});
export const SubmitSessionRequestBody = zod.object({
request: zod.string().min(1),
});
export const SubmitSessionRequestResponse = zod.object({
requestId: zod.string(),
state: zod.enum(["complete", "rejected", "failed"]),
result: zod.string().optional(),
reason: zod.string().optional(),
errorMessage: zod.string().optional(),
debitedSats: zod.number(),
balanceRemaining: zod.number(),
cost: zod
.object({
evalSats: zod.number().optional(),
workSats: zod.number().optional(),
totalSats: zod.number().optional(),
btcPriceUsd: zod.number().optional(),
})
.optional(),
});
/**
* Creates a new Lightning invoice to top up the session balance.
Only one pending topup at a time. Paying it resumes a paused session.
* @summary Add sats to a session
*/
export const TopupSessionParams = zod.object({
id: zod.coerce.string(),
});
export const topupSessionBodyAmountSatsMin = 100;
export const topupSessionBodyAmountSatsMax = 10000;
export const TopupSessionBody = zod.object({
amount_sats: zod
.number()
.min(topupSessionBodyAmountSatsMin)
.max(topupSessionBodyAmountSatsMax)
.describe("Deposit amount (10010,000 sats)"),
});
export const TopupSessionResponse = zod.object({
sessionId: zod.string(),
topup: zod.object({
paymentRequest: zod.string().optional(),
amountSats: zod.number().optional(),
paymentHash: zod
.string()
.optional()
.describe("Only present in stub\/dev mode"),
}),
});
/**
* Runs the agent without payment. Limited to 5 requests per IP per hour.
* @summary Free demo (rate-limited)
*/
export const RunDemoQueryParams = zod.object({
request: zod.coerce.string(),
});
export const RunDemoResponse = zod.object({
result: zod.string(),
});
/**
* @summary List all conversations
*/
export const ListGeminiConversationsResponseItem = zod.object({
id: zod.number(),
title: zod.string(),
createdAt: zod.date(),
});
export const ListGeminiConversationsResponse = zod.array(
ListGeminiConversationsResponseItem,
);
/**
* @summary Create a new conversation
*/
export const CreateGeminiConversationBody = zod.object({
title: zod.string(),
});
/**
* @summary Get conversation with messages
*/
export const GetGeminiConversationParams = zod.object({
id: zod.coerce.number(),
});
export const GetGeminiConversationResponse = zod.object({
id: zod.number(),
title: zod.string(),
createdAt: zod.date(),
messages: zod.array(
zod.object({
id: zod.number(),
conversationId: zod.number(),
role: zod.string(),
content: zod.string(),
createdAt: zod.date(),
}),
),
});
/**
* @summary Delete a conversation
*/
export const DeleteGeminiConversationParams = zod.object({
id: zod.coerce.number(),
});
/**
* @summary List messages in a conversation
*/
export const ListGeminiMessagesParams = zod.object({
id: zod.coerce.number(),
});
export const ListGeminiMessagesResponseItem = zod.object({
id: zod.number(),
conversationId: zod.number(),
role: zod.string(),
content: zod.string(),
createdAt: zod.date(),
});
export const ListGeminiMessagesResponse = zod.array(
ListGeminiMessagesResponseItem,
);
/**
* @summary Send a message and receive an AI response (SSE stream)
*/
export const SendGeminiMessageParams = zod.object({
id: zod.coerce.number(),
});
export const SendGeminiMessageBody = zod.object({
content: zod.string(),
model: zod
.string()
.optional()
.describe("Gemini model override (default: gemini-3-flash-preview)"),
});
/**
* @summary Generate an image from a text prompt
*/
export const GenerateGeminiImageBody = zod.object({
prompt: zod.string(),
});
export const GenerateGeminiImageResponse = zod.object({
b64_json: zod.string(),
mimeType: zod.string(),
});

View File

@@ -1,3 +0,0 @@
// TypeScript types derived from Zod schemas in ./api
// All schemas and their inferred types are exported from ./api via src/index.ts
export {};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface ClaimRefundRequest {
/** BOLT11 invoice for exactly refundAmountSats */
invoice: string;
}

View File

@@ -0,0 +1,14 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface ClaimRefundResponse {
ok: boolean;
refundAmountSats: number;
paymentHash: string;
message: string;
}

View File

@@ -0,0 +1,35 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import type { CostLedgerRefundState } from "./costLedgerRefundState";
/**
* Honest post-work accounting stored after the job completes
*/
export interface CostLedger {
actualInputTokens?: number;
actualOutputTokens?: number;
/** Sum of actualInputTokens + actualOutputTokens */
totalTokens?: number;
/** Raw Anthropic token cost (no infra, no margin) */
actualCostUsd?: number;
/** What we honestly charged in USD (actual token cost + DO infra + margin) */
actualChargeUsd?: number;
/** Original estimate used to create the work invoice */
estimatedCostUsd?: number;
/** Honest sats charge (actual cost converted at the locked BTC price) */
actualAmountSats?: number;
/** Amount the user originally paid in sats */
workAmountSats?: number;
/** Sats owed back to the user (workAmountSats - actualAmountSats, >= 0) */
refundAmountSats?: number;
/** Lifecycle of the refund for this job */
refundState?: CostLedgerRefundState;
marginPct?: number;
/** BTC/USD price locked at invoice creation time */
btcPriceUsd?: number;
}

View File

@@ -0,0 +1,19 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
/**
* Lifecycle of the refund for this job
*/
export type CostLedgerRefundState =
(typeof CostLedgerRefundState)[keyof typeof CostLedgerRefundState];
export const CostLedgerRefundState = {
not_applicable: "not_applicable",
pending: "pending",
paid: "paid",
} as const;

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface CreateGeminiConversationBody {
title: string;
}

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface CreateJobRequest {
/** @minLength 1 */
request: string;
}

View File

@@ -0,0 +1,15 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import type { InvoiceInfo } from "./invoiceInfo";
export interface CreateJobResponse {
jobId: string;
/** ISO 8601 timestamp of job creation */
createdAt: Date;
evalInvoice: InvoiceInfo;
}

View File

@@ -0,0 +1,16 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface CreateSessionRequest {
/**
* Deposit amount (10010,000 sats)
* @minimum 100
* @maximum 10000
*/
amount_sats: number;
}

View File

@@ -0,0 +1,15 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import type { SessionInvoiceInfo } from "./sessionInvoiceInfo";
import type { SessionState } from "./sessionState";
export interface CreateSessionResponse {
sessionId: string;
state: SessionState;
invoice: SessionInvoiceInfo;
}

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface DemoResponse {
result: string;
}

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface ErrorResponse {
error: string;
}

View File

@@ -0,0 +1,13 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface GeminiConversation {
id: number;
title: string;
createdAt: Date;
}

View File

@@ -0,0 +1,15 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import type { GeminiMessage } from "./geminiMessage";
export interface GeminiConversationWithMessages {
id: number;
title: string;
createdAt: Date;
messages: GeminiMessage[];
}

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface GeminiError {
error: string;
}

View File

@@ -0,0 +1,15 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface GeminiMessage {
id: number;
conversationId: number;
role: string;
content: string;
createdAt: Date;
}

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface GenerateGeminiImageBody {
prompt: string;
}

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface GenerateGeminiImageResponse {
b64_json: string;
mimeType: string;
}

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface HealthStatus {
status: string;
}

View File

@@ -0,0 +1,40 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export * from "./claimRefundRequest";
export * from "./claimRefundResponse";
export * from "./costLedger";
export * from "./costLedgerRefundState";
export * from "./createGeminiConversationBody";
export * from "./createJobRequest";
export * from "./createJobResponse";
export * from "./createSessionRequest";
export * from "./createSessionResponse";
export * from "./demoResponse";
export * from "./errorResponse";
export * from "./geminiConversation";
export * from "./geminiConversationWithMessages";
export * from "./geminiError";
export * from "./geminiMessage";
export * from "./generateGeminiImageBody";
export * from "./generateGeminiImageResponse";
export * from "./healthStatus";
export * from "./invoiceInfo";
export * from "./jobState";
export * from "./jobStatusResponse";
export * from "./pricingBreakdown";
export * from "./runDemoParams";
export * from "./sendGeminiMessageBody";
export * from "./sessionCostBreakdown";
export * from "./sessionInvoiceInfo";
export * from "./sessionRequestBody";
export * from "./sessionRequestResponse";
export * from "./sessionRequestResponseState";
export * from "./sessionState";
export * from "./sessionStatusResponse";
export * from "./topupSessionResponse";

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface InvoiceInfo {
paymentRequest: string;
amountSats: number;
}

View File

@@ -0,0 +1,19 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export type JobState = (typeof JobState)[keyof typeof JobState];
export const JobState = {
awaiting_eval_payment: "awaiting_eval_payment",
evaluating: "evaluating",
rejected: "rejected",
awaiting_work_payment: "awaiting_work_payment",
executing: "executing",
complete: "complete",
failed: "failed",
} as const;

View File

@@ -0,0 +1,27 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import type { CostLedger } from "./costLedger";
import type { InvoiceInfo } from "./invoiceInfo";
import type { JobState } from "./jobState";
import type { PricingBreakdown } from "./pricingBreakdown";
export interface JobStatusResponse {
jobId: string;
state: JobState;
/** ISO 8601 timestamp of job creation (always present) */
createdAt: Date;
/** ISO 8601 timestamp of job completion; null when not yet complete */
completedAt?: Date | null;
evalInvoice?: InvoiceInfo;
workInvoice?: InvoiceInfo;
pricingBreakdown?: PricingBreakdown;
reason?: string;
result?: string;
costLedger?: CostLedger;
errorMessage?: string;
}

View File

@@ -0,0 +1,19 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
/**
* Cost breakdown shown with the work invoice (estimations at invoice-creation time)
*/
export interface PricingBreakdown {
/** Total estimated cost in USD (token cost + DO infra + margin) */
estimatedCostUsd?: number;
/** Originator margin percentage applied */
marginPct?: number;
/** BTC/USD spot price used to convert the invoice to sats */
btcPriceUsd?: number;
}

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export type RunDemoParams = {
request: string;
};

View File

@@ -0,0 +1,13 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface SendGeminiMessageBody {
content: string;
/** Gemini model override (default: gemini-3-flash-preview) */
model?: string;
}

View File

@@ -0,0 +1,14 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface SessionCostBreakdown {
evalSats?: number;
workSats?: number;
totalSats?: number;
btcPriceUsd?: number;
}

View File

@@ -0,0 +1,14 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface SessionInvoiceInfo {
paymentRequest?: string;
amountSats?: number;
/** Only present in stub/dev mode */
paymentHash?: string;
}

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export interface SessionRequestBody {
/** @minLength 1 */
request: string;
}

View File

@@ -0,0 +1,20 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import type { SessionCostBreakdown } from "./sessionCostBreakdown";
import type { SessionRequestResponseState } from "./sessionRequestResponseState";
export interface SessionRequestResponse {
requestId: string;
state: SessionRequestResponseState;
result?: string;
reason?: string;
errorMessage?: string;
debitedSats: number;
balanceRemaining: number;
cost?: SessionCostBreakdown;
}

View File

@@ -0,0 +1,16 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export type SessionRequestResponseState =
(typeof SessionRequestResponseState)[keyof typeof SessionRequestResponseState];
export const SessionRequestResponseState = {
complete: "complete",
rejected: "rejected",
failed: "failed",
} as const;

View File

@@ -0,0 +1,16 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
export type SessionState = (typeof SessionState)[keyof typeof SessionState];
export const SessionState = {
awaiting_payment: "awaiting_payment",
active: "active",
paused: "paused",
expired: "expired",
} as const;

View File

@@ -0,0 +1,23 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import type { SessionInvoiceInfo } from "./sessionInvoiceInfo";
import type { SessionState } from "./sessionState";
export interface SessionStatusResponse {
sessionId: string;
state: SessionState;
balanceSats: number;
minimumBalanceSats?: number;
/** Bearer token for authenticating requests; present when active or paused */
macaroon?: string;
expiresAt?: Date;
/** Present when state is awaiting_payment */
invoice?: SessionInvoiceInfo;
/** Present when a topup invoice is outstanding */
pendingTopup?: SessionInvoiceInfo;
}

View File

@@ -0,0 +1,13 @@
/**
* Generated by orval v8.5.3 🍺
* Do not edit manually.
* Api
* API specification
* OpenAPI spec version: 0.1.0
*/
import type { SessionInvoiceInfo } from "./sessionInvoiceInfo";
export interface TopupSessionResponse {
sessionId: string;
topup: SessionInvoiceInfo;
}