# OpenFIGI Rust Client
[](https://crates.io/crates/openfigi-rs)
[](https://docs.rs/openfigi-rs)
[](https://opensource.org/licenses/MIT)
[](https://github.com/NotAProfDev/openfigi-rs/actions)
> **âšī¸ API Notice:** The API is subject to change in the future and is not yet stable.
A high-performance Rust client library for the [OpenFIGI API](https://www.openfigi.com/api), providing type-safe access to financial instrument identification and mapping services.
OpenFIGI is Bloomberg's open symbology initiative that provides standardized identification for financial instruments across asset classes and markets worldwide.
## ⨠Features
- **đ Type-safe API** - Strongly typed request/response models with compile-time validation
- **⥠Async/await support** - Built on `reqwest` with full async support and connection pooling
- **đ§ Middleware support** - Extensible HTTP middleware for retries, logging, and observability
- **đ Comprehensive error handling** - Detailed error types with OpenFIGI-specific context
- **đ Production ready** - Connection pooling, timeouts, and efficient resource management
- **đ Environment integration** - Automatic API key detection from environment variables
- **đ Rate limit awareness** - Automatic rate limit detection and informative error messages
- **đ Batch operations** - Support for bulk requests (up to 100 with API key, 5 without)
## đ Quick Start
Add this to your `Cargo.toml`:
```toml
[dependencies]
openfigi-rs = "<latest-version>"
```
### Basic Usage
```rust
use openfigi_rs::client::OpenFIGIClient;
use openfigi_rs::model::enums::IdType;
use serde_json::json;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a client (uses OPENFIGI_API_KEY env var if available)
let client = OpenFIGIClient::new();
// Map an ISIN to FIGI
let mapping_results = client
.mapping(IdType::IdIsin, json!("US4592001014"))
.send()
.await?;
// Access the FIGI from the first result
let data = mapping_results.data();
println!("FIGI: {}", data[0].figi);
println!("Name: {}", data[0].display_name());
Ok(())
}
```
### With Custom Configuration
```rust
use openfigi_rs::client::OpenFIGIClient;
use reqwest_middleware::ClientBuilder;
use reqwest_retry::{RetryTransientMiddleware, policies::ExponentialBackoff};
use std::time::Duration;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure HTTP client with retry middleware
let http_client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let retry_policy = ExponentialBackoff::builder().build_with_max_retries(3);
let middleware_client = ClientBuilder::new(http_client)
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
.build();
let client = OpenFIGIClient::builder()
.middleware_client(middleware_client)
.api_key("your-api-key")
.build()?;
Ok(())
}
```
## đ Authentication & Rate Limits
### API Key Setup
Set your API key as an environment variable:
```bash
export OPENFIGI_API_KEY="your-api-key"
```
Or configure it explicitly:
```rust
let client = OpenFIGIClient::builder()
.api_key("your-api-key")
.build()?;
```
### Rate Limits
| Max Amount of Requests | 25 Per Minute | 25 Per 6 Seconds |
| Max Jobs Per Request | 10 Jobs | 100 Jobs |
## đ API Endpoints
### Mapping Endpoint
Convert third-party identifiers to FIGIs:
```rust
use openfigi_rs::model::enums::{IdType, Currency, ExchCode};
// Single mapping request
let result = client
.mapping(IdType::IdIsin, "US4592001014")
.currency(Currency::USD)
.exch_code(ExchCode::US)
.send()
.await?;
// Bulk mapping request
use openfigi_rs::model::request::MappingRequest;
let requests = vec![
MappingRequest::new(IdType::IdIsin, json!("US4592001014")),
MappingRequest::new(IdType::Ticker, json!("AAPL")),
];
let results = client
.bulk_mapping()
.add_requests(requests)
.send()
.await?;
```
### Search Endpoint
Text-based instrument search:
```rust
use openfigi_rs::model::enums::Currency;
let results = client
.search("apple")
.currency(Currency::USD)
.send()
.await?;
```
### Filter Endpoint
Filter instruments by criteria:
```rust
use openfigi_rs::model::enums::SecurityType;
let results = client
.filter()
.query("technology")
.security_type(SecurityType::CommonStock)
.send()
.await?;
```
## đ ī¸ Advanced Usage
### Error Handling
```rust
use openfigi_rs::error::OpenFIGIError;
match client.mapping(IdType::IdIsin, json!("INVALID")).send().await {
Ok(results) => {
for result in &results {
match result.data() {
Some(data) => println!("Found {} FIGIs", data.len()),
None => println!("Error: {}", result.error().unwrap_or("Unknown")),
}
}
}
Err(OpenFIGIError::ReqwestError(e)) if e.is_timeout() => {
println!("Request timed out - consider retry");
}
Err(OpenFIGIError::ResponseError(e)) if e.status.as_u16() == 429 => {
println!("Rate limit exceeded - implement backoff");
}
Err(e) => println!("Other error: {}", e),
}
```
### Production Configuration
```rust
use std::time::Duration;
use reqwest_middleware::ClientBuilder;
use reqwest_retry::{RetryTransientMiddleware, policies::ExponentialBackoff};
let http_client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.connect_timeout(Duration::from_secs(5))
.pool_idle_timeout(Duration::from_secs(90))
.pool_max_idle_per_host(10)
.build()?;
let retry_policy = ExponentialBackoff::builder()
.retry_bounds(Duration::from_millis(100), Duration::from_secs(30))
.build_with_max_retries(3);
let middleware_client = ClientBuilder::new(http_client)
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
.build();
let client = OpenFIGIClient::builder()
.middleware_client(middleware_client)
.api_key(std::env::var("OPENFIGI_API_KEY")?)
.build()?;
```
## đ Documentation
- [API Documentation](https://docs.rs/openfigi-rs) - Complete API reference
- [OpenFIGI API Documentation](https://www.openfigi.com/api/documentation) - Official API docs
## đ¤ Contributing
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for details.
## đ License
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
## đ Acknowledgments
- [OpenFIGI](https://www.openfigi.com/) for providing the API and documentation
- [Bloomberg](https://www.bloomberg.com/) for the OpenFIGI initiative
- [OMG](https://www.omg.org/spec/FIGI) for providing documentation
- The Rust community for excellent HTTP and async libraries
## đ Support
- đ [Documentation](https://docs.rs/openfigi-rs)
- đ [Issue Tracker](https://github.com/NotAProfDev/openfigi-rs/issues)
- đŦ [Discussions](https://github.com/NotAProfDev/openfigi-rs/discussions)
---
**Note**: This library is not officially affiliated with Bloomberg or OpenFIGI. It's an independent implementation of the OpenFIGI API client for Rust.