Skip to main content

cbr_finapi_rs/
lib.rs

1//! Typed client for CBR public APIs.
2//!
3//! Includes:
4//! - GIS AntiFraud (mandatory from 2026-03-01)
5//! - TsPI (Citizen Digital Profile)
6//! - EBS (Unified Biometric System)
7
8#![cfg_attr(not(feature = "std"), no_std)]
9
10extern crate alloc;
11#[cfg(feature = "client")]
12use alloc::string::String;
13
14pub mod antifraud;
15#[cfg(feature = "client")]
16pub mod ebs;
17#[cfg(feature = "client")]
18pub mod tspi;
19
20#[cfg(feature = "client")]
21use reqwest::Client as HttpClient;
22#[cfg(feature = "client")]
23use std::time::Duration;
24
25#[derive(Debug, thiserror::Error)]
26pub enum CbrApiError {
27    #[cfg(feature = "client")]
28    #[error("HTTP Error: {0}")]
29    Http(#[from] reqwest::Error),
30    #[error("Rate Limit Exceeded (429)")]
31    RateLimited,
32    #[error("Service Unavailable (503)")]
33    Unavailable,
34    #[error("API JSON Parse Error: {0}")]
35    Json(#[from] serde_json::Error),
36    #[error("Authentication Error: {0}")]
37    Auth(alloc::string::String),
38}
39
40#[cfg(feature = "client")]
41pub struct CbrApiClient {
42    http: HttpClient,
43    base_url: String,
44    api_key: String,
45}
46
47#[cfg(feature = "client")]
48impl CbrApiClient {
49    pub fn builder() -> CbrApiBuilder {
50        CbrApiBuilder::default()
51    }
52
53    pub fn antifraud(&self) -> antifraud::AntiFraudClient<'_> {
54        antifraud::AntiFraudClient::new(self)
55    }
56
57    pub fn tspi(&self) -> tspi::TspiClient<'_> {
58        tspi::TspiClient::new(self)
59    }
60
61    pub fn ebs(&self) -> ebs::EbsClient<'_> {
62        ebs::EbsClient::new(self)
63    }
64}
65
66#[cfg(feature = "client")]
67#[derive(Default)]
68pub struct CbrApiBuilder {
69    base_url: Option<String>,
70    api_key: Option<String>,
71}
72
73#[cfg(feature = "client")]
74impl CbrApiBuilder {
75    pub fn base_url(mut self, url: impl Into<String>) -> Self {
76        self.base_url = Some(url.into());
77        self
78    }
79
80    pub fn api_key(mut self, key: impl Into<String>) -> Self {
81        self.api_key = Some(key.into());
82        self
83    }
84
85    pub fn build(self) -> Result<CbrApiClient, CbrApiError> {
86        let base_url = self
87            .base_url
88            .unwrap_or_else(|| "https://finapi.cbr.ru".to_string());
89        let api_key = self
90            .api_key
91            .ok_or_else(|| CbrApiError::Auth("Missing API Key".into()))?;
92
93        let http = HttpClient::builder()
94            .timeout(Duration::from_secs(10))
95            .build()?;
96
97        Ok(CbrApiClient {
98            http,
99            base_url,
100            api_key,
101        })
102    }
103}