The Cultivator Dashboard

Store API v1

Programmable, scoped, read-only API so your AI agents (Claude, GPT, whatever) can plug straight into your store's data. One store, one key, your data — your rules.

Bearer authCORS openJSON only120 req/min/key

Quickstart

  1. Ask your account manager for an API key, or (if you're an admin) mint one at /dashboard/stores/{id}/api-keys.
  2. Copy the key the moment it appears — it's shown once. Store it in an env var: CULTIVATOR_KEY=cvx_live_…
  3. Hit any endpoint with the key in the Authorization header.
# Base URL
https://dashboard.thecultivator.co/api/v1/stores/{slug}

# Every request
curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  https://dashboard.thecultivator.co/api/v1/stores/your-slug/summary

Authentication

Pass your key as a standard bearer token on every request. Keys are scoped to a single store — they cannot read any other client's data, ever.

GET /api/v1/stores/your-slug/kpis
Authorization: Bearer cvx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Keys are stored as SHA-256 hashes. We can't recover a lost key — revoke it and mint a new one. Every successful request updates lastUsedAt so you can spot stale keys.

Scopes

Each key is issued with one or more of these scopes. Use the smallest set your agent actually needs.

ScopeGrants access to
allEvery endpoint (use for internal agents)
kpis:read/summary, /kpis
orders:read/orders, /products
campaigns:read/campaigns/meta, /campaigns/google, /email/klaviyo
customers:read/customers

Endpoints

GET/summaryscope: all

One-shot store overview: last 30d revenue, ROAS, AOV, customer count, top attributed sources.

Example request

curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  https://dashboard.thecultivator.co/api/v1/stores/your-slug/summary

Example response

{
  "success": true,
  "data": {
    "store": {
      "id": "cl123...",
      "slug": "your-slug",
      "name": "Your Store",
      "domain": "yourstore.com",
      "timezone": "Australia/Brisbane"
    },
    "integrations": {
      "shopify": { "connected": true, "lastSyncAt": "2026-04-18T03:00:00Z" },
      "meta":    { "connected": true, "lastSyncAt": "2026-04-18T03:00:00Z" },
      "google":  { "connected": true, "lastSyncAt": "2026-04-18T03:00:00Z" }
    },
    "last30d": {
      "revenue": 84210.55,
      "orders": 412,
      "aov": 204.39,
      "adSpend": 19870.22,
      "mer": 4.23,
      "meta":   { "spend": 12400.50, "purchases": 198, "roas": 3.97 },
      "google": { "spend": 7469.72,  "conversions": 142, "roas": 5.12 }
    },
    "customers": { "totalUnique": 3421, "newCustomersLast30d": 287 },
    "topAttributedSources": [
      { "source": "meta_ads",   "orders": 198, "revenue": 41210 },
      { "source": "google_ads", "orders": 142, "revenue": 29840 },
      { "source": "klaviyo",    "orders":  48, "revenue":  8120 }
    ]
  },
  "meta": { "storeSlug": "your-slug", "requestId": "abc-123", "period": "last30d" }
}
GET/kpisscope: kpis:read

Aggregated KPIs (revenue, orders, blended ROAS, MER, CPA, Meta/Google splits) with target comparisons.

Query parameters

  • periodtoday | 7d | 30d (default) | 90d?period=7d

Example request

curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  "https://dashboard.thecultivator.co/api/v1/stores/your-slug/kpis?period=7d"

Example response

{
  "success": true,
  "data": {
    "shopify": { "revenue": 18200.10, "orders": 89, "aov": 204.49 },
    "meta":    { "spend": 2800.40, "purchases": 42, "roas": 4.12, "cpc": 1.32, "cpm": 18.4 },
    "google":  { "spend": 1720.22, "conversions": 31, "roas": 5.42, "cpc": 0.98 },
    "blended": { "totalAdSpend": 4520.62, "totalTrackedRevenue": 18200.10, "mer": 4.02 },
    "comparisons": [
      { "metric": "MER",         "actual": 4.02, "target": 4.0,  "variance":  0.5, "health": "green" },
      { "metric": "Meta ROAS",   "actual": 4.12, "target": 4.5,  "variance": -8.4, "health": "amber" }
    ]
  },
  "meta": { "storeSlug": "your-slug", "requestId": "abc-123", "period": "last7d", "days": 7 }
}
GET/ordersscope: orders:read

Paginated orders with attribution (UTM, first/last touch, click IDs). Default window: last 30 days.

Query parameters

  • fromISO date (YYYY-MM-DD)?from=2026-04-01
  • toISO date (YYYY-MM-DD)?to=2026-04-18
  • limit1–500 (default 100)?limit=50
  • cursorOrder ID for pagination (pass meta.nextCursor)

Example request

curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  "https://dashboard.thecultivator.co/api/v1/stores/your-slug/orders?limit=2"

Example response

{
  "success": true,
  "data": [
    {
      "id": "clx...",
      "shopifyOrderId": "6254128...",
      "orderNumber": "#1042",
      "totalPrice": 219.95,
      "currency": "AUD",
      "createdAt": "2026-04-18T02:14:00Z",
      "customerEmail": "[email protected]",
      "customerName": "Jane D.",
      "isNewCustomer": true,
      "attributedSource": "meta_ads",
      "attributionConfidence": "high",
      "utmSource": "facebook",
      "utmMedium": "paid",
      "utmCampaign": "spring-sale-v2"
    }
  ],
  "meta": {
    "storeSlug": "your-slug",
    "period": { "from": "2026-03-19", "to": "2026-04-18" },
    "count": 2,
    "limit": 2,
    "nextCursor": "clx-next-id"
  }
}
GET/productsscope: orders:read

Top products by revenue (derived from synced Shopify data). Returns empty list if no product snapshot yet.

Query parameters

  • limit1–200 (default 50)

Example request

curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  https://dashboard.thecultivator.co/api/v1/stores/your-slug/products

Example response

{
  "success": true,
  "data": [
    { "title": "Hero Serum 30ml", "revenue": 18420, "orders": 210, "aov": 87.71 },
    { "title": "Daily Cleanser",  "revenue": 11230, "orders": 140, "aov": 80.21 }
  ],
  "meta": { "storeSlug": "your-slug", "count": 2, "source": "snapshot" }
}
GET/customersscope: customers:read

Unique customers with lifetime spend + order count. Max 500 per call, ordered by totalSpent desc.

Query parameters

  • limit1–500 (default 100)

Example request

curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  "https://dashboard.thecultivator.co/api/v1/stores/your-slug/customers?limit=3"

Example response

{
  "success": true,
  "data": [
    {
      "email": "[email protected]",
      "name": "VIP Customer",
      "orderCount": 14,
      "totalSpent": 2810.40,
      "firstOrderAt": "2025-08-12T01:00:00Z",
      "lastOrderAt":  "2026-04-12T12:30:00Z"
    }
  ],
  "meta": { "storeSlug": "your-slug", "count": 3, "limit": 3 }
}
GET/campaigns/metascope: campaigns:read

Meta ads performance: totals + per-day breakdown.

Query parameters

  • fromISO date
  • toISO date

Example request

curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  "https://dashboard.thecultivator.co/api/v1/stores/your-slug/campaigns/meta?from=2026-04-01&to=2026-04-18"

Example response

{
  "success": true,
  "data": {
    "totals": {
      "spend": 9840.22, "impressions": 1240300, "clicks": 12400,
      "purchases": 142, "leads": 88,
      "cpc": 0.79, "cpm": 7.93, "cpa": 69.30, "roas": 4.12
    },
    "daily": [
      { "date": "2026-04-01", "spend": 512.30, "purchases": 8, "roas": 4.40 }
    ]
  },
  "meta": { "storeSlug": "your-slug", "period": { "from": "2026-04-01", "to": "2026-04-18" }, "days": 18 }
}
GET/campaigns/googlescope: campaigns:read

Google ads performance: totals + per-day breakdown.

Query parameters

  • fromISO date
  • toISO date

Example request

curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  "https://dashboard.thecultivator.co/api/v1/stores/your-slug/campaigns/google?from=2026-04-01&to=2026-04-18"

Example response

{
  "success": true,
  "data": {
    "totals": {
      "spend": 5420.00, "impressions": 820000, "clicks": 8800,
      "conversions": 98, "conversionValue": 28420,
      "cpc": 0.62, "cpa": 55.30, "roas": 5.24
    },
    "daily": [
      { "date": "2026-04-01", "spend": 320.10, "conversions": 6, "roas": 5.80 }
    ]
  },
  "meta": { "storeSlug": "your-slug", "period": { "from": "2026-04-01", "to": "2026-04-18" }, "days": 18 }
}
GET/email/klaviyoscope: campaigns:read

Klaviyo email performance: revenue, sends, opens, clicks, open/click rates.

Query parameters

  • fromISO date
  • toISO date

Example request

curl -H "Authorization: Bearer $CULTIVATOR_KEY" \
  "https://dashboard.thecultivator.co/api/v1/stores/your-slug/email/klaviyo?from=2026-04-01&to=2026-04-18"

Example response

{
  "success": true,
  "data": {
    "totals": {
      "emailRevenue": 8210.40, "emailsSent": 42300,
      "opens": 11800, "clicks": 2120, "orders": 98,
      "openRate": 27.90, "clickRate": 5.01, "revenuePerEmail": 0.19
    },
    "daily": [
      { "date": "2026-04-01", "revenue": 420.10, "sent": 2100, "opens": 580, "clicks": 110, "orders": 6 }
    ]
  },
  "meta": { "storeSlug": "your-slug", "period": { "from": "2026-04-01", "to": "2026-04-18" }, "days": 18 }
}

Response shape

Every successful response has this envelope. Parse data — skip meta unless you need debugging info.

{
  "success": true,
  "data": { /* endpoint-specific payload */ },
  "meta": {
    "storeSlug": "your-slug",
    "requestId": "uuid-for-this-request",
    "period": "last30d" // varies by endpoint
  }
}

Response headers you can use:

  • X-Store-Slug — echoed back so you can confirm you hit the right store
  • X-RateLimit-Remaining — requests left in the current 60s window
  • X-Request-Id — use when reporting issues

Error codes

StatusMeaning
401Invalid, revoked, or missing bearer key
403Key lacks the required scope for this endpoint
404Store slug not found, or key belongs to a different store
429Rate limit exceeded (120 req/min per key, 300 req/min per IP)
500Server error — retry with exponential backoff

Error body is the same envelope with success: false and a human-readable error field.

Rate limits

  • 120 requests/minute per key (sliding window)
  • 300 requests/minute per IP (belt-and-braces)
  • Burst and back off with exponential jitter on 429. Check the X-RateLimit-Remaining header.
  • Need higher limits? Talk to your account manager — we'll raise them for known workloads.

CORS

All v1 endpoints respond with Access-Control-Allow-Origin: * so browser-side agents work out of the box. Since access is strictly key-gated, open CORS is safe. This may tighten if we ship write endpoints in the future.