API Reference

Every request (except health checks) requires a Bearer token. All responses are JSON.

Authentication

How to create, use, and manage API tokens.

All API endpoints (except GET /api/v1/health) require a valid Bearer token. Tokens are created through Settings → API Tokens in the web UI.

Creating a token

  1. Navigate to SettingsAPI Tokens in the web UI.
  2. Enter a token name and choose a scope (read or read_write).
  3. Click Create to generate the token.

Token values are shown only once at creation time. Be sure to copy and store them securely.

Token format

Tokens are 128 hex-character strings with a ms_ prefix:

<example>: ms_3c5a7f9b1e4d8c0a6f2e3b9d8c7a6f5e4d3c2b1a09876543210abcdef123456

Token scopes

Scope Description
read Read-only access. Accepts GET endpoints only.
read_write Full access. Accepts all endpoints including POST, PUT, PATCH, and DELETE.

Including the token in requests

Send the token in the Authorization header as a Bearer token:

Authorization: Bearer ms_3c5a7f9b1e4d8c0a6f2e3b9d8c7a6f5e4d3c2b1a09876543210abcdef123456

Memories

Create, read, update, and delete memories in your family.

GET /api/v1/memories read scope

List memories for the authenticated user’s family, with cursor-based pagination.

Parameters

Param Description
cursor Pagination cursor from a previous next_cursor meta value.
per_page Number of results per page (1–100, default 25).
q Full-text search query across memory content.

Response

{
   "data": [
     { "id": "aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaaaa",
       "family_id": "bbbbbbbb-bbbb-4bbb-bbbb-bbbbbbbbbbbb",
       "created_by_user_id": "cccccccc-cccc-4ccc-cccc-cccccccccccc",
       "title": "...", "transcript": "...",
       "notes": "...", "recorded_at": "2025-01-01T00:00:00Z",
       "location_name": "...",
       "tags": [], "visibility": "visible",
       "transcription_status": "completed",
       "transcription_completed_at": "2025-01-01T00:00:00Z",
       "ai_data": null, "ai_extraction_status": null,
       "ai_extraction_completed_at": null,
       "created_at": "2025-01-01T00:00:00Z",
       "updated_at": "2025-01-01T00:00:00Z",
       "first_memory": false }
   ],
   "meta": {
     "next_cursor": "cmVjb3JkZWQtYXQtdXVpZD18MQ==",
     "total_count": 42
   }
}
GET /api/v1/memories/:id read scope

Return a single memory’s details.

Response

{
   "data": {
     "id": "aaaaaaaa-aaaa-4aaa-aaaa-aaaaaaaaaaaa",
     "family_id": "bbbbbbbb-bbbb-4bbb-bbbb-bbbbbbbbbbbb",
     "created_by_user_id": "cccccccc-cccc-4ccc-cccc-cccccccccccc",
     "title": "...",
     "transcript": "...",
     "notes": "...",
     "recorded_at": "2025-01-01T00:00:00Z",
     "location_name": "...",
     "tags": [],
     "visibility": "visible",
     "transcription_status": "completed",
     "transcription_completed_at": "2025-01-01T00:00:00Z",
     "ai_data": null,
     "ai_extraction_status": null,
     "ai_extraction_completed_at": null,
     "created_at": "2025-01-01T00:00:00Z",
     "updated_at": "2025-01-01T00:00:00Z",
     "first_memory": false
   }
}
POST /api/v1/memories write scope

Create a new memory. Returns 201 Created.

Accepted params

Param Description
audioAudio file blob (mutually exclusive with transcript).
recorded_atWhen the memory was recorded.
duration_secondsAudio duration in seconds.
transcript_languageLanguage of the transcript.
transcriptText transcript (mutually exclusive with audio).
titleMemory title.
notesNarrative notes.
location_nameLocation name.
visibilityVisibility state.
pinnedPin the memory.
tags[]Array of tags.

Response (201)

{
   "data": {
     "id": 1,
     "family_id": 1,
     "created_by_user_id": 1,
     ...
   }
}
PUT /api/v1/memories/:id write scope

Update an existing memory. Returns 200 OK.

Accepted params

Param Description
titleMemory title.
notesNarrative notes.
recorded_atWhen the memory was recorded.
visibilityVisibility state.
pinnedPin the memory.
tags[]Array of tags.

Response (200)

{
   "data": {
     "id": 1,
     ...
   }
}
DELETE /api/v1/memories/:id write scope

Delete a memory. Audio attachments are purged.

Response

204 No Content

Tokens

Manage API tokens programmatically.

GET /api/v1/tokens read scope

List active (non-revoked) API tokens for the user's family.

Response

{
    "data": [
      {
        "id": 1,
        "name": "Mobile App",
        "scope": "read_write",
        "family_id": 1,
        "last_used_at": "2025-01-01T00:00:00Z",
        "created_at": "2025-01-01T00:00:00Z"
      }
    ]
}
POST /api/v1/tokens write scope

Create a new API token. Returns 201 with a one-time token field.

Accepted params

Param Description
token[name]Token name (max 100 chars).
token[scope]Scope: read or read_write.

Response (201)

{
    "data": {
      "id": 1,
      "name": "Mobile App",
      "scope": "read_write",
      "family_id": 1,
      "last_used_at": null,
      "created_at": "2025-01-01T00:00:00Z",
      "token": "ms_3c5a7f9b1e4d8c0a6f2e3b9d8c7a6f5e4d3c2b1a09876543210abcdef123456"
    }
}

token is shown only once.

DELETE /api/v1/tokens/:id write scope

Revoke an active API token.

Response

204 No Content
POST /api/v1/tokens/:id/rotate write scope

Rotate a token. Returns the new raw token once.

Response

{
    "data": {
      "id": 1,
      "name": "Mobile App",
      "scope": "read_write",
      "family_id": 1,
      "last_used_at": null,
      "created_at": "2025-01-01T00:00:00Z",
      "token": "ms_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2"
    }
}

Family

Manage family members and send invitations.

Family Summary

GET /api/v1/family read scope

Returns summary information for the authenticated user's family.

Response

{
  "data": {
    "id": "ffffffff-ffff-4fff-ffff-ffffffffffff",
    "name": "The Smiths",
    "plan_code": "premium",
    "member_count": 4
  }
}

Disposition of Fields

Authenticated API account-management fields—such as family_id, created_by_user_id, membership and user IDs, member email, plan and member counts, and processing state—support family management and integration within the authenticated account. These fields are intentionally not portable export fields.

Portable exports independently use family_name, minimal member name/role/joined_at, and archival memory and media fields. They retain memory and media object IDs where needed to cross-reference archived metadata and files, while omitting account-management IDs, email addresses, and processing state.

GET /api/v1/family/members read scope

List all members of the authenticated user's family.

Response

{
     "data": [
       {
         "id": "dddddddd-dddd-4ddd-dddd-dddddddddddd",
         "user_id": "eeeeeeee-eeee-4eee-eeee-eeeeeeeeeeee",
         "name": "Jane Doe",
         "email": "jane@example.com",
         "role": "owner",
         "joined_at": "2025-01-01T00:00:00Z"
       }
     ]
}
PATCH /api/v1/family/members/:id write scope + admin/owner

Update a family member's role. Requires admin or owner role.

Accepted params

Param Description
roleNew role: owner, admin, member, or viewer.

Response (200)

{
     "data": {
       "id": "dddddddd-dddd-4ddd-dddd-dddddddddddd",
       "user_id": "eeeeeeee-eeee-4eee-eeee-eeeeeeeeeeee",
       "name": "Jane Doe",
       "email": "jane@example.com",
       "role": "admin",
       "joined_at": "2025-01-01T00:00:00Z"
     }
}
DELETE /api/v1/family/members/:id write scope + admin/owner

Remove a family member. Cannot remove yourself.

Response

204 No Content
POST /api/v1/family/invitations write scope

Send an invitation to join the family. An email is sent to the invitation address.

Accepted params

Param Description
invitation[email]Email address of the person to invite.
invitation[role]Role to assign: owner, admin, or member.

Response (201)

{
     "data": {
       "id": 1,
       "email": "invitee@example.com",
       "role": "member",
       "status": "pending"
     }
}

Health

Check API availability without authentication.

Health

GET /api/v1/health

No authentication required. Returns a JSON body confirming the API is operational.

Response

{
  "status": "ok"
}

Error Responses

Standard error formats returned by all endpoints.

Error Responses

All API errors follow a consistent JSON structure with an error or errors object.

Single errors

Returned for authentication failures, forbidden access, and general errors.

{
  "error": {
    "code": "...",
    "message": "..."
  }
}

Validation errors

Returned when request body parameter validation fails. Fields are keyed by attribute.

{
  "errors": {
    "field": ["message"]
  }
}