# auth

# Agent Authentication — VINTrakID

> **⚠ Closed beta — automated agent registration is NOT supported.**
> VINTrakID is currently in a **closed enterprise beta** for vetted partners
> (dealerships, lenders, insurance carriers, and select fleet operators).
> Self-service agent / bot registration is intentionally disabled. To request
> access, send a request through the human-driven partner signup page at
> <https://vintrakid.com/partner/signup> or email **partners@vintrakid.com**.
> Once approved, the credentials issued by our partner-onboarding team can be
> used with the OAuth-compatible flows documented below.

> **Discovery roots**
> - OAuth Authorization Server: <https://vintrakid.com/.well-known/oauth-authorization-server>
> - OAuth Protected Resource:  <https://vintrakid.com/.well-known/oauth-protected-resource>
> - API Catalog:               <https://vintrakid.com/.well-known/api-catalog>
> - MCP Server Card:           <https://vintrakid.com/.well-known/mcp/server-card.json>
> - OpenAPI 3.1 spec:          <https://vintrakid.com/api/openapi.json>

VINTrakID exposes a public REST API at `https://vintrakid.com/api`. Public read endpoints
require no authentication. Write endpoints, partner-scoped data, and any
endpoint touching a user's saved vehicles or BuyerSignal records require a
session cookie or bearer token issued by the auth endpoints below.

VINTrakID's underlying implementation is **JWT in an HTTP-only cookie**, not full
OAuth 2.0. We publish the discovery metadata in OAuth-compatible format so that
agents implementing RFC 8414 / RFC 9728 can authenticate without per-vendor code.

---

## Registration

```http
POST /api/auth/register HTTP/1.1
Host: vintrakid.com
Content-Type: application/json

{
  "email": "agent@example.com",
  "password": "<min-12-chars>",
  "display_name": "ExampleAgent",
  "consent_to_data_usage_policy": true
}
```

Returns `201 Created` and sets a session cookie `vintrakid_session` (also
returned in the body as `access_token` for non-browser agents).

## Token acquisition (RFC 6749 § 4.3 — Resource Owner Password)

```http
POST /api/auth/login HTTP/1.1
Host: vintrakid.com
Content-Type: application/json

{
  "email": "agent@example.com",
  "password": "..."
}
```

Returns:

```json
{
  "access_token": "<jwt>",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": "vehicle.read vehicle.write report.read profile.read profile.write"
}
```

## Calling protected endpoints

Pass the JWT in either form:

```http
# Recommended for non-browser agents
GET /api/v1/vehicles HTTP/1.1
Authorization: Bearer <jwt>

# Or via the auto-set cookie
GET /api/v1/vehicles HTTP/1.1
Cookie: vintrakid_session=<jwt>
```

## <a id="claims"></a>JWT claims

| Claim | Description |
|---|---|
| `sub` | User UUID |
| `email` | User email |
| `tier` | One of `free`, `monitor`, `insight_plus`, `partner`, `enterprise` |
| `scopes` | Space-separated scope list (matches Authorization Server metadata) |
| `iat` | Issued-at (Unix seconds) |
| `exp` | Expiry (Unix seconds, 24h after `iat`) |
| `jti` | JWT ID (used by revocation endpoint) |

## <a id="revocation"></a>Revocation

```http
POST /api/auth/logout HTTP/1.1
Authorization: Bearer <jwt>
```

Returns `204 No Content` and clears the session cookie. The `jti` is added to a
short-lived deny list (TTL = remaining token lifetime).

---

## Scopes

| Scope | What it grants |
|---|---|
| `vehicle.read` | List & read user's saved vehicles |
| `vehicle.write` | Add, update, delete saved vehicles + alerts |
| `report.read` | Read user's PDF reports |
| `report.share` | Generate share-tokens for reports |
| `partner.read` | Read partner profile + plan limits |
| `partner.portfolio.read` | Read partner-owned vehicle portfolio |
| `partner.buyer-signals.read` | Read anonymized buyer-intent signals |
| `profile.read` | Read user profile |
| `profile.write` | Edit user profile |

The default scopes for a fresh `password` grant are:
`vehicle.read vehicle.write report.read profile.read profile.write`.
Partner accounts receive the `partner.*` scopes automatically based on their
plan tier.

---

## Rate limits

| Audience | Limit |
|---|---|
| Anonymous | 60 req / min / IP |
| Authenticated user | 60 req / min / user |
| Partner | 600 req / min / org |

When exceeded, endpoints return `429 Too Many Requests` with `Retry-After` in
seconds and a `RateLimit-*` response header set per RFC 9745.

---

## Programmatic agent registration

Agents and MCP clients that want a long-lived token instead of session cookies
should use the standard registration flow above, then store the returned
`access_token` securely. A separate machine-to-machine client-credentials
grant is on the Q2 2026 roadmap — until then, use a user account dedicated to
the agent and rotate the password every 90 days.

For questions or to request an enterprise OAuth client, email
**partners@vintrakid.com**.
