Overview

Atrict exposes a JSON API for kids, memories, photos, families, permissions, and invites. Authenticate with an OAuth bearer token issued by the token endpoint, then call the API directly or experiment with it in the in-browser Swagger UI.

Getting credentials

  1. Open Settings → API access.
  2. Click "Create API client", name it, pick scopes, confirm with step-up.
  3. Copy the client ID and client secret once — we don't store the plaintext.

OAuth flow

Atrict supports the client_credentials grant for machine-to-machine access. Exchange your client_id + client_secret at /api/oauth/token to receive a short-lived JWT bearer token (default TTL: 15 minutes). Send the token in the Authorization header on every API request.

1 Your script holds credentials Client ID + secret stored in your environment, never in source control.
2 POST /api/oauth/token grant_type=client_credentials over HTTPS with HTTP Basic auth.
3 Get a Bearer token JWT (HS256), 15-minute TTL. Cache it; don't request a new one per call.
4 Call /api/… Send Authorization: Bearer <token>. Re-exchange credentials when the token expires.

Calling the API

# exchange credentials
curl -s -u "$ATRICT_CLIENT_ID:$ATRICT_CLIENT_SECRET" \
  https://atrict.com/api/oauth/token \
  -d "grant_type=client_credentials" \
  -d "scope=common:read"

# list kids
curl https://atrict.com/api/kids \
  -H "Authorization: Bearer $TOKEN"

Pagination

List endpoints return a PageResult<T> envelope — { items, nextCursor }. To fetch the next page, pass ?cursor=<nextCursor>. When nextCursor is null, you've reached the end. Cursors are opaque base64-encoded values; don't decode or generate them yourself.

Errors

Errors follow RFC 7807 (Problem Details). Common codes:

  • 401 — missing or invalid Bearer token (re-exchange credentials)
  • 403 — token's scopes don't cover the operation
  • 404 — resource doesn't exist or caller has no access (intentionally indistinguishable to avoid leaking existence)
  • 413 — request body too large (photo upload limits)
  • 422 — validation failed; errors object lists per-field messages
  • 429 — rate-limited; back off and retry after the Retry-After header

Rate limits

When a limit is hit the API responds with HTTP 429 Too Many Requests and a Retry-After header (seconds). Recommended client behavior is exponential backoff anchored on that header. Domain-level limits (invites) also surface as inline errors in the HTMX flows.

Scope Limit Window Partition Errors
/api/oauth/token 10 1m client_id (form) → IP 429 Too Many Requests + Retry-After
/api/* (default) 60 1m client_id (claim) → IP 429 Too Many Requests + Retry-After
Invite resend (per invite) 1 5m Invite 429 Too Many Requests + Retry-After (HTMX: inline message)
Invite issuance (per user) 10 24h Issuer user 429 Too Many Requests + Retry-After (HTMX: inline message)

Model reference

Note: The model reference below is generated from the live OpenAPI spec and is in English regardless of your interface language.

ChangeRoleRequest

Request body for changing a permission row's role. Owner cannot be set or changed.
role*
Role

CreateFamilyRequest

Request body for creating a family. Form-encoded for HTMX, JSON for API.
name*
string · 1..100
Display name. Required, trimmed; max 100 chars.

CreateInviteRequest

Request body for creating an invite. Form-encoded for HTMX, JSON for API.
email*
string (email) · 3..254
Recipient email address. Required; normalized (trim + lowercase) by the service.
role
Role

CreateKidRequest

Request body for creating a kid. Form-encoded for HTMX, JSON for API.
name*
string · 1..100
Display name. Required, trimmed; max 100 chars.
birthDate
string (date), nullable
Calendar date of birth (no time component, no timezone). Optional.
gender
Gender
birthHeightCm
number (double), nullable · ≥ 0, ≤ 300
Birth height in centimeters, if known.
birthWeightKg
number (double), nullable · ≥ 0, ≤ 500
Birth weight in kilograms, if known.
familyId
integer (int32), nullable
Family to attach the kid to. Null falls back to user's default family.

CreateMemoryRequest

Request body for creating a memory. Photos are uploaded as multipart and bound separately; this model carries only the structured non-binary fields.
text
string, nullable · 0..5000
Free-form text body. Optional, but the memory must end up with text, a metric, or at least one photo.
occurredOn*
string (date)
Calendar date the memory occurred on. Required.
heightCm
number (double), nullable · ≥ 0, ≤ 300
Recorded height in centimeters at the time of the memory.
weightKg
number (double), nullable · ≥ 0, ≤ 500
Recorded weight in kilograms at the time of the memory.

FamilyModel

Public representation of a family. A family is a grouping of kids that share an owner / creator and that other users can be invited into.
id
integer (int32)
Unique family identifier.
name*
string, nullable
Display name.
createdById
integer (int32)
User id of the creator (also the implicit owner).
createdAt
string (date-time)
Created-at timestamp (UTC).

FamilyModelPageResult

Generic page envelope for cursor-paginated endpoints. `NextCursor` is null when there are no more pages.
items
array, nullable
Items in the current page (may be empty on a final page).
nextCursor
string, nullable
Opaque cursor for the next page; null if no more pages.

Gender

(no properties)

InviteModel

Public representation of an invite. The opaque Atrict.Api.Models.InviteModel.Token is only included for invites the caller is authorized to act on (their own kid's pending invite list); recipient-facing endpoints expose only the metadata.
id
integer (int32)
Unique invite identifier.
token
string (uuid)
Opaque token used in the public landing URL.
kidId
integer (int32)
Kid the invite grants access to.
email*
string, nullable
Recipient email address (lower-cased on create).
role
Role
createdAt
string (date-time)
Created-at timestamp (UTC).
expiresAt
string (date-time)
Expires-at timestamp (UTC). Default TTL is 14 days; resending refreshes it.
createdById
integer (int32)
User id that created the invite (typically the kid's owner).
acceptedAt
string (date-time), nullable
Accepted-at timestamp (UTC); null while pending.
acceptedByUserId
integer (int32), nullable
User id that accepted; null while pending.
revokedAt
string (date-time), nullable
Revoked-at timestamp (UTC); also set when the invite was naturally expired by the sweep job.

InviteModelPageResult

Generic page envelope for cursor-paginated endpoints. `NextCursor` is null when there are no more pages.
items
array, nullable
Items in the current page (may be empty on a final page).
nextCursor
string, nullable
Opaque cursor for the next page; null if no more pages.

KidModel

Public representation of a Kid. Returned from API endpoints; never includes permission bookkeeping or soft-delete state.
id
integer (int32)
Unique kid identifier.
name*
string, nullable
Display name.
birthDate
string (date), nullable
Calendar date of birth (no time component, no timezone). Null if not recorded.
gender
Gender
familyId
integer (int32)
Family the kid belongs to.
ownerId
integer (int32)
Owner of the kid (user id).
birthHeightCm
number (double), nullable
Birth height in centimeters, if recorded.
birthWeightKg
number (double), nullable
Birth weight in kilograms, if recorded.
hasAvatar
boolean
True when an avatar image is uploaded.
createdAt
string (date-time)
Created-at timestamp (UTC).

KidModelPageResult

Generic page envelope for cursor-paginated endpoints. `NextCursor` is null when there are no more pages.
items
array, nullable
Items in the current page (may be empty on a final page).
nextCursor
string, nullable
Opaque cursor for the next page; null if no more pages.

MemoryModel

Public representation of a memory entry on a kid's timeline.
id
integer (int32)
Unique memory identifier.
kidId
integer (int32)
Kid this memory belongs to.
authorId
integer (int32)
Author user id.
text
string, nullable
Free-form text body (may be empty when memory is photo- or metric-only).
occurredOn
string (date)
Calendar date the memory occurred on (no time component, no timezone).
createdAt
string (date-time)
Created-at timestamp (UTC).
editedAt
string (date-time), nullable
Last-edited timestamp (UTC); null if never edited.
heightCm
number (double), nullable
Recorded height in centimeters at the time of the memory.
weightKg
number (double), nullable
Recorded weight in kilograms at the time of the memory.
photos
array, nullable
Photos attached to this memory, ordered by display index.

MemoryModelPageResult

Generic page envelope for cursor-paginated endpoints. `NextCursor` is null when there are no more pages.
items
array, nullable
Items in the current page (may be empty on a final page).
nextCursor
string, nullable
Opaque cursor for the next page; null if no more pages.

MemoryPhotoStatus

(no properties)

PermissionModel

Public representation of a permission row — a single user's role on a single kid.
id
integer (int32)
Unique permission identifier.
kidId
integer (int32)
Kid the permission applies to.
userId
integer (int32)
User the permission was granted to.
role
Role
grantedAt
string (date-time)
Granted-at timestamp (UTC).
grantedById
integer (int32)
User id that granted this permission (typically the kid's owner).
inviteId
integer (int32), nullable
Invite id this permission was granted from, if any.

PermissionModelPageResult

Generic page envelope for cursor-paginated endpoints. `NextCursor` is null when there are no more pages.
items
array, nullable
Items in the current page (may be empty on a final page).
nextCursor
string, nullable
Opaque cursor for the next page; null if no more pages.

PhotoModel

Public representation of a photo attached to a memory.
id
integer (int32)
Unique photo identifier.
memoryId
integer (int32)
Owning memory id.
kidId
integer (int32)
Owning kid id (denormalized for permission checks).
orderIndex
integer (int32)
Display order within the memory (0-based).
originalFilename*
string, nullable
Original filename as uploaded by the client.
width
integer (int32)
Pixel width of the encoded image.
height
integer (int32)
Pixel height of the encoded image.
status
MemoryPhotoStatus
createdAt
string (date-time)
Created-at timestamp (UTC).

ProblemDetails

type
string, nullable
title
string, nullable
status
integer (int32), nullable
detail
string, nullable
instance
string, nullable

RenameFamilyRequest

Request body for renaming a family.
name*
string · 1..100
New display name. Required, trimmed; max 100 chars.

Role

(no properties)

TokenErrorResponse

RFC 6749 §5.2 error response.
error*
string, nullable
RFC 6749 error code: invalid_request, invalid_client, invalid_grant, unauthorized_client, unsupported_grant_type, invalid_scope.
error_description
string, nullable
Optional human-readable description.

TokenResponse

RFC 6749 §5.1 successful token response.
access_token*
string, nullable
Signed JWT access token.
token_type
string, nullable
Always "Bearer".
expires_in*
integer (int32)
Access-token lifetime in seconds.
refresh_token
string, nullable
Refresh-token plaintext. Omitted for grants that don't issue one (client_credentials).
scope*
string, nullable
Granted scopes (space-separated).

UpdateKidRequest

Request body for updating a kid. All fields are full-replace (HTMX edit form posts every field on every save).
name*
string · 1..100
Display name. Required, trimmed; max 100 chars.
birthDate
string (date), nullable
Calendar date of birth (no time component, no timezone). Optional.
gender
Gender
birthHeightCm
number (double), nullable · ≥ 0, ≤ 300
Birth height in centimeters.
birthWeightKg
number (double), nullable · ≥ 0, ≤ 500
Birth weight in kilograms.
familyId
integer (int32), nullable
Family the kid belongs to. Setting a different family moves the kid.

UpdateMemoryRequest

Request body for updating a memory. Photos and removal lists travel as separate multipart parameters in the HTMX flow; the API will model those differently in a later task.
text
string, nullable · 0..5000
Free-form text body. Optional, but the memory must end up with text, a metric, or at least one photo.
occurredOn*
string (date)
Calendar date the memory occurred on. Required.
heightCm
number (double), nullable · ≥ 0, ≤ 300
Recorded height in centimeters at the time of the memory.
weightKg
number (double), nullable · ≥ 0, ≤ 500
Recorded weight in kilograms at the time of the memory.

ValidationProblemDetails

type
string, nullable
title
string, nullable
status
integer (int32), nullable
detail
string, nullable
instance
string, nullable
errors
object, nullable