memsearchmanual
MEMSEARCH / MANUAL

Local API

Use the current FastAPI endpoints on 127.0.0.1:7242, with request, response, and error examples.

The backend exposes JSON over HTTP. The default base URL is:

http://127.0.0.1:7242

Start it with the desktop app or from backend:

uv run memsearch serve

Network safety

Unauthenticated API with broad CORS

The API has no authentication or authorization. Its CORS middleware allows every origin, method, and header. The default 127.0.0.1 bind limits listening to the local Mac; changing MEMSEARCH_HOST to 0.0.0.0 or a network interface can expose search metadata, thumbnails, configuration changes, indexing controls, and destructive index clearing to other clients that can reach the port.

Keep the loopback default. If remote access is required, put authentication and network controls in front of the service; the current app does not provide them.

Endpoint map

MethodPathPurpose
POST/searchEmbed a query and search the local index
GET/statusReturn index statistics and live progress
POST/index/startStart folder indexing
POST/index/photosStart Photos indexing
POST/index/stopRequest cancellation
GET/peopleList named people for autocomplete
POST/people/refreshReload people data and backfill indexed photos
GET/configReturn public runtime configuration
PUT/configUpdate persistent UI-managed settings
DELETE/indexClear all embeddings and thumbnails
GET/thumbnails/{filename}Return one cached JPEG thumbnail

POST /search

{
  "query": "@Mira beach sunset",
  "n_results": 10,
  "modality": "image"
}
FieldTypeDefaultNotes
querystringrequiredSupports @name and @"Full Name" mentions
n_resultsinteger20Maximum results returned
modalitystring or nullnullCurrent values used by clients: image, pdf, text
curl -X POST http://127.0.0.1:7242/search \
  -H 'Content-Type: application/json' \
  -d '{"query":"roadmap about embeddings","n_results":5,"modality":"pdf"}'

Example response:

{
  "results": [
    {
      "file_path": "/Users/me/Documents/Q3-roadmap.pdf",
      "score": 0.8734,
      "modality": "pdf",
      "filename": "Q3-roadmap.pdf",
      "thumbnail_filename": "4602f7....jpg",
      "text_summary": "Q3 roadmap and release priorities...",
      "file_size": 483221,
      "indexed_at": 1778528124.14,
      "person_names": ""
    }
  ],
  "query_time_ms": 42.1,
  "total_indexed": 1387
}

score is cosine similarity (1 - distance). Search returns 503 when Gemini cannot create the query embedding.

Status

GET /status

curl http://127.0.0.1:7242/status

Example while indexing files:

{
  "total": 1387,
  "modalities": { "image": 800, "pdf": 87, "text": 500 },
  "last_indexed_at": 1778528124.14,
  "is_indexing": true,
  "indexed_count": 42,
  "error_count": 1,
  "current_file": "/Users/me/Documents/notes.md",
  "total_files_found": 240,
  "errors": [
    { "file_path": "/Users/me/Documents/broken.pdf", "error": "..." }
  ],
  "folder_progress": {
    "/Users/me/Documents": { "total": 240, "indexed": 42, "errors": 1 }
  },
  "start_time": 1778528000.0,
  "source": "files",
  "phase": null,
  "last_error": null,
  "last_result": null
}

When Photos is active, the backend maps Photos counts and current asset into the common pipeline fields, sets source to photos, and adds a Photos phase. A recent Photos result/error remains visible for roughly 60 seconds.

Folder indexing

POST /index/start

The body is optional. Missing or empty folders use the configured watched folders.

{
  "folders": ["/Users/me/Documents", "/Users/me/Projects"],
  "limit": 250
}
curl -X POST http://127.0.0.1:7242/index/start \
  -H 'Content-Type: application/json' \
  -d '{"folders":["/Users/me/Documents"],"limit":250}'
{
  "status": "started",
  "folders": ["/Users/me/Documents"]
}

The response is immediate; poll /status. Paths that are not directories are silently removed from the resolved run. A request made while either pipeline is active returns 400.

Photos indexing

POST /index/photos

The body is optional.

{
  "limit": 100,
  "favorites_only": true
}
{
  "status": "started",
  "source": "icloud_photos"
}

The endpoint checks Photos permission before starting. It returns 400 if another job is active and 403 if Photos access is not authorized.

Stop indexing

POST /index/stop

curl -X POST http://127.0.0.1:7242/index/stop
{ "status": "cancelling" }

Cancellation is cooperative. A PhotoKit download or in-flight Gemini call may finish before the worker observes the flag.

People

GET /people

{
  "people": [
    { "name": "Mira", "face_count": 214 },
    { "name": "Jordan", "face_count": 87 }
  ]
}

The list is sorted by Photos face count descending. If the Photos database is unavailable, the endpoint returns an empty list rather than an error.

POST /people/refresh

{
  "status": "refreshed",
  "people_count": 28,
  "photos_updated": 742
}

Returns 400 when the people database object is unavailable and 500 when Photos.sqlite cannot be read after refresh.

Configuration

GET /config

{
  "watched_folders": ["/Users/me/Documents"],
  "max_file_size_mb": 50,
  "auto_index_enabled": false,
  "index_photos_enabled": false,
  "embedding_model": "gemini-embedding-2-preview",
  "embedding_dimensions": 768,
  "port": 7242
}

The Gemini key and storage paths are not returned.

PUT /config

All fields are optional:

{
  "watched_folders": ["/Users/me/Documents"],
  "max_file_size_mb": 25,
  "auto_index_enabled": true,
  "index_photos_enabled": false
}
{ "status": "updated" }

The backend saves these fields to MacMemorySearch/config.json and starts, stops, or updates the file watcher as necessary.

Clear the index

DELETE /index

curl -X DELETE http://127.0.0.1:7242/index
{
  "cleared_embeddings": 1387,
  "cleared_thumbnails": 802
}

No confirmation at the API layer

This endpoint immediately deletes the collection and cached thumbnails. It does not delete source files or saved configuration.

Thumbnails

GET /thumbnails/{filename}

Use the thumbnail_filename returned by search:

curl http://127.0.0.1:7242/thumbnails/4602f7....jpg --output preview.jpg

The response is image/jpeg. A filename containing /, \, or .. returns 400; a missing file returns 404.

Error reference

FastAPI errors use a JSON detail field.

StatusCurrent cases
400 Bad RequestIndexing already active; people database unavailable; invalid thumbnail filename
403 ForbiddenPhotos indexing requested without authorized Photos access
404 Not FoundThumbnail missing or route not found
422 Unprocessable EntityRequest body fails FastAPI/Pydantic validation
500 Internal Server ErrorPeople refresh cannot read Photos.sqlite
503 Service UnavailableGemini key/access denied, model missing/renamed, rate limited, or another embedding API error during search

An upstream Gemini 403, 404, or 429 is deliberately translated into a local /search response with status 503 and a more specific detail message.

On this page