Skip to main content

quicknode_sdk/admin/
endpoints.rs

1#[cfg(feature = "rust")]
2use bon::Builder;
3#[cfg(feature = "node")]
4use napi_derive::napi;
5#[cfg(feature = "python")]
6use pyo3::pyclass;
7#[cfg(feature = "python")]
8use pyo3_stub_gen::derive::gen_stub_pyclass;
9use serde::{Deserialize, Serialize};
10
11/// Parameters for `get_endpoints`.
12#[cfg_attr(feature = "python", gen_stub_pyclass)]
13#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
14#[cfg_attr(feature = "node", napi(object))]
15#[cfg_attr(feature = "rust", derive(Builder))]
16#[derive(Debug, Clone, Default, Serialize)]
17pub struct GetEndpointsRequest {
18    /// Maximum number of endpoints returned.
19    #[serde(skip_serializing_if = "Option::is_none")]
20    pub limit: Option<i32>,
21    /// Starting index into the result set.
22    #[serde(skip_serializing_if = "Option::is_none")]
23    pub offset: Option<i32>,
24    /// Search by subdomain or label.
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub search: Option<String>,
27    /// Field to sort results by.
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub sort_by: Option<String>,
30    /// Sort direction (`asc` or `desc`).
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub sort_direction: Option<String>,
33    /// Filter results to endpoints on these networks.
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub networks: Option<Vec<String>>,
36    /// Filter results to endpoints in these statuses.
37    #[serde(skip_serializing_if = "Option::is_none")]
38    pub statuses: Option<Vec<String>>,
39    /// Filter results by label.
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub labels: Option<Vec<String>>,
42    /// When true, return only dedicated endpoints.
43    #[serde(skip_serializing_if = "Option::is_none")]
44    pub dedicated: Option<bool>,
45    /// When true, return only flat-rate endpoints.
46    #[serde(skip_serializing_if = "Option::is_none")]
47    pub is_flat_rate: Option<bool>,
48    /// Filter results by associated tag ids.
49    #[serde(skip_serializing_if = "Option::is_none")]
50    pub tag_ids: Option<Vec<i32>>,
51    /// Filter results by associated tag labels.
52    #[serde(skip_serializing_if = "Option::is_none")]
53    pub tag_labels: Option<Vec<String>>,
54}
55
56/// Response from `get_endpoints`.
57#[cfg_attr(feature = "python", gen_stub_pyclass)]
58#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
59#[cfg_attr(feature = "node", napi(object))]
60#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct GetEndpointsResponse {
62    /// Endpoints on the current page.
63    #[serde(default)]
64    pub data: Vec<Endpoint>,
65    /// Pagination metadata for the response.
66    pub pagination: Option<Pagination>,
67    /// Error message when the request did not succeed.
68    pub error: Option<String>,
69}
70
71/// Pagination metadata for admin list responses.
72#[cfg_attr(feature = "python", gen_stub_pyclass)]
73#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
74#[cfg_attr(feature = "node", napi(object))]
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct Pagination {
77    /// Total number of items matching the query across all pages.
78    pub total: i64,
79    /// Page size used for this response.
80    pub limit: i32,
81    /// Starting index of this page within the full result set.
82    pub offset: i32,
83}
84
85/// Summary representation of an endpoint in list responses.
86#[cfg_attr(feature = "python", gen_stub_pyclass)]
87#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
88#[cfg_attr(feature = "node", napi(object))]
89#[derive(Debug, Clone, Serialize, Deserialize)]
90pub struct Endpoint {
91    /// Unique endpoint identifier.
92    pub id: String,
93    /// Quicknode-assigned subdomain.
94    pub name: String,
95    /// Human-readable label.
96    pub label: Option<String>,
97    /// Current operational status (e.g. `active`, `paused`).
98    pub status: String,
99    /// Blockchain the endpoint serves (e.g. `ethereum`).
100    pub chain: String,
101    /// Specific network within the chain (e.g. `mainnet`).
102    pub network: String,
103    /// Whether the endpoint is dedicated.
104    pub is_dedicated: bool,
105    /// Whether the endpoint is billed at a flat rate.
106    pub is_flat_rate: bool,
107    /// HTTP RPC URL.
108    pub http_url: String,
109    /// WebSocket RPC URL, when available.
110    pub wss_url: Option<String>,
111    /// Tags applied to the endpoint.
112    #[serde(default)]
113    pub tags: Vec<EndpointTag>,
114    /// Whether the endpoint is configured to serve multiple chains/networks.
115    #[serde(default)]
116    pub is_multichain: bool,
117}
118
119/// Tag reference as returned on an endpoint.
120#[cfg_attr(feature = "python", gen_stub_pyclass)]
121#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
122#[cfg_attr(feature = "node", napi(object))]
123#[derive(Debug, Clone, Serialize, Deserialize)]
124pub struct EndpointTag {
125    /// Tag identifier.
126    pub tag_id: i32,
127    /// Tag label.
128    pub label: String,
129}
130
131/// Parameters for `create_endpoint`.
132#[cfg_attr(feature = "python", gen_stub_pyclass)]
133#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
134#[cfg_attr(feature = "node", napi(object))]
135#[cfg_attr(feature = "rust", derive(Builder))]
136#[derive(Debug, Clone, Default, Serialize)]
137pub struct CreateEndpointRequest {
138    /// Blockchain the endpoint should serve (e.g. `ethereum`).
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub chain: Option<String>,
141    /// Specific network within the chain (e.g. `mainnet`).
142    #[serde(skip_serializing_if = "Option::is_none")]
143    pub network: Option<String>,
144}
145
146/// Response from `create_endpoint`.
147#[cfg_attr(feature = "python", gen_stub_pyclass)]
148#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
149#[cfg_attr(feature = "node", napi(object))]
150#[derive(Debug, Clone, Serialize, Deserialize)]
151pub struct CreateEndpointResponse {
152    /// The newly created endpoint.
153    pub data: SingleEndpoint,
154    /// Error message when the request did not succeed.
155    pub error: Option<String>,
156}
157
158/// Full representation of a single endpoint, including its security and rate limits.
159#[cfg_attr(feature = "python", gen_stub_pyclass)]
160#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
161#[cfg_attr(feature = "node", napi(object))]
162#[derive(Debug, Clone, Serialize, Deserialize)]
163pub struct SingleEndpoint {
164    /// Unique endpoint identifier.
165    pub id: String,
166    /// Human-readable label.
167    pub label: Option<String>,
168    /// Current operational status.
169    pub status: Option<String>,
170    /// Blockchain the endpoint serves.
171    pub chain: String,
172    /// Specific network within the chain.
173    pub network: String,
174    /// HTTP RPC URL.
175    pub http_url: String,
176    /// WebSocket RPC URL, when available.
177    pub wss_url: Option<String>,
178    /// Endpoint security configuration.
179    pub security: Option<EndpointSecurity>,
180    /// Endpoint rate limits.
181    pub rate_limits: Option<EndpointRateLimits>,
182    /// Tags applied to the endpoint.
183    #[serde(default)]
184    pub tags: Vec<EndpointTag>,
185    /// Whether the endpoint is configured to serve multiple chains/networks.
186    #[serde(default)]
187    pub is_multichain: bool,
188}
189
190/// Rate limits applied to an endpoint.
191#[cfg_attr(feature = "python", gen_stub_pyclass)]
192#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
193#[cfg_attr(feature = "node", napi(object))]
194#[derive(Debug, Clone, Serialize, Deserialize)]
195pub struct EndpointRateLimits {
196    /// Whether rate limits are applied per client IP instead of per endpoint.
197    pub rate_limit_by_ip: Option<bool>,
198    /// Account-level rate limit, when applicable.
199    pub account: Option<i32>,
200    /// Requests per second.
201    pub rps: Option<i32>,
202    /// Requests per minute.
203    pub rpm: Option<i32>,
204    /// Requests per day.
205    pub rpd: Option<i32>,
206}
207
208/// Security configuration for an endpoint — the aggregate of tokens, JWTs,
209/// referrers, domain masks, IPs, and request filters plus their enabled
210/// toggles.
211#[cfg_attr(feature = "python", gen_stub_pyclass)]
212#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
213#[cfg_attr(feature = "node", napi(object))]
214#[derive(Debug, Clone, Serialize, Deserialize)]
215pub struct EndpointSecurity {
216    /// Per-feature enabled/disabled toggles.
217    pub options: Option<EndpointSecurityOptions>,
218    /// Authentication tokens configured on the endpoint.
219    pub tokens: Option<Vec<EndpointToken>>,
220    /// JWTs configured on the endpoint.
221    pub jwts: Option<Vec<EndpointJwt>>,
222    /// Allowed referrer URLs/domains.
223    pub referrers: Option<Vec<EndpointReferrer>>,
224    /// Configured domain masks.
225    pub domain_masks: Option<Vec<EndpointDomainMask>>,
226    /// Whitelisted IP addresses.
227    pub ips: Option<Vec<EndpointIp>>,
228    /// Request (method) filters.
229    pub request_filters: Option<Vec<EndpointRequestFilter>>,
230}
231
232/// Boolean toggles controlling which security features are enabled.
233#[cfg_attr(feature = "python", gen_stub_pyclass)]
234#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
235#[cfg_attr(feature = "node", napi(object))]
236#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct EndpointSecurityOptions {
238    /// Whether token authentication is enforced.
239    pub tokens: Option<bool>,
240    /// Whether JWT validation is enforced.
241    pub jwts: Option<bool>,
242    /// Whether domain masking is enabled.
243    #[serde(rename = "domainMasks")]
244    pub domain_masks: Option<bool>,
245    /// Whether IP whitelisting is enforced.
246    pub ips: Option<bool>,
247    /// Whether referrer validation is enforced.
248    pub referrers: Option<bool>,
249    /// Whether request (method) filtering is enforced.
250    #[serde(rename = "requestFilters")]
251    pub request_filters: Option<bool>,
252    /// Custom header used to identify the client IP.
253    #[serde(rename = "ipCustomHeader")]
254    pub ip_custom_header: Option<EndpointIpCustomHeaderOption>,
255}
256
257/// Custom header option value for IP identification.
258#[cfg_attr(feature = "python", gen_stub_pyclass)]
259#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
260#[cfg_attr(feature = "node", napi(object))]
261#[derive(Debug, Clone, Serialize, Deserialize)]
262pub struct EndpointIpCustomHeaderOption {
263    /// Header name (e.g. `X-Forwarded-For`).
264    pub value: Option<String>,
265}
266
267/// Authentication token configured on an endpoint.
268#[cfg_attr(feature = "python", gen_stub_pyclass)]
269#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
270#[cfg_attr(feature = "node", napi(object))]
271#[derive(Clone, Serialize, Deserialize)]
272pub struct EndpointToken {
273    /// Token identifier.
274    pub id: String,
275    /// Token secret.
276    pub token: String,
277}
278
279// Manual Debug redacts `token` so accidental println!/tracing of an
280// EndpointSecurity response does not leak the raw RPC access token.
281impl std::fmt::Debug for EndpointToken {
282    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283        f.debug_struct("EndpointToken")
284            .field("id", &self.id)
285            .field("token", &"[redacted]")
286            .finish()
287    }
288}
289
290/// JWT configured on an endpoint for signed-request authentication.
291#[cfg_attr(feature = "python", gen_stub_pyclass)]
292#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
293#[cfg_attr(feature = "node", napi(object))]
294#[derive(Clone, Serialize, Deserialize)]
295pub struct EndpointJwt {
296    /// JWT identifier.
297    pub id: String,
298    /// Public key used to verify signed JWTs.
299    pub public_key: String,
300    /// Key identifier (`kid`) embedded in JWT headers.
301    pub kid: String,
302    /// Human-readable name.
303    pub name: String,
304}
305
306// Manual Debug redacts `public_key` — credential material per CLAUDE.md policy.
307impl std::fmt::Debug for EndpointJwt {
308    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
309        f.debug_struct("EndpointJwt")
310            .field("id", &self.id)
311            .field("public_key", &"[redacted]")
312            .field("kid", &self.kid)
313            .field("name", &self.name)
314            .finish()
315    }
316}
317
318/// Allowed referrer entry for request-origin validation.
319#[cfg_attr(feature = "python", gen_stub_pyclass)]
320#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
321#[cfg_attr(feature = "node", napi(object))]
322#[derive(Debug, Clone, Serialize, Deserialize)]
323pub struct EndpointReferrer {
324    /// Referrer entry identifier.
325    pub id: String,
326    /// Allowed referrer URL or domain.
327    pub referrer: Option<String>,
328}
329
330/// Domain mask configured on an endpoint.
331#[cfg_attr(feature = "python", gen_stub_pyclass)]
332#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
333#[cfg_attr(feature = "node", napi(object))]
334#[derive(Debug, Clone, Serialize, Deserialize)]
335pub struct EndpointDomainMask {
336    /// Domain mask identifier.
337    pub id: String,
338    /// Masking domain.
339    pub domain: String,
340}
341
342/// Whitelisted IP address on an endpoint.
343#[cfg_attr(feature = "python", gen_stub_pyclass)]
344#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
345#[cfg_attr(feature = "node", napi(object))]
346#[derive(Debug, Clone, Serialize, Deserialize)]
347pub struct EndpointIp {
348    /// IP entry identifier.
349    pub id: String,
350    /// Whitelisted IP address.
351    pub ip: String,
352}
353
354/// Request (method) filter configured on an endpoint.
355#[cfg_attr(feature = "python", gen_stub_pyclass)]
356#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
357#[cfg_attr(feature = "node", napi(object))]
358#[derive(Debug, Clone, Serialize, Deserialize)]
359pub struct EndpointRequestFilter {
360    /// Filter identifier.
361    pub id: String,
362    /// Whitelisted RPC methods.
363    #[serde(default)]
364    pub method: Vec<String>,
365}
366
367/// Response from `show_endpoint`.
368#[cfg_attr(feature = "python", gen_stub_pyclass)]
369#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
370#[cfg_attr(feature = "node", napi(object))]
371#[derive(Debug, Clone, Serialize, Deserialize)]
372pub struct ShowEndpointResponse {
373    /// The endpoint, when found.
374    pub data: Option<SingleEndpoint>,
375    /// Error message when the request did not succeed.
376    pub error: Option<String>,
377}
378
379/// Parameters for `update_endpoint`.
380#[cfg_attr(feature = "python", gen_stub_pyclass)]
381#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
382#[cfg_attr(feature = "node", napi(object))]
383#[cfg_attr(feature = "rust", derive(Builder))]
384#[derive(Debug, Clone, Default, Serialize)]
385pub struct UpdateEndpointRequest {
386    /// New human-readable label.
387    #[serde(skip_serializing_if = "Option::is_none")]
388    pub label: Option<String>,
389}
390
391/// Parameters for `update_endpoint_status`.
392#[cfg_attr(feature = "python", gen_stub_pyclass)]
393#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
394#[cfg_attr(feature = "node", napi(object))]
395#[cfg_attr(feature = "rust", derive(Builder))]
396#[derive(Debug, Clone, Default, Serialize)]
397pub struct UpdateEndpointStatusRequest {
398    /// New status (`active` or `paused`).
399    pub status: String,
400}
401
402/// Response from `update_endpoint_status`.
403#[cfg_attr(feature = "python", gen_stub_pyclass)]
404#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
405#[cfg_attr(feature = "node", napi(object))]
406#[derive(Debug, Clone, Serialize, Deserialize)]
407pub struct UpdateEndpointStatusResponse {
408    /// Confirmation string returned by the API.
409    pub data: Option<String>,
410    /// Error message when the request did not succeed.
411    pub error: Option<String>,
412}
413
414/// Parameters for `create_tag` (on a specific endpoint).
415#[cfg_attr(feature = "python", gen_stub_pyclass)]
416#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
417#[cfg_attr(feature = "node", napi(object))]
418#[cfg_attr(feature = "rust", derive(Builder))]
419#[derive(Debug, Clone, Default, Serialize)]
420pub struct CreateTagRequest {
421    /// Label for the new tag. Maximum 25 characters.
422    #[serde(skip_serializing_if = "Option::is_none")]
423    pub label: Option<String>,
424}
425
426/// Response from `get_endpoint_security`.
427#[cfg_attr(feature = "python", gen_stub_pyclass)]
428#[cfg_attr(feature = "python", pyclass(get_all, set_all))]
429#[cfg_attr(feature = "node", napi(object))]
430#[derive(Debug, Clone, Serialize, Deserialize)]
431pub struct GetEndpointSecurityResponse {
432    /// The endpoint's security configuration.
433    pub data: Option<EndpointSecurity>,
434    /// Error message when the request did not succeed.
435    pub error: Option<String>,
436}