PhotoFlow Documentation Help

API Documentation

Overview

PhotoFlow exposes RESTful APIs through the AppGateway for frontend applications and external integrations.

Base URLs

Environment

URL

Development

https://dev.api.photoflow.vn

UAT

https://uat.api.photoflow.vn

Production

https://api.photoflow.vn

Authentication

All authenticated endpoints require a JWT Bearer token:

Authorization: Bearer <access_token>

Token Acquisition

Tokens are obtained through the OAuth2 flow with Google:

POST /api/v1/auth/login Content-Type: application/json { "provider": "Google", "code": "<oauth_authorization_code>", "redirectUri": "https://app.photoflow.vn/callback" }

Response:

{ "accessToken": "eyJhbGciOiJIUzI1NiIs...", "refreshToken": "eyJhbGciOiJIUzI1NiIs...", "expiresIn": 3600 }

Token Refresh

POST /api/v1/auth/refresh Content-Type: application/json { "refreshToken": "<refresh_token>" }

API Categories

Album APIs

Endpoint

Method

Auth

Description

/api/v1/albums

GET

Photographer

List albums

/api/v1/albums

POST

Photographer

Create album

/api/v1/albums/{id}

GET

Photographer

Get album detail

/api/v1/albums/{id}

PUT

Photographer

Update album

/api/v1/albums/{id}

DELETE

Photographer

Delete album

/api/v1/albums/{id}/transitions

GET

PhotographerOrAnonymous

Get available transitions

/api/v1/albums/{id}/state

PUT

PhotographerOrAnonymous

Trigger state change

Album Tag APIs

Endpoint

Method

Auth

Description

/api/v1/albums/{albumId}/tags

GET

Photographer

List album tags

/api/v1/albums/{albumId}/tags/{tagId}

GET

Photographer

Get tag detail

/api/v1/albums/{albumId}/tags/{tagId}/url

PUT

Photographer

Update tag URL

Photo APIs

Endpoint

Method

Auth

Description

/api/v1/albums/{albumId}/tags/{tagId}/photos

GET

PhotographerOrAnonymous

List photos

/api/v1/albums/{albumId}/photos/{photoId}

GET

PhotographerOrAnonymous

Get photo detail

/api/v1/albums/{albumId}/photos/{photoId}/vote

POST

PhotographerOrAnonymous

Vote photo

/api/v1/albums/{albumId}/photos/{photoId}/comments

GET

PhotographerOrAnonymous

Get comments

/api/v1/albums/{albumId}/photos/{photoId}/comments

POST

PhotographerOrAnonymous

Add comment

Public APIs (Anonymous)

Endpoint

Method

Auth

Description

/api/v1/public/albums/{publicUrl}

GET

Anonymous

Get album by public URL

/api/v1/public/albums/{publicUrl}/photos

GET

Anonymous

Get photos

/api/v1/public/albums/{publicUrl}/feedback

POST

Anonymous

Submit feedback

Storage APIs

Endpoint

Method

Auth

Description

/api/v1/storage/folders

GET

Photographer

List folders

/api/v1/storage/folders/{id}

GET

Photographer

Get folder detail

/api/v1/storage/folders/{id}/sync

POST

Photographer

Sync folder

/api/v1/storage/folders/{id}/photos

GET

Photographer

Get photos in folder

Request/Response Formats

List Albums Request

GET /api/v1/albums?searchTerm=wedding&states=Raw,Stock&page=1&pageSize=20 Authorization: Bearer <token>

List Albums Response

{ "data": [ { "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "name": "Wedding Album 2024", "assignee": "John Doe", "assigneeId": "user-123", "albumState": "Stock", "albumStateDisplay": "Ready for Rating", "createdAt": 1703001600000, "currentStateEnteredAt": 1703088000000, "lastUpdatedByUserName": "admin" } ], "pagination": { "page": 1, "pageSize": 20, "totalCount": 45, "totalPages": 3 } }

Get Transitions Response

{ "transitions": [ { "event": "Rate", "fromState": "Stock", "toState": "Rate", "isRetry": false, "retryReason": null, "disable": false, "disableReason": null }, { "event": "Close", "fromState": "Stock", "toState": "Closed", "isRetry": false, "retryReason": null, "disable": false, "disableReason": null } ] }

Trigger State Change Request

PUT /api/v1/albums/{id}/state Authorization: Bearer <token> Content-Type: application/json { "trigger": "Rate", "url": "https://drive.google.com/drive/folders/abc123" }

Vote Photo Request

POST /api/v1/albums/{albumId}/photos/{photoId}/vote Authorization: Bearer <token> Content-Type: application/json { "voted": true }

Error Responses

Standard Error Format

{ "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1", "title": "Bad Request", "status": 400, "detail": "Invalid album state transition", "instance": "/api/v1/albums/123/state", "errors": { "trigger": ["Cannot transition from 'Init' to 'Stock' directly"] } }

Common Error Codes

Status

Description

400

Bad Request - Invalid input data

401

Unauthorized - Missing or invalid token

403

Forbidden - Insufficient permissions

404

Not Found - Resource doesn't exist

409

Conflict - State transition not allowed

500

Internal Server Error

Rate Limiting

API requests are rate-limited per user:

Tier

Requests/min

Burst

Standard

100

200

Premium

500

1000

Rate limit headers:

X-RateLimit-Limit: 100 X-RateLimit-Remaining: 95 X-RateLimit-Reset: 1703001660

Pagination

List endpoints support pagination:

Parameter

Type

Default

Description

page

int

1

Page number

pageSize

int

20

Items per page (max: 100)

Filtering & Sorting

Filter Parameters

GET /api/v1/albums?states=Raw,Stock&createdFrom=2024-01-01&createdTo=2024-12-31

Sort Parameters

GET /api/v1/albums?sortBy=createdAt&sortOrder=desc

Swagger/OpenAPI

Interactive API documentation is available at:

  • Development: https://dev.api.photoflow.vn/swagger/index.html

  • UAT: https://uat.api.photoflow.vn/swagger/index.html

Last modified: 25 February 2026