For developers

API reference

Plug DEXUN AdWhiz's three-platform AI optimization into your own tools, scripts, or backend via REST.

Base URL

All API requests go to this root:

https://www.7275.com/api/v1

HTTPS is required. HTTP requests are rejected (not redirected).

Authentication

All requests need a Bearer token in the Authorization header. Generate one in dashboard → Settings → API Keys. Keys come in live and test flavors and can only access their own environment.

curl https://www.7275.com/api/v1/accounts \
  -H "Authorization: Bearer dxk_live_...your-key..."
  • live key format: starts with dxk_live_, 64 characters
  • test key format: starts with dxk_test_, scoped to the sandbox account
  • Never use keys in front-end code — proxy through your own backend
  • If leaked, immediately revoke and regenerate in dashboard

Use directly from Claude Desktop / Cursor (MCP server)

We ship a zero-dependency Model Context Protocol server so MCP clients like Claude Desktop and Cursor can read your AdWhiz state directly. No code to write — copy a config block, paste your API key, restart the client.

  • Five read-only tools: list ad accounts, surface AI recommendations, get this-month savings, view recent activity, check API quota
  • Mutation tools (apply / pause) deliberately not exposed yet — they wait until the optimizer exits shadow mode and we have calibration evidence to gate them
  • Single Node 18+ script. Zero npm install. Runs on offline / airgapped machines just fine
  • Your API key never leaves your machine. All requests HTTPS-direct to www.7275.com

Add this to Claude Desktop's claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):

{
  "mcpServers": {
    "adwhiz": {
      "command": "node",
      "args": ["/path/to/mcp-server/src/index.mjs"],
      "env": {
        "ADWHIZ_API_KEY": "dxk_live_..."
      }
    }
  }
}

Full install guide, Cursor config and troubleshooting on GitHub: github.com/dexun-inc/adwhiz/mcp-server.

Endpoints

The v1 API exposes 13 core endpoints covering identity, account reads, recommendation generation (applying one is not available yet), audit logs, API key management, quota introspection, and the changelog feed.

MethodPathDescription
GET/meReturns the calling token owner + remaining rate-limit quota (whoami)
GET/accountsList all ad accounts the current user has connected (across all three platforms)
GET/accounts/{id}/campaignsList campaigns, ad groups, keywords, and 7/30-day metrics for one account
POST/recommendations/generateHave the AI generate a fresh batch of optimization recommendations
GET/recommendationsList all pending / applied / dismissed recommendations
POST/recommendations/{id}/applyApply one recommendation — not available yet: returns 501 not_supported and changes nothing
POST/recommendations/{id}/dismissDismiss one recommendation — not available yet: returns 501 not_supported and changes nothing
POST/changes/{id}/rollbackRoll back an applied change — not available yet: returns 501 not_supported and changes nothing
GET/audit-log(Deprecated, sunset 2027-05-23) Full audit log. Use /audit-events instead — backed by the real audit_events table with ?kind filtering
GET/audit-eventsSecurity audit-events stream (sign-in / password / OAuth / subscription), with ?since + ?kind filters
GET/api-keysList the caller's API keys (incl. lastUsedAt + active); hashedKey is never returned
GET/usageRead the current tier, RPM limit, remaining, and reset_at without a probe request
GET/changelogProduct changelog JSON feed (public, no auth) with ETag + ?lang + ?limit (1..50) + ?since=YYYY-MM-DD — canonical incremental-poll shape

Example request

Generate fresh three-platform optimization recommendations:

curl -X POST https://www.7275.com/api/v1/recommendations/generate \
  -H "Authorization: Bearer dxk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "account_id": "ga-548-203-7184",
    "platforms": ["google_ads", "meta_ads", "tiktok_ads"],
    "window": "7d"
  }'

Example response:

{
  "summary": "Pausing 3 high-CPA keywords and reallocating budget...",
  "recommendations": [
    {
      "id": "rec_001",
      "type": "pause_keyword",
      "target": { "accountId": "ga-548-203-7184", "keywordText": "wool socks" },
      "title": "Pause broad-match 'wool socks'",
      "reason": "7-day CPA $45.82 vs target $8",
      "expectedImpact": "Save ~$412/week",
      "confidence": "high"
    }
  ]
}

Incrementally polling /changelog

/api/v1/changelog is a public endpoint (no API key required) with four bandwidth-saving knobs: ETag + If-None-Match, Last-Modified + If-Modified-Since (curl -z), ?since=YYYY-MM-DD for date-filtered fetches, and ?limit=N for size-capped fetches. SDKs and cron scripts can combine these to poll frequently without re-downloading the same JSON.

# 1. First call — store the ETag (or Last-Modified) you get back.
curl -i 'https://www.7275.com/api/v1/changelog?limit=10'

# 2. Subsequent calls — pass the stored ETag.
#    Server returns 304 with empty body if nothing has shipped.
curl -i 'https://www.7275.com/api/v1/changelog?limit=10' \
  -H 'If-None-Match: "abc123..."'

# 3. Or anchor on a date instead of an ETag.
#    Only entries whose `date >= since` come back; pair with ?limit
#    to cap the response size.
curl 'https://www.7275.com/api/v1/changelog?since=2026-01-01&limit=20'

# 4. curl -z for Last-Modified-style conditional GET (no ETag needed):
curl -z 'Mon, 20 May 2026 00:00:00 GMT' \
  'https://www.7275.com/api/v1/changelog'

Rate limits

Tiered by subscription plan to avoid hammering upstream Google / Meta / TikTok quotas:

  • Professional: 120 requests/minute
  • Business: 600 requests/minute
  • Enterprise: custom (typically 3,000 requests/minute)
  • Over the limit returns 429 + retry-after header — exponential backoff recommended

Error codes

All errors return JSON with error.code, error.message, and error.request_id:

HTTP statusMeaning
401Missing or invalid API key
403Account not authorized for this resource (insufficient OAuth scope)
404Resource not found or deleted
422Invalid request parameters
429Rate limit exceeded — wait for retry-after header
500Server error — automatically reported
503Upstream platform API temporarily unavailable (Google / Meta / TikTok)