REST API REFERENCE

UNDERCART API

Query enriched Shopify store data — revenue estimates, technology stacks, ad presence, and more — over HTTPS with a single API-key header. Every response is JSON.

Pointing an AI agent at this? Skip the HTTP — add Undercart as an MCP connector and ask in natural language.MCP docs →

Overview

The Undercart REST API is served under the base URL below. All endpoints require authentication and return a consistent JSON envelope. Endpoints that expose store data count against your plan's monthly lookup quota.

Base URL:  https://undercart.co/api/v1

Authentication

Authenticate every request with an API key in the X-API-Key header. Create and manage keys from the dashboard (Settings → API keys); the full key is shown once at creation and stored only as a hash. Keys look like sk_live_…. A logged-in browser session cookie also authenticates requests to the same endpoints.

curl https://undercart.co/api/v1/me \
  -H "X-API-Key: sk_live_9f2a…"

Response format

Every endpoint returns the same envelope. On success, data holds the payload; on failure, error holds a human-readable message. List endpoints add a meta object with pagination details.

{
  "success": true,
  "data": { /* endpoint payload */ },
  "meta": {                 // list endpoints only
    "limit": 50,
    "total": 681240,
    "totalIsApproximate": true,   // true for the unfiltered catalog count
    "nextCursor": "eyJ2Ijo…",     // pass back as ?cursor= for the next page
    "prevCursor": null
  }
}

List endpoints use keyset (cursor) pagination: read meta.nextCursor and pass it back as ?cursor= with dir=next (or prev). A null cursor means there are no more pages in that direction.

Errors & rate limits

Errors use standard HTTP status codes with success: false and an error message.

ParameterTypeDescription
400Bad RequestInvalid or missing query/body parameters.
401UnauthorizedMissing or invalid API key / session.
403ForbiddenAuthenticated but lacking permission (admin-only route).
404Not FoundNo matching store.
429Too Many RequestsMonthly store-lookup quota reached; the message includes the plan cap and reset date.
500Server ErrorUnexpected error.

Store-data endpoints meter one store access per requestagainst your plan's monthly cap. When you exceed it the API returns 429 until the quota resets at the start of the next month.

List / search stores

GET/api/v1/stores

Search and filter the store catalog. Returns a page of store summaries. By default the full catalog is in scope (including dormant, not-yet-enriched discovery rows); pass enriched=true to restrict to fully enriched stores.

ParameterTypeDescription
qstringCase-insensitive match on domain or store name.
countrystringISO country filter.
categorystringStore category filter.
revenueMin / revenueMaxnumberEstimated annual revenue bounds (USD).
shopifyPlanstringFilter by detected Shopify plan.
techStackstringComma-separated app/tech names; matches stores using all of them.
enrichedbooleantrue/false — restrict to enriched stores only.
trackingEmailbooleantrue/false — only stores whose email marketing is being tracked (newsletter subscribed and at least one email captured).
sortenumestimatedAnnualRevenue | productCount | lastCrawledAt | firstSeenAt | name | domain (default: estimatedAnnualRevenue).
orderenumasc | desc (default: desc).
cursor / dirstringKeyset pagination cursor and direction (next | prev).
limitnumberPage size, 1–100 (default: 50).
curl https://undercart.co/api/v1/stores \
  -H "X-API-Key: sk_live_9f2a…" \
  -G -d "revenueMin=1000000" \
     -d "techStack=klaviyo" \
     -d "sort=estimatedAnnualRevenue" \
     -d "limit=2"

# → 200 OK
{
  "success": true,
  "data": [
    {
      "id": "clw…",
      "domain": "maplestone.co",
      "name": "Maple & Stone",
      "country": "US",
      "category": "Home & Living",
      "estimatedAnnualRevenue": 11400000,
      "estimatedMonthlyRevenue": 950000,
      "revenueConfidence": 0.72,
      "revenueTier": "high",
      "productCount": 1284,
      "lastCrawledAt": "2026-06-29T02:00:00.000Z",
      "techCount": 37,
      "topTech": ["Shopify Plus", "Klaviyo", "Gorgias", "Recharge"]
    }
  ],
  "meta": { "limit": 2, "total": 4120, "nextCursor": "eyJ2Ijo…" }
}

Get store by domain

GET/api/v1/stores/by-domain?domain=<domain>

Returns the full enriched profile for a single known store, keyed by domain — revenue, plan, catalog stats, active tech stack (grouped), ad presence, and social profiles. Responds 404 if the domain is not in the catalog.

curl "https://undercart.co/api/v1/stores/by-domain?domain=maplestone.co" \
  -H "X-API-Key: sk_live_9f2a…"

# → 200 OK
{
  "success": true,
  "data": {
    "id": "clw…",
    "domain": "maplestone.co",
    "name": "Maple & Stone",
    "category": "Home & Living",
    "country": "US",
    "foundedYear": 2019,
    "shopifyPlan": "Shopify Plus",
    "estimatedAnnualRevenue": 11400000,
    "revenueConfidence": 0.72,
    "productCount": 1284,
    "avgProductPrice": 68.5,
    "currency": "USD",
    "techStack": [
      { "techName": "Klaviyo", "techCategory": "Email & SMS" }
    ],
    "adPresence": [
      { "platform": "meta", "isActive": true, "lastCheckedAt": "2026-06-29T…" }
    ],
    "socialProfiles": [
      { "platform": "instagram", "profileUrl": "https://…", "followers": 84000 }
    ]
  }
}

Look up or enqueue a crawl

POST/api/v1/stores/lookup

Look up a store by domain. If it is already known, the full profile is returned immediately (200). If it is not yet in the catalog, a discovery/enrichment job is enqueued and the endpoint responds 202 Accepted with a job id.

curl -X POST https://undercart.co/api/v1/stores/lookup \
  -H "X-API-Key: sk_live_9f2a…" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "newstore.com" }'

# → 202 Accepted   (store was not yet known)
{
  "success": true,
  "data": { "jobId": "123", "domain": "newstore.com", "status": "queued" }
}

Get store by ID

GET/api/v1/stores/{storeId}

Returns the complete store record by its Undercart ID, including the full tech stack, recent revenue history, ad presence, social profiles, and any traffic data.

Get store tech stack

GET/api/v1/stores/{storeId}/tech

Returns the store's detected technologies grouped by category (email/SMS, support, subscriptions, analytics, etc.), each with version, first/last-seen timestamps, and whether it is currently active.

Get revenue history

GET/api/v1/stores/{storeId}/revenue

Returns the store's historical revenue estimates, most recent first.

ParameterTypeDescription
limitnumberNumber of estimates to return, 1–100 (default: 30).
methodenumFilter to one signal: composite | traffic | tech_stack | product | ad_spend | social.

Bulk export

GET/api/v1/stores/export

Streams a filtered result set for offline use. Accepts the same filters as the list endpoint (search, country, category, revenueMin/Max, shopifyPlan, enriched, trackingEmail, sort, order). Choose the output with format=csv (default) or format=json, and pick columns with a comma-separated columns= list. Exports are capped at 50,000 rows.

curl "https://undercart.co/api/v1/stores/export?format=json&revenueMin=1000000" \
  -H "X-API-Key: sk_live_9f2a…" -o stores.json

Identity

GET/api/v1/me

Returns the authenticated caller's id and role. Useful for verifying a key works.

{ "success": true, "data": { "id": "usr_…", "role": "user" } }
GET AN API KEY
Start free with 100 lookups/month. Provision a key from the dashboard.
Start free →