Installs and removals

GET/v1/events

Streams app installs and removals across Shopify stores, oldest first, at 1 credit per store in each page.

View as MarkdownOpenAPI specAll docs for LLMs

  • Auth: API key (Authentication)
  • Scope: events:read
  • Cost: 1 credit per distinct store in the page.

Use it to watch for changes: who started or stopped running an app since your last read. Save pagination.nextCursor and resume from it next time.

The change stream, oldest first, so you can read it forward: page with the cursor, and resume a later read with since set to the last detectedAt you have (cursors last 24 hours). An event is reported by the scan that saw the change: the change happened between previousScanAt and detectedAt. A store's first scan reports no installs (we cannot say when they happened), and removals are only inferred from a scan that read the whole live page. Each event carries the store's current country, region and industry. With country, region or industry, a page can hold fewer than limit events while hasMore is true. 1 credit per row. Scope events:read.

Request

curl "https://api.installgraph.com/v1/events?app=klaviyo&type=removed&since=2026-10-01T00%3A00%3A00Z&limit=1" \
  -H "Authorization: Bearer $INSTALLGRAPH_API_KEY"

Query parameters

Name Type Required Description
app string No Example: klaviyo.
type string No One of installed, removed.
since string (date-time) No Events detected at or after this time (ISO 8601).
until string (date-time) No Events detected before this time (ISO 8601).
country string No ISO 3166-1 alpha-2 country the store sells from (Shopify's Shopify.country). Example: US.
region Region No A world region, i.e. its countries. Combined with country, both must hold. One of north-america, latin-america, europe, middle-east-africa, asia-pacific.
industry string No A top-level industry (Apparel, which also matches stores placed at that level only) or a subcategory (Apparel/Footwear). GET /v1/industries lists them. Example: Apparel/Footwear.
aov string No One or more typical order-value bands in USD, comma-separated (100-200,200-500). GET /v1/industries lists them. Example: 100-200.
limit integer No 1–500. Default 100.
cursor string No pagination.nextCursor from the previous page, unchanged, within 24 hours, with the same key's account and the same filters.

Response

200. The example's stores are fictional.

{
  "data": [
    {
      "id": "evt_6720a4c3f1b2",
      "type": "removed",
      "domain": "example.com",
      "app": {
        "slug": "klaviyo",
        "name": "Klaviyo",
        "category": "email-sms"
      },
      "detectedAt": "2026-10-12T04:20:31.000Z",
      "previousScanAt": "2026-10-05T03:58:10.000Z",
      "lastSeenAt": "2026-10-05T03:58:10.000Z",
      "country": "US",
      "region": "north-america",
      "industry": {
        "category": "Apparel",
        "subcategory": "Footwear",
        "path": "/Apparel/Footwear",
        "confidence": "high"
      },
      "pricePoint": {
        "aovBand": "100-200",
        "label": "$100–200",
        "confidence": "medium",
        "medianProductPriceUsd": 128,
        "productPriceRangeUsd": [
          95,
          165
        ],
        "productPricesSeen": 24
      }
    }
  ],
  "pagination": {
    "nextCursor": "eyJrIjoiZXZlbnRzIiwiaWQiOiJldnRfNjcyMGE0YzNmMWIyIn0",
    "hasMore": true
  },
  "meta": {
    "requestId": "6f1c2a9e-4b7d-4e2a-9c51-0d3b8e7f2a14",
    "creditsUsed": 1,
    "creditsCharged": 1,
    "creditsRemaining": 46,
    "freeRepulls": 0
  }
}

Fields

Field Type Description
data[].id string
data[].type string One of installed, removed.
data[].domain string
data[].app AppSummary
data[].app.slug string Example: klaviyo.
data[].app.name string Example: Klaviyo.
data[].app.category Category One of 28 values (see Data model).
data[].app.kind string shopify-app: an app installed from Shopify. web: a website technology installed outside Shopify, by pasting its tag into the theme or through a tag manager (Google Tag Manager, Meta Pixel, Hotjar). A vendor with both has one entry of each (meta-pixel and meta-facebook-instagram-app). One of shopify-app, web.
data[].detectedAt string (date-time) The scan that saw the change.
data[].previousScanAt string (date-time) | null The healthy scan before it.
data[].lastSeenAt string (date-time) | null For a removal, the last scan that still saw the app.
data[].country string | null The store's current country.
data[].region Region | null One of north-america, latin-america, europe, middle-east-africa, asia-pacific.
data[].industry Industry | null Our reading of what the store sells, from its homepage, in the Store Leads taxonomy.
data[].industry.category string Example: Apparel.
data[].industry.subcategory string | null Null when the store fits a category but none of its subcategories (a general bookshop). Example: Footwear.
data[].industry.path string /Books & Literature alone when there is no subcategory. Example: /Apparel/Footwear.
data[].industry.confidence string | null One of high, medium, low.
data[].pricePoint PricePoint | null The store's typical order value, in USD bands so it reads the same in every country. Our own reading of the homepage: the product prices shown there (converted from the store's currency), and what is sold.
data[].pricePoint.aovBand string One of under-25, 25-50, 50-100, 100-200, 200-500, 500-1000, 1000-plus.
data[].pricePoint.label string Example: $100–200.
data[].pricePoint.confidence string | null One of high, medium, low.
data[].pricePoint.medianProductPriceUsd integer | null Median product price on the homepage, in USD.
data[].pricePoint.productPriceRangeUsd integer[] | null Interquartile range of homepage product prices, in USD.
data[].pricePoint.productPricesSeen integer

Every keyed response also carries meta (requestId, creditsUsed, creditsRemaining, freeRepulls) and the X-Credits-* and X-RateLimit-* headers. See Credits and Rate limits.

Lists page with limit and cursor. See Pagination.

Errors

Status Code Meaning What to do
400 invalid_request A parameter or body field is missing or malformed. Fix the request; message names the field. Do not retry unchanged.
400 invalid_cursor The cursor is not one this endpoint issued (edited, truncated, or from another list). Pass pagination.nextCursor back unchanged, or start again without a cursor.
401 missing_api_key No key was sent. Send Authorization: Bearer sfs_… or X-API-Key: sfs_….
401 invalid_api_key The key is not one we issued. Check for truncation or whitespace; keys are sfs_ plus 32 letters and digits.
401 api_key_revoked The key was revoked. Make a new key at installgraph.com/account.
402 insufficient_credits The balance cannot cover one row or lookup. Nothing was charged. Buy credits: error.offers.pack.buyUrl, or POST /v1/billing/purchase if agent purchases are on.
402 usage_cap_reached The account unlocked 40,000 distinct stores in the last 30 days. Wait for the window to roll, or Talk to us: error.offers.talkToUs.url.
403 insufficient_scope The key lacks this endpoint's scope. Use a key with the scope the endpoint lists (GET /v1/usage shows yours).
403 api_key_suspended The key is suspended. Talk to us, quoting requestId.
429 rate_limited Too many requests this minute. Wait Retry-After seconds, then retry.

All codes: Errors.