Long-Lived API Token Authentication
How to generate, use, verify, and revoke Valora's long-lived bearer tokens for routes protected by the auth:api guard.
Overview
A long-lived API token is a bearer credential tied to your user record (vl_… for production, sd_… for sandbox). It stays valid until you replace it by generating a new one or revoke it. Use it on any route that requires the auth:api guard.
API hosts:
- Production
https://valora.spotahome.com/(sandbox compatible);- Staging / testing
https://valora-testing.laravel.cloud/(sandbox compatible).Token lifecycle routes use
/api/v1/tokens/...on either host. Customer and employee data in the sandbox environment use/api/sandbox/v1/...(typically on the staging host).
You can obtain a token in either of these ways:
- Web app (Settings) — While logged into Valora in the browser, use Settings → API Tokens to mint or rotate tokens without calling the public generate endpoints. Details: From Settings (browser).
- HTTP API — Exchange email + password (no prior bearer token) via
POST https://valora.spotahome.com/api/v1/tokens/generateorPOST https://valora.spotahome.com/api/v1/tokens/generate/sandbox, or call the authenticated employee-only token endpoints if you already have a session token (documented in the tables below).
There are two separate tokens — one for production and one for sandbox. They are independent: generating or revoking one does not affect the other.
Note: Valora stores only a hash of the token in the database. The plain token is shown once when it is generated (in the browser UI or in the JSON response). Copy it immediately and store it securely.
Generate a token
From Settings (browser)
For people using the Valora web UI:
- Sign in with your normal Valora account (session auth).
- Open Settings → API Tokens in the browser.
- From here you can click on Generate Production Token or Generate Sandbox Token.
- Each successful generation writes a new
vl_…orsd_…token and replaces the previous hash for that environment on your user record (any old bearer of that environment stops working). - Copy the value from the read-only field before leaving the page; it is not shown again.
This path does not require posting your password to the public POST https://valora.spotahome.com/api/v1/tokens/generate endpoints; it requires an existing web session (auth middleware on the settings route group).
Production token (HTTP)
Exchange your credentials for a production token.
| Method | URL | Auth required |
|---|---|---|
POST |
https://valora.spotahome.com/api/v1/tokens/generate |
No |
Request
POST https://valora.spotahome.com/api/v1/tokens/generate
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
{
"message": "API token generated successfully",
"api_token": "vl_AbCdEfGhIjKlMnOpQrStUvWxYz...",
"environment": "production",
"note": "Please save this token in a secure location. You will not be able to access it again."
}
Sandbox token (HTTP)
Same HTTP flow as production, but issues a sandbox token scoped to the sandbox environment. You can also generate the sandbox token from Settings → API Tokens in the browser (see From Settings (browser)).
| Method | URL | Auth required |
|---|---|---|
POST |
https://valora.spotahome.com/api/v1/tokens/generate/sandbox |
No |
Request
POST https://valora.spotahome.com/api/v1/tokens/generate/sandbox
Accept: application/json
Content-Type: application/json
{
"email": "you@example.com",
"password": "your-password"
}
Success response — 200 OK
{
"message": "Sandbox API token generated successfully",
"api_token": "sd_SbCdEfGhIjKlMnOpQrStUvWxYz...",
"environment": "sandbox",
"note": "Please save this token in a secure location. You will not be able to access it again."
}
Use your token
Send the token as a bearer credential on every request:
GET https://valora.spotahome.com/api/v1/c/transactions
Authorization: Bearer vl_AbCdEfGhIjKlMnOpQrStUvWxYz...
Accept: application/json
Verify your token
Confirm that your current token is valid and check which environment it belongs to.
| Method | URL | Auth required |
|---|---|---|
GET |
https://valora.spotahome.com/api/v1/tokens/verify |
Yes (auth:api) |
Request
GET https://valora.spotahome.com/api/v1/tokens/verify
Authorization: Bearer vl_AbCdEfGhIjKlMnOpQrStUvWxYz...
Accept: application/json
Success response — 200 OK
{
"message": "Token is valid",
"environment": "production"
}
The environment field is either "production" or "sandbox" depending on which token you sent.
Check rate limits
Retrieve the active rate-limit plan, usage, remaining requests, and reset time for the token owner.
| Method | URL | Auth required |
|---|---|---|
GET |
https://valora.spotahome.com/api/v1/tokens/limits |
Yes (auth:api) |
Request
GET https://valora.spotahome.com/api/v1/tokens/limits
Authorization: Bearer vl_AbCdEfGhIjKlMnOpQrStUvWxYz...
Accept: application/json
Success response — 200 OK
{
"message": "Rate limits retrieved successfully",
"rate_limits": {
"audience": "customer",
"plan": {
"id": 12,
"name": "Business",
"slug": "business"
},
"limits": [
{
"window": "minute",
"limit": 120,
"used": 42,
"remaining": 78,
"resets_in_seconds": 31,
"resets_at": "2026-05-03T22:30:00+02:00"
}
]
}
}
Revoke a token
Auto-detect environment
Revoke the token you are currently using. The endpoint detects the environment from the token automatically.
| Method | URL | Auth required |
|---|---|---|
POST |
https://valora.spotahome.com/api/v1/tokens/revoke |
Yes (auth:api) |
Request
POST https://valora.spotahome.com/api/v1/tokens/revoke
Authorization: Bearer vl_AbCdEfGhIjKlMnOpQrStUvWxYz...
Accept: application/json
Success response — 200 OK
{
"message": "production API token revoked successfully",
"status": "revoked",
"environment": "production"
}
Already revoked — 200 OK
{
"message": "No active production API token found. Token may have already been revoked.",
"status": "already_revoked",
"environment": "production"
}
Revoke production explicitly
Force-revoke your production token regardless of which token you are sending.
| Method | URL | Auth required |
|---|---|---|
POST |
https://valora.spotahome.com/api/v1/tokens/revoke/production |
Yes (auth:api) |
Request
POST https://valora.spotahome.com/api/v1/tokens/revoke/production
Authorization: Bearer vl_AbCdEfGhIjKlMnOpQrStUvWxYz...
Accept: application/json
Success response — 200 OK
{
"message": "Production API token revoked successfully",
"status": "revoked",
"environment": "production"
}
Revoke sandbox explicitly
Force-revoke your sandbox token.
| Method | URL | Auth required |
|---|---|---|
POST |
https://valora.spotahome.com/api/v1/tokens/revoke/sandbox |
Yes (auth:api) |
Request
POST https://valora.spotahome.com/api/v1/tokens/revoke/sandbox
Authorization: Bearer vl_AbCdEfGhIjKlMnOpQrStUvWxYz...
Accept: application/json
Success response — 200 OK
{
"message": "Sandbox API token revoked successfully",
"status": "revoked",
"environment": "sandbox"
}
Re-generate while authenticated
If you already have a valid token and want to rotate it without re-entering your password, use these authenticated endpoints. They issue a fresh token and invalidate the previous one.
| Method | URL | Token type issued |
|---|---|---|
POST |
https://valora.spotahome.com/api/v1/tokens/generate/production |
Production |
POST |
https://valora.spotahome.com/api/v1/tokens/generate/sandbox/token |
Sandbox |
Request (production)
POST https://valora.spotahome.com/api/v1/tokens/generate/production
Authorization: Bearer vl_AbCdEfGhIjKlMnOpQrStUvWxYz...
Accept: application/json
Success response — 200 OK
{
"message": "API token generated successfully",
"api_token": "vl_NewTokenValueHere...",
"environment": "production"
}
Note: These endpoints require
auth:apiwith a valid token of any environment. Unlike the public generate endpoints, they do not include the one-time-view note because you are already authenticated when you call them.
Errors
401 Unauthorized — missing or invalid token
{
"message": "Unauthenticated."
}
You sent a request to a protected endpoint without a token, or with an expired/revoked one.
422 Unprocessable Entity — validation failure
{
"message": "The email field is required.",
"errors": {
"email": ["The email field is required."]
}
}
One or more required fields in your request body are missing or invalid.
422 Unprocessable Entity — wrong credentials
{
"message": "The given data was invalid.",
"errors": {
"email": ["The provided credentials are incorrect."]
}
}
Your email/password combination did not match any account.