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