anthropic_api/admin/invites.rs
1//! # Organization Invites Admin API
2//!
3//! This module provides a Rust interface to Anthropic's Admin API for managing organization invites, which allows you to
4//! list, get, create, and delete invites to your organization.
5//!
6//! ## Key Features
7//!
8//! - List all invites with pagination support
9//! - Get detailed information about a specific invite
10//! - Create new invites to the organization
11//! - Delete pending invites
12//!
13//! ## Basic Usage
14//!
15//! ```no_run
16//! use anthropic_api::{admin::invites::*, Credentials};
17//!
18//! #[tokio::main]
19//! async fn main() {
20//! let credentials = Credentials::from_env();
21//!
22//! // List invites
23//! let invites = InviteList::builder()
24//! .credentials(credentials.clone())
25//! .create()
26//! .await
27//! .unwrap();
28//!
29//! println!("Organization invites: {:?}", invites.data);
30//!
31//! // Get a specific invite
32//! if let Some(invite) = invites.data.first() {
33//! let invite_details = Invite::builder(&invite.id)
34//! .credentials(credentials.clone())
35//! .create()
36//! .await
37//! .unwrap();
38//!
39//! println!("Invite details: {:?}", invite_details);
40//! }
41//! }
42//! ```
43
44use crate::{anthropic_request_json, ApiResponseOrError, Credentials};
45use derive_builder::Builder;
46use reqwest::Method;
47use serde::{Deserialize, Serialize};
48
49/// Organization role of an invited user
50#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
51#[serde(rename_all = "lowercase")]
52pub enum InviteRole {
53 /// Regular user
54 User,
55 /// Developer role
56 Developer,
57 /// Billing administrator
58 Billing,
59 /// Organization administrator
60 Admin,
61}
62
63/// Status of an invite
64#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
65#[serde(rename_all = "lowercase")]
66pub enum InviteStatus {
67 /// Invite has been accepted
68 Accepted,
69 /// Invite has expired
70 Expired,
71 /// Invite has been deleted
72 Deleted,
73 /// Invite is pending acceptance
74 Pending,
75}
76
77/// An invite to the organization
78#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
79pub struct Invite {
80 /// Unique invite identifier
81 pub id: String,
82 /// Email of the user being invited
83 pub email: String,
84 /// RFC 3339 datetime string indicating when the invite was created
85 pub invited_at: String,
86 /// RFC 3339 datetime string indicating when the invite expires
87 pub expires_at: String,
88 /// Role assigned to the invited user
89 pub role: InviteRole,
90 /// Current status of the invite
91 pub status: InviteStatus,
92 /// Object type (always "invite" for Invites)
93 #[serde(rename = "type")]
94 pub invite_type: String,
95}
96
97/// Response from the List Invites API
98#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
99pub struct InviteList {
100 /// List of invites in the organization
101 pub data: Vec<Invite>,
102 /// First ID in the data list (for pagination)
103 pub first_id: Option<String>,
104 /// Last ID in the data list (for pagination)
105 pub last_id: Option<String>,
106 /// Indicates if there are more results in the requested page direction
107 pub has_more: bool,
108}
109
110/// Response from the Delete Invite API
111#[derive(Deserialize, Debug, Clone, Eq, PartialEq)]
112pub struct InviteDeleted {
113 /// ID of the deleted invite
114 pub id: String,
115 /// Object type (always "invite_deleted" for deleted invites)
116 #[serde(rename = "type")]
117 pub deleted_type: String,
118}
119
120/// Request parameters for listing invites
121#[derive(Serialize, Builder, Debug, Clone)]
122#[builder(derive(Clone, Debug, PartialEq))]
123#[builder(pattern = "owned")]
124#[builder(name = "InviteListBuilder")]
125#[builder(setter(strip_option, into))]
126pub struct InviteListRequest {
127 /// ID of the object to use as a cursor for pagination (previous page)
128 #[builder(default)]
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub before_id: Option<String>,
131
132 /// ID of the object to use as a cursor for pagination (next page)
133 #[builder(default)]
134 #[serde(skip_serializing_if = "Option::is_none")]
135 pub after_id: Option<String>,
136
137 /// Number of items to return per page (1-1000)
138 #[builder(default)]
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub limit: Option<u32>,
141
142 /// Credentials for authentication (not serialized)
143 #[serde(skip_serializing)]
144 #[builder(default)]
145 pub credentials: Option<Credentials>,
146}
147
148/// Request parameters for getting a specific invite
149#[derive(Serialize, Builder, Debug, Clone)]
150#[builder(derive(Clone, Debug, PartialEq))]
151#[builder(pattern = "owned")]
152#[builder(name = "InviteBuilder")]
153#[builder(setter(strip_option, into))]
154pub struct InviteRequest {
155 /// Invite identifier
156 pub invite_id: String,
157
158 /// Credentials for authentication (not serialized)
159 #[serde(skip_serializing)]
160 #[builder(default)]
161 pub credentials: Option<Credentials>,
162}
163
164/// Request parameters for creating an invite
165#[derive(Serialize, Builder, Debug, Clone)]
166#[builder(derive(Clone, Debug, PartialEq))]
167#[builder(pattern = "owned")]
168#[builder(name = "InviteCreateBuilder")]
169#[builder(setter(strip_option, into))]
170pub struct InviteCreateRequest {
171 /// Email of the user to invite
172 pub email: String,
173
174 /// Role for the invited user (cannot be "admin")
175 pub role: InviteRole,
176
177 /// Credentials for authentication (not serialized)
178 #[serde(skip_serializing)]
179 #[builder(default)]
180 pub credentials: Option<Credentials>,
181}
182
183/// Request parameters for deleting an invite
184#[derive(Serialize, Builder, Debug, Clone)]
185#[builder(derive(Clone, Debug, PartialEq))]
186#[builder(pattern = "owned")]
187#[builder(name = "InviteDeleteBuilder")]
188#[builder(setter(strip_option, into))]
189pub struct InviteDeleteRequest {
190 /// Invite identifier
191 pub invite_id: String,
192
193 /// Credentials for authentication (not serialized)
194 #[serde(skip_serializing)]
195 #[builder(default)]
196 pub credentials: Option<Credentials>,
197}
198
199impl InviteList {
200 /// Creates a builder for listing invites.
201 ///
202 /// # Example
203 ///
204 /// ```no_run
205 /// # use anthropic_api::{admin::invites::*, Credentials};
206 /// # #[tokio::main]
207 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
208 /// let credentials = Credentials::from_env();
209 ///
210 /// let invites = InviteList::builder()
211 /// .credentials(credentials)
212 /// .limit(10u32)
213 /// .create()
214 /// .await?;
215 /// # Ok(())
216 /// # }
217 /// ```
218 pub fn builder() -> InviteListBuilder {
219 InviteListBuilder::create_empty()
220 }
221
222 /// Lists invites in the organization with the given request parameters.
223 ///
224 /// # Example
225 ///
226 /// ```no_run
227 /// # use anthropic_api::{admin::invites::*, Credentials};
228 /// # #[tokio::main]
229 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
230 /// let credentials = Credentials::from_env();
231 /// let request = InviteListRequest {
232 /// before_id: None,
233 /// after_id: None,
234 /// limit: Some(20),
235 /// credentials: Some(credentials),
236 /// };
237 ///
238 /// let invites = InviteList::create(request).await?;
239 /// # Ok(())
240 /// # }
241 /// ```
242 pub async fn create(request: InviteListRequest) -> ApiResponseOrError<Self> {
243 let credentials_opt = request.credentials.clone();
244
245 // Build query parameters
246 let mut query_params = Vec::new();
247 if let Some(before_id) = &request.before_id {
248 query_params.push(("before_id", before_id.clone()));
249 }
250 if let Some(after_id) = &request.after_id {
251 query_params.push(("after_id", after_id.clone()));
252 }
253 if let Some(limit) = request.limit {
254 query_params.push(("limit", limit.to_string()));
255 }
256
257 anthropic_request_json(
258 Method::GET,
259 "organizations/invites",
260 |r| r.query(&query_params),
261 credentials_opt,
262 )
263 .await
264 }
265}
266
267impl Invite {
268 /// Creates a builder for getting a specific invite.
269 ///
270 /// # Example
271 ///
272 /// ```no_run
273 /// # use anthropic_api::{admin::invites::*, Credentials};
274 /// # #[tokio::main]
275 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
276 /// let credentials = Credentials::from_env();
277 ///
278 /// let invite = Invite::builder("invite_123456789")
279 /// .credentials(credentials)
280 /// .create()
281 /// .await?;
282 /// # Ok(())
283 /// # }
284 /// ```
285 pub fn builder(invite_id: impl Into<String>) -> InviteBuilder {
286 InviteBuilder::create_empty().invite_id(invite_id)
287 }
288
289 /// Gets information about a specific invite.
290 ///
291 /// # Example
292 ///
293 /// ```no_run
294 /// # use anthropic_api::{admin::invites::*, Credentials};
295 /// # #[tokio::main]
296 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
297 /// let credentials = Credentials::from_env();
298 /// let request = InviteRequest {
299 /// invite_id: "invite_123456789".to_string(),
300 /// credentials: Some(credentials),
301 /// };
302 ///
303 /// let invite = Invite::create(request).await?;
304 /// # Ok(())
305 /// # }
306 /// ```
307 pub async fn create(request: InviteRequest) -> ApiResponseOrError<Self> {
308 let credentials_opt = request.credentials.clone();
309 let route = format!("organizations/invites/{}", request.invite_id);
310
311 anthropic_request_json(Method::GET, &route, |r| r, credentials_opt).await
312 }
313
314 /// Creates a builder for creating a new invite.
315 ///
316 /// # Example
317 ///
318 /// ```no_run
319 /// # use anthropic_api::{admin::invites::*, Credentials};
320 /// # #[tokio::main]
321 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
322 /// let credentials = Credentials::from_env();
323 ///
324 /// let new_invite = Invite::create_builder()
325 /// .credentials(credentials)
326 /// .email("user@example.com")
327 /// .role(InviteRole::Developer)
328 /// .create()
329 /// .await?;
330 /// # Ok(())
331 /// # }
332 /// ```
333 pub fn create_builder() -> InviteCreateBuilder {
334 InviteCreateBuilder::create_empty()
335 }
336
337 /// Creates a new invite with the given request parameters.
338 ///
339 /// # Example
340 ///
341 /// ```no_run
342 /// # use anthropic_api::{admin::invites::*, Credentials};
343 /// # #[tokio::main]
344 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
345 /// let credentials = Credentials::from_env();
346 /// let request = InviteCreateRequest {
347 /// email: "user@example.com".to_string(),
348 /// role: InviteRole::Developer,
349 /// credentials: Some(credentials),
350 /// };
351 ///
352 /// let new_invite = Invite::create_new(request).await?;
353 /// # Ok(())
354 /// # }
355 /// ```
356 pub async fn create_new(request: InviteCreateRequest) -> ApiResponseOrError<Self> {
357 let credentials_opt = request.credentials.clone();
358
359 anthropic_request_json(
360 Method::POST,
361 "organizations/invites",
362 |r| r.json(&request),
363 credentials_opt,
364 )
365 .await
366 }
367
368 /// Creates a builder for deleting an invite.
369 ///
370 /// # Example
371 ///
372 /// ```no_run
373 /// # use anthropic_api::{admin::invites::*, Credentials};
374 /// # #[tokio::main]
375 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
376 /// let credentials = Credentials::from_env();
377 ///
378 /// let deleted_invite = Invite::delete_builder("invite_123456789")
379 /// .credentials(credentials)
380 /// .create()
381 /// .await?;
382 /// # Ok(())
383 /// # }
384 /// ```
385 pub fn delete_builder(invite_id: impl Into<String>) -> InviteDeleteBuilder {
386 InviteDeleteBuilder::create_empty().invite_id(invite_id)
387 }
388
389 /// Deletes an invite from the organization.
390 ///
391 /// # Example
392 ///
393 /// ```no_run
394 /// # use anthropic_api::{admin::invites::*, Credentials};
395 /// # #[tokio::main]
396 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
397 /// let credentials = Credentials::from_env();
398 /// let request = InviteDeleteRequest {
399 /// invite_id: "invite_123456789".to_string(),
400 /// credentials: Some(credentials),
401 /// };
402 ///
403 /// let deleted_invite = Invite::delete(request).await?;
404 /// # Ok(())
405 /// # }
406 /// ```
407 pub async fn delete(request: InviteDeleteRequest) -> ApiResponseOrError<InviteDeleted> {
408 let credentials_opt = request.credentials.clone();
409 let route = format!("organizations/invites/{}", request.invite_id);
410
411 anthropic_request_json(Method::DELETE, &route, |r| r, credentials_opt).await
412 }
413}
414
415// Builder convenience methods
416impl InviteListBuilder {
417 /// Creates a new invite list request and returns the response.
418 ///
419 /// This is a convenience method that builds the request from the builder
420 /// and sends it to the Invites API.
421 ///
422 /// # Example
423 ///
424 /// ```no_run
425 /// # use anthropic_api::{admin::invites::*, Credentials};
426 /// # #[tokio::main]
427 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
428 /// let credentials = Credentials::from_env();
429 ///
430 /// let invites = InviteList::builder()
431 /// .credentials(credentials)
432 /// .limit(10u32)
433 /// .create()
434 /// .await?;
435 /// # Ok(())
436 /// # }
437 /// ```
438 pub async fn create(self) -> ApiResponseOrError<InviteList> {
439 let request = self.build().unwrap();
440 InviteList::create(request).await
441 }
442}
443
444impl InviteBuilder {
445 /// Creates a new invite request and returns the response.
446 ///
447 /// This is a convenience method that builds the request from the builder
448 /// and sends it to the Invites API.
449 ///
450 /// # Example
451 ///
452 /// ```no_run
453 /// # use anthropic_api::{admin::invites::*, Credentials};
454 /// # #[tokio::main]
455 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
456 /// let credentials = Credentials::from_env();
457 ///
458 /// let invite = Invite::builder("invite_123456789")
459 /// .credentials(credentials)
460 /// .create()
461 /// .await?;
462 /// # Ok(())
463 /// # }
464 /// ```
465 pub async fn create(self) -> ApiResponseOrError<Invite> {
466 let request = self.build().unwrap();
467 Invite::create(request).await
468 }
469}
470
471impl InviteCreateBuilder {
472 /// Creates a new invite create request and returns the response.
473 ///
474 /// This is a convenience method that builds the request from the builder
475 /// and sends it to the Invites API.
476 ///
477 /// # Example
478 ///
479 /// ```no_run
480 /// # use anthropic_api::{admin::invites::*, Credentials};
481 /// # #[tokio::main]
482 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
483 /// let credentials = Credentials::from_env();
484 ///
485 /// let new_invite = Invite::create_builder()
486 /// .credentials(credentials)
487 /// .email("user@example.com")
488 /// .role(InviteRole::Developer)
489 /// .create()
490 /// .await?;
491 /// # Ok(())
492 /// # }
493 /// ```
494 pub async fn create(self) -> ApiResponseOrError<Invite> {
495 let request = self.build().unwrap();
496 Invite::create_new(request).await
497 }
498}
499
500impl InviteDeleteBuilder {
501 /// Creates a new invite delete request and returns the response.
502 ///
503 /// This is a convenience method that builds the request from the builder
504 /// and sends it to the Invites API.
505 ///
506 /// # Example
507 ///
508 /// ```no_run
509 /// # use anthropic_api::{admin::invites::*, Credentials};
510 /// # #[tokio::main]
511 /// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
512 /// let credentials = Credentials::from_env();
513 ///
514 /// let deleted_invite = Invite::delete_builder("invite_123456789")
515 /// .credentials(credentials)
516 /// .create()
517 /// .await?;
518 /// # Ok(())
519 /// # }
520 /// ```
521 pub async fn create(self) -> ApiResponseOrError<InviteDeleted> {
522 let request = self.build().unwrap();
523 Invite::delete(request).await
524 }
525}
526
527#[cfg(test)]
528mod tests {
529 use super::*;
530 use crate::Credentials;
531
532 #[tokio::test]
533 #[ignore] // Requires admin API key
534 async fn test_list_invites() {
535 let credentials = Credentials::from_env();
536
537 let invites = InviteList::builder()
538 .credentials(credentials)
539 .create()
540 .await
541 .unwrap();
542
543 assert!(invites.data.len() > 0);
544 }
545
546 #[tokio::test]
547 #[ignore] // Requires admin API key
548 async fn test_get_invite() {
549 let credentials = Credentials::from_env();
550
551 // First get an invite ID from the list
552 let invites = InviteList::builder()
553 .credentials(credentials.clone())
554 .create()
555 .await
556 .unwrap();
557
558 if let Some(invite) = invites.data.first() {
559 let invite_id = &invite.id;
560
561 // Then get that specific invite
562 let invite_details = Invite::builder(invite_id)
563 .credentials(credentials)
564 .create()
565 .await
566 .unwrap();
567
568 assert_eq!(invite_details.id, *invite_id);
569 }
570 }
571}