Skip to main content

apify_client/
models.rs

1//! Data models for Apify API resources.
2//!
3//! Each resource is modelled with the fields most commonly used by clients, mirroring
4//! the reference JavaScript client. To remain forward-compatible with additive changes to
5//! the API, none of the models set `deny_unknown_fields`, so unknown API fields are ignored
6//! rather than breaking deserialization. Most resource models additionally capture any unknown
7//! fields in an `extra` map via `#[serde(flatten)]` so they remain accessible to callers.
8
9use std::collections::HashMap;
10
11use chrono::{DateTime, Utc};
12use serde::{Deserialize, Serialize};
13use serde_json::Value;
14
15/// Convenience alias for the catch-all map of unmodelled JSON fields.
16pub type Extra = HashMap<String, Value>;
17
18/// An Actor on the Apify platform.
19#[derive(Debug, Clone, Deserialize, Serialize)]
20#[serde(rename_all = "camelCase")]
21pub struct Actor {
22    /// Unique Actor ID.
23    pub id: String,
24    /// ID of the user who owns the Actor.
25    #[serde(default)]
26    pub user_id: Option<String>,
27    /// Technical name of the Actor (used in API paths).
28    #[serde(default)]
29    pub name: Option<String>,
30    /// Username of the Actor's owner.
31    #[serde(default)]
32    pub username: Option<String>,
33    /// Human-readable title shown in the UI.
34    #[serde(default)]
35    pub title: Option<String>,
36    /// Description of what the Actor does.
37    #[serde(default)]
38    pub description: Option<String>,
39    /// Whether the Actor is publicly available in Apify Store.
40    #[serde(default)]
41    pub is_public: Option<bool>,
42    /// When the Actor was created.
43    #[serde(default)]
44    pub created_at: Option<DateTime<Utc>>,
45    /// When the Actor was last modified.
46    #[serde(default)]
47    pub modified_at: Option<DateTime<Utc>>,
48    /// Any other fields returned by the API.
49    #[serde(flatten)]
50    pub extra: Extra,
51}
52
53/// A single execution of an Actor (an Actor run).
54#[derive(Debug, Clone, Deserialize, Serialize)]
55#[serde(rename_all = "camelCase")]
56pub struct ActorRun {
57    /// Unique run ID.
58    pub id: String,
59    /// ID of the Actor that produced this run.
60    #[serde(default)]
61    pub act_id: Option<String>,
62    /// ID of the task that started this run, if any.
63    #[serde(default)]
64    pub actor_task_id: Option<String>,
65    /// ID of the user who owns the run.
66    #[serde(default)]
67    pub user_id: Option<String>,
68    /// Current run status, e.g. `READY`, `RUNNING`, `SUCCEEDED`, `FAILED`, `ABORTED`, `TIMED-OUT`.
69    #[serde(default)]
70    pub status: Option<String>,
71    /// Optional human-readable status message.
72    #[serde(default)]
73    pub status_message: Option<String>,
74    /// When the run started.
75    #[serde(default)]
76    pub started_at: Option<DateTime<Utc>>,
77    /// When the run finished (absent while still running).
78    #[serde(default)]
79    pub finished_at: Option<DateTime<Utc>>,
80    /// ID of the build used for the run.
81    #[serde(default)]
82    pub build_id: Option<String>,
83    /// Default dataset ID associated with the run.
84    #[serde(default)]
85    pub default_dataset_id: Option<String>,
86    /// Default key-value store ID associated with the run.
87    #[serde(default)]
88    pub default_key_value_store_id: Option<String>,
89    /// Default request queue ID associated with the run.
90    #[serde(default)]
91    pub default_request_queue_id: Option<String>,
92    /// URL of the run's container, if running.
93    #[serde(default)]
94    pub container_url: Option<String>,
95    /// Any other fields returned by the API.
96    #[serde(flatten)]
97    pub extra: Extra,
98}
99
100/// Terminal run/build statuses, used by wait-for-finish helpers.
101pub(crate) const TERMINAL_STATUSES: &[&str] =
102    &["SUCCEEDED", "FAILED", "ABORTED", "TIMED-OUT", "TIMED_OUT"];
103
104impl ActorRun {
105    /// Returns `true` if the run has reached a terminal state.
106    pub fn is_terminal(&self) -> bool {
107        self.status
108            .as_deref()
109            .map(|s| TERMINAL_STATUSES.contains(&s))
110            .unwrap_or(false)
111    }
112}
113
114/// A build of an Actor.
115#[derive(Debug, Clone, Deserialize, Serialize)]
116#[serde(rename_all = "camelCase")]
117pub struct Build {
118    /// Unique build ID.
119    pub id: String,
120    /// ID of the Actor that was built.
121    #[serde(default)]
122    pub act_id: Option<String>,
123    /// Current build status.
124    #[serde(default)]
125    pub status: Option<String>,
126    /// When the build started.
127    #[serde(default)]
128    pub started_at: Option<DateTime<Utc>>,
129    /// When the build finished.
130    #[serde(default)]
131    pub finished_at: Option<DateTime<Utc>>,
132    /// Build number, e.g. `0.1.2`.
133    #[serde(default)]
134    pub build_number: Option<String>,
135    /// Any other fields returned by the API.
136    #[serde(flatten)]
137    pub extra: Extra,
138}
139
140impl Build {
141    /// Returns `true` if the build has reached a terminal state.
142    pub fn is_terminal(&self) -> bool {
143        self.status
144            .as_deref()
145            .map(|s| TERMINAL_STATUSES.contains(&s))
146            .unwrap_or(false)
147    }
148}
149
150/// An Actor task (a saved, reusable Actor configuration).
151#[derive(Debug, Clone, Deserialize, Serialize)]
152#[serde(rename_all = "camelCase")]
153pub struct Task {
154    /// Unique task ID.
155    pub id: String,
156    /// ID of the Actor this task runs.
157    #[serde(default)]
158    pub act_id: Option<String>,
159    /// ID of the user who owns the task.
160    #[serde(default)]
161    pub user_id: Option<String>,
162    /// Technical name of the task.
163    #[serde(default)]
164    pub name: Option<String>,
165    /// Human-readable title.
166    #[serde(default)]
167    pub title: Option<String>,
168    /// When the task was created.
169    #[serde(default)]
170    pub created_at: Option<DateTime<Utc>>,
171    /// When the task was last modified.
172    #[serde(default)]
173    pub modified_at: Option<DateTime<Utc>>,
174    /// Any other fields returned by the API.
175    #[serde(flatten)]
176    pub extra: Extra,
177}
178
179/// A dataset storage.
180#[derive(Debug, Clone, Deserialize, Serialize)]
181#[serde(rename_all = "camelCase")]
182pub struct Dataset {
183    /// Unique dataset ID.
184    pub id: String,
185    /// Technical name of the dataset, if named.
186    #[serde(default)]
187    pub name: Option<String>,
188    /// ID of the owner.
189    #[serde(default)]
190    pub user_id: Option<String>,
191    /// When the dataset was created.
192    #[serde(default)]
193    pub created_at: Option<DateTime<Utc>>,
194    /// When the dataset was last modified.
195    #[serde(default)]
196    pub modified_at: Option<DateTime<Utc>>,
197    /// Total number of items in the dataset.
198    #[serde(default)]
199    pub item_count: Option<i64>,
200    /// Any other fields returned by the API.
201    #[serde(flatten)]
202    pub extra: Extra,
203}
204
205/// A key-value store storage.
206#[derive(Debug, Clone, Deserialize, Serialize)]
207#[serde(rename_all = "camelCase")]
208pub struct KeyValueStore {
209    /// Unique store ID.
210    pub id: String,
211    /// Technical name of the store, if named.
212    #[serde(default)]
213    pub name: Option<String>,
214    /// ID of the owner.
215    #[serde(default)]
216    pub user_id: Option<String>,
217    /// When the store was created.
218    #[serde(default)]
219    pub created_at: Option<DateTime<Utc>>,
220    /// When the store was last modified.
221    #[serde(default)]
222    pub modified_at: Option<DateTime<Utc>>,
223    /// Any other fields returned by the API.
224    #[serde(flatten)]
225    pub extra: Extra,
226}
227
228/// Metadata about a single key in a key-value store.
229#[derive(Debug, Clone, Deserialize, Serialize)]
230#[serde(rename_all = "camelCase")]
231pub struct KeyValueStoreKey {
232    /// The record key.
233    pub key: String,
234    /// Size of the record value in bytes.
235    #[serde(default)]
236    pub size: Option<i64>,
237    /// Any other fields returned by the API.
238    #[serde(flatten)]
239    pub extra: Extra,
240}
241
242/// Result of listing keys in a key-value store (key-based pagination).
243#[derive(Debug, Clone, Deserialize, Serialize)]
244#[serde(rename_all = "camelCase")]
245pub struct KeyValueStoreKeysPage {
246    /// Maximum number of keys returned for this request.
247    #[serde(default)]
248    pub limit: i64,
249    /// Whether there are more keys to fetch.
250    #[serde(default)]
251    pub is_truncated: bool,
252    /// The key the listing started after.
253    #[serde(default)]
254    pub exclusive_start_key: Option<String>,
255    /// The value to use as `exclusive_start_key` for the next page.
256    #[serde(default)]
257    pub next_exclusive_start_key: Option<String>,
258    /// The keys of this page.
259    #[serde(default)]
260    pub items: Vec<KeyValueStoreKey>,
261}
262
263/// A record (key + value + content type) in a key-value store.
264#[derive(Debug, Clone)]
265pub struct KeyValueStoreRecord {
266    /// The record key.
267    pub key: String,
268    /// The raw value bytes.
269    pub value: Vec<u8>,
270    /// The MIME content type of the value, if reported by the API.
271    pub content_type: Option<String>,
272}
273
274impl KeyValueStoreRecord {
275    /// Interprets the value as UTF-8 text.
276    pub fn as_text(&self) -> Result<String, std::string::FromUtf8Error> {
277        String::from_utf8(self.value.clone())
278    }
279
280    /// Deserializes the value as JSON into `T`.
281    pub fn json<T: serde::de::DeserializeOwned>(&self) -> Result<T, serde_json::Error> {
282        serde_json::from_slice(&self.value)
283    }
284}
285
286/// A request queue storage.
287#[derive(Debug, Clone, Deserialize, Serialize)]
288#[serde(rename_all = "camelCase")]
289pub struct RequestQueue {
290    /// Unique queue ID.
291    pub id: String,
292    /// Technical name of the queue, if named.
293    #[serde(default)]
294    pub name: Option<String>,
295    /// ID of the owner.
296    #[serde(default)]
297    pub user_id: Option<String>,
298    /// When the queue was created.
299    #[serde(default)]
300    pub created_at: Option<DateTime<Utc>>,
301    /// When the queue was last modified.
302    #[serde(default)]
303    pub modified_at: Option<DateTime<Utc>>,
304    /// Total number of requests ever added.
305    #[serde(default)]
306    pub total_request_count: Option<i64>,
307    /// Any other fields returned by the API.
308    #[serde(flatten)]
309    pub extra: Extra,
310}
311
312/// A single request stored in a request queue.
313#[derive(Debug, Clone, Deserialize, Serialize)]
314#[serde(rename_all = "camelCase")]
315pub struct RequestQueueRequest {
316    /// Unique request ID (assigned by the API; omit when adding a new request).
317    #[serde(default, skip_serializing_if = "Option::is_none")]
318    pub id: Option<String>,
319    /// The URL to be processed.
320    pub url: String,
321    /// Unique key used for deduplication (defaults to `url`).
322    #[serde(default, skip_serializing_if = "Option::is_none")]
323    pub unique_key: Option<String>,
324    /// HTTP method, defaults to `GET`.
325    #[serde(default, skip_serializing_if = "Option::is_none")]
326    pub method: Option<String>,
327    /// Arbitrary user data attached to the request.
328    #[serde(default, skip_serializing_if = "Option::is_none")]
329    pub user_data: Option<Value>,
330    /// Any other fields returned by the API.
331    #[serde(flatten)]
332    pub extra: Extra,
333}
334
335/// Result of adding (or updating) a request in a queue.
336#[derive(Debug, Clone, Deserialize, Serialize)]
337#[serde(rename_all = "camelCase")]
338pub struct RequestQueueOperationInfo {
339    /// ID of the request that was added or updated.
340    pub request_id: String,
341    /// Whether the request was already present in the queue.
342    #[serde(default)]
343    pub was_already_present: bool,
344    /// Whether the request had already been handled.
345    #[serde(default)]
346    pub was_already_handled: bool,
347}
348
349/// The head of a request queue (requests waiting to be processed).
350#[derive(Debug, Clone, Deserialize, Serialize)]
351#[serde(rename_all = "camelCase")]
352pub struct RequestQueueHead {
353    /// Maximum number of requests returned.
354    #[serde(default)]
355    pub limit: i64,
356    /// Whether more than one client has accessed the queue.
357    #[serde(default)]
358    pub had_multiple_clients: bool,
359    /// The requests at the head of the queue.
360    #[serde(default)]
361    pub items: Vec<RequestQueueRequest>,
362    /// Any other fields returned by the API.
363    #[serde(flatten)]
364    pub extra: Extra,
365}
366
367/// A schedule that triggers Actor or task runs on a cron expression.
368#[derive(Debug, Clone, Deserialize, Serialize)]
369#[serde(rename_all = "camelCase")]
370pub struct Schedule {
371    /// Unique schedule ID.
372    pub id: String,
373    /// ID of the owner.
374    #[serde(default)]
375    pub user_id: Option<String>,
376    /// Technical name of the schedule.
377    #[serde(default)]
378    pub name: Option<String>,
379    /// The cron expression that determines when the schedule fires.
380    #[serde(default)]
381    pub cron_expression: Option<String>,
382    /// Whether the schedule is currently enabled.
383    #[serde(default)]
384    pub is_enabled: Option<bool>,
385    /// Any other fields returned by the API.
386    #[serde(flatten)]
387    pub extra: Extra,
388}
389
390/// A webhook that notifies an external URL on Actor events.
391#[derive(Debug, Clone, Deserialize, Serialize)]
392#[serde(rename_all = "camelCase")]
393pub struct Webhook {
394    /// Unique webhook ID.
395    pub id: String,
396    /// ID of the owner.
397    #[serde(default)]
398    pub user_id: Option<String>,
399    /// The URL that receives the webhook POST request.
400    #[serde(default)]
401    pub request_url: Option<String>,
402    /// Event types that trigger this webhook.
403    #[serde(default)]
404    pub event_types: Vec<String>,
405    /// Any other fields returned by the API.
406    #[serde(flatten)]
407    pub extra: Extra,
408}
409
410/// A single dispatch (invocation) of a webhook.
411#[derive(Debug, Clone, Deserialize, Serialize)]
412#[serde(rename_all = "camelCase")]
413pub struct WebhookDispatch {
414    /// Unique dispatch ID.
415    pub id: String,
416    /// ID of the webhook that produced this dispatch.
417    #[serde(default)]
418    pub webhook_id: Option<String>,
419    /// Any other fields returned by the API.
420    #[serde(flatten)]
421    pub extra: Extra,
422}
423
424/// Account information about a user.
425#[derive(Debug, Clone, Deserialize, Serialize)]
426#[serde(rename_all = "camelCase")]
427pub struct User {
428    /// Unique user ID.
429    pub id: String,
430    /// Username.
431    #[serde(default)]
432    pub username: Option<String>,
433    /// Any other fields returned by the API (public or private depending on the call).
434    #[serde(flatten)]
435    pub extra: Extra,
436}
437
438/// A single Actor entry as returned by the Apify Store listing.
439#[derive(Debug, Clone, Deserialize, Serialize)]
440#[serde(rename_all = "camelCase")]
441pub struct ActorStoreListItem {
442    /// Unique Actor ID.
443    pub id: String,
444    /// Technical name of the Actor.
445    #[serde(default)]
446    pub name: Option<String>,
447    /// Username of the Actor's owner.
448    #[serde(default)]
449    pub username: Option<String>,
450    /// Human-readable title.
451    #[serde(default)]
452    pub title: Option<String>,
453    /// Any other fields returned by the API.
454    #[serde(flatten)]
455    pub extra: Extra,
456}
457
458/// An Actor version.
459#[derive(Debug, Clone, Deserialize, Serialize)]
460#[serde(rename_all = "camelCase")]
461pub struct ActorVersion {
462    /// The version number, e.g. `0.1`.
463    pub version_number: String,
464    /// The source type of the version, e.g. `SOURCE_FILES`, `GIT_REPO`, `TARBALL`, `GITHUB_GIST`.
465    #[serde(default)]
466    pub source_type: Option<String>,
467    /// Any other fields returned by the API.
468    #[serde(flatten)]
469    pub extra: Extra,
470}
471
472/// An environment variable attached to an Actor version.
473#[derive(Debug, Clone, Deserialize, Serialize)]
474#[serde(rename_all = "camelCase")]
475pub struct ActorEnvVar {
476    /// The environment variable name.
477    pub name: String,
478    /// The value (may be omitted for secret variables in responses).
479    #[serde(default, skip_serializing_if = "Option::is_none")]
480    pub value: Option<String>,
481    /// Whether the variable is a secret.
482    #[serde(default, skip_serializing_if = "Option::is_none")]
483    pub is_secret: Option<bool>,
484    /// Any other fields returned by the API.
485    #[serde(flatten)]
486    pub extra: Extra,
487}