// EZConfig - Community-maintained API rate limits and concurrency settings // // Usage: // import ezconfig // // case ezconfig.get_config("api.openai.com") { // Some(config) -> { // // Use config.rps and config.max_concurrent // } // None -> { // // Use default values // } // } import gleam/dict.{type Dict} import gleam/option.{type Option} /// API rate limit configuration pub type ApiConfig { ApiConfig( rps: Int, // Requests per second max_concurrent: Int, // Maximum concurrent requests notes: String, ) } /// Community-maintained API configurations /// Update this dict and publish a new version to add/modify APIs fn api_configs() -> Dict(String, ApiConfig) { dict.from_list([ #( "api.openai.com", ApiConfig(60, 10, "Tier 1: 60 req/min = 1 req/sec, but bursts allowed"), ), #( "api.anthropic.com", ApiConfig(50, 5, "Claude API rate limits"), ), #( "api.stripe.com", ApiConfig( 100, 20, "Stripe has high rate limits, can handle concurrent requests well", ), ), #( "api.github.com", ApiConfig( 10, 3, "GitHub API: 5000 req/hour = ~1.4 req/sec, be conservative", ), ), #( "api.twitter.com", ApiConfig(15, 5, "Twitter API v2 rate limits vary by endpoint"), ), #( "graph.facebook.com", ApiConfig(200, 10, "Facebook Graph API has high limits"), ), #( "www.googleapis.com", ApiConfig(10, 5, "Google APIs vary widely, this is conservative default"), ), #( "slack.com", ApiConfig(1, 1, "Slack webhooks: 1 req/sec tier limit"), ), #( "discord.com", ApiConfig(50, 10, "Discord API has generous rate limits"), ), #( "api.sendgrid.com", ApiConfig(10, 5, "SendGrid email API"), ), #( "api.twilio.com", ApiConfig(20, 5, "Twilio messaging API"), ), #( "api.hubspot.com", ApiConfig(10, 3, "HubSpot CRM API: 100 req/10sec = 10 req/sec"), ), #( "api.notion.com", ApiConfig(3, 2, "Notion API: 3 req/sec rate limit"), ), #( "api.airtable.com", ApiConfig(5, 2, "Airtable API: 5 req/sec rate limit"), ), #( "shopify.com", ApiConfig(2, 2, "Shopify REST API: 2 req/sec (burst 40)"), ), ]) } /// Get configuration for a specific API domain pub fn get_config(domain: String) -> Option(ApiConfig) { dict.get(api_configs(), domain) |> option.from_result } /// Get RPS for a domain, or None if not configured pub fn get_rps(domain: String) -> Option(Int) { case get_config(domain) { option.Some(config) -> option.Some(config.rps) option.None -> option.None } } /// Get max_concurrent for a domain, or None if not configured pub fn get_max_concurrent(domain: String) -> Option(Int) { case get_config(domain) { option.Some(config) -> option.Some(config.max_concurrent) option.None -> option.None } } /// Get all configured domains pub fn list_domains() -> List(String) { dict.keys(api_configs()) } /// Check if a domain has a configuration pub fn has_config(domain: String) -> Bool { case get_config(domain) { option.Some(_) -> True option.None -> False } }