Integrations API

Server-to-server endpoints for driving your aelor.gallery studio from your own site — for example, an embedded client area on your marketing site. Authenticate with an integration API key created under Dashboard → Settings → Integration API keys.

Keys are fvk_…, shown once at creation. Use them only from your server — never ship a key in browser code. Send it as Authorization: Bearer fvk_….

Scopes: galleries:read, galleries:write, grants:manage.

Endpoints

GET /api/integrations/galleries?status=

List galleries (metadata only — never codes). Scope: galleries:read.

GET /api/integrations/galleries/{slug}

Full metadata + presentation. Scope: galleries:read.

{
  "slug": "marie-david-2026", "title": "Marie & David", "coupleNames": "Marie & David",
  "eventDate": "2026-08-15", "status": "delivered", "isPublished": true,
  "photoCount": 240,
  "cover": { "url": "https://…signed…", "focalX": 50, "focalY": 50 },
  "grants": [{ "level": "client", "requireEventDate": true, "expiresAt": null }]
}

Access codes are never returned — only their existence and metadata. To give a couple a code, rotate one (below); the plaintext is returned that one time.

PATCH /api/integrations/galleries/{slug}

Update title, coupleNames, status, isPublished. Scope: galleries:write.

PUT /api/integrations/galleries/{slug}/cover

{ "photoId": "…"|null, "focalX": 0-100, "focalY": 0-100 }. Scope: galleries:write.

POST /api/integrations/galleries/{slug}/grants/{level}/rotate

level = client | guest. Scope: grants:manage. Body (all optional): { "requireEventDate": bool, "expiresAt": iso|null, "code": "explicit" }. Returns the plaintext code once:

{ "level": "client", "code": "K7QW-9MTS" }

Errors

Every error is JSON with error (what went wrong), fix (what to do), and docs (this page). Authentication failures distinguish a missing key, a malformed Authorization header, an unrecognized key format, and a revoked key.

Questions? hello@aelor.gallery