Authentication

The API uses three authentication models, one per audience. Each endpoint URL tells you which one applies.

Public Endpoints — No Authentication

Endpoints under /api/v1/* (without /me/ or /admin/ prefixes) are public. No token, no key, no header required. Just hit them.

curl https://your-site.com/api/v1/posts

Rate limit: 60 requests per minute per IP address.

User Authentication — Sanctum Tokens

Endpoints under /api/v1/me/* require a bearer token. Tokens are issued via POST /api/v1/auth/login (existing users) or POST /api/v1/auth/register (new accounts).

Step 1: Get a Token

For an existing user:

curl -X POST https://your-site.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "email": "[email protected]",
    "password": "your-password",
    "device_name": "my-mobile-app"
  }'

Response:

{
  "success": true,
  "message": "Logged in successfully",
  "data": {
    "token": "1|abc123XYZ...",
    "token_type": "Bearer",
    "user": {
      "id": 8,
      "name": "You",
      "email": "[email protected]",
      "email_verified": true
    }
  }
}

Store the token value. It's the only thing that proves who you are.

Step 2: Use the Token

Send it in the Authorization header on every subsequent request:

curl https://your-site.com/api/v1/me \
  -H "Authorization: Bearer 1|abc123XYZ..." \
  -H "Accept: application/json"

Step 3: Revoke When Done

curl -X POST https://your-site.com/api/v1/auth/logout \
  -H "Authorization: Bearer 1|abc123XYZ..."

The token is deleted server-side. Any future request with it returns 401.

Token Abilities (Scopes)

Sanctum tokens carry abilities — fine-grained permissions that limit what the token can do. A read-only mobile token can't accidentally delete a comment.

Available Abilities

Ability What it allows
user Read own profile, manage own tokens
comments:write Post comments on behalf of the user
tickets:write Open support tickets
newsletter:manage Subscribe/unsubscribe to newsletter
admin Full admin endpoints (/api/v1/admin/*)

Issuing Scoped Tokens

When a user creates a token via POST /api/v1/me/tokens, they pick the abilities:

curl -X POST https://your-site.com/api/v1/me/tokens \
  -H "Authorization: Bearer YOUR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Read-only mobile app",
    "abilities": ["user"]
  }'

The default auth/login flow issues a token with just ["user"]. To get an admin-capable token, see "Admin Authentication" below.

What Happens Without the Right Ability

If a token tries to hit an endpoint that requires an ability it doesn't have, the API returns 403 Forbidden with errors.code: "FORBIDDEN". The token isn't revoked — it just can't access that specific endpoint.

Admin Authentication

Admin endpoints (/api/v1/admin/*) require a token with the admin ability. There's no /auth/login endpoint that issues admin tokens directly — this is intentional. Admin access is bootstrapped by the site owner, not granted via API.

Creating an Admin Token

On the server, in php artisan tinker:

$user = App\Models\User::where('email', '[email protected]')->first();
$token = $user->createToken('my-integration', ['admin']);
echo $token->plainTextToken;
// 6|xyz789ABC...

That token has ["admin"] ability. It can hit any /api/v1/admin/* endpoint at 30 requests/minute.

Why Not Issue Admin Tokens via API?

If /auth/login returned admin tokens automatically, anyone who phished an admin's password would get full programmatic access. By requiring explicit token creation via tinker (or the upcoming admin UI), we limit the blast radius of credential theft.

Token Expiry

By default, Sanctum tokens don't expire until revoked. This is intentional for mobile apps where you don't want users to re-login every week.

To set expiry, configure config/sanctum.php:

'expiration' => 60 * 24 * 30, // 30 days

After this, tokens older than 30 days return 401.

Rate Limits

Endpoint group Rate
/api/v1/auth/login 5/min per IP
/api/v1/auth/register 3/min per IP
/api/v1/auth/forgot-password 3/min per IP
/api/v1/me/* 120/min per user
/api/v1/admin/* 30/min per user
Other /api/v1/* (public) 60/min per IP

Exceeded limits return 429 Too Many Requests with a Retry-After header.

Security Best Practices

  1. Never commit tokens to git. Store in env vars or a secrets manager.
  2. Use device-specific tokens. Issue one token per mobile install, web SPA, or integration. Revoke individually if compromised.
  3. Scope tokens to minimum abilities. A "read-only widget" token doesn't need admin.
  4. Rotate admin tokens periodically. Generate a fresh one, update your integration, delete the old one.
  5. Verify HTTPS. The API only accepts HTTPS in production. The bearer token is in the Authorization header — never put it in URL query strings (those show up in logs).

Next Steps