Skip to main content

agentmail/types/
apps.rs

1use serde::{Deserialize, Serialize};
2
3use crate::util::QueryBuilder;
4
5/// An app that can connect to AgentMail inboxes, from the app directory.
6#[derive(Clone, Debug, Deserialize)]
7pub struct App {
8    /// Unique app id (UUID).
9    pub app_id: String,
10    /// URL slug, e.g. `my-agent-app`.
11    #[serde(default)]
12    pub slug: Option<String>,
13    /// Display name.
14    #[serde(default)]
15    pub name: Option<String>,
16    /// Last update (RFC 3339), when set.
17    #[serde(default)]
18    pub updated_at: Option<String>,
19    /// Marketing description.
20    #[serde(default)]
21    pub description: Option<String>,
22    /// Logo image URL.
23    #[serde(default)]
24    pub logo_url: Option<String>,
25    /// Terms-of-service URL.
26    #[serde(default)]
27    pub terms_url: Option<String>,
28    /// Privacy-policy URL.
29    #[serde(default)]
30    pub privacy_url: Option<String>,
31    /// Directory categories, e.g. `ai`, `productivity`.
32    #[serde(default)]
33    pub categories: Vec<String>,
34    /// Signups this app's owner may create, when capped.
35    #[serde(default)]
36    pub owner_signup_limit: Option<u32>,
37}
38
39/// List filters for `list_apps` (includes pagination).
40#[derive(Clone, Debug, Default)]
41pub struct AppsListFilters {
42    /// Maximum apps per page.
43    pub limit: Option<u32>,
44    /// Cursor from a previous response's `next_page_token`.
45    pub page_token: Option<String>,
46    /// Only apps in this directory category.
47    pub category: Option<String>,
48}
49
50impl AppsListFilters {
51    pub(crate) fn query(&self) -> Vec<(&'static str, String)> {
52        QueryBuilder::new()
53            .opt("limit", self.limit.as_ref())
54            .opt("page_token", self.page_token.as_ref())
55            .opt("category", self.category.as_ref())
56            .build()
57    }
58}
59
60/// One page of apps from `list_apps`.
61#[derive(Clone, Debug, Deserialize)]
62pub struct AppList {
63    /// Total apps (not just this page).
64    pub count: u64,
65    /// This page of apps.
66    #[serde(default)]
67    pub apps: Vec<App>,
68    /// Cursor for the next page; `None` on the last page.
69    #[serde(default)]
70    pub next_page_token: Option<String>,
71}
72
73/// One page of apps from `search_apps` (no pagination cursor).
74#[derive(Clone, Debug, Deserialize)]
75pub struct AppSearchList {
76    /// Total matching apps.
77    pub count: u64,
78    /// The matching apps.
79    #[serde(default)]
80    pub apps: Vec<App>,
81}
82
83/// Body for `connect_app`: start a human's connection to an app. The human
84/// opens [`ConnectAppResult::magic_url`] and approves; the API key id in the
85/// result is the connection's credential handle.
86#[derive(Clone, Debug, Default, Serialize)]
87pub struct ConnectApp {
88    /// The inbox to connect; omitted means the whole organization.
89    #[serde(skip_serializing_if = "Option::is_none")]
90    pub inbox_id: Option<String>,
91    /// Confirm the app's disclosure on the human's behalf.
92    #[serde(skip_serializing_if = "Option::is_none")]
93    pub accept_disclosure: Option<bool>,
94}
95
96/// The response to `connect_app`.
97#[derive(Clone, Debug, Deserialize)]
98pub struct ConnectAppResult {
99    /// The API key created for this connection.
100    pub api_key_id: String,
101    /// The URL the human opens to approve the connection.
102    pub magic_url: String,
103    /// When `magic_url` expires (RFC 3339).
104    pub expires_at: String,
105}
106
107/// One page of an app's accounts from `list_app_accounts`.
108#[derive(Clone, Debug, Deserialize)]
109pub struct AppAccountList {
110    /// The app, when resolved.
111    #[serde(default)]
112    pub app: Option<App>,
113    /// Total accounts for the app (not just this page).
114    pub count: u64,
115    /// This page of accounts.
116    #[serde(default)]
117    pub accounts: Vec<crate::Account>,
118    /// Cursor for the next page; `None` on the last page.
119    #[serde(default)]
120    pub next_page_token: Option<String>,
121}