| Crates.io | openfigi-rs |
| lib.rs | openfigi-rs |
| version | 0.3.4 |
| created_at | 2025-06-17 16:50:31.253625+00 |
| updated_at | 2025-08-09 15:12:27.325956+00 |
| description | A Rust client for interacting with the OpenFIGI API and parsing financial data. |
| homepage | https://github.com/NotAProfDev/openfigi-rs |
| repository | https://github.com/NotAProfDev/openfigi-rs |
| max_upload_size | |
| id | 1716028 |
| size | 720,821 |
A high-performance asynchronous Rust client library for the OpenFIGI 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.
This library is designed with a focus on ergonomics, correctness, and production readiness.
tokio and reqwest for high-concurrency applications.reqwest-middleware for custom logic like retries, logging, and tracing.First, add the crate to your project's dependencies:
cargo add openfigi-rs
use openfigi_rs::client::OpenFIGIClient;
use openfigi_rs::model::enums::IdType;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// Create a client. It will use the OPENFIGI_API_KEY env var if available.
let client = OpenFIGIClient::new();
// Map an ISIN to its corresponding FIGI
let mapping_results = client
.mapping(IdType::ID_ISIN, "US4592001014") // IBM
.send()
.await?;
// The result is a vector of responses. Let's inspect the first one.
let data = mapping_results.data();
println!("FIGI: {}", data[0].figi);
println!("Name: {}", data[0].display_name());
// You can also pretty-print the full debug output
// println!("{:#?}", mapping_results);
Ok(())
}
The client can be configured with an API key to access higher rate limits.
The client automatically detects the OPENFIGI_API_KEY environment variable.
export OPENFIGI_API_KEY="your-secret-key"
You can also provide the key explicitly using the builder pattern.
# use openfigi_rs::client::OpenFIGIClient;
# #[tokio::main]
# async fn main() -> anyhow::Result<()> {
#
let client = OpenFIGIClient::builder()
.api_key("your-secret-key")
.build()?;
# Ok(())
# }
For production environments, you'll want to configure timeouts and retry policies. This library is built on reqwest and reqwest-middleware, making customization easy.
use openfigi_rs::client::OpenFIGIClient;
use reqwest_middleware::ClientBuilder;
use reqwest_retry::{policies::ExponentialBackoff, RetryTransientMiddleware};
use std::time::Duration;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// 1. Create a base reqwest client with timeouts
let http_client = reqwest::Client::builder()
.timeout(Duration::from_secs(15))
.connect_timeout(Duration::from_secs(5))
.build()?;
// 2. Configure a retry policy
let retry_policy = ExponentialBackoff::builder().build_with_max_retries(3);
// 3. Build the middleware client
let middleware_client = ClientBuilder::new(http_client)
.with(RetryTransientMiddleware::new_with_policy(retry_policy))
.build();
// 4. Build the OpenFIGI client with the custom middleware client
let client = OpenFIGIClient::builder()
.middleware_client(middleware_client)
.api_key("your-secret-key")
.build()?;
Ok(())
}
| Limitation | Without API Key | With API Key |
|---|---|---|
| Request Rate | 25 per minute | 250 per minute (25 per 6s) |
| Jobs per Request | 10 jobs | 100 jobs |
The client supports all three OpenFIGI API v3 endpoints.
| Endpoint | Purpose | Batch Support |
|---|---|---|
| /mapping | Map third-party identifiers to FIGIs. | ✓ |
| /search | Perform a text-based search for instruments. | ✗ |
| /filter | Search for instruments using specific criteria. | ✗ |
Convert third-party identifiers to FIGIs:
use openfigi_rs::client::OpenFIGIClient;
use openfigi_rs::model::enums::{IdType, Currency, ExchCode};
use openfigi_rs::model::request::MappingRequest;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = OpenFIGIClient::new();
// Single mapping request with optional parameters
let single_result = client
.mapping(IdType::ID_ISIN, "US4592001014")
.currency(Currency::USD)
.exch_code(ExchCode::US)
.send()
.await?;
// Bulk mapping request for multiple identifiers using a prebuilt vector of requests
let requests = vec![
MappingRequest::new(IdType::ID_ISIN, "US4592001014"),
MappingRequest::new(IdType::TICKER, "AAPL"),
];
let bulk_results = client
.bulk_mapping()
.add_requests(requests)
.send()
.await?;
// Bulk mapping request with inline closures
let result = client
.bulk_mapping()
.add_request_with(|j| {
// Simple mapping request
j.id_type(IdType::ID_ISIN)
.id_value("US4592001014")
})?
.add_request_with(|j| {
// Complex mapping request with filters
j.id_type(IdType::TICKER)
.id_value("IBM")
.currency(Currency::USD)
.exch_code(ExchCode::US)
})?
.send()
.await?;
Ok(())
}
Text-based instrument search:
use openfigi_rs::client::OpenFIGIClient;
use openfigi_rs::model::enums::Currency;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = OpenFIGIClient::new();
let results = client
.search("apple")
.currency(Currency::USD)
.send()
.await?;
Ok(())
}
Filter instruments by criteria:
use openfigi_rs::client::OpenFIGIClient;
use openfigi_rs::model::enums::SecurityType;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let client = OpenFIGIClient::new();
let results = client
.filter()
.query("technology")
.security_type(SecurityType::CommonStock)
.send()
.await?;
Ok(())
}
The library provides a comprehensive OpenFIGIError enum. A common task is handling responses in a bulk request where some jobs may succeed and others may fail.
The API returns a 200 OK with a body containing either a data array or an error message for each job.
use openfigi_rs::client::OpenFIGIClient;
use openfigi_rs::error::OpenFIGIError;
use openfigi_rs::model::{enums::IdType, request::MappingRequest};
async fn handle_mapping() -> anyhow::Result<()> {
let client = OpenFIGIClient::new();
let requests = vec![
MappingRequest::new(IdType::ID_ISIN, "US4592001014"), // Valid
MappingRequest::new(IdType::ID_ISIN, "INVALID_ISIN"), // Invalid
];
match client.bulk_mapping().add_requests(requests).send().await {
Ok(mapping_results) => {
// Handle successful results
for (_index, data) in mapping_results.successes() {
println!("SUCCESS: Found {} instruments.", data.data().len());
}
// Handle failed results
for (_index, error) in mapping_results.failures() {
println!("API ERROR: {}", error);
}
}
// Handle network errors, timeouts, etc.
Err(e) => {
eprintln!("An unexpected network error occurred: {}", e);
}
}
Ok(())
}
Contributions are welcome! Please see CONTRIBUTING.md for guidelines on how to submit patches, report issues, and suggest features.
This project is licensed under the MIT License. See the LICENSE file for details.
reqwest, reqwest-middleware, serde, and tokio.For help with this library, please use the following resources:
Disclaimer: This library is an independent project and is not officially affiliated with, endorsed by, or sponsored by Bloomberg L.P. or the OpenFIGI project.