Immiche - Immich API Client Library#
A clean Eio-based OCaml library for interacting with Immich instances, focusing on people and face recognition data.
Overview#
Immiche provides a straightforward API for interacting with Immich's people management endpoints. It uses the Requests library for HTTP operations and follows Eio patterns for concurrency and resource management.
Features#
- Fetch all people from an Immich instance
- Search for people by name
- Fetch individual person details
- Download person thumbnails
- Full Eio integration (no Lwt dependency)
- Type-safe API with result types for error handling
API#
Types#
(* Client type - encapsulates session with connection pooling *)
type ('clock, 'net) t
type person = {
id: string;
name: string;
birth_date: string option;
thumbnail_path: string;
is_hidden: bool;
}
type people_response = {
total: int;
visible: int;
people: person list;
}
Client Creation#
create#
Create an Immich client with connection pooling.
val create :
sw:Eio.Switch.t ->
env:< clock: _ ; net: _ ; fs: _ ; .. > ->
?requests_session:('clock, 'net) Requests.t ->
base_url:string ->
api_key:string ->
unit -> ('clock, 'net) t
Parameters:
sw- Eio switch for resource managementenv- Eio environment (provides clock, net, fs)requests_session- Optional Requests session for connection pooling. If not provided, a new session is created.base_url- Base URL of the Immich instance (e.g., "https://photos.example.com")api_key- API key for authentication
Returns: An Immich client configured for the specified instance
API Functions#
All API functions take a client as their first parameter. The client automatically handles:
- Connection pooling (reuses TCP connections)
- Authentication (API key set as default header)
- Base URL configuration
fetch_people#
Fetch all people from an Immich instance.
val fetch_people : ('clock, 'net) t -> people_response
search_person#
Search for people by name.
val search_person : ('clock, 'net) t -> name:string -> person list
fetch_person#
Fetch details for a specific person.
val fetch_person : ('clock, 'net) t -> person_id:string -> person
download_thumbnail#
Download a person's thumbnail image.
val download_thumbnail :
('clock, 'net) t ->
fs:_ Eio.Path.t ->
person_id:string ->
output_path:string ->
(unit, [> `Msg of string]) result
Example Usage#
Basic Usage#
open Eio.Std
let () =
Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
(* Create client once with connection pooling *)
let client = Immiche.create ~sw ~env
~base_url:"https://photos.example.com"
~api_key:"your-api-key" () in
(* Fetch all people - connection pooling automatic *)
let response = Immiche.fetch_people client in
Printf.printf "Total people: %d\n" response.total;
(* Search for a person - reuses connections *)
let results = Immiche.search_person client ~name:"John" in
(* Download first result's thumbnail *)
match results with
| person :: _ ->
let result = Immiche.download_thumbnail client
~fs:(Eio.Stdenv.fs env)
~person_id:person.id
~output_path:"thumbnail.jpg" in
begin match result with
| Ok () -> print_endline "Thumbnail downloaded!"
| Error (`Msg err) -> Printf.eprintf "Error: %s\n" err
end
| [] -> print_endline "No results found"
Sharing Connection Pools#
You can share a Requests.t session across multiple API clients for maximum connection reuse:
Eio_main.run @@ fun env ->
Switch.run @@ fun sw ->
(* Create shared Requests session *)
let shared_session = Requests.create ~sw env in
(* Create multiple clients sharing the same connection pools *)
let immich1 = Immiche.create ~sw ~env ~requests_session:shared_session
~base_url:"https://photos1.example.com"
~api_key:"key1" () in
let immich2 = Immiche.create ~sw ~env ~requests_session:shared_session
~base_url:"https://photos2.example.com"
~api_key:"key2" () in
(* Both clients share the same connection pools! *)
let people1 = Immiche.fetch_people immich1 in
let people2 = Immiche.fetch_people immich2 in
()
Dependencies#
eio- Concurrent I/O libraryrequests- HTTP client libraryezjsonm- JSON parsinguri- URI encodingfmt- Formattingptime- Time handling
Implementation Notes#
- Uses
Requests.tfor session-based HTTP requests with connection pooling - Authentication via
x-api-keyheader (set as default on session creation) - Direct Eio style - no Lwt dependencies
- Connection pools shared across derived sessions
- Extracted and adapted from
bushel/bin/bushel_faces.ml
Benefits#
✅ Connection Pooling - Automatic TCP connection reuse across requests
✅ Clean API - Session-level configuration passed once, not per-request
✅ Injectable Sessions - Can share Requests.t across multiple libraries
✅ Type Safety - Client parameterized by clock/net types
✅ Immutable Configuration - Derived sessions don't affect original
License#
ISC