Skip to content
Developers

API reference

Read your audits, client reports and connected ad accounts from your own dashboards, spreadsheets and scripts. The API is read-only: it can't start audits, change reports or touch your ad accounts.

Access

The API is included in the Scale plan. Create a key in the app under Settings → API. You can have up to five active keys, and you can revoke any of them there at any time.

A key is shown once, when you create it. We store only a hash of it, so we can't show it to you again: if you lose one, revoke it and create another. Treat keys like passwords and keep them out of browser code and public repositories.

Authentication

Send the key in the Authorization header on every request. All endpoints live under https://paid-ads-audit-production.up.railway.app/api/public/v1.

Authorization: Bearer ar_live_…

Each request sees only the data of the account that created the key. The plan is checked on every request, so if the account moves off Scale its keys answer 402 until it upgrades again.

Rate limits

60 requests per minute per key. Over that, the API answers 429 with a Retry-After header giving the seconds to wait.

Conventions

  • Responses are JSON. A single object comes back as {"data": {…}}.
  • Lists come back as {"data": […], "pagination": {…}}, newest first. Page with limit (1 to 100, default 25) and offset; next_offset is the offset of the next page, or null on the last one.
  • Timestamps are ISO 8601 in UTC. Report periods are dates (YYYY-MM-DD).
  • Platforms are google_ads, ga4 and meta_ads (Meta Ads audits are coming soon). Connected accounts can also be amazon_ads.
  • New fields may be added to responses; existing fields won't be removed or renamed within v1.

List audits

GET /audits. Optional filters: platform and since (an ISO date or datetime; audits created at or after it). score is 0 to 100, or null when the account had no data to score (data_status is then no_data).

curl "https://paid-ads-audit-production.up.railway.app/api/public/v1/audits?limit=2&platform=google_ads&since=2026-09-01" \
  -H "Authorization: Bearer $AUDITROGER_API_KEY"
{
  "data": [
    {
      "id": "6f1c1f0e-2c1b-4d8e-9a57-0b7d0c7a51e2",
      "platform": "google_ads",
      "account": {
        "id": "0a4e3b1c-8f7d-4a51-9a2c-5d9b7e6f1a20",
        "account_id": "123-456-7890",
        "name": "Acme Store"
      },
      "status": "completed",
      "score": 72,
      "data_status": "ok",
      "issue_counts": { "total": 9, "critical": 2, "warning": 5, "info": 2 },
      "created_at": "2026-09-12T08:01:44+00:00",
      "completed_at": "2026-09-12T08:03:10+00:00"
    }
  ],
  "pagination": { "limit": 2, "offset": 0, "has_more": true, "next_offset": 2 }
}

Get an audit

GET /audits/{id}. Everything in the list, plus headline metrics, the issues found and Roger's summary. status is completed once an audit has finished. date_range is the period key the audit ran on: last_7d, last_14d, last_30d, last_60d, last_90d and so on, or custom:YYYY-MM-DD:YYYY-MM-DD.

summary fields depend on the platform. Google Ads and Meta Ads audits carry spend, conversions and costs, as below. GA4 audits carry sessions, users and engagement instead, and leave the spend fields out; a GA4 summary looks like the second example.

curl "https://paid-ads-audit-production.up.railway.app/api/public/v1/audits/6f1c1f0e-2c1b-4d8e-9a57-0b7d0c7a51e2" \
  -H "Authorization: Bearer $AUDITROGER_API_KEY"
{
  "data": {
    "id": "6f1c1f0e-2c1b-4d8e-9a57-0b7d0c7a51e2",
    "platform": "google_ads",
    "account": { "id": "0a4e3b1c-…", "account_id": "123-456-7890", "name": "Acme Store" },
    "status": "completed",
    "score": 72,
    "data_status": "ok",
    "issue_counts": { "total": 9, "critical": 2, "warning": 5, "info": 2 },
    "created_at": "2026-09-12T08:01:44+00:00",
    "completed_at": "2026-09-12T08:03:10+00:00",
    "summary": {
      "currency": "USD",
      "date_range": "last_30d",
      "total_spend": 18250.4,
      "total_conversions": 312,
      "total_clicks": 9120,
      "ctr": 3.1,
      "cpc": 2.0,
      "cpa": 58.49
    },
    "issues": [
      {
        "title": "Non-converting search terms",
        "description": "41 search terms spent money without a conversion.",
        "impact": "Wasted spend",
        "recommendation": "Add them as negative keywords.",
        "category": "keywords",
        "severity": "critical"
      }
    ],
    "insights": {
      "executive_summary": "The account converts well on brand terms…",
      "quick_wins": ["Add 41 negative keywords", "Cap mobile bids on campaign X"]
    }
  }
}
"summary": {
  "currency": "GBP",
  "date_range": "last_30d",
  "property_id": "123456789",
  "total_sessions": 12000,
  "total_users": 9000,
  "total_pageviews": 30000,
  "bounce_rate": 35.0,
  "avg_session_duration": 95.0,
  "engagement_rate": 65.0,
  "total_key_events": 420,
  "total_revenue": 15000.0
}

List client reports

GET /reports. Your client performance reports, with the three figures each report leads with. Supports limit and offset. cost_per_lead isnull when there were no verified leads to divide the spend by, never 0.

curl "https://paid-ads-audit-production.up.railway.app/api/public/v1/reports" \
  -H "Authorization: Bearer $AUDITROGER_API_KEY"
{
  "data": [
    {
      "id": "b3a9…",
      "title": "Monthly Performance Report",
      "client_name": "Acme Dental",
      "platform": "google_ads",
      "channel_label": "Google Ads",
      "ad_account_id": "0a4e3b1c-…",
      "period_start": "2026-08-01",
      "period_end": "2026-08-31",
      "compare_start": "2026-07-01",
      "compare_end": "2026-07-31",
      "currency": "USD",
      "status": "draft",
      "summary": { "verified_leads": 48, "spend": 3120.5, "cost_per_lead": 65.01, "synced": true },
      "last_synced_at": "2026-09-01T09:12:00+00:00",
      "created_at": "2026-09-01T09:10:31+00:00"
    }
  ],
  "pagination": { "limit": 25, "offset": 0, "has_more": false, "next_offset": null }
}

Get a client report

GET /reports/{id}. The report's headline figures, enquiries by channel and campaign performance. Individual leads and their contact details are never returned. Cost figures (cost_per_lead, cpc, cost_per_conversion) are null when there is nothing to divide by, such as a month with spend but no enquiries.

curl "https://paid-ads-audit-production.up.railway.app/api/public/v1/reports/b3a9…" \
  -H "Authorization: Bearer $AUDITROGER_API_KEY"
{
  "data": {
    "id": "b3a9…",
    "title": "Monthly Performance Report",
    "…": "every field from the list above, with summary null",
    "agency_name": "North Agency",
    "headline": {
      "verified_leads": 48, "spend": 3120.5, "cost_per_lead": 65.01,
      "clicks": 1840, "impressions": 52011, "ctr": 3.54, "cpc": 1.7,
      "google_conversions": 61, "revenue": 0, "won": 12, "close_rate": 25.0
    },
    "lead_channels": [
      { "channel": "web_form", "label": "Web form", "count": 31, "share": 65 },
      { "channel": "phone", "label": "Phone", "count": 17, "share": 35 }
    ],
    "campaigns": [
      { "campaign_id": "2011", "name": "Search | Implants", "status": "ENABLED",
        "spend": 2210.0, "impressions": 30110, "clicks": 1204, "ctr": 4.0,
        "cpc": 1.84, "conversions": 40.0, "cost_per_conversion": 55.25 }
    ]
  }
}

List connected accounts

GET /accounts. The ad and analytics accounts connected to AuditRoger, newest first. needs_reconnect is true when the platform has revoked access or the account was disconnected, and it must be reconnected in the app. Access tokens are never returned.

curl "https://paid-ads-audit-production.up.railway.app/api/public/v1/accounts" \
  -H "Authorization: Bearer $AUDITROGER_API_KEY"
{
  "data": [
    {
      "id": "0a4e3b1c-8f7d-4a51-9a2c-5d9b7e6f1a20",
      "platform": "google_ads",
      "account_id": "123-456-7890",
      "name": "Acme Store",
      "needs_reconnect": false,
      "connected_at": "2026-06-02T14:20:05+00:00"
    }
  ]
}

Errors

Errors carry a stable code to branch on and a message for people.

{
  "detail": {
    "code": "plan_lacks_api",
    "message": "API access is part of the Scale plan. Upgrade at https://www.auditroger.com/pricing."
  }
}
  • 400 invalid_parameter: a bad limit, offset, platform or since.
  • 401 missing_api_key: no Authorization header. invalid_api_key: a header that isn't a valid key (unknown, mistyped or not an ar_live_ key). api_key_revoked: a revoked key.
  • 402 plan_lacks_api: the key's account isn't on a plan that includes the API.
  • 404 not_found: no such audit or report in your account, or no such endpoint. Ids belonging to other accounts are reported the same way.
  • 429 rate_limited: more than 60 requests in a minute. Wait for Retry-After seconds.
  • 500 server_error: something failed on our side. Retry after a short wait; if it persists, email us.

Questions

Email hello@auditroger.com.