Nikhil Sachdeva Photography
All documentation

Engineering

API Reference

Status: Living document · Owner: Engineering · Last reviewed: 2026-07-07

All endpoints are Next.js Route Handlers under /api. Unless noted as public, every route runs the shared guard: session check → per-IP rate limit → Zod validation → timeout/retry → leak-proof error envelope.

Auth legend: 🔒 requires a valid Studio session · 🌐 public/edge · 🤖 machine (webhook/cron with a shared secret).


Identity

GET /api/studio/ms/login 🌐

Starts the Microsoft Entra ID OAuth 2.0 authorization-code flow. Sets a signed CSRF state nonce and redirects to Entra ID (where MFA is enforced).

GET /api/studio/ms/callback 🌐

OAuth redirect target. Validates state, exchanges the code, checks the returned email against the allowlist, encrypts and stores the refresh token, and mints the Studio session cookie.

POST /api/studio/login 🌐

Password sign-in. On success, issues the HMAC session cookie (12h, HTTP-only).

POST /api/studio/logout 🔒

Clears the Studio session.


Studio state

GET /api/studio/state 🔒

Returns the current snapshot and its version.

POST /api/studio/state 🔒

Writes a new snapshot. Uses optimistic concurrency (send the version you based your edit on) under a Postgres advisory lock. A version mismatch returns a conflict for the client to reconcile.

GET /api/studio/monitor 🔒

Operational status for the console (health, recent activity).

GET /api/studio/search 🔒

Search across the photo library.

POST /api/studio/notify 🔒

Internal notification hook for the console.


Cloud ingestion (OneDrive & Google Drive)

Both providers share one import model: download bytes once → derive private renditions → run AI → delete the staged original. The full-res original is never permanently stored on our side (see ADR-009).

GET /api/studio/drive 🔒

Lists images in a watched folder / returns the delta for a provider (?provider=microsoft|google).

POST /api/studio/drive/materialize 🔒

Takes raw cloud files (vendor URLs) and returns durable /api/media rendition paths, downloading + transcoding + deleting the staged original server-side. Used by the interactive picker and the client-side watched-folder poll so they match the headless pipeline.

POST /api/studio/onedrive 🔒

Triggers an on-demand OneDrive delta sync.

POST /api/studio/onedrive/subscription 🔒

Creates or renews the Graph change-notification subscription.

POST /api/studio/onedrive/webhook 🤖

Graph change-notification receiver. Answers the validation handshake, verifies clientState, then pulls the delta. Writes are concurrency-safe.


AI agents

Each agent accepts photo/post context and returns a structured result. Results are cached by a hash of (agent + prompt + input) and fall back to a deterministic mock if the model is unavailable.

EndpointAuthPurpose
POST /api/agents/curator🔒Score and select the strongest frames
POST /api/agents/editor🔒Editing / crop / treatment guidance
POST /api/agents/copywriter🔒Captions and long-form copy
POST /api/agents/hashtags🔒Tag sets per post
POST /api/agents/scheduler🔒Proposed posting cadence

Publishing

POST /api/publish/instagram 🔒

Creates an Instagram media container and publishes it. Runs a tighter rate limit; the publish call is non-idempotent and never retried. Stores the returned permalink on success.

GET /api/ig-image/[id] 🌐

Serves an image rendition for Instagram publishing.


Platform utilities

POST /api/revalidate 🤖

Revalidates public gallery/collection routes after a publish or ingest.

GET /api/cron/maintenance 🤖

Scheduled job (requires CRON_SECRET). Renews Microsoft tokens and the OneDrive subscription so ingestion keeps working with no browser open.


Error envelope

Failures return a consistent, non-leaking JSON shape:

{ "error": { "code": "string", "message": "human-readable, safe to display" } }

Internal details (stack traces, upstream payloads) are never returned to clients.