CoEditor CRM docs
Reference

App API Routes

CRM HTTP routes for subscription list, cancel, and winback—authentication, request data, and responses.

Paths below are relative to your CRM deployment origin (the same host as the dashboard)—for example https://your-crm.example.com/api/subscriptions.

These routes support end-user flows on your site (typically with Piano): list Stripe subscriptions, cancel at period end, or apply a winback price during cancellation.


Authentication

RequirementDetails
Query tokenPiano JWT for the signed-in user. Payload must include aud (Piano application id) and sub (Piano user id).
Header OriginBrowser Origin matching the publication’s configured origin. Used with aud to resolve the publication and Stripe accounts.

Missing or invalid values return 400 with { "error": "..." }. Winback also calls Piano token verification; failure returns 401.

Configure winback offers in publication Settings (Smart actions) before calling winback from production.


GET /api/subscriptions

List Stripe subscriptions for the Piano user behind token.

Request

PartRequired
Origin headerYes
token queryYes

Response 200

{
  "subscriptions": [ /* Stripe subscription objects */ ]
}

Each item is a Stripe Subscription, plus:

FieldTypeDescription
stripeAccountIdstring | nullStripe account id when multiple accounts exist
stripeAccountNamestring | nullAccount title from CRM

May include expanded schedule when subscription schedules apply.

Errors 400

Origin not found., Token not found., Invalid token - no aud., Publication not found., Piano user not found., CRM Stripe accounts not found.


DELETE /api/subscriptions/{stripeSubscriptionId}

Schedule cancellation at end of current billing period (cancel_at_period_end: true). Releases an attached Stripe subscription schedule first when present.

Request

PartRequired
Origin headerYes
token queryYes
Path stripeSubscriptionIdYes (e.g. sub_...)

Response 200

{
  "success": true,
  "data": { /* updated Stripe subscription */ }
}

Errors 400

Auth/publication errors as above; Subscription not found., Failed to cancel subscription., Failed to release subscription., Failed to get Stripe client for this publication.


POST /api/subscriptions/winback

Apply a winback Stripe Price when the user accepts an alternate plan in your cancellation UI.

Request

PartRequired
Origin headerYes
token queryYes (verified with Piano)

JSON body:

FieldTypeRequiredDescription
subscriptionIdstringYesStripe subscription id
newPriceIdstringYesStripe Price id for the winback offer
{
  "subscriptionId": "sub_1Example",
  "newPriceId": "price_1WinbackOffer"
}

Response 200 (no schedule template for price)

{
  "data": {
    "message": "Plan changed. No schedule for this price."
  },
  "error": null
}

Response 200 (schedule at period end)

{
  "success": true,
  "message": "Subscription plan will change at the end of your current billing period",
  "data": {
    "subscriptionId": "sub_1Example",
    "currentPeriodEnd": 1735689600,
    "newPriceId": "price_1WinbackOffer"
  }
}

Errors

StatusWhen
400Missing auth, body, publication, user, or subscription; Stripe client unavailable
401Invalid token.
500Plan change or schedule failure (may include correlation id)

Typical cancellation flow

sequenceDiagram
  participant User as Subscriber
  participant Site as Your site
  participant CRM as CoEditor API

  User->>Site: Start cancellation
  Site->>CRM: GET /api/subscriptions?token=...
  CRM-->>Site: subscriptions
  alt Winback accepted
    Site->>CRM: POST /api/subscriptions/winback
    Note over Site,CRM: subscriptionId, newPriceId
  else Cancel
    Site->>CRM: DELETE /api/subscriptions/{id}?token=...
  end

Not covered here

Auth, Google mailbox, AI, webhooks, and other internal CRM routes are documented in engineering docs. This page lists routes customer integrations call from public cancellation and account flows.

On this page