Dashboard Settings API Docs

ChurnShield API

Integrate ChurnShield payment recovery data into your own applications, dashboards, and workflows. The API is available on the Scale plan.

Base URL:

https://getchurnshield.com/.netlify/functions/public-api

Authentication

All requests require a valid API key passed via the Authorization header using the Bearer scheme.

Generate API keys from the Settings page. Keys are prefixed with cs_live_.

Request Header
Authorization: Bearer cs_live_your_api_key_here
Keep your keys secret. Do not expose API keys in client-side code, public repositories, or URLs. If a key is compromised, revoke it immediately from Settings.

Rate Limits

The API is rate limited to 60 requests per minute per API key. Rate limit status is returned in response headers:

HeaderDescription
X-RateLimit-LimitMaximum requests per minute (60)
X-RateLimit-RemainingRequests remaining in the current window
Retry-AfterSeconds to wait before retrying (only on 429)

Error Handling

All errors return a consistent JSON structure:

{
  "success": false,
  "error": {
    "code": "unauthorized",
    "message": "Missing or invalid API key"
  }
}
StatusCodeMeaning
401unauthorizedMissing or malformed API key
401invalid_keyAPI key is invalid or revoked
400unknown_endpointThe endpoint parameter is missing or invalid
405method_not_allowedWrong HTTP method for this endpoint
429rate_limitedToo many requests; slow down
500internal_errorSomething went wrong on our end

GET /status

GET ?endpoint=status

Returns your account status, plan, and high-level recovery stats.

curl
curl -H "Authorization: Bearer cs_live_xxx" \
  "https://getchurnshield.com/.netlify/functions/public-api?endpoint=status"
JavaScript
const res = await fetch(
  "https://getchurnshield.com/.netlify/functions/public-api?endpoint=status",
  { headers: { Authorization: "Bearer cs_live_xxx" } }
);
const { success, data } = await res.json();
Response
{
  "success": true,
  "data": {
    "account_id": "uuid",
    "plan": "scale",
    "company_name": "Acme Inc",
    "is_active": true,
    "subscription_count": 1240,
    "active_failures": 8
  }
}

GET /failures

GET ?endpoint=failures

List payment failures. Supports pagination and status filtering.

ParameterTypeDescription
limitintegerResults per page (default 20, max 100)
offsetintegerSkip this many results (default 0)
statusstringFilter by status: new, retrying, dunning, recovered, abandoned
curl
curl -H "Authorization: Bearer cs_live_xxx" \
  "https://getchurnshield.com/.netlify/functions/public-api?endpoint=failures&limit=5&status=retrying"
Response
{
  "success": true,
  "data": {
    "failures": [
      {
        "id": "uuid",
        "stripe_invoice_id": "in_xxx",
        "stripe_customer_id": "cus_xxx",
        "customer_email": "jane@example.com",
        "customer_name": "Jane Doe",
        "decline_code": "insufficient_funds",
        "decline_category": "soft",
        "amount": 4999,
        "currency": "usd",
        "amount_display": "$49.99 usd",
        "status": "retrying",
        "retry_count": 1,
        "max_retries": 3,
        "next_retry_at": "2026-03-25T10:00:00Z",
        "created_at": "2026-03-22T14:30:00Z"
      }
    ],
    "total": 42,
    "limit": 5,
    "offset": 0,
    "has_more": true
  }
}

GET /recoveries

GET ?endpoint=recoveries

List successfully recovered payments, sorted by recovery date.

ParameterTypeDescription
limitintegerResults per page (default 20, max 100)
offsetintegerSkip this many results (default 0)
curl
curl -H "Authorization: Bearer cs_live_xxx" \
  "https://getchurnshield.com/.netlify/functions/public-api?endpoint=recoveries&limit=10"
Response
{
  "success": true,
  "data": {
    "recoveries": [
      {
        "id": "uuid",
        "customer_email": "jane@example.com",
        "amount": 4999,
        "currency": "usd",
        "amount_display": "$49.99 usd",
        "recovered_amount": 4999,
        "recovered_display": "$49.99 usd",
        "recovered_at": "2026-03-23T09:15:00Z",
        "created_at": "2026-03-20T14:30:00Z"
      }
    ],
    "total": 156,
    "limit": 10,
    "offset": 0,
    "has_more": true
  }
}

GET /analytics

GET ?endpoint=analytics

Returns aggregate recovery metrics for the last 30 days.

curl
curl -H "Authorization: Bearer cs_live_xxx" \
  "https://getchurnshield.com/.netlify/functions/public-api?endpoint=analytics"
Response
{
  "success": true,
  "data": {
    "period": "last_30_days",
    "total_failures": 87,
    "total_failed_amount": "$4,350.00",
    "total_failed_cents": 435000,
    "recovered_count": 62,
    "recovered_amount": "$3,100.00",
    "recovered_cents": 310000,
    "active_count": 12,
    "recovery_rate_percent": 71.3,
    "by_category": {
      "soft": 65,
      "hard": 18,
      "fraud": 4
    }
  }
}

GET /retries

GET ?endpoint=retries

List retry attempts with their status and results.

ParameterTypeDescription
limitintegerResults per page (default 20, max 100)
offsetintegerSkip this many results (default 0)
curl
curl -H "Authorization: Bearer cs_live_xxx" \
  "https://getchurnshield.com/.netlify/functions/public-api?endpoint=retries&limit=10"
Response
{
  "success": true,
  "data": {
    "retries": [
      {
        "id": "uuid",
        "payment_failure_id": "uuid",
        "attempt_number": 2,
        "scheduled_at": "2026-03-23T10:00:00Z",
        "executed_at": "2026-03-23T10:00:12Z",
        "result": "success",
        "error_message": null,
        "created_at": "2026-03-20T14:30:00Z"
      }
    ],
    "total": 245,
    "limit": 10,
    "offset": 0,
    "has_more": true
  }
}

POST /retry

POST ?endpoint=retry

Manually trigger a payment retry for a specific failure. This calls the Stripe API to re-attempt the invoice payment.

Request Body (JSON)
FieldTypeDescription
failure_idstringRequired. The UUID of the payment failure to retry.
curl
curl -X POST \
  -H "Authorization: Bearer cs_live_xxx" \
  -H "Content-Type: application/json" \
  -d '{"failure_id": "uuid-of-failure"}' \
  "https://getchurnshield.com/.netlify/functions/public-api?endpoint=retry"
JavaScript
const res = await fetch(
  "https://getchurnshield.com/.netlify/functions/public-api?endpoint=retry",
  {
    method: "POST",
    headers: {
      Authorization: "Bearer cs_live_xxx",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ failure_id: "uuid-of-failure" }),
  }
);
const { success, data } = await res.json();
Response (success)
{
  "success": true,
  "data": {
    "retried": true,
    "success": true,
    "failure_id": "uuid",
    "recovered_amount": 4999,
    "recovered_display": "$49.99"
  }
}
Response (payment failed again)
{
  "success": true,
  "data": {
    "retried": true,
    "success": false,
    "failure_id": "uuid",
    "error": "Your card was declined."
  }
}