JWT Authentication
How to log in, use, refresh, inspect, and log out of Valora's JWT-based API for routes protected by the auth:api_jwt guard.
Overview
JWTs are short-lived access tokens with a default TTL of 30 minutes. When a token expires you must either refresh it (before or shortly after expiry) or log in again to get a new one.
Unlike the long-lived API token, a JWT is not stored on the server — it is self-contained. Refreshing it issues a new token and blacklists the old one immediately.
Use JWTs for routes that require auth:api_jwt. Do not send JWTs to auth:api routes, and do not send long-lived API tokens to auth:api_jwt routes.
API hosts: Production
https://valora.spotahome.com/(sandbox compatible); Staging / testinghttps://valora-testing.laravel.cloud/(sandbox compatible). JWT routes live under/api/auth/jwt/...on either host.
HTTP rate limiting
All routes in routes/api.php sit behind Laravel's api middleware group, which applies throttle:api. POST https://valora.spotahome.com/api/auth/jwt/login (no bearer token yet) counts as a guest request (60 requests per minute per IP by default; API_RATE_LIMIT_GUEST_PER_MINUTE). Authenticated auth:api_jwt requests use the per-user limits for customers (120/min default) or employees (5000/min default); see config/valora.php and AppServiceProvider::configureRateLimiting.
Log in
Exchange your credentials for a JWT.
| Method | URL | Auth required |
|---|---|---|
POST |
https://valora.spotahome.com/api/auth/jwt/login |
No |
Request
POST https://valora.spotahome.com/api/auth/jwt/login
Accept: application/json
Content-Type: application/json
{
"email": "you@example.com",
"password": "your-password"
}
Request body
| Field | Type | Required | Description |
|---|---|---|---|
email |
string | Yes | Your account email address. |
password |
string | Yes | Your account password. |
Success response — 200 OK
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczovL2FwaS52YWxvcmEuY29tIiwiaWF0IjoxNzA5MDAwMDAwLCJleHAiOjE3MDkwMDE4MDAsIm5iZiI6MTcwOTAwMDAwMCwianRpIjoiQWJDZEVmR2hJaksiLCJzdWIiOiI0MiIsInBydiI6IjIzYmQ1Yzg5NDlmNjAwYWRiMzllNzAxYzQwMDg3MmRiN2E1OTc2ZjcifQ.SIGNATURE",
"token_type": "bearer",
"expires_in_minutes": 30
}
| Field | Type | Description |
|---|---|---|
access_token |
string | The JWT to use in all subsequent requests. |
token_type |
string | Always "bearer". |
expires_in_minutes |
integer | How many minutes until the token expires (default: 30). |
Use your token
Pass the JWT in the Authorization header on every request to a auth:api_jwt protected route:
GET https://valora.spotahome.com/api/auth/jwt/me
Authorization: Bearer eyJ0eXAiOiJKV1Qi...
Accept: application/json
Get your user info
Confirm your identity and retrieve basic profile data for the token's owner.
| Method | URL | Auth required |
|---|---|---|
GET |
https://valora.spotahome.com/api/auth/jwt/me |
Yes (auth:api_jwt) |
Request
GET https://valora.spotahome.com/api/auth/jwt/me
Authorization: Bearer eyJ0eXAiOiJKV1Qi...
Accept: application/json
Success response — 200 OK
{
"email": "you@example.com",
"name": "Jane",
"family_name": "Doe",
"role": "finance_member
}
| Field | Type | Description |
|---|---|---|
email |
string | Your email address. |
name |
string | Your first name. |
family_name |
string | Your last name. |
role |
string | Your role. |
Refresh your token
Issue a new token before (or just after) the current one expires. The old token is immediately blacklisted — replace it on your end after calling this endpoint.
| Method | URL | Auth required |
|---|---|---|
POST |
https://valora.spotahome.com/api/auth/jwt/refresh |
Yes (auth:api_jwt) |
Request
POST https://valora.spotahome.com/api/auth/jwt/refresh
Authorization: Bearer eyJ0eXAiOiJKV1Qi...
Accept: application/json
Success response — 200 OK
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.NEW_PAYLOAD.NEW_SIGNATURE",
"token_type": "bearer",
"expires_in_minutes": 30
}
Replace your stored token with the new access_token immediately. The old one cannot be used again.
Note: If the token has already expired beyond the refresh grace period, you will receive a
401and must log in again.
Log out
Blacklist the current token and end your session. Discard the token on your end after calling this — it will not work again.
| Method | URL | Auth required |
|---|---|---|
POST |
https://valora.spotahome.com/api/auth/jwt/logout |
Yes (auth:api_jwt) |
Request
POST https://valora.spotahome.com/api/auth/jwt/logout
Authorization: Bearer eyJ0eXAiOiJKV1Qi...
Accept: application/json
Success response — 200 OK
{
"message": "Successfully logged out"
}
Errors
401 Unauthorized — invalid credentials
Returned by the login endpoint when your email or password is wrong.
{
"message": "Invalid credentials"
}
401 Unauthorized — expired token
{
"message": "Token has expired"
}
Call POST https://valora.spotahome.com/api/auth/jwt/refresh to get a new token, or log in again if the grace period has passed.
401 Unauthorized — invalid token
{
"message": "Token is invalid"
}
The token is malformed or was blacklisted. Log in again to get a fresh one.
401 Unauthorized — missing token
{
"message": "Token absent or invalid"
}
No Authorization header was sent, or the value could not be parsed as a JWT.
422 Unprocessable Entity — validation failure
{
"message": "The email field is required.",
"errors": {
"email": ["The email field is required."],
"password": ["The password field is required."]
}
}
500 Internal Server Error — token creation failure
{
"message": "Could not create token"
}
An unexpected error occurred on the server while signing the JWT. Retry the request. If the error persists, contact support.