agentmail/types/api_keys.rs
1use serde::{Deserialize, Serialize};
2use std::collections::BTreeMap;
3
4/// An API key's permission flags, keyed by permission name (e.g.
5/// `message_send`, `calendar_event_create`). Modeled as a map so permission
6/// additions don't require a client release; unknown names are preserved.
7pub type ApiKeyPermissions = BTreeMap<String, bool>;
8
9/// The public-key material bound to a `public_key` API key (JWK plus its
10/// RFC 7638 thumbprint), as the API returns it.
11#[derive(Clone, Debug, Deserialize)]
12pub struct PublicKeyMaterial {
13 /// The public JWK (`kty`, `crv`, `x`, `y`).
14 #[serde(default)]
15 pub jwk: Option<serde_json::Value>,
16 /// Unpadded base64url RFC 7638 SHA-256 thumbprint of the JWK.
17 #[serde(default)]
18 pub fingerprint: Option<String>,
19}
20
21/// The agent that created a `public_key` API key.
22#[derive(Clone, Debug, Deserialize)]
23pub struct ApiKeyCreator {
24 /// The creating key's id.
25 pub api_key_id: String,
26}
27
28/// An API key, as the API returns it. The wire shape is a oneOf over bearer
29/// keys and `public_key` credentials; every field defaults so both parse.
30/// The secret material itself is never returned here (see [`CreatedApiKey`]).
31#[derive(Clone, Debug, Deserialize)]
32pub struct ApiKey {
33 /// `bearer` or `public_key`.
34 #[serde(rename = "type", default)]
35 pub key_type: Option<String>,
36 /// Unique key id.
37 pub api_key_id: String,
38 /// The key's non-secret prefix, for identification.
39 #[serde(default)]
40 pub prefix: Option<String>,
41 /// Human-readable name.
42 #[serde(default)]
43 pub name: Option<String>,
44 /// The pod the key is scoped to, when applicable.
45 #[serde(default)]
46 pub pod_id: Option<String>,
47 /// The inbox the key is scoped to, when applicable.
48 #[serde(default)]
49 pub inbox_id: Option<String>,
50 /// Your reference id, for `public_key` credentials.
51 #[serde(default)]
52 pub client_id: Option<String>,
53 /// Public-key material, for `public_key` credentials.
54 #[serde(default)]
55 pub public_key: Option<PublicKeyMaterial>,
56 /// Registration state of a `public_key` credential: `pending` or `active`.
57 #[serde(default)]
58 pub status: Option<String>,
59 /// When the key was last used (RFC 3339).
60 #[serde(default)]
61 pub used_at: Option<String>,
62 /// The key's permissions.
63 #[serde(default)]
64 pub permissions: Option<ApiKeyPermissions>,
65 /// The key that created this one, for `public_key` credentials.
66 #[serde(default)]
67 pub created_by: Option<ApiKeyCreator>,
68 /// When the key was created (RFC 3339).
69 #[serde(default)]
70 pub created_at: Option<String>,
71 /// When the key was last updated (RFC 3339).
72 #[serde(default)]
73 pub updated_at: Option<String>,
74 /// When the key stops working (RFC 3339), when it expires.
75 #[serde(default)]
76 pub expires_at: Option<String>,
77}
78
79/// Request body for `create_api_key`. The default (no `public_key`) mints a
80/// bearer key; setting `public_key` registers a `public_key` credential
81/// instead. The full secret of a bearer key is returned exactly once, in
82/// [`CreatedApiKey::api_key`].
83#[derive(Clone, Debug, Default, Serialize)]
84pub struct CreateApiKey {
85 /// Human-readable name for the key.
86 #[serde(skip_serializing_if = "Option::is_none")]
87 pub name: Option<String>,
88 /// The permissions to grant.
89 #[serde(skip_serializing_if = "Option::is_none")]
90 pub permissions: Option<ApiKeyPermissions>,
91 /// When the key should stop working (RFC 3339).
92 #[serde(skip_serializing_if = "Option::is_none")]
93 pub expires_at: Option<String>,
94 /// Your reference id, when registering a `public_key` credential.
95 #[serde(skip_serializing_if = "Option::is_none")]
96 pub client_id: Option<String>,
97 /// The public JWK (`kty`, `crv`, `x`, `y`); its presence selects the
98 /// `public_key` credential flow.
99 #[serde(skip_serializing_if = "Option::is_none")]
100 pub public_key: Option<serde_json::Value>,
101}
102
103/// Body for `update_api_key`. Fields left `None` stay unchanged.
104#[derive(Clone, Debug, Default, Serialize)]
105pub struct UpdateApiKey {
106 /// Replace the human-readable name.
107 #[serde(skip_serializing_if = "Option::is_none")]
108 pub name: Option<String>,
109 /// Replace the permission set.
110 #[serde(skip_serializing_if = "Option::is_none")]
111 pub permissions: Option<ApiKeyPermissions>,
112}
113
114/// The response to `create_api_key`. The full `api_key` secret is
115/// returned exactly once, here; store it now, as it cannot be retrieved again.
116#[derive(Clone, Debug, Deserialize)]
117pub struct CreatedApiKey {
118 /// Unique key id.
119 pub api_key_id: String,
120 /// The full secret key. Shown only on creation.
121 pub api_key: String,
122 /// The key's non-secret prefix.
123 #[serde(default)]
124 pub prefix: Option<String>,
125 /// Human-readable name.
126 #[serde(default)]
127 pub name: Option<String>,
128 /// The pod the key is scoped to, when applicable.
129 #[serde(default)]
130 pub pod_id: Option<String>,
131 /// The inbox the key is scoped to, when applicable.
132 #[serde(default)]
133 pub inbox_id: Option<String>,
134 /// The granted permissions.
135 #[serde(default)]
136 pub permissions: Option<ApiKeyPermissions>,
137 /// When the key was created (RFC 3339).
138 #[serde(default)]
139 pub created_at: Option<String>,
140}
141
142/// One page of API keys from `list_api_keys_page`.
143#[derive(Clone, Debug, Deserialize)]
144pub struct ApiKeyList {
145 /// Total keys in the account (not just this page).
146 pub count: u64,
147 /// This page of keys.
148 #[serde(default)]
149 pub api_keys: Vec<ApiKey>,
150 /// Cursor for the next page; `None` on the last page.
151 #[serde(default)]
152 pub next_page_token: Option<String>,
153}