GET
/oauth/authorizeHiển thị trang consent để người dùng cấp quyền cho ứng dụng.
Query Parameters
client_id*Client ID của ứng dụngredirect_uri*URL callback đã đăng kýscope*Quyền truy cập (cách nhau bởi space)stateString ngẫu nhiên để bảo mậtResponse
Redirect về redirect_uri với parameters:
?code=AUTH_CODE&state=YOUR_STATE
POST
/api/oauth/tokenĐổi authorization code lấy access token.
Request Body (JSON)
{
"grant_type": "authorization_code",
"code": "AUTH_CODE",
"client_id": "YOUR_CLIENT_ID",
"client_secret": "YOUR_CLIENT_SECRET",
"redirect_uri": "YOUR_CALLBACK_URL"
}Response (200 OK)
{
"access_token": "...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "profile email"
}Errors
400 - Invalid or expired code401 - Invalid client credentialsGET
/api/oauth/userinfoLấy thông tin user với access token.
Headers
Authorization: Bearer YOUR_ACCESS_TOKEN
Response (200 OK)
{
"id": "user-uuid",
"email": "user@example.com", // nếu có scope 'email'
"full_name": "John Doe", // nếu có scope 'profile'
"avatar_url": "https://..." // nếu có scope 'profile'
}Errors
401 - Invalid or expired tokenGET
/api/settings Lấy danh sách settings của user. Yêu cầu scope settings:read.
Headers
Authorization: Bearer YOUR_ACCESS_TOKEN
Query Parameters
client_idLọc theo app (optional)Response (200 OK)
{
"settings": [
{
"key": "theme",
"value": "dark",
"client_id": "app_xxx",
"updated_at": "2025-12-29T10:00:00Z"
}
]
}POST
/api/settings Lưu setting cho user. Yêu cầu scope settings:write.
Headers
Authorization: Bearer YOUR_ACCESS_TOKEN Content-Type: application/json
Request Body
{
"client_id": "YOUR_CLIENT_ID",
"key": "preferences",
"value": {
"theme": "dark",
"language": "vi"
}
}value có thể là string, number, boolean, array, hoặc object
Response (200 OK)
{
"success": true,
"setting": {
"key": "preferences",
"value": {...},
"client_id": "app_xxx",
"updated_at": "2025-12-29T10:00:00Z"
}
}DELETE
/api/settings/:key Xóa setting. Yêu cầu scope settings:write.
Headers
Authorization: Bearer YOUR_ACCESS_TOKEN
Query Parameters
client_id*Client IDResponse (200 OK)
{
"success": true
}