use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use surf::http::headers::AUTHORIZATION;
use crate::{error::OpenRouterError, types::ApiResponse, utils::handle_error};
#[derive(Serialize, Deserialize, Debug)]
pub struct ApiKey {
pub name: Option<String>,
pub label: Option<String>,
pub limit: Option<f64>,
pub disabled: Option<bool>,
pub created_at: Option<String>,
pub updated_at: Option<String>,
pub hash: Option<String>,
pub key: Option<String>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct ApiKeyDetails {
pub label: String,
pub usage: f64,
pub is_free_tier: bool,
pub is_provisioning_key: bool,
pub rate_limit: RateLimit,
pub limit: Option<f64>,
pub limit_remaining: Option<f64>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct RateLimit {
pub requests: f64,
pub interval: String,
}
#[derive(Serialize)]
struct CreateApiKeyRequest {
name: String,
limit: Option<f64>,
}
#[derive(Serialize)]
struct UpdateApiKeyRequest {
name: Option<String>,
disabled: Option<bool>,
limit: Option<f64>,
}
pub async fn get_current_api_key(
base_url: &str,
api_key: &str,
) -> Result<ApiKeyDetails, OpenRouterError> {
let url = format!("{base_url}/key");
let mut response = surf::get(url)
.header(AUTHORIZATION, format!("Bearer {api_key}"))
.send()
.await?;
if response.status().is_success() {
let api_response: ApiResponse<_> = response.body_json().await?;
Ok(api_response.data)
} else {
handle_error(response).await?;
unreachable!()
}
}
pub async fn list_api_keys(
base_url: &str,
api_key: &str,
offset: Option<f64>,
include_disabled: Option<bool>,
) -> Result<Vec<ApiKey>, OpenRouterError> {
let url = format!("{base_url}/keys");
let mut query_params = HashMap::new();
if let Some(offset) = offset {
query_params.insert("offset", offset.to_string());
}
if let Some(include_disabled) = include_disabled {
query_params.insert("include_disabled", include_disabled.to_string());
}
let mut response = surf::get(url)
.header(AUTHORIZATION, format!("Bearer {api_key}"))
.query(&query_params)?
.await?;
if response.status().is_success() {
let api_response: ApiResponse<_> = response.body_json().await?;
Ok(api_response.data)
} else {
handle_error(response).await?;
unreachable!()
}
}
pub async fn create_api_key(
base_url: &str,
api_key: &str,
name: &str,
limit: Option<f64>,
) -> Result<ApiKey, OpenRouterError> {
let url = format!("{base_url}/keys");
let request = CreateApiKeyRequest {
name: name.to_string(),
limit,
};
let mut response = surf::post(url)
.header(AUTHORIZATION, format!("Bearer {api_key}"))
.body_json(&request)?
.await?;
if response.status().is_success() {
let api_response: ApiResponse<_> = response.body_json().await?;
Ok(api_response.data)
} else {
handle_error(response).await?;
unreachable!()
}
}
pub async fn get_api_key(
base_url: &str,
api_key: &str,
hash: &str,
) -> Result<ApiKey, OpenRouterError> {
let url = format!("{base_url}/keys/{hash}");
let mut response = surf::get(&url)
.header(AUTHORIZATION, format!("Bearer {api_key}"))
.await?;
if response.status().is_success() {
let api_response: ApiResponse<_> = response.body_json().await?;
Ok(api_response.data)
} else {
handle_error(response).await?;
unreachable!()
}
}
pub async fn delete_api_key(
base_url: &str,
api_key: &str,
hash: &str,
) -> Result<bool, OpenRouterError> {
let url = format!("{base_url}/api/v1/keys/{hash}");
let response = surf::delete(&url)
.header(AUTHORIZATION, format!("Bearer {api_key}"))
.await?;
if response.status().is_success() {
Ok(true)
} else {
handle_error(response).await?;
unreachable!()
}
}
pub async fn update_api_key(
base_url: &str,
api_key: &str,
hash: &str,
name: Option<String>,
disabled: Option<bool>,
limit: Option<f64>,
) -> Result<ApiKey, OpenRouterError> {
let url = format!("{base_url}/keys/{hash}");
let request = UpdateApiKeyRequest {
name,
disabled,
limit,
};
let mut response = surf::patch(&url)
.header(AUTHORIZATION, format!("Bearer {api_key}"))
.body_json(&request)?
.await?;
if response.status().is_success() {
let api_response: ApiResponse<_> = response.body_json().await?;
Ok(api_response.data)
} else {
handle_error(response).await?;
unreachable!()
}
}