Skip to main content

Files API Guide

Access historical pricing page scrape files by version, quarter, month, or ISO week. This API provides URLs to screenshots, markdown, HTML, and OCR data for pricing intelligence.

Overview

The Files API allows you to retrieve scrape file URLs from the PricingSaaS intelligence database. Each scrape includes multiple file formats:
  • Screenshot (Cloudinary) - Visual screenshot of the pricing page
  • Markdown - Text content extracted in markdown format
  • HTML - Full HTML source of the page
  • OCR - OCR data in JSON format
All endpoints require authentication and cost 1 credit per request.

Authentication

Include your API key in the request headers using either method:
# Bearer token (recommended)
Authorization: Bearer YOUR_API_KEY

# Or X-API-Key header
X-API-Key: YOUR_API_KEY

Endpoints

1. Get Files by Version

Retrieve scrape files for a specific version (date). Endpoint: GET /files/:slug/version/:version Version Format: YYYYMMDD (e.g., 20251010 for October 10, 2025) Example Request:
curl -X GET "https://api.pricingsaas.com/functions/v1/api/files/stripe/version/20251010" \
  -H "Authorization: Bearer YOUR_API_KEY"
Example Response:
{
  "files": [
    {
      "slug": "stripe",
      "version": "20251010",
      "page_url": "https://stripe.com/pricing",
      "screenshot_url": "https://res.cloudinary.com/dd6dkaan9/image/upload/v1753010719/pricing_pages/pricing_stripe_20251010.jpg",
      "markdown_url": "https://pricingsaas-scrapes.s3.amazonaws.com/stripe/20251010/pricingpage.md",
      "html_url": "https://pricingsaas-scrapes.s3.amazonaws.com/stripe/20251010/pricingpage.html",
      "screenshot_url": "https://pricingsaas-scrapes.s3.amazonaws.com/stripe/20251010/screenshot.jpeg",
      "ocr_url": "https://qulnbyjrczvoxemtrili.supabase.co/storage/v1/object/public/pricingsaas/stripe/20251010/ocr.json",
      "scraper": "aws",
      "valid": true,
      "score": 9,
      "banner_free": false,
      "created_at": "2025-10-10T19:05:06.30215Z",
      "updated_at": "2025-10-10T20:03:26.468662Z"
    }
  ],
  "count": 1
}

2. Get Files by Quarter

Retrieve all scrape files for a specific quarter. Endpoint: GET /files/:slug/quarter/:quarter Quarter Format: YYYYQ# where # is 1-4 (e.g., 2025Q4 for Q4 2025: October-December) Quarter Mappings:
  • Q1 = January - March
  • Q2 = April - June
  • Q3 = July - September
  • Q4 = October - December
Example Request:
curl -X GET "https://api.pricingsaas.com/functions/v1/api/files/stripe/quarter/2025Q4" \
  -H "Authorization: Bearer YOUR_API_KEY"
Example Response:
{
  "files": [
    {
      "slug": "stripe",
      "version": "20251201",
      "page_url": "https://stripe.com/pricing",
      "screenshot_url": "https://res.cloudinary.com/...",
      "markdown_url": "https://pricingsaas-scrapes.s3.amazonaws.com/...",
      "html_url": "https://pricingsaas-scrapes.s3.amazonaws.com/...",
      "ocr_url": "https://qulnbyjrczvoxemtrili.supabase.co/...",
      "scraper": "aws",
      "valid": true,
      "score": 9,
      "created_at": "2025-12-01T10:00:00Z"
    },
    {
      "slug": "stripe",
      "version": "20251101",
      "...": "..."
    }
  ],
  "count": 3,
  "period": {
    "start": "20251001",
    "end": "20251231"
  }
}

3. Get Files by Month

Retrieve all scrape files for a specific month. Endpoint: GET /files/:slug/month/:month Month Formats:
  • YYYYM## (e.g., 2025M12 for December 2025)
  • YYYY## (e.g., 202512 for December 2025)
Example Request:
curl -X GET "https://api.pricingsaas.com/functions/v1/api/files/stripe/month/2025M12" \
  -H "Authorization: Bearer YOUR_API_KEY"
Example Response:
{
  "files": [
    {
      "slug": "stripe",
      "version": "20251215",
      "page_url": "https://stripe.com/pricing",
      "screenshot_url": "https://res.cloudinary.com/...",
      "markdown_url": "https://pricingsaas-scrapes.s3.amazonaws.com/...",
      "html_url": "https://pricingsaas-scrapes.s3.amazonaws.com/...",
      "ocr_url": "https://qulnbyjrczvoxemtrili.supabase.co/...",
      "scraper": "aws",
      "valid": true,
      "score": 10,
      "created_at": "2025-12-15T08:00:00Z"
    }
  ],
  "count": 2,
  "period": {
    "start": "20251201",
    "end": "20251231"
  }
}

4. Get Files by ISO Week

Retrieve all scrape files for a specific ISO 8601 week. Endpoint: GET /files/:slug/week/:week Week Format: YYYYW## where ## is the ISO week number 1-53 (e.g., 2025W42 for week 42 of 2025) ISO Week Notes:
  • Weeks start on Monday and end on Sunday
  • Week 1 is the week containing the first Thursday of the year
  • Some years have 53 weeks
Example Request:
curl -X GET "https://api.pricingsaas.com/functions/v1/api/files/stripe/week/2025W42" \
  -H "Authorization: Bearer YOUR_API_KEY"
Example Response:
{
  "files": [
    {
      "slug": "stripe",
      "version": "20251015",
      "page_url": "https://stripe.com/pricing",
      "screenshot_url": "https://res.cloudinary.com/...",
      "markdown_url": "https://pricingsaas-scrapes.s3.amazonaws.com/...",
      "html_url": "https://pricingsaas-scrapes.s3.amazonaws.com/...",
      "ocr_url": "https://qulnbyjrczvoxemtrili.supabase.co/...",
      "scraper": "firecrawl",
      "valid": true,
      "score": 8,
      "created_at": "2025-10-15T12:00:00Z"
    }
  ],
  "count": 1,
  "period": {
    "start": "20251013",
    "end": "20251019"
  }
}

5. Get Files by Flexible Period (Unified Endpoint)

Retrieve scrape files using any supported period format. This unified endpoint automatically detects the format and returns the appropriate results. Endpoint: GET /files/:slug/period/:period Supported Formats:
  • Version: YYYYMMDD (e.g., 20251010 for October 10, 2025)
  • Quarter: YYYYQ# (e.g., 2025Q4 for Q4 2025)
  • Week: YYYYW## (e.g., 2025W42 for week 42 of 2025)
  • Month: YYYYM## or YYYY## (e.g., 2025M12 or 202512 for December 2025)
Format Detection: The endpoint automatically detects which format you’re using based on the pattern. You don’t need to specify the format separately. Example Requests:
# Using version format
curl -X GET "https://api.pricingsaas.com/functions/v1/api/files/stripe/period/20251010" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Using quarter format
curl -X GET "https://api.pricingsaas.com/functions/v1/api/files/stripe/period/2025Q4" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Using week format
curl -X GET "https://api.pricingsaas.com/functions/v1/api/files/stripe/period/2025W42" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Using month format
curl -X GET "https://api.pricingsaas.com/functions/v1/api/files/stripe/period/2025M12" \
  -H "Authorization: Bearer YOUR_API_KEY"
Example Response:
{
  "files": [
    {
      "slug": "stripe",
      "version": "20251001",
      "page_url": "https://stripe.com/pricing",
      "screenshot_url": "https://res.cloudinary.com/...",
      "markdown_url": "https://pricingsaas-scrapes.s3.amazonaws.com/...",
      "html_url": "https://pricingsaas-scrapes.s3.amazonaws.com/...",
      "ocr_url": "https://qulnbyjrczvoxemtrili.supabase.co/..."
    }
  ],
  "count": 1,
  "period": {
    "start": "20251001",
    "end": "20251231"
  },
  "format": "quarter",
  "version": "20251001"
}
Response Fields (in addition to standard file fields):
FieldTypeDescription
period.startstringStart date of the period in YYYYMMDD format
period.endstringEnd date of the period in YYYYMMDD format
formatstringDetected format: version, quarter, week, or month
versionstring | nullSpecific version returned. For periods, this is the earliest version in the range
Error Handling: The endpoint provides clear, actionable error messages: Invalid Format Example:
{
  "error": "Invalid period format. Expected one of:\n  - Version: YYYYMMDD (e.g., 20251010)\n  - Quarter: YYYYQ# (e.g., 2025Q4)\n  - Week: YYYYW## (e.g., 2025W42)\n  - Month: YYYYM## or YYYY## (e.g., 2025M12 or 202512)",
  "code": "INVALID_PERIOD_FORMAT",
  "details": {
    "provided": "2025-Q4",
    "examples": {
      "version": "20251010",
      "quarter": "2025Q4",
      "week": "2025W42",
      "month": "2025M12 or 202512"
    }
  }
}
Invalid Values Example:
{
  "error": "Invalid quarter: Quarter must be between 1 and 4",
  "code": "INVALID_QUARTER"
}
Benefits:
  • Simplicity: Single endpoint for all period queries
  • Flexibility: No need to remember format-specific endpoints
  • Clear Errors: Automatic format detection with helpful error messages
  • Consistent Response: All formats return the same response structure
When to Use:
  • ✅ Building new integrations or applications
  • ✅ Accepting period inputs from users who may use different formats
  • ✅ Dynamic queries where the period format varies
Backward Compatibility: The format-specific endpoints (/version/{version}, /quarter/{quarter}, /week/{week}, /month/{month}) remain available and unchanged.

Response Schema

ScrapeFile Object

FieldTypeDescription
slugstringCompany slug identifier
versionstringScrape version in YYYYMMDD format
page_urlstringURL of the original pricing page
screenshot_urlstring | nullCloudinary URL to screenshot image
markdown_urlstring | nullS3 URL to markdown version
html_urlstring | nullS3 URL to HTML version
ocr_urlstring | nullSupabase storage URL to OCR JSON
scraperstring | nullScraper used: local-claude, scrapingBee, aws, firecrawl
validboolean | nullWhether the scrape is valid
scoreinteger | nullQuality score (0-10)
banner_freeboolean | nullWhether the page is free of banners
created_atstring | nullISO 8601 timestamp
updated_atstring | nullISO 8601 timestamp

Error Handling

400 Bad Request - Invalid Format

{
  "error": "Invalid version format. Expected YYYYMMDD (e.g., 20251010)",
  "code": "INVALID_VERSION"
}

401 Unauthorized - Missing/Invalid API Key

{
  "error": "Unauthorized - Invalid or missing API key",
  "code": "AUTH_INVALID"
}

429 Too Many Requests - Insufficient Credits

{
  "error": "Insufficient credits",
  "code": "INSUFFICIENT_CREDITS",
  "details": {
    "remaining": 0,
    "limit": 1000,
    "required": 1,
    "reset_at": "2025-02-01T00:00:00Z",
    "seconds_until_reset": 2640,
    "message": "This request requires 1 credit but you have 0 remaining. Credits reset in 44 minutes."
  }
}

500 Internal Server Error

{
  "error": "Failed to fetch files",
  "code": "DB_ERROR"
}

Rate Limiting & Credits

  • Cost: 1 credit per request (all endpoints)
  • Default Limit: 1,000 credits per month
  • Reset: Credits reset on the 1st of each month
  • Headers: Check X-RateLimit-Remaining and X-RateLimit-Reset response headers

Best Practices

  1. Cache responses - Files don’t change after creation, cache aggressively
  2. Use version endpoint for exact dates when available
  3. Use period endpoints (quarter/month/week) for historical analysis
  4. Handle empty results - Not all companies have scrapes for all periods
  5. Check valid and score fields - Filter for high-quality scrapes
  6. Respect rate limits - Monitor credit usage

Code Examples

JavaScript/Node.js

const API_KEY = 'your_api_key';
const BASE_URL = 'https://api.pricingsaas.com/functions/v1/api';

async function getFilesByVersion(slug, version) {
  const response = await fetch(
    `${BASE_URL}/files/${slug}/version/${version}`,
    {
      headers: {
        'Authorization': `Bearer ${API_KEY}`
      }
    }
  );

  if (!response.ok) {
    throw new Error(`API error: ${response.status}`);
  }

  return response.json();
}

// Usage
const files = await getFilesByVersion('stripe', '20251010');
console.log(`Found ${files.count} files`);

Unified Period Endpoint

async function getFilesByPeriod(slug, period) {
  const response = await fetch(
    `https://api.pricingsaas.com/functions/v1/api/files/${slug}/period/${period}`,
    {
      headers: {
        'Authorization': 'Bearer YOUR_API_KEY'
      }
    }
  );

  if (!response.ok) {
    const error = await response.json();
    console.error('API Error:', error.error);
    console.error('Error Code:', error.code);
    if (error.details) {
      console.error('Details:', error.details);
    }
    throw new Error(error.error);
  }

  return response.json();
}

// Usage - works with any format!
try {
  const result = await getFilesByPeriod('stripe', '2025Q4');
  console.log(`Format: ${result.format}`);
  console.log(`Period: ${result.period.start} to ${result.period.end}`);
  console.log(`Files found: ${result.count}`);
  console.log(`Version: ${result.version}`);
} catch (error) {
  console.error('Failed to fetch files:', error.message);
}

Python

import requests

API_KEY = 'your_api_key'
BASE_URL = 'https://api.pricingsaas.com/functions/v1/api'

def get_files_by_quarter(slug, quarter):
    response = requests.get(
        f'{BASE_URL}/files/{slug}/quarter/{quarter}',
        headers={'Authorization': f'Bearer {API_KEY}'}
    )
    response.raise_for_status()
    return response.json()

# Usage
files = get_files_by_quarter('stripe', '2025Q4')
print(f"Found {files['count']} files for Q4 2025")

cURL

# Get files for a specific month
curl -X GET \
  "https://api.pricingsaas.com/functions/v1/api/files/stripe/month/2025M12" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  | jq '.files[] | {version, screenshot_url}'

Use Cases

Track Pricing Changes Over Time

Monitor how a competitor’s pricing evolves quarter over quarter:
# Get Q3 2025 files
curl "https://api.pricingsaas.com/functions/v1/api/files/stripe/quarter/2025Q3" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Get Q4 2025 files
curl "https://api.pricingsaas.com/functions/v1/api/files/stripe/quarter/2025Q4" \
  -H "Authorization: Bearer YOUR_API_KEY"

Download All Pricing Pages for Analysis

Retrieve all markdown files for a specific month for text analysis:
const files = await getFilesByMonth('stripe', '2025M10');
for (const file of files.files) {
  if (file.markdown_url && file.valid && file.score >= 8) {
    const markdown = await fetch(file.markdown_url).then(r => r.text());
    // Analyze pricing data
  }
}


Support

For questions or issues: