Shared Integration Rules
Authentication and Token Model
Access token
The API returns an access JWT after register, login, and refresh. Send it on
protected routes as Authorization: Bearer <access_token>.
The default lifetime is 15 minutes.
Refresh token
Refresh tokens last 30 days and rotate on every successful refresh. A reused,
revoked, or expired refresh token is rejected.
Same-site browser
Use token_transport=cookie when you want the refresh token stored in
an HttpOnly, Secure cookie for frontends running on
.auctionsguru.com.
Cross-site browser / Vercel
Use token_transport=json so the refresh token is returned in JSON and
can be stored explicitly by frontends hosted on unrelated domains.
Mobile / native apps
Use token_transport=json so the refresh token is returned in JSON and
can be stored in secure OS storage.
Why refresh rotates
A successful refresh revokes the old refresh token and creates a new one, which
blocks replay of older tokens.
Password changes force re-login
Password change and password reset revoke all refresh tokens and invalidate older
access tokens across devices.
Protected route access
Only active users with the customer role can use protected public API
routes.
Base URL
https://api.auctionsguru.com
Standard Headers
| Header |
When to send it |
Accept: application/json |
Send on every request. |
Content-Type: application/json |
Send on JSON endpoints. |
Authorization: Bearer <access_token> |
Required on protected routes. |
X-Device-Name: <label> |
Optional fallback if you do not send device_name in JSON. |
Multipart Rule
Avatar upload is not JSON
POST /api/v1/me/avatar must use
multipart/form-data. In browser code, let the browser set the
multipart boundary automatically.
Current Rate Limit Defaults
| Endpoint group |
Default limit |
| Register | 5 requests / minute |
| Login | 10 requests / minute |
| Refresh | 30 requests / minute |
| Forgot password | 5 requests / minute |
| Reset password | 5 requests / minute |
These values come from the current application defaults and can change per
environment.
Response Shapes
Success Response
{
"message": "Profile retrieved successfully.",
"data": {
"user": {
"name": "Alice Customer",
"email": "alice@example.com",
"avatar_url": null,
"email_verified_at": null
}
}
}
Auth Token Response
{
"message": "Login successful.",
"data": {
"user": {
"name": "Alice Customer",
"email": "alice@example.com",
"avatar_url": null,
"email_verified_at": null
},
"access_token": "<jwt-access-token>",
"token_type": "Bearer",
"expires_in": 900,
"refresh_token": "<refresh-token-or-null>",
"refresh_token_expires_at": "2026-05-04T12:00:00Z",
"refresh_token_transport": "json"
}
}
422 Validation Error Shape
Laravel validation errors follow the standard JSON error structure below. The top-level
message can vary depending on the failing fields.
{
"message": "<validation summary>",
"errors": {
"email": [
"The email field is required."
],
"password": [
"The password field confirmation does not match."
]
}
}
Client Flows
Same-site Browser / Next.js
For browser-based frontends running on .auctionsguru.com, the best default
is cookie refresh transport: keep the access token in memory, let the browser store the
refresh token as an HttpOnly cookie, and call refresh with
credentials: 'include'.
Important browser rule
The API now accepts cross-origin requests from any origin, but cookie-based refresh still
depends on the refresh cookie domain and SameSite policy. Frontends on unrelated
domains should use JSON refresh transport instead of relying on the cookie flow.
Login with cookie refresh transport
const response = await fetch('https://api.auctionsguru.com/api/v1/auth/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify({
email: 'alice@example.com',
password: 'Password@123',
token_transport: 'cookie',
device_name: 'Next.js Web App'
})
});
const result = await response.json();
const accessToken = result.data.access_token;
Refresh using the HttpOnly cookie
const response = await fetch('https://api.auctionsguru.com/api/v1/auth/refresh', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify({
token_transport: 'cookie'
})
});
const result = await response.json();
const newAccessToken = result.data.access_token;
Authenticated profile request
const response = await fetch('https://api.auctionsguru.com/api/v1/me', {
method: 'GET',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`
}
});
const profile = await response.json();
Logout with cookie refresh transport
await fetch('https://api.auctionsguru.com/api/v1/auth/logout', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
credentials: 'include'
});
Avatar upload from the browser
const formData = new FormData();
formData.append('avatar', fileInput.files[0]);
const response = await fetch('https://api.auctionsguru.com/api/v1/me/avatar', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: formData
});
Cross-site Browser / Vercel
For frontends hosted on unrelated domains such as
https://auctions-guru.vercel.app, use token_transport=json
on register, login, and refresh. Do not rely on the refresh cookie in that setup.
Register with JSON refresh transport
const registerResponse = await fetch('https://api.auctionsguru.com/api/v1/auth/register', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'Alice Customer',
email: 'alice@example.com',
password: 'Password@123',
password_confirmation: 'Password@123',
device_name: 'Vercel Web App',
token_transport: 'json'
})
});
const registerResult = await registerResponse.json();
const accessToken = registerResult.data.access_token;
const refreshToken = registerResult.data.refresh_token;
Refresh with JSON transport
const refreshResponse = await fetch('https://api.auctionsguru.com/api/v1/auth/refresh', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
refresh_token: refreshToken,
token_transport: 'json'
})
});
const refreshResult = await refreshResponse.json();
const newAccessToken = refreshResult.data.access_token;
const newRefreshToken = refreshResult.data.refresh_token;
Logout with JSON refresh transport
await fetch('https://api.auctionsguru.com/api/v1/auth/logout', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': `Bearer ${newAccessToken}`
},
body: JSON.stringify({
refresh_token: newRefreshToken
})
});
Mobile / Native Apps
For mobile apps, use token_transport=json. That returns the refresh token
in the response body so it can be stored in secure OS storage and sent explicitly during
refresh.
Store access token
Keep it in memory and attach it as a bearer token on protected API requests.
Store refresh token
Use secure OS storage such as Keychain or Keystore. Do not keep it in plain storage.
Refresh strategy
When the access token expires or is close to expiring, call
/api/v1/auth/refresh and replace both stored tokens with the new values.
Mobile login example
curl -X POST "https://api.auctionsguru.com/api/v1/auth/login" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"password": "Password@123",
"token_transport": "json",
"device_name": "iPhone 16"
}'
Mobile refresh example
curl -X POST "https://api.auctionsguru.com/api/v1/auth/refresh" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "<refresh-token>",
"token_transport": "json"
}'
Implemented Category
User Management
User Management
Everything currently exposed by the public API belongs to this category. It covers
account access, token/session lifecycle, password recovery, profile maintenance, and
avatar updates for customer users.
StatusImplemented
Base Paths/api/v1/auth, /api/v1/me
Endpoints10 total
Protected AccessActive users with the customer role
Auth and Session
Register, login, refresh, and logout. This group manages customer access and token
lifecycle.
Password Recovery
Forgot password and reset password. This group restores access without login.
Profile and Account
Current profile, profile update, password change, and avatar upload.
Auth and Session
These endpoints create sessions, rotate tokens, and end authenticated sessions for
customer users.
| Method |
Path |
Auth |
Purpose |
View |
| POST | /api/v1/auth/register | Public | Create a new customer account and issue tokens. | View |
| POST | /api/v1/auth/login | Public | Authenticate an existing customer account. | View |
| POST | /api/v1/auth/refresh | Public with refresh token | Rotate the refresh token and issue a new access token. | View |
| POST | /api/v1/auth/logout | Bearer + refresh token | Revoke the current session and clear the refresh token. | View |
POST
/api/v1/auth/register
Why this call: Create a new public customer account and start an authenticated session immediately.
AuthPublic
HeadersAccept, Content-Type
Body typeJSON
Next stepStore the access token and continue as an authenticated user.
Request Fields
| Field | Required | Notes |
name | Yes | String, max 255. |
email | Yes | Must be a valid email. Duplicate active emails return 422. |
password | Yes | Must satisfy the backend password rules. |
password_confirmation | Yes | Must match password. |
device_name | No | Optional device label for the refresh token record. |
token_transport | No | cookie or json. Default is cookie. |
cURL Example
curl -X POST "https://api.auctionsguru.com/api/v1/auth/register" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"name": "Alice Customer",
"email": "alice@example.com",
"password": "Password@123",
"password_confirmation": "Password@123",
"device_name": "Next.js Web App",
"token_transport": "cookie"
}'
Success Response
{
"message": "Registration successful.",
"data": {
"user": {
"name": "Alice Customer",
"email": "alice@example.com",
"avatar_url": null,
"email_verified_at": null
},
"access_token": "<jwt-access-token>",
"token_type": "Bearer",
"expires_in": 900,
"refresh_token": null,
"refresh_token_expires_at": "2026-05-04T12:00:00Z",
"refresh_token_transport": "cookie"
}
}
Common Failures
| Status | Case |
| 422 | Invalid email, weak password, or duplicate active email. |
| 403 | An existing matching account is inactive. |
| 500 | The customer role is missing from the backend configuration. |
Cookie transport stores the refresh token as a secure cookie. JSON transport returns it in data.refresh_token. Cross-site browser apps such as Vercel should use json.
Why this call: Authenticate an existing customer account and receive fresh access and refresh tokens.
AuthPublic
HeadersAccept, Content-Type
Body typeJSON
Next stepUse the access token on protected routes.
Request Fields
| Field | Required | Notes |
email | Yes | Valid email. |
password | Yes | Plain-text password. |
device_name | No | Optional refresh token device label. |
token_transport | No | cookie or json. Default is cookie. |
cURL Example
curl -X POST "https://api.auctionsguru.com/api/v1/auth/login" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"password": "Password@123",
"token_transport": "json",
"device_name": "Android App"
}'
Same-site Next.js Fetch Example
const response = await fetch('https://api.auctionsguru.com/api/v1/auth/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify({
email: 'alice@example.com',
password: 'Password@123',
token_transport: 'cookie'
})
});
Cross-site Browser Fetch Example
const response = await fetch('https://api.auctionsguru.com/api/v1/auth/login', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
email: 'alice@example.com',
password: 'Password@123',
token_transport: 'json',
device_name: 'Vercel Web App'
})
});
Success Response
{
"message": "Login successful.",
"data": {
"user": {
"name": "Alice Customer",
"email": "alice@example.com",
"avatar_url": null,
"email_verified_at": null
},
"access_token": "<jwt-access-token>",
"token_type": "Bearer",
"expires_in": 900,
"refresh_token": "<refresh-token>",
"refresh_token_expires_at": "2026-05-04T12:00:00Z",
"refresh_token_transport": "json"
}
}
Common Failures
| Status | Case |
| 401 | Email or password is incorrect. |
| 403 | User is inactive. |
| 403 | User exists but is not a customer. |
A successful login updates the user's last_login_at timestamp.
POST
/api/v1/auth/refresh
Why this call: Rotate the refresh token and get a new access token without asking the user to log in again.
AuthPublic with valid refresh token
HeadersAccept, usually Content-Type
Body typeJSON
Next stepReplace any stored refresh token with the newly returned one.
Request Fields
| Field | Required | Notes |
refresh_token | Cookie flow: No. JSON flow: Yes. | When using token_transport=json, pass the refresh token in the body. With cookie flow, the cookie is enough. |
token_transport | No | cookie or json. Default is cookie. |
device_name | No | Accepted by validation, but refresh keeps the existing stored device label. |
cURL Example for JSON Transport
curl -X POST "https://api.auctionsguru.com/api/v1/auth/refresh" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "<refresh-token>",
"token_transport": "json"
}'
Same-site Next.js Fetch Example for Cookie Transport
const response = await fetch('https://api.auctionsguru.com/api/v1/auth/refresh', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
credentials: 'include',
body: JSON.stringify({
token_transport: 'cookie'
})
});
Cross-site Browser Fetch Example for JSON Transport
const response = await fetch('https://api.auctionsguru.com/api/v1/auth/refresh', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
refresh_token: refreshToken,
token_transport: 'json'
})
});
Success Response
{
"message": "Token refreshed successfully.",
"data": {
"user": {
"name": "Alice Customer",
"email": "alice@example.com",
"avatar_url": null,
"email_verified_at": null
},
"access_token": "<new-jwt-access-token>",
"token_type": "Bearer",
"expires_in": 900,
"refresh_token": "<new-refresh-token>",
"refresh_token_expires_at": "2026-05-04T12:20:00Z",
"refresh_token_transport": "json"
}
}
Common Failures
| Status | Case |
| 401 | Refresh token is invalid, expired, or revoked. |
| 403 | User is inactive or is not a customer. |
| 422 | No refresh token was supplied in the cookie flow or request body. |
If refresh succeeds, discard the old refresh token immediately. Reusing it later will fail.
Why this call: End the current authenticated session by revoking the current refresh token and blacklisting the current access token.
AuthBearer token required
HeadersAccept, Authorization
Body typeJSON or cookie-backed empty body
Next stepDelete stored access token client-side.
Request Fields
| Field | Required | Notes |
refresh_token | Cookie flow: No. JSON flow: Yes. | The endpoint needs the current refresh token from either the cookie or the body. |
cURL Example for JSON Transport
curl -X POST "https://api.auctionsguru.com/api/v1/auth/logout" \
-H "Accept: application/json" \
-H "Authorization: Bearer <jwt-access-token>" \
-H "Content-Type: application/json" \
-d '{
"refresh_token": "<refresh-token>"
}'
Next.js Fetch Example for Cookie Transport
await fetch('https://api.auctionsguru.com/api/v1/auth/logout', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
credentials: 'include'
});
Success Response
{
"message": "Logged out successfully."
}
Common Failures
| Status | Case |
| 401 | Missing or invalid bearer token. |
| 401 | The refresh token is invalid or does not belong to the authenticated user. |
| 422 | No refresh token was supplied in the cookie flow or request body. |
Password Recovery
These endpoints recover account access without an active session. They are public, but
they still follow normal validation and rate limiting rules.
| Method |
Path |
Auth |
Purpose |
View |
| POST | /api/v1/auth/forgot-password | Public | Send the password reset email flow. | View |
| POST | /api/v1/auth/reset-password | Public | Reset the password using the email token. | View |
POST
/api/v1/auth/forgot-password
Why this call: Start the password reset email flow without revealing whether the email exists.
AuthPublic
HeadersAccept, Content-Type
Body typeJSON
Next stepUser checks the reset email and follows the reset link.
Request Fields
| Field | Required | Notes |
email | Yes | Valid email address. |
cURL Example
curl -X POST "https://api.auctionsguru.com/api/v1/auth/forgot-password" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com"
}'
Success Response
{
"message": "If your email address exists in our system, you will receive a password reset link shortly."
}
Common Failures
| Status | Case |
| 422 | Email is missing or not a valid email address. |
The same message is returned for known and unknown emails, which helps prevent account enumeration.
POST
/api/v1/auth/reset-password
Why this call: Complete the password reset after the user receives the reset token from the email link.
AuthPublic
HeadersAccept, Content-Type
Body typeJSON
Next stepUser must log in again after the password has been reset.
Request Fields
| Field | Required | Notes |
email | Yes | Email that received the reset link. |
token | Yes | Password reset token from the email link. |
password | Yes | New password that meets the password rules. |
password_confirmation | Yes | Must match password. |
cURL Example
curl -X POST "https://api.auctionsguru.com/api/v1/auth/reset-password" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"email": "alice@example.com",
"token": "<reset-token-from-email>",
"password": "NewPassword@123",
"password_confirmation": "NewPassword@123"
}'
Success Response
{
"message": "Password has been reset successfully."
}
Common Failures
| Status | Case |
| 422 | The reset token is invalid or has expired. |
| 422 | Password does not satisfy validation rules. |
A successful reset revokes all refresh tokens and invalidates older access tokens, so every device must log in again.
Profile and Account
These endpoints operate on the authenticated customer profile after login. Every call
in this group requires a bearer access token.
| Method |
Path |
Auth |
Purpose |
View |
| GET | /api/v1/me | Bearer | Fetch the current customer profile. | View |
| PATCH | /api/v1/me | Bearer | Update profile fields. | View |
| PUT | /api/v1/me/password | Bearer | Change the password and revoke all active sessions. | View |
| POST | /api/v1/me/avatar | Bearer | Upload or replace the profile avatar. | View |
Why this call: Retrieve the current authenticated customer's profile details.
AuthBearer token required
HeadersAccept, Authorization
Body typeNone
Next stepUse the returned data to hydrate account UI.
cURL Example
curl -X GET "https://api.auctionsguru.com/api/v1/me" \
-H "Accept: application/json" \
-H "Authorization: Bearer <jwt-access-token>"
Next.js Fetch Example
const response = await fetch('https://api.auctionsguru.com/api/v1/me', {
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`
}
});
Success Response
{
"message": "Profile retrieved successfully.",
"data": {
"user": {
"name": "Alice Customer",
"email": "alice@example.com",
"avatar_url": "https://api.auctionsguru.com/storage/avatars/alice.jpg",
"email_verified_at": null
}
}
}
Common Failures
| Status | Case |
| 401 | Missing, invalid, expired, revoked, or outdated access token. |
| 403 | User is inactive or not a customer. |
Why this call: Update the current user's profile fields without changing the password.
AuthBearer token required
HeadersAccept, Authorization, Content-Type
Body typeJSON
Next stepReplace local profile state with the returned user object.
Request Fields
| Field | Required | Notes |
name | No | Optional, but at least one of name or email must be sent. |
email | No | Optional. Must be unique across users. |
cURL Example
curl -X PATCH "https://api.auctionsguru.com/api/v1/me" \
-H "Accept: application/json" \
-H "Authorization: Bearer <jwt-access-token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Alice Updated",
"email": "alice.updated@example.com"
}'
Success Response
{
"message": "Profile updated successfully.",
"data": {
"user": {
"name": "Alice Updated",
"email": "alice.updated@example.com",
"avatar_url": null,
"email_verified_at": null
}
}
}
Common Failures
| Status | Case |
| 401 | Bearer token missing or invalid. |
| 422 | At least one profile field must be provided. |
| 422 | Email is already used by another user. |
If the email value changes, the backend lowercases it and clears email_verified_at.
Why this call: Change the current user's password while authenticated.
AuthBearer token required
HeadersAccept, Authorization, Content-Type
Body typeJSON
Next stepForce the user through a new login flow.
Request Fields
| Field | Required | Notes |
current_password | Yes | Must match the current password. |
password | Yes | New password. Must differ from current_password. |
password_confirmation | Yes | Needed for the confirmation rule. |
cURL Example
curl -X PUT "https://api.auctionsguru.com/api/v1/me/password" \
-H "Accept: application/json" \
-H "Authorization: Bearer <jwt-access-token>" \
-H "Content-Type: application/json" \
-d '{
"current_password": "Password@123",
"password": "NewPassword@123",
"password_confirmation": "NewPassword@123"
}'
Success Response
{
"message": "Password changed successfully. Please log in again on all devices."
}
Common Failures
| Status | Case |
| 401 | Bearer token missing or invalid. |
| 422 | current_password is wrong. |
| 422 | New password fails validation, confirmation, or difference rules. |
This endpoint revokes all refresh tokens and invalidates existing access tokens across devices.
Why this call: Upload or replace the current user's avatar and receive the public avatar URL.
AuthBearer token required
HeadersAccept, Authorization
Body typemultipart/form-data
Next stepUpdate profile UI with the returned avatar_url.
Request Fields
| Field | Required | Notes |
avatar | Yes | Image file only. Allowed types: jpg, jpeg, png, webp. Maximum size: 5120 KB. |
cURL Example
curl -X POST "https://api.auctionsguru.com/api/v1/me/avatar" \
-H "Accept: application/json" \
-H "Authorization: Bearer <jwt-access-token>" \
-F "avatar=@/absolute/path/to/avatar.jpg"
Next.js Fetch Example
const formData = new FormData();
formData.append('avatar', file);
const response = await fetch('https://api.auctionsguru.com/api/v1/me/avatar', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': `Bearer ${accessToken}`
},
body: formData
});
Success Response
{
"message": "Avatar uploaded successfully.",
"data": {
"user": {
"name": "Alice Customer",
"email": "alice@example.com",
"avatar_url": "https://api.auctionsguru.com/storage/avatars/abc123.jpg",
"email_verified_at": null
}
}
}
Common Failures
| Status | Case |
| 401 | Bearer token missing or invalid. |
| 422 | File is missing, too large, or not an allowed image type. |
Uploading a new avatar replaces the old stored avatar file when one already exists.