Prerequisites
- A Swift 5.9+ project with
ipapi-swiftadded - A free ip-api.io API key
Switch over the IpApiError enum
Each API-status case carries the relevant details. Switch over the specific case you care about.
do {
let info = try await client.lookup(ip: "8.8.8.8")
print(info.ip)
} catch let error as IpApiError {
switch error {
case .rateLimit(_, _, let reset):
print("quota hit — resets at \(reset)")
case .authentication:
print("check your API key")
case .invalidRequest(let message):
print("bad request: \(message)")
case .server(let status):
print("ip-api.io is having trouble (status \(status)), try later")
case .transport(let underlying):
print("transport / decode error: \(underlying)")
}
} .transport, which wraps the underlying URLSession /
DecodingError — they are not an API status error.
Handle rate limits with the .rateLimit case
On HTTP 429 you get .rateLimit, carrying the x-ratelimit-* header values (-1 when a header is absent). Because the client never retries, reset tells you when to.
case .rateLimit(let limit, let remaining, let reset):
print(limit) // your quota for the window
print(remaining) // requests left (0 here)
print(reset) // Unix timestamp when quota renews
// schedule a retry at `reset` instead of hammering the API Check quota proactively with rateLimit
Read your current limits without triggering a 429, so you can throttle in advance.
let rl = try await client.rateLimit()
print(rl.planName ?? "")
print("\(rl.ipApi.remaining) / \(rl.ipApi.limit)")
print(String(format: "%.1f%% used", rl.emailApi.usagePercent)) Account usage with usageSummary
Aggregate usage for the current period — handy for dashboards and internal alerts.
let usage = try await client.usageSummary()
print(usage.totalRequests, usage.successfulRequests)
print(usage.rateLimitedRequests, usage.quotaConsumed)
print(usage.periodStart, usage.periodEnd)