Code Review - OpenFIGI Http Client

Hey everyone,

I'm currently learning Rust and not a professional developer — this crate is part of my journey to level up in idiomatic Rust and API design. I started out with Python and stumbled into Rust last year, and after building a few small tools, I’ve completely fallen for the language.

This time around, I put together a wrapper for the OpenFIGI API to simplify the process of mapping instrument identifiers like FIGI, ISIN, and CUSIP. I built the client semi-manually using reqwest and serde. Link: NotAProfDev/openfigi-rs: A modern, strongly-typed Rust client for the OpenFIGI API

I know this is a pretty general request, but I’d really appreciate a code review and any feedback you’re willing to share to help me improve — especially around:

  • Whether I'm writing Rust idiomatically
  • Struct and error handling design
  • Usability and ergonomics of the API
  • CI setup and testing best practices
  • Anything that could be cleaner, more robust, or more maintainable

Thanks so much in advance!

Just wanted to share a few more thoughts as I continue refining the crate.

I’ve been reviewing other HTTP clients and noticed some interesting patterns that I might incorporate:

  • Using Cow<str> for string fields: This seems like a smart way to avoid unnecessary allocations when dealing with borrowed vs owned strings. Curious if folks think this is worth the complexity in a client like this?

  • Type-state pattern: I came across this in some builder-style APIs, where you encode valid states at the type level. It looks powerful for guiding correct usage, especially for multi-step configuration. I’m wondering if it could help make the client more robust or expressive.

I’d love to hear if anyone has experience applying these patterns in HTTP clients or API wrappers. Are they overkill for something like OpenFIGI, or do they add meaningful value?

Thanks again for reading and for any insights!

As I continue refining the OpenFIGI client, I’m debating whether to introduce an abstraction layer between the raw API responses and the public-facing interface. The idea is to make the client more ergonomic and resilient to upstream changes, without hiding too much of the underlying structure.

Most of the API wrappers I’ve looked at on GitHub seem to expose the raw responses directly—at least from what I could tell. Maybe I’m just missing the abstraction layers buried in the codebases, or maybe it’s not common practice in Rust?

Would it be idiomatic to implement something like an adapter that reshapes the raw responses into a more user-friendly format? Or is it better to keep things transparent and let users handle the raw types themselves?

Curious how others approach this—especially when balancing usability, transparency, and long-term maintainability.