Rust SDK
orizn (crates.io)
The official crate. Async on tokio, typed errors, one dependency to add.
What was executed to write this page
orizn 1.0.1 pulled from crates.io into a fresh cargo project, compiled, and run against the live API. The output blocks are the real stdout of that binary. The known issue below was found by running it, then confirmed in the published crate source.
Before you start
- A Rust toolchain with cargo.
- An Orizn API key. Free tier: 50 requests/month, no credit card — get one at visa.orizn.app/visa-api. It is 5 requests until you confirm your email, so click the link in the confirmation mail.
- Country codes are ISO 3166-1 alpha-3 — FRA, JPN, USA. Alpha-2 codes (FR, JP) are rejected with a 400, they are not silently converted.
Walkthrough
1. Add the dependency
[dependencies]
orizn = "1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }2. Your first call — the complete main.rs
use orizn::Orizn;
#[tokio::main]
async fn main() -> Result<(), orizn::Error> {
// with_key(...), or Orizn::new() which reads ORIZN_API_KEY
let client = Orizn::with_key(std::env::var("ORIZN_API_KEY").expect("set ORIZN_API_KEY"));
let visa = client.get_visa("FRA", "JPN", "en").await?;
println!("requirement = {}", visa.requirement);
println!("visa_free_days = {:?}", visa.visa_free_days);
println!("description = {}", visa.description);
println!("documents = {:#?}", visa.documents_required);
Ok(())
}requirement = visa_free
visa_free_days = Some(90)
description = France citizens can enter Japan without a visa for a stay of up to 90 days. A valid passport is required.
documents = [
"Valid passport (6 months minimum)",
"Return or onward ticket",
"Proof of accommodation",
"Proof of sufficient funds",
]3. Known issue in 1.0.1 — use get_visa, not check
The crate exposes a check() method for cheap yes-or-no lookups. In the currently published version it does not attach the API key to the request, and /api/v1/visa/check has required a key since 2026. It therefore fails for everyone, always:
Error: AuthRequiredget_visa() sends the key correctly and returns everything check() would have, plus the rest of the record. Use it until a fixed crate ships. The JavaScript and Python SDKs already carry the equivalent fix.
When it goes wrong
Every failure the integration can hand you, with the message it actually prints.
No key, or a rejected key
Error::AuthRequiredError: AuthRequiredCovers both 401 and 403 — the variant does not distinguish them, so check the key exists before blaming the plan.
Valid codes, no record for that pair
Error::NotFoundError: NotFound { passport: "FRA", destination: "XXX" }The variant carries both codes, so you can log which pair was missing without threading context through.
Any use of check() in 1.0.1
Error::AuthRequiredFails even with a valid key — see the section above.Call get_visa() instead.
All three rows were reproduced by running the binary. Rate limiting was not reproduced: the key used to write this page is uncapped.
End to end: an entry-rules check in a service
The realistic shape in Rust is a fallible lookup behind your own error type, so a missing pair does not read like a network failure.
use orizn::{Orizn, Error};
pub enum Entry { Allowed { days: Option<i32> }, NeedsVisa, Refused, Unknown }
pub async fn entry_rules(c: &Orizn, passport: &str, dest: &str) -> Result<Entry, Error> {
match c.get_visa(passport, dest, "en").await {
Ok(v) => Ok(match v.requirement.as_str() {
"visa_free" | "freedom_of_movement" => Entry::Allowed { days: v.visa_free_days },
// 52 pairs. No visa unlocks these — do not fold them into NeedsVisa.
"no_admission" | "admission_refused" => Entry::Refused,
"not_applicable" | "special" => Entry::Unknown,
_ => Entry::NeedsVisa,
}),
// A pair we have no record for is UNKNOWN, never "no visa needed".
Err(Error::NotFound { .. }) => Ok(Entry::Unknown),
Err(e) => Err(e),
}
}Source & reference
Other integrations
50 requests a month, no credit card
All 15 languages included on the free plan. Hit a wall with this tutorial? Mail [email protected] — a tutorial that does not work is a bug.