Authentication
Get your API key at /signup. Include it in every request as a Bearer token.
curl https://saaspricingarchive.com/v1/account \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Your key is shown once at signup and sent to your email. To rotate it, call
POST /v1/account/keys. The old key is immediately invalidated.
Tiers
Paid tiers differ on how far back the history goes and how you can get it out.
Every paid tier reads every company in the archive.
Starter's 12 months is a rolling window counted from today, so it moves forward each day.
It applies to /pricing/history and the CSV export alike.
January 2021 is where the archive as a whole starts. Individual companies start
later and have gaps. Read first_captured and total_snapshots
from /v1/companies/:id for a given company's real depth. That
endpoint is available on every tier, including free.
Change alerts are checked once a day. A day with no change on the companies you follow
sends no email.
Raw HTML snapshots cover pages the crawler fetched itself, which starts in April 2026.
Pricing records recovered from the Internet Archive carry prices and a page hash, but the
page itself was never stored, so a company's snapshot list starts when we began crawling
it rather than when its pricing history starts.
Endpoints
Returns global statistics about the archive.
Auth: Not required Tier: All
Curl example
curl https://saaspricingarchive.com/v1/stats
Sample response
{
"data": {
"total_companies": 500,
"total_records": 10835,
"last_crawl": "2026-09-20T02:28:32.325Z",
"earliest_record": "2021-01-01T00:12:20.000Z"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2026-04-05T10:00:00Z"
}
} Search and list companies in the archive.
Auth: Required Tier: All
Parameters
| Name | Type | Required | Description |
| q | string | No | Search query. Matches company name or domain. |
| category | string | No | Filter by category slug (e.g., "productivity"). |
| page | number | No | Page number. Default: 1. |
| per_page | number | No | Results per page. Default: 50. Max: 100. |
Curl example
curl "https://saaspricingarchive.com/v1/companies?q=notion&per_page=10" \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Sample response
{
"data": [
{
"id": "uuid",
"name": "Notion",
"domain": "notion.so",
"category": "Productivity",
"pricing_url": "https://notion.so/pricing",
"is_top_100": true,
"tier_access_rank": 1
}
],
"meta": {
"request_id": "req_abc",
"timestamp": "..."
},
"pagination": {
"total": 500,
"page": 1,
"per_page": 50
}
} Get a single company by UUID or domain (e.g., notion.so).
Auth: Required Tier: All
Curl example
curl https://saaspricingarchive.com/v1/companies/notion.so \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
List all categories with their company counts.
Auth: Required Tier: All
Curl example
curl https://saaspricingarchive.com/v1/categories \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Sample response
{
"data": [
{
"name": "Productivity",
"slug": "productivity",
"company_count": 47
}
],
"meta": { ... }
} List all companies in a given category.
Auth: Required Tier: All
Parameters
| Name | Type | Required | Description |
| page | number | No | Page number. Default: 1. |
| per_page | number | No | Results per page. Default: 50. Max: 100. |
Curl example
curl "https://saaspricingarchive.com/v1/categories/productivity/companies" \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Latest pricing data for a company. This is the core endpoint. Free keys are limited to the top 100 companies; every paid tier reads every company in the archive.
Auth: Required Tier: Free (top 100), Starter and above (all companies)
Curl example
curl https://saaspricingarchive.com/v1/companies/notion.so/pricing \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Sample response
{
"data": {
"company": {
"name": "Notion",
"domain": "notion.so",
"category": "Productivity",
"total_snapshots": 18,
"pricing_changes_detected": 4,
"first_captured": "2021-03-01",
"last_captured": "2026-03-28"
},
"captured_at": "2026-03-28T09:14:22Z",
"source_type": "live_crawl",
"currency": "USD",
"free_tier_exists": true,
"enterprise_plan_exists": true,
"extraction_confidence": 0.94,
"plans": [
{
"name": "Free",
"price_monthly": 0,
"price_annual_per_month": 0,
"price_unit": null,
"is_highlighted": false,
"features": [
"Unlimited pages & blocks",
"Share with up to 10 guests",
"7-day page history"
]
},
{
"name": "Plus",
"price_monthly": 12,
"price_annual_per_month": 8,
"price_unit": "user",
"is_highlighted": true,
"features": [
"Unlimited guests",
"30-day page history",
"Unlimited file uploads"
]
}
]
},
"meta": {
"request_id": "req_7x2k9m",
"timestamp": "2026-03-28T09:14:23Z"
}
} All historical pricing records for a company, ordered newest first. Starter tier is capped to 1 year back. Pro and Enterprise have full history.
Auth: Required Tier: Starter+
Parameters
| Name | Type | Required | Description |
| from | string (ISO date) | No | Start date filter. E.g., 2024-01-01. |
| to | string (ISO date) | No | End date filter. E.g., 2025-01-01. |
| cursor | string (ISO date) | No | Pagination cursor. Pass next_cursor from previous response. |
| limit | number | No | Number of records. Default: 20. Max: 100. |
Curl example
curl "https://saaspricingarchive.com/v1/companies/notion.so/pricing/history?limit=5" \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Pagination
Responses include a pagination object with limit, next_cursor,
and has_more. Pass next_cursor as the cursor param to fetch the next page.
Only records where the pricing page changed against the record before it. The comparison runs on the stored page rather than on the extracted prices, so a record can appear here after a page edit that left every price alone. Useful for building change-detection pipelines. Same parameters as /history.
Auth: Required Tier: Starter+
Curl example
curl "https://saaspricingarchive.com/v1/companies/notion.so/pricing/changes" \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Lists raw HTML snapshot metadata for a company, newest first. Metadata only. Use the id from a row here with the endpoint below to fetch the HTML itself. Only pages the crawler fetched are stored, so this list starts in April 2026 and a company crawled since then has no rows older than that. Records recovered from the Internet Archive have no stored page and never appear here. Each row's source_type says which kind it is, and a company with nothing stored returns an empty list rather than an error.
Auth: Required Tier: Enterprise
Parameters
| Name | Type | Required | Description |
| cursor | string | No | Pagination cursor. Pass next_cursor from the previous response. |
| limit | number | No | Number of snapshots. Default: 20. Max: 100. |
Curl example
curl "https://saaspricingarchive.com/v1/companies/notion.so/snapshots?limit=5" \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE" Sample response
{
"data": [
{
"id": "8f14e...",
"captured_at": "2026-03-28T09:14:22Z",
"source_type": "live_crawl",
"source_url": "https://notion.so/pricing",
"byte_length": 618422,
"html_hash": "b6d767d..."
}
],
"meta": { ... },
"pagination": {
"limit": 20,
"next_cursor": "MjAyNi0wMy0y...",
"has_more": true
}
} Returns one snapshot's raw HTML exactly as captured. The snapshot id must belong to the company in the path. An id from a different company returns 404, the same as an id that doesn't exist.
Auth: Required Tier: Enterprise
Curl example
curl https://saaspricingarchive.com/v1/companies/notion.so/snapshots/8f14e... \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE" \
-o snapshot.html Response
Content-Type: text/html. The body is the stored HTML, unmodified.
X-Snapshot-Id and X-Snapshot-Captured-At headers carry the
snapshot's id and capture date.
Usage and limits
Each snapshot fetch counts as 10 API calls against your monthly limit, since a single
snapshot averages several hundred KB, well above a typical response. Enterprise is
unlimited, so this has no practical effect today.
Streams the whole archive (or a filtered slice) as a single CSV file — one row per plan per pricing record — instead of paging through /pricing/history one company at a time. Starter tier is capped to 1 year back, same as /pricing/history.
Auth: Required Tier: Starter+
Parameters
| Name | Type | Required | Description |
| since | string (ISO date) | No | Start date filter. E.g., 2024-01-01. |
| until | string (ISO date) | No | End date filter. E.g., 2025-01-01. |
| company | string (domain) | No | Limit to one or more companies. Repeatable, e.g. ?company=notion.so&company=slack.com. |
| source_type | string | No | Either live_crawl or wayback_bootstrap. |
Curl example
curl "https://saaspricingarchive.com/v1/export/pricing.csv?since=2024-01-01" \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE" \
-o pricing-export.csv
Columns
company_domain, company_name, category, captured_at, source_type, extraction_model, plan_name,
price_monthly, price_annual_per_month, currency, pricing_model, unit_price, unit_label,
minimum_monthly, is_highlighted, feature_count, record_id — one row per plan per pricing record.
Usage and limits
Each export counts as 25 API calls against your monthly limit, and is capped at 5 exports per day
(UTC). A full archive export streams as it's generated rather than loading into memory first, so
large exports may take a little while to complete — keep the connection open until it finishes.
Returns current account info with usage statistics.
Auth: Required Tier: All
Curl example
curl https://saaspricingarchive.com/v1/account \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Sample response
{
"data": {
"id": "uuid",
"email": "[email protected]",
"tier": "free",
"api_key_prefix": "spa_abcd1234...",
"usage": {
"monthly_calls": 142,
"monthly_limit": 1000,
"calls_reset_at": "2026-05-01T00:00:00Z",
"remaining": 858
}
},
"meta": { ... }
} Rotate your API key. The old key is immediately invalidated. The new key is shown once in the response.
Auth: Required Tier: All
Curl example
curl -X POST https://saaspricingarchive.com/v1/account/keys \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Sample response
{
"data": {
"api_key": "spa_new_key_here...",
"prefix": "spa_abcd1234...",
"message": "New API key generated."
}
} Upgrade to a paid tier. Returns a Stripe checkout URL. Open it in a browser to complete payment. Your tier updates automatically after payment.
Auth: Required Tier: All
Parameters (JSON body)
| Name | Type | Required | Description |
| tier | string | Yes | Target tier: "starter", "pro", or "enterprise". |
| success_url | string | No | Redirect URL after successful payment. |
| cancel_url | string | No | Redirect URL if the user cancels checkout. |
Curl example
curl -X POST https://saaspricingarchive.com/v1/upgrade \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE" \
-H "Content-Type: application/json" \
-d '{"tier": "starter"}' Sample response
{
"data": {
"checkout_url": "https://checkout.stripe.com/c/pay/cs_...",
"tier": "starter"
}
} Get a link to the Stripe billing portal. Use it to update your card, cancel, or view invoices. Requires a prior upgrade. Returns 400 if you haven't upgraded yet.
Auth: Required Tier: Starter+
Curl example
curl -X POST https://saaspricingarchive.com/v1/account/billing-portal \
-H "Authorization: Bearer spa_YOUR_API_KEY_HERE"
Sample response
{
"data": {
"portal_url": "https://billing.stripe.com/..."
}
} Error codes
All errors return a JSON body with code, message, and status.
| Code | Status | Description |
| missing_api_key | 401 | No Authorization header was included in the request. |
| invalid_api_key | 401 | Key not found or incorrect. |
| invalid_api_key_format | 401 | Key doesn't match the expected spa_ prefix format. |
| account_inactive | 403 | Your account has been deactivated. |
| tier_required | 403 | This endpoint requires a higher tier. Upgrade at /signup. |
| rate_limit_exceeded | 429 | Monthly call limit reached. Resets at the start of your next billing cycle. |
| export_daily_limit_exceeded | 429 | You've hit the 5-exports-per-day limit on /export/pricing.csv. Resets at UTC midnight. |
| validation_error | 400 | One or more request parameters are invalid. Check the message field for details. |
| not_found | 404 | The requested resource was not found. |
| email_already_registered | 409 | Signup attempted with an email that already has an account. |
| invalid_upgrade | 400 | You are already on this tier or higher. |
| no_subscription | 400 | The billing portal requires a prior upgrade. |
| checkout_error | 500 | Stripe checkout session creation failed. Try again or contact support. |
| internal_server_error | 500 | Unexpected server error. If this persists, contact support. |