openapi: 3.1.0 info: title: swsh Public API Documentation version: 0.1.0 description: $ref: "./docs/introduction.md" servers: - url: https://public-api.joinswsh.com description: Production server security: - ApiKeyAuth: [] paths: /ping: get: summary: Ping the server operationId: ping tags: - ping responses: "200": description: Server is alive content: application/json: schema: $ref: "#/components/schemas/ResponsePing" /album/createAlbum: post: summary: Create a new album operationId: createAlbum tags: - album requestBody: required: true content: application/json: schema: type: object required: - name properties: name: $ref: "#/components/schemas/AlbumName" responses: "200": description: Album created successfully content: application/json: schema: $ref: "#/components/schemas/ResponseSingleAlbum" "400": $ref: "#/components/responses/InvalidRequestError" /album/editAlbum: post: summary: Edit an existing album operationId: editAlbum tags: - album requestBody: required: true content: application/json: schema: type: object required: - albumId properties: albumId: type: string description: The ID of the album to edit example: "22222222-2222-2222-2222-222222222222" name: $ref: "#/components/schemas/AlbumName" responses: "200": description: Album edited successfully content: application/json: schema: $ref: "#/components/schemas/ResponseSingleAlbum" "400": $ref: "#/components/responses/InvalidRequestError" "404": description: Album not found /album/deleteAlbum: post: summary: Delete an existing album operationId: deleteAlbum tags: - album requestBody: required: true content: application/json: schema: type: object required: - albumId properties: albumId: type: string description: The ID of the album to delete example: "22222222-2222-2222-2222-222222222222" responses: "200": description: Album deleted successfully content: application/json: schema: $ref: "#/components/schemas/ResponseSuccess" "400": $ref: "#/components/responses/InvalidRequestError" "404": description: Album not found /album/getAlbum: get: summary: Retrieve a specific album operationId: getAlbum tags: - album parameters: - name: albumId in: query description: ID of the album to retrieve required: true schema: type: string example: "22222222-2222-2222-2222-222222222222" responses: "200": description: Album retrieved successfully content: application/json: schema: $ref: "#/components/schemas/ResponseSingleAlbum" "400": $ref: "#/components/responses/InvalidRequestError" "404": description: Album not found /album/getAlbums: get: summary: Retrieve all albums the caller has access to operationId: getAlbums tags: - album parameters: - name: limit in: query description: The maximum number of albums to retrieve required: false schema: type: integer example: 10 minimum: 1 maximum: 64 default: 32 - name: cursor in: query description: A cursor received from a previous request to retrieve the next page of results required: false schema: type: string - name: search in: query description: A search query to filter albums by name (case-insensitive, substring match) required: false schema: type: string example: "vacation" - name: relationship in: query description: Filter albums by relationship to the caller (e.g., "Admin", "Participant") required: false schema: $ref: "#/components/schemas/AlbumRelationship" responses: "200": description: Albums retrieved successfully content: application/json: schema: $ref: "#/components/schemas/ResponseAlbumsCursor" "400": $ref: "#/components/responses/InvalidRequestError" /album/getPreviewPhotos: get: summary: Retrieve preview photos for a specific album description: Preview photos are a subset of the album's photos (max. 32 photos) that anyone can view when the preview feature is ON for that album operationId: getPreviewPhotos tags: - album parameters: - name: albumId in: query description: ID of the album to retrieve preview photos for required: true schema: type: string example: "22222222-2222-2222-2222-222222222222" responses: "200": description: Preview photos retrieved successfully content: application/json: schema: $ref: "#/components/schemas/ResponsePreviewPhotos" "404": description: Album not found /album/getPhotos: get: summary: Retrieve photos for a specific album description: Retrieves the photos in an album. A photo can be an image, live photo, or video. operationId: getPhotos tags: - album parameters: - name: albumId in: query description: ID of the album to retrieve photos for required: true schema: type: string example: "22222222-2222-2222-2222-222222222222" - name: filterLabel in: query description: Filter photos by a specific public label (case-sensitive, exact match) required: false schema: type: string example: "Vacation" minLength: 1 maxLength: 40 - name: filterRestrictedLabel in: query description: Filter photos by a specific restricted label (case-sensitive, exact match). Requires admin access to the album. required: false schema: type: string example: "Family" minLength: 1 maxLength: 40 responses: "200": description: Photos retrieved successfully content: application/json: schema: $ref: "#/components/schemas/ResponsePhotos" "404": description: Album not found /photo/checkPhotoLabel: get: summary: Checks if a photo has a specific label. operationId: checkPhotoLabel tags: - photo parameters: - name: photoId in: query description: The ID of the photo to check required: true schema: type: string example: "44444444-4444-4444-4444-444444444444" - name: label in: query description: The label to check for on the photo (max. 40 characters) required: true schema: type: string example: "Vacation" minLength: 1 maxLength: 40 responses: "200": description: Label check result content: application/json: schema: $ref: "#/components/schemas/ResponseLabelCheckResult" "400": $ref: "#/components/responses/InvalidRequestError" /photo/addPhotoLabel: post: summary: Add a label to a photo. Requires admin access to the album. operationId: addPhotoLabel tags: - photo requestBody: required: true content: application/json: schema: type: object required: - albumId - photoId - label properties: albumId: type: string description: The ID of the album containing the photo example: "22222222-2222-2222-2222-222222222222" photoId: type: string description: The ID of the photo to label example: "44444444-4444-4444-4444-444444444444" label: type: string description: The label to add to the photo (max. 40 characters) example: "Vacation" minLength: 1 maxLength: 40 isHidden: type: boolean description: Whether or not the label is hidden from non-admin users. Defaults to false. default: false responses: "200": description: Label added successfully content: application/json: schema: $ref: "#/components/schemas/ResponseSuccess" "400": $ref: "#/components/responses/InvalidRequestError" "404": description: Album or photo not found /photo/removePhotoLabel: post: summary: Remove a label from a photo. Requires admin access to the album. operationId: removePhotoLabel tags: - photo requestBody: required: true content: application/json: schema: type: object required: - albumId - photoId - label properties: albumId: type: string description: The ID of the album containing the photo example: "22222222-2222-2222-2222-222222222222" photoId: type: string description: The ID of the photo to remove the label from example: "44444444-4444-4444-4444-444444444444" label: type: string description: The label to remove from the photo (max. 40 characters) example: "Vacation" minLength: 1 maxLength: 40 isHidden: type: boolean description: Whether or not the label is hidden from non-admin users. Defaults to false. default: false responses: "200": description: Label removed successfully content: application/json: schema: $ref: "#/components/schemas/ResponseSuccess" "400": $ref: "#/components/responses/InvalidRequestError" "404": description: Album or photo not found /webhook/createSubscription: post: summary: Subscribe to a webhook operationId: createSubscription tags: - webhook requestBody: required: true content: application/json: schema: oneOf: - $ref: "#/components/schemas/WebhookConfigNewPhoto" - $ref: "#/components/schemas/WebhookConfigNewAlbum" - $ref: "#/components/schemas/WebhookConfigPhotoLabelAdded" description: The configuration for the webhook subscription. responses: "200": description: Webhook subscription created successfully content: application/json: schema: $ref: "#/components/schemas/ResponseWebhookConfig" "400": $ref: "#/components/responses/InvalidRequestError" "403": $ref: "#/components/responses/ForbiddenError" /webhook/getSubscriptions: get: summary: Retrieve all webhook subscriptions for the caller operationId: getSubscriptions tags: - webhook parameters: - name: limit in: query description: The maximum number of webhook subscriptions to retrieve required: false schema: type: integer example: 10 minimum: 1 maximum: 64 default: 32 - name: cursor in: query description: A cursor received from a previous request to retrieve the next page of results required: false schema: type: string responses: "200": description: Webhook subscriptions retrieved successfully content: application/json: schema: $ref: "#/components/schemas/ResponseWebhookConfigs" /webhook/deleteSubscription: post: summary: Delete a webhook subscription operationId: deleteSubscription tags: - webhook requestBody: required: true content: application/json: schema: type: object required: - webhookId properties: webhookId: type: string description: The ID of the webhook subscription to delete example: "33333333-3333-3333-3333-333333333333" responses: "200": description: Webhook subscription deleted successfully content: application/json: schema: $ref: "#/components/schemas/ResponseSuccess" "400": $ref: "#/components/responses/InvalidRequestError" webhooks: newPhoto: post: description: A new photo has been added to the album. Includes images, live photos, and videos. Requires admin access to the album. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/WebhookPayloadPhoto" newAlbum: post: description: A new album has been created. Triggers when the user account either creates a new album or is added to an existing album. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/WebhookPayloadAlbum" photoLabelAdded: post: description: A label has been added to an Active photo in an album. Requires admin access to the album. Photo label webhooks are rate-limited per photo per label to reduce the risk for recursive calls. requestBody: required: true content: application/json: schema: $ref: "#/components/schemas/WebhookPayloadPhoto" components: securitySchemes: ApiKeyAuth: type: apiKey in: header name: x-api-key description: An API key generated from the developer dashboard. This should be passed into the `x-api-key` header on every request. schemas: AlbumId: type: string example: "22222222-2222-2222-2222-222222222222" AlbumName: type: string example: "My Album" minLength: 1 maxLength: 40 AlbumRelationship: type: string description: A user's relationship to an album enum: - Admin - Participant Album: type: object required: - albumId properties: albumId: $ref: "#/components/schemas/AlbumId" name: $ref: "#/components/schemas/AlbumName" ownerId: type: string example: "11111111-1111-1111-1111-111111111111" shareUrl: type: string description: A URL that can be shared with others to view the album. This URL is static and will always point to the album. You can safely cache this URL for future use. example: "https://joinswsh.com/album/abcdef" numPhotos: type: integer description: The number of photos in the album example: 5 numParticipants: type: integer description: The number of participants in the album (inclusive of the album owner) example: 2 PreviewPhoto: type: object required: - photoId - originalUrl - stableUrl properties: photoId: type: string width: type: integer height: type: integer originalUrl: type: string description: A signed URL to access the originally uploaded image stableUrl: type: string description: A signed URL to access the stable version of the image (JPEG or WebP, <15 MB) Photo: type: object required: - photoId - originalUrl - stableUrl - downloadUrl properties: photoId: type: string width: type: integer height: type: integer originalUrl: type: string description: A signed URL to access the uploaded image. For videos, this is a thumbnail image. stableUrl: type: string description: A signed URL to access the stable version of the image (JPEG or WebP, <15 MB) or a thumbnail of the video (JPEG or WebP, <15 MB) videoUrl: type: string description: A signed URL to access the originally uploaded video. Only present if the photo is a video or live photo. downloadUrl: type: string description: A signed URL to download the original file (image or video) as it was uploaded. This URL is either the originalUrl or originalVideoUrl, depending on the media type. labels: type: array description: The labels associated with the photo items: type: string restrictedLabels: type: array description: The labels associated with the photo that are hidden from non-admin users items: type: string Warnings: type: array items: type: string example: - "Example warning" Cursor: type: string description: A cursor to be used in subsequent requests to retrieve the next page of results. If this is `{}`, there are no more results to retrieve. ResponseSingleAlbum: type: object required: - data properties: data: $ref: "#/components/schemas/Album" warnings: $ref: "#/components/schemas/Warnings" ResponseAlbumsCursor: type: object required: - data properties: data: type: array items: $ref: "#/components/schemas/Album" cursor: $ref: "#/components/schemas/Cursor" warnings: $ref: "#/components/schemas/Warnings" ResponsePing: type: object required: - data properties: data: type: object required: - message - callerId properties: message: type: string example: "Pong!" callerId: type: string example: "11111111-1111-1111-1111-111111111111" warnings: $ref: "#/components/schemas/Warnings" ResponsePreviewPhotos: type: object required: - data properties: data: type: array items: $ref: "#/components/schemas/PreviewPhoto" warnings: $ref: "#/components/schemas/Warnings" ResponsePhotos: type: object required: - data properties: data: type: array items: $ref: "#/components/schemas/Photo" warnings: $ref: "#/components/schemas/Warnings" ResponseSuccess: type: object required: - data properties: data: type: object required: - message properties: message: type: string example: "Success!" warnings: $ref: "#/components/schemas/Warnings" ResponseLabelCheckResult: type: object required: - data properties: data: type: object required: - hasLabel properties: hasLabel: type: boolean description: Whether or not the photo has the specified label example: true warnings: $ref: "#/components/schemas/Warnings" WebhookConfigNewPhoto: type: object required: - event - targetUrl - albumId properties: event: type: string description: The event subscribed to. enum: - newPhoto targetUrl: type: string description: The URL to send the webhook to. Must be a valid HTTPS URL. example: "https://example.com/webhook" metadata: $ref: "#/components/schemas/WebhookMetadata" albumId: $ref: "#/components/schemas/AlbumId" WebhookConfigNewAlbum: type: object required: - event - targetUrl properties: event: type: string description: The event subscribed to. enum: - newAlbum targetUrl: type: string description: The URL to send the webhook to. Must be a valid HTTPS URL. example: "https://example.com/webhook" metadata: $ref: "#/components/schemas/WebhookMetadata" WebhookConfigPhotoLabelAdded: type: object required: - event - targetUrl - albumId - label properties: event: type: string description: The event subscribed to. enum: - photoLabelAdded targetUrl: type: string description: The URL to send the webhook to. Must be a valid HTTPS URL. example: "https://example.com/webhook" metadata: $ref: "#/components/schemas/WebhookMetadata" albumId: $ref: "#/components/schemas/AlbumId" label: type: string description: The label to filter events by (max. 40 characters) example: "Vacation" minLength: 1 maxLength: 40 WebhookConfig: type: object required: - webhookId - config properties: webhookId: type: string description: The unique identifier for the webhook subscription example: "33333333-3333-3333-3333-333333333333" config: oneOf: - $ref: "#/components/schemas/WebhookConfigNewPhoto" - $ref: "#/components/schemas/WebhookConfigNewAlbum" - $ref: "#/components/schemas/WebhookConfigPhotoLabelAdded" description: The configuration for the webhook subscription, which includes the event type, target URL, and any additional metadata. WebhookMetadata: type: object description: Additional metadata included in the webhook request. This can be used to pass custom data to the webhook handler. Valid value types are string, number, and boolean. additionalProperties: oneOf: - type: string - type: number - type: boolean ResponseWebhookConfig: type: object required: - data properties: data: $ref: "#/components/schemas/WebhookConfig" warnings: $ref: "#/components/schemas/Warnings" ResponseWebhookConfigs: type: object required: - data properties: data: type: array items: $ref: "#/components/schemas/WebhookConfig" cursor: $ref: "#/components/schemas/Cursor" warnings: $ref: "#/components/schemas/Warnings" WebhookPayloadPhoto: type: object required: - data properties: data: $ref: "#/components/schemas/Photo" metadata: $ref: "#/components/schemas/WebhookMetadata" WebhookPayloadAlbum: type: object required: - data properties: data: $ref: "#/components/schemas/Album" metadata: $ref: "#/components/schemas/WebhookMetadata" responses: InvalidRequestError: description: Invalid request. The request was malformed or missing required parameters. content: application/json: schema: type: object properties: message: type: string example: "Invalid request" required: - message ForbiddenError: description: Forbidden. The caller does not have permission to perform this action. content: application/json: schema: type: object properties: message: type: string example: "Forbidden" required: - message