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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
//! Transaction Endpoints
//!
//! This module contains methods for retrieving settled and pending transactions.
use crate::{AccountId, Cursor, PaginatedResponse, PendingTransaction, Transaction, UserToken};
use super::AkahuClient;
use reqwest::Method;
use std::collections::HashMap;
impl AkahuClient {
/// Get a list of the user's settled transactions within a specified time range.
///
/// This endpoint returns settled transactions for all accounts that the user has connected
/// to your application. The response is paginated - use the `cursor.next` value to fetch
/// subsequent pages.
///
/// **Important Notes:**
/// - Time range defaults to the entire range accessible to your app if not specified
/// - Transactions will look different depending on your app's permissions
/// - All transaction timestamps are in UTC
/// - The start query parameter is exclusive (transactions after this timestamp)
/// - The end query parameter is inclusive (transactions through this timestamp)
/// - All Akahu timestamps use millisecond resolution (e.g. 2025-01-01T11:59:59.999Z)
/// - Each page contains a maximum of 100 transactions
/// - When querying multiple pages, use the same start/end parameters with the cursor
///
/// # Arguments
///
/// * `user_token` - The user's access token obtained through OAuth
/// * `query` - Optional query parameters to filter by date range and paginate
///
/// # Returns
///
/// A paginated response containing transactions and a cursor for fetching more pages.
///
/// [<https://developers.akahu.nz/reference/get_transactions>]
pub async fn get_transactions(
&self,
user_token: &UserToken,
start: Option<chrono::DateTime<chrono::Utc>>,
end: Option<chrono::DateTime<chrono::Utc>>,
cursor: Option<Cursor>,
) -> crate::error::AkahuResult<PaginatedResponse<Transaction>> {
const URI: &str = "transactions";
let headers = self.build_user_headers(user_token)?;
let mut query_params = HashMap::new();
if let Some(start) = start {
query_params.insert(
"start",
start.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
);
}
if let Some(end) = end {
query_params.insert(
"end",
end.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
);
}
if let Some(cursor) = cursor {
query_params.insert("cursor", cursor.to_string());
}
let url =
reqwest::Url::parse_with_params(&format!("{}/{}", self.base_url, URI), &query_params)?;
let req = self
.client
.request(Method::GET, url)
.headers(headers)
.build()?;
self.execute_request(req).await
}
/// Get a list of the user's pending transactions.
///
/// This endpoint returns pending transactions for all accounts that the user has connected
/// to your application. Pending transactions are not stable - the date or description may
/// change due to the unreliable nature of underlying NZ bank data. They are not assigned
/// unique identifiers and are not enriched by Akahu.
///
/// **Important Notes:**
/// - Pending transactions may change before they settle
/// - They do not have unique IDs
/// - They are not enriched with merchant/category data
/// - All timestamps are in UTC
/// - The `updated_at` field indicates when the transaction was last fetched
/// - This endpoint is not paginated and returns all pending transactions
///
/// # Arguments
///
/// * `user_token` - The user's access token obtained through OAuth
///
/// # Returns
///
/// A vector containing all pending transactions.
///
/// [<https://developers.akahu.nz/reference/get_transactions-pending>]
pub async fn get_pending_transactions(
&self,
user_token: &UserToken,
) -> crate::error::AkahuResult<Vec<PendingTransaction>> {
const URI: &str = "transactions/pending";
let headers = self.build_user_headers(user_token)?;
let req = self
.client
.request(Method::GET, format!("{}/{}", self.base_url, URI))
.headers(headers)
.build()?;
let response: crate::models::ListResponse<PendingTransaction> =
self.execute_request(req).await?;
Ok(response.items)
}
/// Get settled transactions for a specific account within a specified time range.
///
/// This endpoint returns settled transactions for a specific connected account.
/// The response is paginated - use the `cursor.next` value to fetch subsequent pages.
///
/// **Important Notes:**
/// - Time range defaults to the entire range accessible to your app if not specified
/// - All transaction timestamps are in UTC
/// - The start query parameter is exclusive (transactions after this timestamp)
/// - The end query parameter is inclusive (transactions through this timestamp)
/// - All Akahu timestamps use millisecond resolution
/// - Each page contains a maximum of 100 transactions
/// - When querying multiple pages, use the same start/end parameters with the cursor
///
/// # Arguments
///
/// * `user_token` - The user's access token obtained through OAuth
/// * `account_id` - The unique identifier for the account (prefixed with `acc_`)
/// * `query` - Optional query parameters to filter by date range and paginate
///
/// # Returns
///
/// A paginated response containing transactions and a cursor for fetching more pages.
///
/// [<https://developers.akahu.nz/reference/get_accounts-id-transactions>]
pub async fn get_account_transactions(
&self,
user_token: &UserToken,
account_id: &AccountId,
start: Option<chrono::DateTime<chrono::Utc>>,
end: Option<chrono::DateTime<chrono::Utc>>,
cursor: Option<Cursor>,
) -> crate::error::AkahuResult<PaginatedResponse<Transaction>> {
let uri = format!("accounts/{}/transactions", account_id.as_str());
let headers = self.build_user_headers(user_token)?;
let mut query_params = HashMap::new();
if let Some(start) = start {
query_params.insert(
"start",
start.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
);
}
if let Some(end) = end {
query_params.insert(
"end",
end.to_rfc3339_opts(chrono::SecondsFormat::Millis, true),
);
}
if let Some(cursor) = cursor {
query_params.insert("cursor", cursor.to_string());
}
let url =
reqwest::Url::parse_with_params(&format!("{}/{}", self.base_url, uri), &query_params)?;
let req = self
.client
.request(Method::GET, url)
.headers(headers)
.build()?;
self.execute_request(req).await
}
/// Get pending transactions for a specific account.
///
/// This endpoint returns pending transactions for a specific connected account.
/// Pending transactions are not stable - the date or description may change due to
/// the unreliable nature of underlying NZ bank data. They are not assigned unique
/// identifiers and are not enriched by Akahu.
///
/// **Important Notes:**
/// - Pending transactions may change before they settle
/// - They do not have unique IDs
/// - They are not enriched with merchant/category data
/// - All timestamps are in UTC
/// - The `updated_at` field indicates when the transaction was last fetched
/// - This endpoint is not paginated and returns all pending transactions
///
/// # Arguments
///
/// * `user_token` - The user's access token obtained through OAuth
/// * `account_id` - The unique identifier for the account (prefixed with `acc_`)
///
/// # Returns
///
/// A vector containing all pending transactions for the account.
///
/// [<https://developers.akahu.nz/reference/get_accounts-id-transactions-pending>]
pub async fn get_account_pending_transactions(
&self,
user_token: &UserToken,
account_id: &AccountId,
) -> crate::error::AkahuResult<Vec<PendingTransaction>> {
let uri = format!("accounts/{}/transactions/pending", account_id.as_str());
let headers = self.build_user_headers(user_token)?;
let req = self
.client
.request(Method::GET, format!("{}/{}", self.base_url, uri))
.headers(headers)
.build()?;
let response: crate::models::ListResponse<PendingTransaction> =
self.execute_request(req).await?;
Ok(response.items)
}
}