On this page

Photo albums of a community. Every route sits behind the router-level feature gate requireFeature(albums): a plan without it gets 403 FEATURE_NOT_AVAILABLE, reads included. Tenant context comes from ?communityId= (or X-Tenant-Id / the custom domain).

Reads are optionalAuth and follow the community's read scope:

  • An APPROVED member reads every album. Hidden albums are for albums:manage and albums:moderate only.
  • A guest, or a signed-in non-member, reads only albums opted into guest preview, in a PUBLIC community whose plan includes albums.
  • Anyone else gets 404.

Writes need an APPROVED member who isn't suspended or blocked from media. Editing ANY album needs albums:manage or albums:moderate. Anyone may edit their OWN album. albums:create lets you create and edit your own, never anyone else's.

14 endpoints.

MethodPathSummary
GET/api/albumsList albums
POST/api/albumsCreate an album (optionally with photos)
DELETE/api/albums/{albumId}Delete an album (owner, or albums:manage | albums:moderate)
GET/api/albums/{albumId}One album
PUT/api/albums/{albumId}Edit an album's details (owner, or albums:manage | albums:moderate)
POST/api/albums/{albumId}/hideHide an album (albums:manage | albums:moderate)
DELETE/api/albums/{albumId}/imagesRemove one photo (owner, or albums:manage | albums:moderate)
POST/api/albums/{albumId}/imagesAdd photos (owner, or albums:manage | albums:moderate)
DELETE/api/albums/{albumId}/images/allRemove every photo (owner, or albums:manage | albums:moderate)
PUT/api/albums/{albumId}/images/reorderReorder photos (owner, or albums:manage | albums:moderate)
POST/api/albums/{albumId}/likeToggle your like
GET/api/albums/{albumId}/likesWho liked an album
POST/api/albums/{albumId}/unhideUnhide an album (albums:manage | albums:moderate)
GET/api/albums/preview/{slug}/{albumId}Link-preview data for an album (no auth)

Auth: optional — a token changes what you can see (see "Who may read what").

Parameters

NameInRequiredTypeDescription
communityIdquerynostring (uuid)—
qquerynostringSearch in title and description
pagequerynointeger—
limitquerynointeger—

Responses

StatusDescriptionBody
200success, albums: [Album], pagination—
404The caller may not read this community's albums—

Needs albums:manage or albums:create. The community is the one the guards checked. A body communityId that disagrees is refused with 400 COMMUNITY_MISMATCH. Photos count against the plan's storage and are refused over the cap. Up to 50 photos, 25 MB each. Only PUBLIC communities that opted albums into guest preview accept isGuestVisible=true.

Auth: Bearer JWT required.

Request body (required) — application/json

Type: CreateAlbumRequest

Responses

StatusDescriptionBody
201success, data: Album—
400title missing, COMMUNITY_MISMATCH, ALBUM_IMAGE_LIMIT, or guest preview not allowed—
403Not a member, missing permission, RESTRICTION_BLOCKED, FEATURE_NOT_AVAILABLE, or storage cap reached—

Gives the photos' storage back and removes the album from the home feed. Auth: Bearer JWT required.

Responses

StatusDescriptionBody
200success, message—

A hidden album, or one a guest may not preview, answers 404 exactly as a missing id does. Auth: optional — a token changes what you can see (see "Who may read what").

Responses

StatusDescriptionBody
200success, data: Album—
404Not found or not visible to this caller—

Auth: Bearer JWT required.

Request body — application/json

FieldTypeRequiredDescription
titlestringno—
descriptionstringno—
isGuestVisiblebooleanno—

Responses

StatusDescriptionBody
200success, data: Album—
400NO_FIELDS_TO_UPDATE—
404ALBUM_NOT_FOUND—

A hidden album leaves every listing. It, its likes and its comment thread answer 404 to everyone but moderators. Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
albumIdpathyesstring (uuid)—

Responses

StatusDescriptionBody
200success, data: Album—
404ALBUM_NOT_FOUND—

Auth: Bearer JWT required.

Request body (required) — application/json

FieldTypeRequiredDescription
imageUrlstringyesThe photo's url as stored

Responses

StatusDescriptionBody
200success, data: Album — the cover becomes the first remaining photo—
404ALBUM_NOT_FOUND—

Appended atomically, so concurrent uploads never lose photos. At most 50 per album. Counts against storage. Auth: Bearer JWT required.

Request body (required) — multipart/form-data

FieldTypeRequiredDescription
albumImagesstring (binary)[]no—

Responses

StatusDescriptionBody
200success, data: Album—
400No images—
404ALBUM_NOT_FOUND—

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
albumIdpathyesstring (uuid)—

Responses

StatusDescriptionBody
200success, data: Album—
404ALBUM_NOT_FOUND—

images must be an exact reordering of the album's current photos, matched by filename (url for old photos). The server stores its own copy of each photo, never the client's. The first photo becomes the cover.

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
albumIdpathyesstring (uuid)—

Request body (required) — application/json

FieldTypeRequiredDescription
imagesobject[]yes—

Responses

StatusDescriptionBody
200success, data: Album—
400INVALID_IMAGE_ORDER—
404ALBUM_NOT_FOUND—

Any APPROVED member not blocked from liking, on an album they may open (a hidden one answers 404). The album's creator is notified while still a member. Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
albumIdpathyesstring (uuid)—

Responses

StatusDescriptionBody
200success, data: { liked, likeCount }—
404Not found or hidden—

Readable exactly when the album is (same rule as GET /api/albums/albumId). Auth: optional — a token changes what you can see (see "Who may read what").

Parameters

NameInRequiredTypeDescription
albumIdpathyesstring (uuid)—
pagequerynointeger—
limitquerynointeger—

Responses

StatusDescriptionBody
200success, data: { likes: [{ userId, userName, userAvatar, likedAt }], … } — the community names—
404Not found or not visible to this caller—

Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
albumIdpathyesstring (uuid)—

Responses

StatusDescriptionBody
200success, data: Album—
404ALBUM_NOT_FOUND—

Answers only for an album a guest may see (public community, albums in guest preview, album opted in). Everything else is 404. Auth: Bearer JWT required.

Parameters

NameInRequiredTypeDescription
slugpathyesstring—
albumIdpathyesstring (uuid)—

Responses

StatusDescriptionBody
200success, data: { id, title, description, coverImage, imageCount, community… }—
404Not found or not public—