Client Portal

Portal API Reference

API endpoints for portal integration and automation.

Last updated

The Portal API allows you to integrate portal data into your own systems or build custom client-facing experiences.

Portal API endpoints require authentication via portal session token. These are designed for client-facing integrations, not agency automation.

Authentication

Portal users authenticate via email and password. A session token is stored in an HTTP-only cookie and automatically included in requests.

Login

POST /api/v1/portal/auth/login

Request:
{
  "email": "user@client.com",
  "password": "user-password",
  "clientId": "client-uuid"
}

Response:
{
  "success": true,
  "user": {
    "id": "user-uuid",
    "email": "user@client.com",
    "name": "John Smith"
  }
}

Session

GET /api/v1/portal/auth/session

Response:
{
  "authenticated": true,
  "user": {
    "id": "user-uuid",
    "email": "user@client.com",
    "permissions": ["view_scores", "view_recommendations"]
  }
}

Sites Endpoints

List Sites

GET /api/v1/portal/sites

Response:
{
  "sites": [
    {
      "id": "site-uuid",
      "domain": "example.com",
      "name": "Example Site",
      "latestScore": 75,
      "latestScanAt": "2026-01-27T10:00:00Z"
    }
  ]
}

Get Site Details

GET /api/v1/portal/sites/[id]

Response:
{
  "site": {
    "id": "site-uuid",
    "domain": "example.com",
    "name": "Example Site",
    "latestScore": 75,
    "latestScanAt": "2026-01-27T10:00:00Z"
  },
  "latestScan": {
    "id": "scan-uuid",
    "overallScore": 75,
    "scores": { ... },
    "recommendations": [ ... ],
    "platformReadiness": { ... }
  },
  "scanHistory": [
    { "id": "...", "overallScore": 75, "completedAt": "..." }
  ]
}

Data Endpoints

Get Recommendations

GET /api/v1/portal/recommendations

Response:
{
  "recommendations": [
    {
      "id": "rec-uuid",
      "type": "critical",
      "title": "Add Schema Markup",
      "description": "...",
      "impact": "high",
      "effort": "medium",
      "siteId": "site-uuid",
      "siteName": "Example Site"
    }
  ]
}

Get Competitors

GET /api/v1/portal/competitors

Response:
{
  "competitors": [
    {
      "id": "entity-uuid",
      "name": "Competitor Inc",
      "entityType": "competitor",
      "totalMentions": 15,
      "avgSentiment": 0.2,
      "siteId": "site-uuid"
    }
  ]
}

Profile Endpoints

Get Profile

GET /api/v1/portal/profile

Response:
{
  "user": {
    "id": "user-uuid",
    "email": "user@client.com",
    "name": "John Smith",
    "permissions": ["view_scores", "view_recommendations"],
    "lastLoginAt": "2026-01-27T10:00:00Z"
  }
}

Update Profile

PATCH /api/v1/portal/profile

Request:
{
  "name": "John Smith Updated"
}

Response:
{
  "user": {
    "id": "user-uuid",
    "email": "user@client.com",
    "name": "John Smith Updated"
  }
}

Change Password

Changing a password invalidates every session token issued before the change, across every device and browser. The caller's own session cookie is re-issued in the response so they stay logged in on the current device. New passwords must be between 8 and 72 characters.

POST /api/v1/portal/auth/change-password

Request:
{
  "currentPassword": "old-password",
  "newPassword": "new-password",
  "confirmPassword": "new-password"
}

Response:
{
  "success": true
}

Error Responses

All endpoints return standard error responses:

// 401 Unauthorized
{ "error": "Not authenticated" }

// 403 Forbidden
{ "error": "Permission denied" }

// 404 Not Found
{ "error": "Site not found" }

// 500 Internal Server Error
{ "error": "Failed to get sites" }
Was this page useful?