rusty_openai/openai_api/
projects.rs

1use crate::{error_handling::OpenAIResult, openai::OpenAI};
2use serde::Serialize;
3use serde_json::Value;
4
5/// [`ProjectsApi`] struct to interact with the projects endpoints of the API.
6#[allow(dead_code)]
7pub struct ProjectsApi<'a>(pub(crate) &'a OpenAI<'a>);
8
9#[allow(dead_code)]
10#[derive(Serialize)]
11struct CreateProjectRequest<'a> {
12    /// The friendly name of the project
13    name: &'a str,
14
15    /// Optional description of the business, project, or use case
16    #[serde(skip_serializing_if = "Option::is_none")]
17    app_use_case: Option<&'a str>,
18
19    /// Optional business URL or social media link
20    #[serde(skip_serializing_if = "Option::is_none")]
21    business_website: Option<&'a str>,
22}
23
24#[allow(dead_code)]
25#[derive(Serialize)]
26struct CreateProjectUserRequest<'a> {
27    /// The ID of the user
28    user_id: &'a str,
29
30    /// The role of the user (owner or member)
31    role: &'a str,
32}
33
34impl<'a> ProjectsApi<'a> {
35    /// List projects within an organization.
36    ///
37    /// # Arguments
38    ///
39    /// * `limit` - Optional limit on the number of objects to return (1-100, default 20).
40    /// * `after` - Optional cursor for pagination.
41    /// * `include_archived` - Optional flag to include archived projects.
42    ///
43    /// # Returns
44    ///
45    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
46    pub async fn list_projects(
47        &self,
48        limit: Option<u8>,
49        after: Option<&str>,
50        include_archived: Option<bool>,
51    ) -> OpenAIResult<Value> {
52        let mut url = "/organization/projects".to_string();
53        let mut query_params = Vec::new();
54
55        if let Some(limit) = limit {
56            query_params.push(format!("limit={}", limit));
57        }
58        if let Some(after) = after {
59            query_params.push(format!("after={}", after));
60        }
61        if let Some(include_archived) = include_archived {
62            query_params.push(format!("include_archived={}", include_archived));
63        }
64
65        if !query_params.is_empty() {
66            url.push('?');
67            url.push_str(&query_params.join("&"));
68        }
69
70        self.0.get(&url).await
71    }
72
73    /// Create a new project in the organization.
74    ///
75    /// # Arguments
76    ///
77    /// * `name` - The friendly name of the project.
78    /// * `app_use_case` - Optional description of the business, project, or use case.
79    /// * `business_website` - Optional business URL or social media link.
80    ///
81    /// # Returns
82    ///
83    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
84    pub async fn create_project(
85        &self,
86        name: &str,
87        app_use_case: Option<&str>,
88        business_website: Option<&str>,
89    ) -> OpenAIResult<Value> {
90        let body = CreateProjectRequest {
91            name,
92            app_use_case,
93            business_website,
94        };
95
96        self.0.post_json("/organization/projects", &body).await
97    }
98
99    /// Retrieve information about a specific project.
100    ///
101    /// # Arguments
102    ///
103    /// * `project_id` - The ID of the project to retrieve.
104    ///
105    /// # Returns
106    ///
107    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
108    pub async fn retrieve_project(&self, project_id: &str) -> OpenAIResult<Value> {
109        let url = format!("/organization/projects/{}", project_id);
110        self.0.get(&url).await
111    }
112
113    /// Modify an existing project in the organization.
114    ///
115    /// # Arguments
116    ///
117    /// * `project_id` - The ID of the project to modify.
118    /// * `name` - The updated name of the project.
119    /// * `app_use_case` - Optional updated description of the business, project, or use case.
120    /// * `business_website` - Optional updated business URL or social media link.
121    ///
122    /// # Returns
123    ///
124    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
125    pub async fn modify_project(
126        &self,
127        project_id: &str,
128        name: &str,
129        app_use_case: Option<&str>,
130        business_website: Option<&str>,
131    ) -> OpenAIResult<Value> {
132        let body = CreateProjectRequest {
133            name,
134            app_use_case,
135            business_website,
136        };
137
138        let url = format!("/organization/projects/{}", project_id);
139        self.0.post_json(&url, &body).await
140    }
141
142    /// Archive a project in the organization.
143    ///
144    /// # Arguments
145    ///
146    /// * `project_id` - The ID of the project to archive.
147    ///
148    /// # Returns
149    ///
150    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
151    pub async fn archive_project(&self, project_id: &str) -> OpenAIResult<Value> {
152        let url = format!("/organization/projects/{}/archive", project_id);
153        self.0.post_json(&url, &serde_json::json!({})).await
154    }
155
156    /// List users in a project.
157    ///
158    /// # Arguments
159    ///
160    /// * `project_id` - The ID of the project.
161    /// * `limit` - Optional limit on the number of objects to return (1-100, default 20).
162    /// * `after` - Optional cursor for pagination.
163    ///
164    /// # Returns
165    ///
166    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
167    pub async fn list_project_users(
168        &self,
169        project_id: &str,
170        limit: Option<u8>,
171        after: Option<&str>,
172    ) -> OpenAIResult<Value> {
173        let mut url = format!("/organization/projects/{}/users", project_id);
174        let mut query_params = Vec::new();
175
176        if let Some(limit) = limit {
177            query_params.push(format!("limit={}", limit));
178        }
179        if let Some(after) = after {
180            query_params.push(format!("after={}", after));
181        }
182
183        if !query_params.is_empty() {
184            url.push('?');
185            url.push_str(&query_params.join("&"));
186        }
187
188        self.0.get(&url).await
189    }
190
191    /// Add a user to a project.
192    ///
193    /// # Arguments
194    ///
195    /// * `project_id` - The ID of the project.
196    /// * `user_id` - The ID of the user to add.
197    /// * `role` - The role of the user (owner or member).
198    ///
199    /// # Returns
200    ///
201    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
202    pub async fn create_project_user(
203        &self,
204        project_id: &str,
205        user_id: &str,
206        role: &str,
207    ) -> OpenAIResult<Value> {
208        let body = CreateProjectUserRequest { user_id, role };
209        let url = format!("/organization/projects/{}/users", project_id);
210        self.0.post_json(&url, &body).await
211    }
212
213    /// Retrieve information about a specific user in a project.
214    ///
215    /// # Arguments
216    ///
217    /// * `project_id` - The ID of the project.
218    /// * `user_id` - The ID of the user.
219    ///
220    /// # Returns
221    ///
222    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
223    pub async fn retrieve_project_user(
224        &self,
225        project_id: &str,
226        user_id: &str,
227    ) -> OpenAIResult<Value> {
228        let url = format!("/organization/projects/{}/users/{}", project_id, user_id);
229        self.0.get(&url).await
230    }
231
232    /// Modify a user's role in a project.
233    ///
234    /// # Arguments
235    ///
236    /// * `project_id` - The ID of the project.
237    /// * `user_id` - The ID of the user.
238    /// * `role` - The new role of the user (owner or member).
239    ///
240    /// # Returns
241    ///
242    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
243    pub async fn modify_project_user(
244        &self,
245        project_id: &str,
246        user_id: &str,
247        role: &str,
248    ) -> OpenAIResult<Value> {
249        let body = serde_json::json!({ "role": role });
250        let url = format!("/organization/projects/{}/users/{}", project_id, user_id);
251        self.0.post_json(&url, &body).await
252    }
253
254    /// Delete a user from a project.
255    ///
256    /// # Arguments
257    ///
258    /// * `project_id` - The ID of the project.
259    /// * `user_id` - The ID of the user to delete.
260    ///
261    /// # Returns
262    ///
263    /// A Result containing the JSON response as [`serde_json::Value`] on success, or an [`OpenAIError`][crate::error_handling::OpenAIError] on failure.
264    pub async fn delete_project_user(
265        &self,
266        project_id: &str,
267        user_id: &str,
268    ) -> OpenAIResult<Value> {
269        let url = format!("/organization/projects/{}/users/{}", project_id, user_id);
270        self.0.delete(&url).await
271    }
272}