API Keys Guide

Use team API keys to call Last Chance from scripts, automation, or other machine clients without a browser session.

Overview

API keys authenticate as your team, not as an individual user. Send the key on every request:

Authorization: Bearer YOUR_API_KEY

Keys are created in Account Settings → API Keys. The full secret is shown once at creation — store it securely (password manager, secrets vault, or environment variable). You can revoke a key at any time; revoked keys stop working immediately and remain visible for audit.

Who can manage keys: Team admins only.

Rate limits (API keys only): Dashboard/session traffic is unaffected.

BucketLimitApplies to
Auth attempts60 / minute per IPAny lc_live_… Bearer (valid or invalid)
Global30 requests / minute per keyDual-auth API routes (including tool-backed MCP calls); not the /mcp entry handshake itself
MCP entry60 / minute per keyRemote MCP endpoint (/mcp) only — separate from the global bucket
Analytics summary20 / minute per key/api/dashboard/stats, /api/analytics/unsubscribe-rates
Analytics attribution6 / minute per key/api/analytics/revenue-impact

AI endpoints keep their existing tighter limits. Exceeding a limit returns 429.

MCP throughput: Each MCP request counts against MCP entry and against the per-IP auth-attempt bucket at /mcp. Each tools/call then counts against global (plus analytics caps when those tools run) — in-process tool handlers do not re-charge auth-attempt. The practical ceiling is about 30 tool calls per minute per key (the global bucket), even though MCP entry allows 60.


Create a key

  1. Open Account Settings → API Keys
  2. Click Create key
  3. Choose a name (for example CI scripts or Billing sync)
  4. Pick scopes (defaults are read-only: pages:read and team:read)
  5. Choose expiry (defaults to 90 days; you can pick 30 / 90 / 365 days or never)
  6. Copy the secret immediately — it will not be shown again

Limits:

  • Up to 20 active keys per team
  • Create rate limit: 10 keys per hour per team

Connect with MCP (Claude / Cursor)

Use a team API key with Last Chance’s hosted MCP server so Claude or Cursor can list pages, check integrations, and pull analytics—without cloning any repo.

Primary app host only. Use https://www.yourlastchance.app/mcp. Branded unsubscribe hosts (for example your-brand.yourlastchance.app) do not serve MCP — those hosts only expose public unsubscribe paths.

  1. Create a key with at least one of pages:read, team:read, analytics:summary:read, or analytics:attribution:read (add the scopes for the tools you need).
  2. In Account Settings → API Keys, click Copy MCP config (template uses YOUR_API_KEY), or Copy MCP config in the “Save your API key” dialog after creating a key (fills in the lc_live_… secret).
  3. Paste into Cursor (~/.cursor/mcp.json or project .cursor/mcp.json) or Claude Desktop / Claude Code remote MCP settings. Replace YOUR_API_KEY if you copied the template.

Example config

{
  "mcpServers": {
    "lastchance": {
      "url": "https://www.yourlastchance.app/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Prefer an env var in Cursor when you manage secrets outside the file:

{
  "mcpServers": {
    "lastchance": {
      "url": "https://www.yourlastchance.app/mcp",
      "headers": {
        "Authorization": "Bearer ${env:LAST_CHANCE_API_KEY}"
      }
    }
  }
}

Set LAST_CHANCE_API_KEY in your environment to your lc_live_… secret (or paste the Bearer value directly — prefer the env var so the key is not committed).

Available tools (read-only)

  • get_team_context — team tier, limits, Klaviyo/Shopify flags
  • list_email_integrations / list_klaviyo_lists — integrations and lists
  • list_unsubscribe_pages / get_unsubscribe_page / list_page_versions — page discovery
  • get_unsubscribe_page_urls — preview / draft / share URLs (prefer shareUrl for stakeholders)
  • get_dashboard_stats / get_unsubscribe_rates — summary analytics (analytics:summary:read)
  • get_revenue_impact — attribution analytics (analytics:attribution:read; requires startDate + endDate)

Revoke the key in Account Settings → API Keys to cut off access immediately.


Authentication

Every machine request needs your API key in the Authorization header:

-H "Authorization: Bearer YOUR_API_KEY"
-H "Content-Type: application/json"

Replace YOUR_API_KEY with the full secret from Account Settings → API Keys. All examples below use https://www.yourlastchance.app.

Cookie/session auth still works for the dashboard. Non-Last Chance Bearer headers are ignored so browser sessions keep working.


Scopes

ScopeAllows
pages:readList and get unsubscribe pages and versions
pages:writeCreate pages, save drafts, archive/primary, attach/detach email lists, toggle list webhooks, delete pages (with confirm)
pages:publishPublish a draft version
pages:aiAI page chat and generate-from-website
team:readTeam context/limits, email integrations status, Klaviyo list discovery
analytics:summary:readDashboard stats and unsubscribe rate trends (aggregated counts only — no email PII)
analytics:attribution:readRevenue impact / churn recovery attribution for a date range

Grant the minimum scopes your client needs. A read-only integration usually only needs pages:read and team:read. Add analytics:summary:read / analytics:attribution:read when the client should pull metrics.


Example requests

Get team context

Requires team:read.

curl -sS "https://www.yourlastchance.app/api/team" \
  -H "Authorization: Bearer YOUR_API_KEY"

Returns team id/name, tier, Klaviyo/Shopify connection flags, subscription/access booleans, and page/AI/analytics limits. API-key responses omit billing provider IDs, shop domain, and other dashboard-only fields.

List email integrations

Requires team:read.

curl -sS "https://www.yourlastchance.app/api/email-integrations" \
  -H "Authorization: Bearer YOUR_API_KEY"

List Klaviyo lists

Requires team:read. Uses the team bound to the API key (do not pass another team’s teamId).

curl -sS "https://www.yourlastchance.app/api/email-integrations/klaviyo/lists" \
  -H "Authorization: Bearer YOUR_API_KEY"

List unsubscribe pages

Requires pages:read.

curl -sS "https://www.yourlastchance.app/api/unsubscribe-pages" \
  -H "Authorization: Bearer YOUR_API_KEY"

Get one page

Requires pages:read.

curl -sS "https://www.yourlastchance.app/api/unsubscribe-pages/PAGE_ID" \
  -H "Authorization: Bearer YOUR_API_KEY"

Get preview, draft, and share URLs

Requires pages:read. Returns absolute URLs for the page (uses your branded public host when configured). Optional versionNumber and experienceKey query params.

FieldUse for
shareUrlSending a link to stakeholders (Slack, email, etc.). Public — no login and no email required. Prefer this for external review.
previewUrlYou testing the published page (same flow as dashboard Preview).
draftUrlYou testing a newer unpublished version. null when the latest version is already published.

Do not send previewUrl or draftUrl to external reviewers; use shareUrl instead.

curl -sS "https://www.yourlastchance.app/api/unsubscribe-pages/PAGE_ID/urls" \
  -H "Authorization: Bearer YOUR_API_KEY"

Create a page from a template

Requires pages:write. Unpaid teams are limited to 3 pages total; paid teams are unlimited.

curl -sS -X POST "https://www.yourlastchance.app/api/unsubscribe-pages" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Stay offer page",
    "templateId": "TEMPLATE_ID"
  }'

Save a draft version

Requires pages:write.

curl -sS -X POST "https://www.yourlastchance.app/api/unsubscribe-pages/PAGE_ID/versions" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Draft from API",
    "versionNumber": 2,
    "globalStyles": ":root { --primary: #111; }",
    "pages": [
      {
        "id": "initial",
        "name": "Initial",
        "html": "<div data-action=\"stay\">Stay subscribed</div>"
      }
    ]
  }'

Required fields: name, versionNumber, globalStyles, and pages (an array of page objects). Use the same JSON shape the dashboard editor saves (HTML/CSS, theme, offers). Unchanged content may return the existing version instead of creating a new one. In practice, fetch the current version first, modify it, then POST.

Publish a version

Requires pages:publish. Publishing requires an active subscription.

curl -sS -X POST "https://www.yourlastchance.app/api/unsubscribe-pages/PAGE_ID/versions/VERSION_ID/publish" \
  -H "Authorization: Bearer YOUR_API_KEY"

Attach a Klaviyo list to a page

Requires pages:write.

curl -sS -X POST "https://www.yourlastchance.app/api/unsubscribe-pages/PAGE_ID/email-lists" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "listId": "KLAVIYO_LIST_ID",
    "listName": "Newsletter",
    "provider": "klaviyo"
  }'

Delete a page (API key only)

Requires pages:write and confirm=true (query or JSON body). Session deletes from the dashboard do not need this flag.

curl -sS -X DELETE "https://www.yourlastchance.app/api/unsubscribe-pages/PAGE_ID?confirm=true" \
  -H "Authorization: Bearer YOUR_API_KEY"

Or:

curl -sS -X DELETE "https://www.yourlastchance.app/api/unsubscribe-pages/PAGE_ID" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"confirm": true}'

Dashboard stats (summary)

Requires analytics:summary:read. Returns aggregated stay/unsubscribe counts, visitor retention, and attributed order revenue for the team (no per-email data).

curl -sS "https://www.yourlastchance.app/api/dashboard/stats" \
  -H "Authorization: Bearer YOUR_API_KEY"

Unsubscribe rates (summary)

Requires analytics:summary:read. Compares Klaviyo unsubscribe rates before/after Last Chance activation. Optional startDate / endDate (ISO). Requires an active Klaviyo integration.

curl -sS "https://www.yourlastchance.app/api/analytics/unsubscribe-rates" \
  -H "Authorization: Bearer YOUR_API_KEY"

Revenue impact (attribution)

Requires analytics:attribution:read. Full-funnel churn recovery and revenue metrics. startDate and endDate are required (ISO date strings). Optional: enforceActivationDate, variantId, attributionWindowMode. Requires an active Klaviyo integration.

curl -sS "https://www.yourlastchance.app/api/analytics/revenue-impact?startDate=2026-01-01&endDate=2026-03-31" \
  -H "Authorization: Bearer YOUR_API_KEY"

Event-level analytics that include email addresses are not available via API keys.


Common errors

StatusCode / messageMeaning
401UnauthorizedMissing/invalid key, revoked key, or expired key
403insufficient_scopeKey lacks a required scope
403Active subscription requiredPublish (and some paid features) need a paid team
400CONFIRMATION_REQUIREDAPI-key page delete missing confirm=true
403API_KEY_LIMIT_REACHEDTeam already has 20 active keys
429Rate limitedToo many API-key requests, AI calls, or key creates

Responses never include Klaviyo OAuth secrets (accessToken, refreshToken, etc.).


Security best practices

  • Prefer short-lived keys (90 days) and rotate before expiry
  • Use the smallest scope set that works
  • Store secrets in env vars or a vault — never commit them
  • Revoke keys you no longer need; check Last used on the API Keys page
  • Do not share one key across unrelated systems if you can avoid it