HomeAPI Documentation

    GenReady API

    v1

    Integrate AI readiness analysis into your applications, CI/CD pipelines, and workflows.

    Quick Start

    The fastest way to get a report - a single API call with waitForCompletion.

    1Get your API key

    Create an API key from your dashboard. Your key will look like gr_live_Ab3xY9... - copy it immediately, it's only shown once.

    Go to API Keys
    2Analyze a URL

    Use waitForCompletion: true to get the report in a single request (waits up to 120s).

    curl -X POST https://genready.ai/api/v1/analyze \
      -H "Authorization: Bearer gr_live_YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"url": "https://example.com", "options": {"waitForCompletion": true}}'
    3Get your results

    The response includes scores, detailed metrics, and a prioritized fix checklist.

    json{
      "data": {
        "reportId": "acae9782-f6aa-46d0-ae79-8aca8eb5a3bf",
        "url": "https://example.com",
        "scope": "full",
        "status": "completed",
        "scores": {
          "overall": 68,
          "content": 62,
          "crawlability": 74,
          "details": { "...": "see Endpoints section for full shape" }
        },
        "fixChecklist": [
          {
            "severity": "critical",
            "category": "crawlability",
            "metric": "Firewall",
            "problem": "WAF is blocking AI crawlers.",
            "fix": "Whitelist AI crawler user agents in your WAF configuration."
          },
          {
            "severity": "high",
            "category": "content",
            "metric": "Facts & Details",
            "problem": "Only 12 entities found in 2,400 words (0.5% density).",
            "fix": "Replace vague claims with named sources and data."
          }
        ],
        "recommendations": [ ... ]
      }
    }

    Prefer async? Omit waitForCompletion and poll GET /reports/:id/status until status is completed. Or register a webhook to get notified automatically.

    Authentication

    All API requests require a valid API key sent as a Bearer token in the Authorization header.

    Authorization: Bearer gr_live_xxxxx

    Create and manage your API keys at /api-keys. Keys are shown once at creation - store them securely.

    Base URL

    https://genready.ai/api/v1

    All endpoint paths below are relative to this base URL.

    Endpoints

    POST/analyze

    Submit a URL for AI readiness analysis.

    Request body:

    json{
      "url": "https://example.com/page",
      "scope": "full",
      "options": {
        "waitForCompletion": false
      }
    }

    Scope options:

    ScopeWhat runsCredit costEst. time
    "full" (default)Content + Crawlability + AI analysis1 credit~25-40s
    "content"Content quality only1 credit~15-25s
    "crawlability"Technical crawlability only1 credit~10-15s

    Response (async - 202):

    json{
      "data": {
        "reportId": "acae9782-f6aa-46d0-ae79-8aca8eb5a3bf",
        "scope": "full",
        "status": "queued",
        "estimatedSeconds": 30,
        "statusUrl": "/api/v1/reports/acae9782-.../status",
        "reportUrl": "/api/v1/reports/acae9782-..."
      },
      "meta": { "requestId": "req_abc123", "timestamp": "2026-03-17T06:00:00Z" }
    }

    Response (sync - waitForCompletion: true, 200):

    Returns the full report directly (same shape as GET /reports/:id). Times out after 120s with a 202 if analysis is still running.

    Error codes:

    StatusCodeReason
    400INVALID_URLURL failed validation
    400INVALID_SCOPEScope must be "full", "content", or "crawlability"
    402CREDITS_EXHAUSTEDMonthly API credits used up
    429RATE_LIMITEDToo many requests per minute
    GET/reports/:id

    Retrieve a completed analysis report.

    Returns the full report data. Response shape adapts to the scope used during analysis.

    Enriched metrics: Each metric in details includes self-documenting metadata: key, name, description, maxScore, category, subcategory, and weight - so you don't need to hardcode metric definitions.

    json{
      "data": {
        "reportId": "acae9782-...",
        "url": "https://example.com/page",
        "scope": "full",
        "status": "completed",
        "createdAt": "2026-03-17T06:00:00Z",
        "completedAt": "2026-03-17T06:00:32Z",
        "scores": {
          "overall": 68,
          "content": 62,
          "crawlability": 74,
          "details": {
            "entity_ratio": {
              "key": "entity_ratio",
              "name": "Facts & Details",
              "description": "Measures the density of named entities...",
              "score": 5.2,
              "verdict": "warn",
              "maxScore": 10,
              "category": "content",
              "subcategory": "helpful_content",
              "weight": 1,
              "wordCount": 1850
            },
            "robots_txt": {
              "key": "robots_txt",
              "name": "AI Access Rules",
              "description": "Checks robots.txt for AI crawler access...",
              "score": 18,
              "verdict": "pass",
              "maxScore": 18,
              "category": "crawlability",
              "subcategory": null,
              "weight": null,
              "aiCrawlersAllowed": true,
              "blockedBots": []
            },
            "ttfb": {
              "key": "ttfb",
              "name": "Loading Speed",
              "description": "Time to first byte measurement...",
              "score": 7,
              "verdict": "warn",
              "maxScore": 10,
              "category": "crawlability",
              "subcategory": null,
              "weight": null,
              "ms": 620
            },
            "...": "additional metrics omitted for brevity"
          }
        },
        "fixChecklist": [
          {
            "severity": "critical",
            "category": "crawlability",
            "metric": "Firewall",
            "problem": "WAF is blocking AI crawlers.",
            "fix": "Whitelist AI crawler user agents in your WAF configuration."
          },
          {
            "severity": "high",
            "category": "content",
            "metric": "Links to Sources",
            "problem": "Only 1 outbound link in 1,850 words.",
            "fix": "Add 3-5 citations to authoritative sources."
          }
        ],
        "recommendations": [
          {
            "priority": "high",
            "category": "content",
            "title": "Add more statistics and data points",
            "description": "Pages with 3+ cited statistics are more likely to be referenced by AI."
          }
        ]
      }
    }

    Fix checklist:

    The fixChecklist array contains actionable items sorted by severity: criticalhighmediumlow. Each item includes the affected metric, a description of the problem, and a concrete fix instruction. Use this to build "what to fix first" UIs.

    If the report is still in progress, returns 202 with status information. If the report belongs to another user, returns 404.

    GET/reports/:id/status

    Check analysis progress for a running or completed report.

    json{
      "data": {
        "reportId": "acae9782-...",
        "scope": "full",
        "status": "analyzing",
        "progress": 65,
        "steps": {
          "fetch": "completed",
          "content_analysis": "in_progress",
          "crawlability_check": "pending",
          "ai_analysis": "pending"
        }
      }
    }

    Status values: queuedanalyzingcompleted | failed

    GET/reports

    List your analysis reports with pagination and filtering.

    Query parameters:

    ParamDefaultDescription
    page1Page number
    limit20Items per page (max 100)
    status-Filter: "completed", "failed", "analyzing"
    since-ISO date - reports created after this time
    url-Filter by analyzed URL (partial match)
    json{
      "data": {
        "reports": [
          {
            "reportId": "acae9782-...",
            "url": "https://example.com",
            "status": "completed",
            "scores": { "overall": 78, "content": 71, "crawlability": 85 },
            "createdAt": "2026-03-17T06:00:00Z"
          }
        ],
        "pagination": { "page": 1, "limit": 20, "total": 47, "totalPages": 3 }
      }
    }
    GET/usage

    Check your current billing period usage.

    json{
      "data": {
        "plan": "pro",
        "billingPeriod": {
          "start": "2026-03-01T00:00:00Z",
          "end": "2026-03-31T23:59:59Z"
        },
        "reports": { "used": 142, "limit": 500, "remaining": 358 },
        "apiCredits": { "used": 87, "limit": 200, "remaining": 113 }
      }
    }
    GET/usage/daily

    Daily breakdown of API calls and reports for the current month.

    json{
      "data": {
        "days": [
          { "date": "2026-03-01", "apiCalls": 12, "reports": 5 },
          { "date": "2026-03-02", "apiCalls": 8, "reports": 3 },
          { "date": "2026-03-03", "apiCalls": 23, "reports": 11 }
        ]
      }
    }

    Only days with activity are included. Days with zero usage are omitted.

    GET/ping

    Health check endpoint. No authentication required.

    json{
      "data": { "status": "ok", "version": "1.0", "timestamp": "2026-03-17T06:00:00Z" }
    }

    Webhooks

    Register webhook URLs to receive notifications when analyses complete - no polling required. Manage webhooks via the CRUD endpoints below, and verify payloads with the signing secret returned at creation.

    Webhook payload format:

    json{
      "event": "report.completed",
      "reportId": "acae9782-...",
      "url": "https://example.com/page",
      "scope": "full",
      "scores": { "overall": 78, "content": 71, "crawlability": 85 },
      "reportUrl": "https://genready.ai/api/v1/reports/acae9782-...",
      "timestamp": "2026-03-17T06:01:30Z"
    }

    Signature verification:

    Every webhook includes an X-GenReady-Signature header with an HMAC-SHA256 signature. Verify it using the secret returned when you created the webhook.

    javascriptconst crypto = require('crypto');
    
    function verifyWebhook(payload, signature, secret) {
      const expected = crypto
        .createHmac('sha256', secret)
        .update(payload)
        .digest('hex');
      return crypto.timingSafeEqual(
        Buffer.from(`sha256=${expected}`),
        Buffer.from(signature)
      );
    }

    Retry behavior: Failed deliveries are retried 3 times with exponential backoff (5s, 30s, 300s). Webhook URLs must be HTTPS.

    POST/webhooks

    Create a new webhook. The signing secret is returned only once - store it securely.

    Request body:

    json{
      "url": "https://your-app.com/hooks/genready",
      "events": ["report.completed"]
    }

    Response (201):

    json{
      "data": {
        "id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
        "apiKeyId": "key-id-...",
        "url": "https://your-app.com/hooks/genready",
        "secret": "whsec_abc123...",
        "events": ["report.completed"],
        "active": true,
        "createdAt": "2026-03-17T06:00:00Z"
      }
    }

    The secret is shown only at creation. You'll need it to verify webhook signatures.

    GET/webhooks

    List all your webhooks.

    json{
      "data": {
        "webhooks": [
          {
            "id": "d290f1ee-...",
            "apiKeyId": "key-id-...",
            "url": "https://your-app.com/hooks/genready",
            "secret": "whsec_****",
            "events": ["report.completed"],
            "active": true,
            "failCount": 0,
            "lastDeliveryAt": "2026-03-17T06:01:30Z",
            "lastDeliveryStatus": 200,
            "createdAt": "2026-03-17T06:00:00Z",
            "updatedAt": "2026-03-17T06:00:00Z"
          }
        ]
      }
    }

    The secret is always masked (whsec_****) - it's only shown once at creation.

    PATCH/webhooks/:id

    Update a webhook's URL, events, or active status.

    Request body (all fields optional):

    json{
      "url": "https://your-app.com/hooks/new-endpoint",
      "events": ["report.completed"],
      "active": false
    }

    Response (200):

    json{
      "data": {
        "id": "d290f1ee-...",
        "apiKeyId": "key-id-...",
        "url": "https://your-app.com/hooks/new-endpoint",
        "secret": "whsec_****",
        "events": ["report.completed"],
        "active": false,
        "failCount": 0,
        "updatedAt": "2026-03-17T07:00:00Z"
      }
    }
    DELETE/webhooks/:id

    Delete a webhook permanently.

    json{
      "data": { "deleted": true }
    }
    GET/webhooks/:id/deliveries

    View delivery history for a webhook (paginated).

    Query parameters:

    ParamDefaultDescription
    page1Page number
    limit20Items per page (max 100)
    json{
      "data": {
        "deliveries": [
          {
            "id": "del-uuid-...",
            "event": "report.completed",
            "reportId": "acae9782-...",
            "statusCode": 200,
            "responseBody": "OK",
            "attempt": 1,
            "durationMs": 142,
            "deliveredAt": "2026-03-17T06:01:30Z"
          }
        ],
        "pagination": { "page": 1, "limit": 20, "total": 5, "totalPages": 1 }
      }
    }
    POST/webhooks/:id/test

    Send a test webhook payload to verify your endpoint.

    json{
      "data": {
        "success": true,
        "statusCode": 200,
        "durationMs": 87,
        "responseBody": "OK"
      }
    }

    Rate Limits

    All API key users share the same rate limit: 60 requests per minute.

    LimitValue
    Requests per minute60
    Rate limit window1 minute (sliding)

    Higher rate limits for Business and Enterprise plans are planned for the future. API credit quotas vary by plan - check GET /usage for your current limits.

    Rate limit headers:

    Every API response includes these headers:

    HeaderDescription
    RateLimit-LimitMaximum requests per minute
    RateLimit-RemainingRequests remaining in current window
    RateLimit-ResetSeconds until the window resets

    When rate limited, you'll receive a 429 response. Wait 60 seconds before retrying.

    Error Handling

    Error envelope:

    json{
      "error": {
        "code": "RATE_LIMITED",
        "message": "Too many requests. Please slow down.",
        "details": { "retryAfterSeconds": 60 }
      },
      "meta": {
        "requestId": "req_abc123",
        "timestamp": "2026-03-17T06:00:00Z"
      }
    }

    Common error codes:

    CodeStatusDescription
    UNAUTHORIZED401Missing or invalid API key
    INVALID_URL400URL failed validation (malformed, private IP, etc.)
    INVALID_SCOPE400Scope must be full, content, or crawlability
    INVALID_ID400Report/webhook ID is not a valid UUID
    VALIDATION_ERROR400Request body failed validation
    CREDITS_EXHAUSTED402Monthly API credits used up
    NOT_FOUND404Report or webhook not found
    RATE_LIMITED429Too many requests - check rate limit headers
    INTERNAL_ERROR500Something went wrong on our end

    Every error response includes a meta.requestId - include it when contacting support.

    Code Examples

    # Synchronous analysis (simplest)
    curl -X POST https://genready.ai/api/v1/analyze \
      -H "Authorization: Bearer gr_live_xxxxx" \
      -H "Content-Type: application/json" \
      -d '{"url": "https://example.com", "options": {"waitForCompletion": true}}'
    
    # Async analysis
    curl -X POST https://genready.ai/api/v1/analyze \
      -H "Authorization: Bearer gr_live_xxxxx" \
      -H "Content-Type: application/json" \
      -d '{"url": "https://example.com"}'
    
    # Poll status
    curl https://genready.ai/api/v1/reports/REPORT_ID/status \
      -H "Authorization: Bearer gr_live_xxxxx"
    
    # Get report
    curl https://genready.ai/api/v1/reports/REPORT_ID \
      -H "Authorization: Bearer gr_live_xxxxx"
    
    # Content-only analysis
    curl -X POST https://genready.ai/api/v1/analyze \
      -H "Authorization: Bearer gr_live_xxxxx" \
      -H "Content-Type: application/json" \
      -d '{"url": "https://example.com", "scope": "content"}'

    API Playground

    Try the API

    Test the analyze endpoint directly from your browser.

    Stored in localStorage only - never sent to our server.

    curl -X POST https://genready.ai/api/v1/analyze \
      -H "Authorization: Bearer YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"url":"https://example.com","scope":"full","options":{"waitForCompletion":true}}'

    SDKs

    Coming Soon

    Official Python and Node.js SDKs are in development.

    In the meantime, the REST API works great with any HTTP library. See the code examples above for quick integration patterns.