Skip to content

One endpoint is the whole integration

If your billing stack isn't one of the four WhyLeft detects automatically, send cancellations yourself. Everything downstream behaves identically.

Authentication

Create an API key in the dashboard under Integrations → API, and send it as a bearer token. Keys are scoped to one Organization and can be revoked at any time.

Header
Authorization: Bearer wl_your_api_key

Keys are secrets — keep them server-side. Anything running in a browser should never hold one. (The Cancellation Capture snippet is different: it uses a separate publishable key that can only write captures, restricted to domains you allow.)

Send a cancellation

POST /api/v1/cancellations — the same pipeline a Stripe-detected cancellation enters: exit interview, AI follow-up, tagging, insights.

Request
curl -X POST https://app.whyleft.com/api/v1/cancellations \
  -H "Authorization: Bearer wl_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_email": "jane@example.com",
    "customer_name": "Jane Okonkwo",
    "plan_name": "Growth",
    "mrr_cents": 14900,
    "idempotency_key": "sub_1a2b3c-cancelled"
  }'
Response · 201
{
  "interview_id": "9f8e7d6c-...",
  "email_queued": true,
  "deduplicated": false
}

Fields

  • customer_emailstringrequired

    Who cancelled. This is the address the exit interview is sent to.

  • customer_namestringoptional

    Used to personalise the greeting. Never sent to the AI.

  • plan_namestringoptional

    The plan they were on. Used for segmenting insights.

  • mrr_centsintegeroptional

    Your customer's monthly revenue, in whole cents (14900 = $149). Drives lost-MRR and impact weighting.

  • cancelled_atISO 8601optional

    Defaults to now. A future date schedules the interview instead of sending immediately.

  • send_before_daysintegeroptional

    For a future cancellation, send the interview this many days before it (0 = on the day). Ignored for past dates.

  • idempotency_keystringoptional

    Send the same key twice and you get the same interview back, with no second email. Use it if your webhook can retry.

  • send_emailbooleanoptional

    Defaults to true. Set false to record the cancellation without interviewing — useful for backfilling history.

Response codes

  • 201Created. The interview exists and the email is queued.
  • 200Deduplicated — this idempotency_key was already used. No second email.
  • 401Missing or invalid API key.
  • 403No active subscription, or the account is pending deletion.
  • 409Duplicate cancellation for this customer.
  • 413Payload over 64 KB.
  • 422Validation failed, or the recipient has unsubscribed. The response names the offending field.
  • 429Rate limited. Respect the Retry-After header.

Retries and idempotency

Webhook deliveries retry. Pass an idempotency_key derived from something stable in your own system — a subscription id, an event id — and a repeated call returns the original interview with deduplicated: true instead of emailing the customer twice.

Requests are rate limited per key, and the body is capped at 64 KB. Every call is recorded in an audit log you can see in the dashboard.

Getting data out

Outbound webhooks fire on WhyLeft events, so you can push interviews and replies into Zapier, n8n, Make, or your own endpoint. Full exports are available from the dashboard, and a GDPR export endpoint returns everything held for a given customer.

Need something the API doesn't cover? Tell us — it's a short list and we'd rather it stayed short.

API questions

Is there an API?

Yes, and it's included — no add-on, no enterprise tier. You can send cancellations in, receive events out via webhooks, and export everything you've collected.

I don't use any of those. Can I still use WhyLeft?

Yes. POST a cancellation to the API from wherever your own cancel logic runs and everything downstream works identically. It's one endpoint, one API key and a handful of fields.

Which billing providers work with WhyLeft?

Stripe, Polar, Lemon Squeezy and Paddle are detected automatically — connect the account and cancellations start flowing.

Anything else works through the API, an outbound webhook from your own backend, manual entry, or a CSV import. The billing provider is a convenience, not a requirement.

Can I get alerts in Slack?

Yes. Connect a workspace and choose what's worth interrupting you for — a reply landing, a high-MRR account cancelling, or an emerging pattern across several interviews.

See also integrations and the security page.

Your next cancellation is coming.

It can be another number on a chart, or the reason you build the right thing next quarter.

No credit card. Cancel in one click — we'd rather you tell us why.