Skip to main content

quantum_sdk/
credits.rs

1//! Credits — purchase credit packs, check balance, view tiers, and apply for dev program.
2//!
3//! Some endpoints (packs, tiers) do not require authentication and can be
4//! called without an API key.
5
6use serde::{Deserialize, Serialize};
7
8use crate::client::Client;
9use crate::error::Result;
10
11/// A credit pack available for purchase.
12#[derive(Debug, Clone, Deserialize)]
13pub struct CreditPack {
14    /// Unique pack identifier.
15    pub id: String,
16
17    /// Display name (e.g. "Starter Pack").
18    #[serde(default)]
19    pub name: Option<String>,
20
21    /// Price in USD.
22    #[serde(default)]
23    pub price_usd: f64,
24
25    /// Number of credit ticks included.
26    #[serde(default)]
27    pub credit_ticks: i64,
28
29    /// Description.
30    #[serde(default)]
31    pub description: Option<String>,
32}
33
34/// Response from listing credit packs.
35#[derive(Debug, Clone, Deserialize)]
36pub struct CreditPacksResponse {
37    /// Available credit packs.
38    pub packs: Vec<CreditPack>,
39}
40
41/// Request to purchase a credit pack.
42#[derive(Debug, Clone, Serialize)]
43pub struct CreditPurchaseRequest {
44    /// The pack ID to purchase.
45    pub pack_id: String,
46
47    /// URL to redirect to after successful payment.
48    #[serde(skip_serializing_if = "Option::is_none")]
49    pub success_url: Option<String>,
50
51    /// URL to redirect to if payment is cancelled.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub cancel_url: Option<String>,
54}
55
56/// Response from purchasing a credit pack.
57#[derive(Debug, Clone, Deserialize)]
58pub struct CreditPurchaseResponse {
59    /// URL to redirect the user to for payment.
60    pub checkout_url: String,
61}
62
63/// Response from checking credit balance.
64#[derive(Debug, Clone, Deserialize)]
65pub struct CreditBalanceResponse {
66    /// Balance in ticks.
67    pub balance_ticks: i64,
68
69    /// Balance in USD.
70    pub balance_usd: f64,
71}
72
73/// A pricing tier.
74#[derive(Debug, Clone, Deserialize)]
75pub struct CreditTier {
76    /// Tier name.
77    #[serde(default)]
78    pub name: Option<String>,
79
80    /// Minimum balance for this tier.
81    #[serde(default)]
82    pub min_balance: i64,
83
84    /// Discount percentage.
85    #[serde(default)]
86    pub discount_percent: f64,
87
88    /// Additional tier data.
89    #[serde(flatten)]
90    pub extra: serde_json::Value,
91}
92
93/// Response from listing credit tiers.
94#[derive(Debug, Clone, Deserialize)]
95pub struct CreditTiersResponse {
96    /// Available tiers.
97    pub tiers: Vec<CreditTier>,
98}
99
100/// Request to apply for the developer program.
101#[derive(Debug, Clone, Serialize)]
102pub struct DevProgramApplyRequest {
103    /// Description of the intended use case.
104    pub use_case: String,
105
106    /// Company name (optional).
107    #[serde(skip_serializing_if = "Option::is_none")]
108    pub company: Option<String>,
109
110    /// Expected monthly spend in USD (optional).
111    #[serde(skip_serializing_if = "Option::is_none")]
112    pub expected_usd: Option<f64>,
113
114    /// Website URL (optional).
115    #[serde(skip_serializing_if = "Option::is_none")]
116    pub website: Option<String>,
117}
118
119/// Response from dev program application.
120#[derive(Debug, Clone, Deserialize)]
121pub struct DevProgramApplyResponse {
122    /// Status of the application (e.g. "submitted", "approved").
123    pub status: String,
124}
125
126impl Client {
127    /// List available credit packs. No authentication required.
128    pub async fn credit_packs(&self) -> Result<CreditPacksResponse> {
129        let (resp, _meta) = self
130            .get_json::<CreditPacksResponse>("/qai/v1/credits/packs")
131            .await?;
132        Ok(resp)
133    }
134
135    /// Purchase a credit pack. Returns a checkout URL for payment.
136    pub async fn credit_purchase(&self, req: &CreditPurchaseRequest) -> Result<CreditPurchaseResponse> {
137        let (resp, _meta) = self
138            .post_json::<CreditPurchaseRequest, CreditPurchaseResponse>(
139                "/qai/v1/credits/purchase",
140                req,
141            )
142            .await?;
143        Ok(resp)
144    }
145
146    /// Get the current credit balance.
147    pub async fn credit_balance(&self) -> Result<CreditBalanceResponse> {
148        let (resp, _meta) = self
149            .get_json::<CreditBalanceResponse>("/qai/v1/credits/balance")
150            .await?;
151        Ok(resp)
152    }
153
154    /// List available credit tiers. No authentication required.
155    pub async fn credit_tiers(&self) -> Result<CreditTiersResponse> {
156        let (resp, _meta) = self
157            .get_json::<CreditTiersResponse>("/qai/v1/credits/tiers")
158            .await?;
159        Ok(resp)
160    }
161
162    /// Apply for the developer program.
163    pub async fn dev_program_apply(&self, req: &DevProgramApplyRequest) -> Result<DevProgramApplyResponse> {
164        let (resp, _meta) = self
165            .post_json::<DevProgramApplyRequest, DevProgramApplyResponse>(
166                "/qai/v1/credits/dev-program",
167                req,
168            )
169            .await?;
170        Ok(resp)
171    }
172}