Skip to Content

Pricing

REST endpoints for Pricing. Base URL https://api.competlab.com; every request needs a CL-API-Key header (see Authentication). Responses wrap in { item } or { items }; errors in { error }.

Get latest pricing intelligence data

GET/v1/projects/{projectId}/pricing

Get the latest pricing intelligence data for all competitors in a project. Returns structured pricing plans, free tier availability, billing options, enterprise pricing, promotions, and competitive gap analysis. Every tracked competitor appears — rows without pricing data carry a pricingDataAvailable reason (no pricing page found, their page didn’t respond, or a temporary problem on our side) instead of being omitted; branch on it before quoting pricing facts. A pricing page is the single most likely thing to be missing, so this is the dimension where the null contract matters most: when your own pricing couldn’t be analyzed, every metric on summary.customer is null and pricingAnalysisAvailable says why. hasFreePlan: null means we did not check, NOT that there is no free plan — a measured false is reported as false and is a real finding. The three gap flags do NOT share one null condition, so read each field’s own description rather than gating all three on the same test: all three are null when your side was unmeasured or no competitor was measured, and hasPriceGap is null on two further conditions the other two don’t carry — fewer than three comparable competitor prices, or your own price not being comparable to the market. Market figures (marketAvgPrice, pricePositionPercent) are null below that three-price threshold, which is ‘not enough market to average’, never zero. Comparable means fixed monthly amounts sharing one currency AND one licensed unit: a per-seat price is never averaged against a flat one, marketPricingUnit says which group was chosen, and every market figure must be quoted with it. A project with no completed run for this dimension yet answers 404 no_data_available — not a missing project and not a failed measurement, just nothing measured here so far; the project itself is fine and get_project still describes it. Distinguish it from project_not_found, which means the id is wrong.

Returns · { item }

Path parameters

NameTypeDescription
projectIdstringProject ID

Request

curl "https://api.competlab.com/v1/projects/507f1f77bcf86cd799439011/pricing" \ -H "CL-API-Key: YOUR_COMPETLAB_API_KEY"

Response 200 OK

{ "item": { "lastUpdatedAt": "2026-03-15T10:00:00.000Z", "summary": { "competitorsChecked": 6, "competitorsSuccessful": 5, "customer": { "domain": "yoursite.com", "popularPlanPrice": 49, "popularPlanCurrency": "USD", "popularPlanUnit": "flat", "popularPlanName": "Professional", "pricingModel": "per-seat", "hasFreePlan": false, "hasFreeTrial": true, "freeTrialDuration": "14 days", "hasEnterprisePricing": true, "tierCount": 3, "pricingAnalysisAvailable": { "available": false, "reason": "pricing_fetch_failed" } }, "marketAvgPrice": 59, "marketCurrency": "USD", "marketPricingUnit": "flat", "pricePositionPercent": 45, "topPriceCompetitor": { "domain": "rival.com", "price": 99, "planName": "Enterprise" }, "lowestPriceCompetitor": { "domain": "rival.com", "price": 99, "planName": "Enterprise" }, "pricingSampleSize": 4, "pricingIsReliable": true, "competitorsWithFreePlan": 2, "competitorsWithFreeTrial": 4, "competitorsWithEnterprise": 3, "activePromotionCount": 1, "hasPriceGap": true, "hasFreeTierGap": false, "hasEnterpriseGap": false, "hasPromotionAlert": true }, "competitors": [ { "domain": "competitor.com", "isOwn": false, "pricingUrl": "https://competitor.com/pricing", "pricingLocationType": "crawled", "content": { "pageTitle": "Acme Pricing - Plans for Every Team", "pageDescription": "Choose from flexible pricing plans starting at $9/month.", "mainHeadline": "Simple, Transparent Pricing", "pricingModel": "per-seat", "plans": [ { "name": "Professional", "price": "$49/month", "summary": "Best for growing teams with advanced features" } ], "popularPlanName": "Professional", "hasFreePlan": true, "freePlanName": "Starter", "hasFreeTrial": true, "freeTrialDuration": "14 days", "billingCycleOffered": "monthly, annual", "annualDiscountAmount": "20%", "moneyBackGuarantee": "30-day money-back guarantee", "hasEnterpriseCustomPricing": true, "enterprisePlanCTA": "Contact Sales", "pricingPageFeatures": "Unlimited projects, Priority support, SSO", "hasActivePromotion": false, "promotionDetails": "" }, "pricingDataAvailable": { "available": false, "reason": "no_page_found" } } ] } }

Errors

StatusCodeMeaning
401api_key_missing · api_key_invalid · api_key_revoked · api_key_expired · insufficient_scopeThe CL-API-Key is missing, malformed, revoked, expired, or lacks the required scope.
404project_not_found · no_data_availableNo project matches the id in the path.

Every error uses the shared { error: { code, message, status } } envelope; code is one of the values listed above.

{ "error": { "code": "api_key_invalid", "message": "Invalid API key", "status": 401 } }

Get pricing run history

GET/v1/projects/{projectId}/pricing/history

Get paginated history of pricing intelligence monitoring runs for a project. Each entry includes run timing and summary statistics with pricing gap analysis. Fields we could not measure are null, with a sibling availability object giving the reason; never read a null as zero, false or absent, and note that a measured 0 / false / empty list is reported as itself and is a real finding.

Returns · { items, pagination }

Path parameters

NameTypeDescription
projectIdstringProject ID

Query parameters

NameTypeRequiredDescription
pagenumberPage number (1-indexed). Default 1. Min 1.
limitnumberNumber of items per page. Default 20. Range 1100.

Request

curl "https://api.competlab.com/v1/projects/507f1f77bcf86cd799439011/pricing/history?page=1&limit=20" \ -H "CL-API-Key: YOUR_COMPETLAB_API_KEY"

Response 200 OK

{ "items": [ { "runId": "507f1f77bcf86cd799439011", "completedAt": "2026-03-15T10:00:00.000Z", "summary": { "competitorsChecked": 6, "competitorsSuccessful": 5, "customer": { "domain": "yoursite.com", "popularPlanPrice": 49, "popularPlanCurrency": "USD", "popularPlanUnit": "flat", "popularPlanName": "Professional", "pricingModel": "per-seat", "hasFreePlan": false, "hasFreeTrial": true, "freeTrialDuration": "14 days", "hasEnterprisePricing": true, "tierCount": 3, "pricingAnalysisAvailable": { "available": false, "reason": "pricing_fetch_failed" } }, "marketAvgPrice": 59, "marketCurrency": "USD", "marketPricingUnit": "flat", "pricePositionPercent": 45, "topPriceCompetitor": { "domain": "rival.com", "price": 99, "planName": "Enterprise" }, "lowestPriceCompetitor": { "domain": "rival.com", "price": 99, "planName": "Enterprise" }, "pricingSampleSize": 4, "pricingIsReliable": true, "competitorsWithFreePlan": 2, "competitorsWithFreeTrial": 4, "competitorsWithEnterprise": 3, "activePromotionCount": 1, "hasPriceGap": true, "hasFreeTierGap": false, "hasEnterpriseGap": false, "hasPromotionAlert": true } } ], "pagination": { "page": 1, "limit": 20, "total": 47, "totalPages": 3, "hasMore": true } }

Paginated — pass page and limit query parameters and follow pagination.hasMore to page through the full set.

Errors

StatusCodeMeaning
401api_key_missing · api_key_invalid · api_key_revoked · api_key_expired · insufficient_scopeThe CL-API-Key is missing, malformed, revoked, expired, or lacks the required scope.

Every error uses the shared { error: { code, message, status } } envelope; code is one of the values listed above.

{ "error": { "code": "api_key_invalid", "message": "Invalid API key", "status": 401 } }

Get pricing data for a specific run

GET/v1/projects/{projectId}/pricing/history/{runId}

Get full pricing intelligence data for a specific historical monitoring run, including per-competitor pricing plans, billing options, free tiers, and enterprise pricing. Competitors the run could not measure appear with a pricingDataAvailable reason instead of being omitted. Fields we could not measure are null; never read a null as zero, false or absent, and note that a measured 0 / false is reported as itself and is a real finding. A run that finished but produced no summary answers 404 run_not_summarized, which is a different fact from run_not_found: the run exists, it just has nothing to report. It used to answer 200 with an all-zero summary invented from the missing one.

Returns · { item }

Path parameters

NameTypeDescription
runIdstringRun ID
projectIdstringProject ID

Request

curl "https://api.competlab.com/v1/projects/507f1f77bcf86cd799439011/pricing/history/507f1f77bcf86cd799439012" \ -H "CL-API-Key: YOUR_COMPETLAB_API_KEY"

Response 200 OK

{ "item": { "runId": "507f1f77bcf86cd799439011", "completedAt": "2026-03-15T10:00:00.000Z", "summary": { "competitorsChecked": 6, "competitorsSuccessful": 5, "customer": { "domain": "yoursite.com", "popularPlanPrice": 49, "popularPlanCurrency": "USD", "popularPlanUnit": "flat", "popularPlanName": "Professional", "pricingModel": "per-seat", "hasFreePlan": false, "hasFreeTrial": true, "freeTrialDuration": "14 days", "hasEnterprisePricing": true, "tierCount": 3, "pricingAnalysisAvailable": { "available": false, "reason": "pricing_fetch_failed" } }, "marketAvgPrice": 59, "marketCurrency": "USD", "marketPricingUnit": "flat", "pricePositionPercent": 45, "topPriceCompetitor": { "domain": "rival.com", "price": 99, "planName": "Enterprise" }, "lowestPriceCompetitor": { "domain": "rival.com", "price": 99, "planName": "Enterprise" }, "pricingSampleSize": 4, "pricingIsReliable": true, "competitorsWithFreePlan": 2, "competitorsWithFreeTrial": 4, "competitorsWithEnterprise": 3, "activePromotionCount": 1, "hasPriceGap": true, "hasFreeTierGap": false, "hasEnterpriseGap": false, "hasPromotionAlert": true }, "competitors": [ { "domain": "competitor.com", "isOwn": false, "pricingUrl": "https://competitor.com/pricing", "pricingLocationType": "crawled", "content": { "pageTitle": "Acme Pricing - Plans for Every Team", "pageDescription": "Choose from flexible pricing plans starting at $9/month.", "mainHeadline": "Simple, Transparent Pricing", "pricingModel": "per-seat", "plans": [ { "name": "Professional", "price": "$49/month", "summary": "Best for growing teams with advanced features" } ], "popularPlanName": "Professional", "hasFreePlan": true, "freePlanName": "Starter", "hasFreeTrial": true, "freeTrialDuration": "14 days", "billingCycleOffered": "monthly, annual", "annualDiscountAmount": "20%", "moneyBackGuarantee": "30-day money-back guarantee", "hasEnterpriseCustomPricing": true, "enterprisePlanCTA": "Contact Sales", "pricingPageFeatures": "Unlimited projects, Priority support, SSO", "hasActivePromotion": false, "promotionDetails": "" }, "pricingDataAvailable": { "available": false, "reason": "no_page_found" } } ] } }

Errors

StatusCodeMeaning
401api_key_missing · api_key_invalid · api_key_revoked · api_key_expired · insufficient_scopeThe CL-API-Key is missing, malformed, revoked, expired, or lacks the required scope.
404run_not_found · run_not_summarizedNo run matches the id in the path.

Every error uses the shared { error: { code, message, status } } envelope; code is one of the values listed above.

{ "error": { "code": "api_key_invalid", "message": "Invalid API key", "status": 401 } }
Last updated on