Auth / API Key Authentication

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:

  1. 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).
  2. HTTP API — Exchange email + password (no prior bearer token) via POST https://valora.spotahome.com/api/v1/tokens/generate or POST 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:

  1. Sign in with your normal Valora account (session auth).
  2. Open Settings → API Tokens in the browser.
  3. From here you can click on Generate Production Token or Generate Sandbox Token.
  4. Each successful generation writes a new vl_… or sd_… token and replaces the previous hash for that environment on your user record (any old bearer of that environment stops working).
  5. 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:api with 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.