API DocumentationEnterprise Only

Full-featured API with the same capabilities as the dashboard

Manage API Keys

🎯Full Feature Parity with Dashboard

The API provides the same capabilities as scanning through the dashboard:

Single URL Crawl
URL List Mode (multi-URL)
JS Error Detection
Desktop & Mobile Googlebot Screenshots
Internal Link Analysis
SEO Score
Team Support
35+ SEO Issue Types
Up to 500 pages/scan
Scan History Access

⚡ Quick Start - Get Running in 5 Minutes

Follow these 3 steps to make your first API call and start scanning websites.

1

Get Your API Key

Generate an API key from the API Keys page

2

Make Your First Request

Copy and run this code:

# 1. Set your API key
export API_KEY="your_api_key_here"

# 2. Trigger a scan
curl -X POST https://jsvisible.com/api/v1/scan \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

# 3. Check your usage
curl https://jsvisible.com/api/v1/usage \
  -H "Authorization: Bearer $API_KEY"
3

You're Ready! 🎉

Start integrating JSVisible into your application

Authentication

API Key Authentication

All API requests require an API key in the Authorization header:

Authorization: Bearer YOUR_API_KEY

Generate your API key from the API Keys page.

✅ Generous API LimitsEnterprise

Enterprise tier includes 200 API scans per month (shared with dashboard). GET requests to view results are unlimited! Perfect for monitoring hundreds of websites daily. Need more? Contact sales@jsvisible.com for custom limits.

Rate Limiting

The API returns rate limit information in response headers:

HTTP/1.1 200 OK
X-Scans-Limit: 200
X-Scans-Remaining: 187
X-Scans-Reset: 1735689600

{
  "success": true,
  ...
}

Tip: Check X-Scans-Remaining to monitor your usage and avoid hitting the limit.

Base URL

https://jsvisible.com/api/v1

Language Examples

Endpoints

POST/api/v1/scan

Trigger a new SEO scan. Supports single URL crawl mode or multi-URL list mode.

Request Body Parameters:

ParameterTypeRequiredDescription
urlstring*Single URL to crawl (discovers and follows links)
urlsstring[]*Array of specific URLs to scan (URL List Mode, max 100)
max_pagesnumberNoMax pages to scan (default: 500 for Enterprise)
team_idstringNoAssociate scan with a team (UUID)

* Either url or urls is required (not both)

🕷️Crawl Mode (Single URL)

Provide a single URL. The crawler will discover and follow internal links automatically.

curl -X POST https://jsvisible.com/api/v1/scan \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com", "max_pages": 50}'
📋URL List Mode (Multiple URLs)

Provide an array of specific URLs. Can include different domains. No auto-discovery.

curl -X POST https://jsvisible.com/api/v1/scan \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "urls": [
      "https://example.com",
      "https://example.com/about",
      "https://example.com/pricing",
      "https://competitor.com"
    ]
  }'
👥Team Context

Associate scans with a team for shared access. Requires appropriate team permissions.

curl -X POST https://jsvisible.com/api/v1/scan \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com",
    "team_id": "550e8400-e29b-41d4-a716-446655440000"
  }'

Response (200 OK):

{
  "success": true,
  "scan_id": "550e8400-e29b-41d4-a716-446655440000",
  "website": "https://example.com",
  "status": "completed",
  "total_issues": 5,
  "total_warnings": 12,
  "pages_analyzed": 25,
  "seo_score": 78,
  
  "mode": "crawl",              // or "url_list"
  "urls_scanned": null,         // number if url_list mode
  
  "screenshots_enabled": true,
  "screenshot_count": 3,
  
  "team_id": null,              // or team UUID
  
  "quota": {
    "scansUsed": 48,
    "scansLimit": 200,
    "scansRemaining": 152
  }
}

Note: Use GET /api/v1/scan/:id to retrieve full scan data including all issues, JS errors, internal links, and screenshots.

GET/api/v1/scans

Retrieve a list of your scans with pagination support.

Query Parameters:

  • limit (optional): Number of results (default: 10, max: 100)
  • offset (optional): Pagination offset (default: 0)

Example:

curl "https://jsvisible.com/api/v1/scans?limit=10&offset=0" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (200 OK):

{
  "success": true,
  "scans": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "website": "https://example.com",
      "total_issues": 5,
      "total_warnings": 12,
      "pages_analyzed": 25,
      "seo_score": 78,
      "crawled_at": "2026-11-20T10:30:00Z"
    }
  ],
  "pagination": {
    "count": 1,
    "limit": 10,
    "offset": 0,
    "total": 47
  }
}
GET/api/v1/scan/:idFull Data

Get complete scan details including all pages, issues, JS errors, internal links, and screenshots.

Example:

curl https://jsvisible.com/api/v1/scan/SCAN_ID \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (200 OK):

{
  "success": true,
  "scan": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "website": "https://example.com",
    "total_issues": 5,
    "total_warnings": 12,
    "pages_analyzed": 25,
    "seo_score": 78,
    "crawled_at": "2026-11-20T10:30:00Z",
    "team_id": null,
    
    "mode": "crawl",
    "screenshots_captured": 3,
    
    // Aggregated JS error counts
    "js_error_summary": {
      "uncaughtExceptions": 2,
      "consoleErrors": 8,
      "failedRequests": 1
    },
    
    // Internal link analysis
    "internal_link_analysis": {
      "total_internal_links": 156,
      "orphan_pages": 3,
      "avg_links_per_page": 6.2,
      "orphan_page_urls": [
        "https://example.com/old-page",
        "https://example.com/hidden-content"
      ]
    },
    
    // Full page-by-page data
    "scan_data": [
      {
        "url": "https://example.com",
        "title": "Example Site - Home",
        "metaDescription": "Welcome to Example Site...",
        "h1Count": 1,
        "h1Text": "Welcome to Example",
        "wordCount": 450,
        "loadTime": "1.24s",
        "issues": ["Missing meta description"],
        "warnings": ["Title too short (28 chars)"],
        
        // Internal links for this page
        "internalLinksCount": 12,
        "internalLinksTo": [],  // Pages linking TO this page
        
        // Per-page JS errors
        "jsErrors": {
          "uncaughtExceptions": 1,
          "consoleErrors": 3,
          "failedRequests": 0
        },
        
        // Screenshots (if captured) - Desktop & Mobile
        "screenshots": {
          "desktop": {
            "userView": {
              "screenshot": "base64...",
              "metrics": { "title": "...", "textLength": 4500 }
            },
            "googlebotView": {
              "screenshot": "base64...",
              "metrics": { "title": "...", "textLength": 4200 }
            }
          },
          "mobile": {
            "userView": {
              "screenshot": "base64...",
              "metrics": { "title": "...", "textLength": 4300 }
            },
            "googlebotView": {
              "screenshot": "base64...",
              "metrics": { "title": "...", "textLength": 4100 }
            }
          },
          "differences": [
            {
              "type": "content_difference",
              "severity": "warning",
              "device": "desktop",
              "message": "Googlebot sees 7% less content"
            }
          ],
          "renderingHealth": "good",
          "summary": "Minor differences detected"
        },
        
        "details": {
          "titleLength": 28,
          "hasCanonical": true,
          "hasStructuredData": false
        }
      }
    ],
    
    // Issues from database
    "issues": [
      {
        "id": 1,
        "page_url": "https://example.com",
        "issue_type": "missing_meta_description",
        "severity": "error",
        "message": "Missing meta description"
      }
    ]
  },
  "quota": {
    "scansUsed": 48,
    "scansLimit": 200,
    "scansRemaining": 152
  }
}
🐛js_error_summary
  • uncaughtExceptions - Runtime JS errors
  • consoleErrors - console.error() calls
  • failedRequests - Failed script/API loads
🔗internal_link_analysis
  • orphan_pages - Pages with 0 internal links
  • avg_links_per_page - Average link count
  • orphan_page_urls - List of orphan URLs
📸screenshots (Desktop & Mobile)
  • desktop.userView - Desktop user screenshot
  • desktop.googlebotView - Desktop Googlebot
  • mobile.userView - Mobile user screenshot
  • mobile.googlebotView - Mobile Googlebot
  • renderingHealth - excellent/good/fair/poor
GET/api/v1/usage

Check your current API usage and quota limits.

Example:

curl https://jsvisible.com/api/v1/usage \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (200 OK):

{
  "success": true,
  "current_period": {
    "start": "2026-01-01T00:00:00Z",
    "end": "2026-02-01T00:00:00Z"
  },
  "scans": {
    "used": 47,
    "limit": 200,
    "remaining": 153,
    "reset_at": "2026-02-01T00:00:00Z"
  },
  "limits": {
    "pages_per_scan": 500,
    "total_pages_per_month": 100000,
    "max_urls_per_list": 100
  },
  "note": "API scans share quota with dashboard scans. GET requests are unlimited."
}

Error Responses

401 Unauthorized

Invalid or missing API key

{
  "success": false,
  "error": "unauthorized",
  "message": "Invalid API key"
}

403 Forbidden

API access requires Enterprise tier, or insufficient team permissions

{
  "success": false,
  "error": "permission_denied",
  "message": "You do not have permission to run scans in this team."
}

429 Too Many Requests

Monthly scan limit reached

{
  "success": false,
  "error": "scan_limit_exceeded",
  "message": "Monthly scan limit reached (200 scans). Resets on February 1, 2026.",
  "quota": {
    "scansUsed": 200,
    "scansLimit": 200,
    "scansRemaining": 0
  }
}

400 Bad Request

Invalid parameters

{
  "success": false,
  "error": "Invalid URL format: not-a-valid-url"
}

Best Practices

  • Keep API keys secure: Never commit them to version control or expose them in client-side code
  • Use URL List Mode for specific pages: When you know exactly which URLs to scan, use urls array instead of crawling
  • Monitor JS errors: Check js_error_summary.uncaughtExceptions for critical JavaScript issues affecting SEO
  • Check internal links: Use internal_link_analysis.orphan_pages to find pages with no internal links
  • Check renderingHealth: Use screenshots.renderingHealth to quickly identify Googlebot rendering issues on desktop and mobile
  • Use teams for organization: Pass team_id to organize scans by project or client
  • Monitor quota: Use /api/v1/usage before batch operations to ensure sufficient quota
  • Handle errors gracefully: Implement retry logic with exponential backoff for rate limits
  • Need higher limits? Contact sales@jsvisible.com for custom enterprise plans

Need Help?

As an Enterprise customer, you have access to priority support.