Skip to main content

nordnet_api/resources/
markets.rs

1//! Resource methods for the `markets` API group.
2//!
3//! # Operations
4//!
5//! | Method | Op | Path |
6//! |--------|-----|------|
7//! | GET | `list_markets` | `/markets` |
8//! | GET | `get_market` | `/markets/{market_id}` |
9//!
10//!
11//! ## Multi-ID lookups for `get_market`
12//!
13//! The Nordnet API path parameter for `get_market` accepts a comma-separated
14//! list of market IDs. This method covers the single-ID case via the
15//! [`MarketId`] newtype, mirroring the [`Client::get_country`] pattern. A
16//! future helper may be added for multi-ID lookups when needed.
17//!
18//!
19//! ## 204 No Content
20//!
21//! `GET /markets/{market_id}` may return HTTP 204 (No Content) when no
22//! matching market is found. The base [`Client::get`] method attempts to
23//! parse the empty response body as JSON, which fails. `get_market` detects
24//! this specific case (a [`Error::Decode`] with an empty body) and maps it
25//! to an empty `Vec`, mirroring [`Client::get_country`].
26
27use crate::client::Client;
28use crate::error::Error;
29use nordnet_model::ids::MarketId;
30use nordnet_model::models::markets::Market;
31
32impl Client {
33    /// `GET /markets` — Returns information about all tradable markets.
34    ///
35    /// # Errors
36    ///
37    /// Returns [`Error::Unauthorized`] (401), [`Error::TooManyRequests`]
38    /// (429), or [`Error::ServiceUnavailable`] (503) as documented.
39    #[doc(alias = "GET /markets")]
40    pub async fn list_markets(&self) -> Result<Vec<Market>, Error> {
41        self.get("/markets").await
42    }
43
44    /// `GET /markets/{market_id}` — Returns information about the market
45    /// identified by `id`.
46    ///
47    /// Returns an empty `Vec` when the API responds with 204 No Content (no
48    /// matching markets).
49    ///
50    /// # Errors
51    ///
52    /// Returns [`Error::BadRequest`] (400), [`Error::Unauthorized`] (401),
53    /// [`Error::TooManyRequests`] (429), or [`Error::ServiceUnavailable`]
54    /// (503) as documented.
55    #[doc(alias = "GET /markets/{market_id}")]
56    pub async fn get_market(&self, id: MarketId) -> Result<Vec<Market>, Error> {
57        let path = format!("/markets/{id}");
58        match self.get::<Vec<Market>>(&path).await {
59            Ok(markets) => Ok(markets),
60            // HTTP 204 No Content: the base client sees an empty body and
61            // produces a Decode error. Map it to an empty Vec instead.
62            Err(Error::Decode { ref body, .. }) if body.trim().is_empty() => Ok(vec![]),
63            Err(e) => Err(e),
64        }
65    }
66}