qiyangdev/openlibrarykit
`OpenLibraryKit` is a Swift 6 package for the [Open Library APIs](https://openlibrary.org/developers/api).
Features
- Swift 6 native API built on
async/await - Typed models for common Open Library responses
- Coverage for search, works, editions, authors, subjects, lists, reading logs, recent changes, covers, legacy read lookups, and generic JSON resources
- Local rate limiting based on Open Library's current documentation
- Automatic
User-Agentinjection for identified requests - Mock-friendly
URLSession-based implementation
Requirements
- Swift 6.1+
- macOS 12+, iOS 15+, tvOS 15+, watchOS 8+
Installation
Add OpenLibraryKit to your Package.swift:
dependencies: [
.package(url: "https://github.com/wangqiyangX/OpenLibraryKit.git", branch: "main")
]Then add the product to your target:
.target(
name: "YourApp",
dependencies: [
.product(name: "OpenLibraryKit", package: "OpenLibraryKit")
]
)Quick Start
Open Library asks clients to identify themselves and recommends these request limits:
- Anonymous requests:
1 request/second - Identified requests with
User-Agentand contact information:3 requests/second
OpenLibraryKit adapts to that automatically.
import OpenLibraryKit
let client = OpenLibraryClient(
identity: OpenLibraryIdentity(
applicationName: "MyLibraryApp",
contact: "contact@example.com"
)
)With an identity configured:
User-Agentis automatically set toMyLibraryApp (contact@example.com)- the local rate limiter automatically uses
3 req/s
Without an identity, the client defaults to 1 req/s.
Rate Limiting
You can customize rate limiting when needed:
let client = OpenLibraryClient(
identity: OpenLibraryIdentity(
applicationName: "MyLibraryApp",
contact: "contact@example.com"
),
rateLimitPolicy: .requestsPerSecond(2)
)Available policies:
.automatic.disabled.requestsPerSecond(Double)
Covered APIs
The package currently covers these Open Library API areas:
- Book Search API
- Work & Edition APIs
- Authors API
- Subjects API
- Covers API
- Lists API, read-only operations
- Your Books API, public reading log access
- Recent Changes API
- Legacy Read API /
api/books - Generic
.jsonresource loading for arbitrary Open Library paths - Search Inside API support for compatible JSON or JSONP responses
Examples
Search for books
let results = try await client.search(
query: "The Hobbit",
page: 1,
limit: 10,
fields: ["key", "title", "author_name", "cover_i"]
)
for doc in results.docs {
print(doc.title ?? "Unknown title")
}Load a work, edition, or author
let work = try await client.work("OL27448W")
let edition = try await client.edition("OL7353617M")
let author = try await client.author("OL26320A")Fetch books by subject
let subject = try await client.subject(
"science_fiction",
details: true,
ebooksOnly: false,
limit: 20
)
print(subject.works.map(\.title))Read public user lists
let lists = try await client.lists(forUser: "mekBot", limit: 10)
let detail = try await client.list(forUser: "mekBot", id: "OL1L")
let subjects = try await client.listSubjects(forUser: "mekBot", id: "OL1L", limit: 20)Read a public reading log
let readingLog = try await client.readingLog(
forUser: "mekBot",
shelf: .wantToRead,
page: 1,
limit: 20
)Access recent changes
let changes = try await client.recentChanges(.day(year: 2026, month: 3, day: 20), limit: 20)Build cover URLs
let coverURL = try client.covers.url(
for: .isbn("9780140328721"),
size: .large
)Use the legacy api/books endpoint
let books = try await client.books(
[.isbn("9780140328721"), .olid("OL7353617M")],
command: .data
)Load any Open Library JSON resource
let work: WorkDetail = try await client.resource(at: "/works/OL27448W")Error Handling
The client throws OpenLibraryError:
.invalidURLComponents.invalidRequest(underlying:).transport(_).invalidResponse.httpStatus(code:body:).decoding(_)
Example:
do {
let work = try await client.work("OL27448W")
print(work.title)
} catch let OpenLibraryError.httpStatus(code, body) {
print("HTTP error:", code, String(decoding: body, as: UTF8.self))
} catch {
print("Unexpected error:", error)
}Notes
- Lists write operations are not implemented yet.
- Search Inside support depends on a compatible Archive.org host and is intentionally lightweight.
- The package is designed for real-time, low-volume API access, not bulk harvesting.
Testing
Run the test suite with:
swift testLicense
OpenLibraryKit is released under the MIT License. See LICENSE.
Package Metadata
Repository: qiyangdev/openlibrarykit
Default branch: main
README: README.md