Workspace API

Subscriptions

Subscriptions endpoints of the Zanfia Workspace API, with schemas and code samples.

5 min readLast updated Nov 4, 2026

Recurring-revenue health: failed subscription charges with live Stripe dunning state (and a one-call retry on the customer's current card), customers on manual-renewal plans whose access lapses soon, and subscriptions set to cancel at period end. Read models only - the same data the dashboard's Orders views show; the retry re-charges the failed Stripe invoice on your connected account. All routes require a Authorization: Bearer header — see Authentication.

Failed subscription payments

GET/subscriptions/failed-payments

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Response Body

application/json

application/json

curl -X GET "https://example.com/subscriptions/failed-payments"
{  "items": [    {      "orderId": "string",      "invoiceId": "string",      "clientEmail": "string",      "customerName": "string",      "productId": "string",      "productName": "string",      "kind": "subscription",      "paymentCycle": 0,      "totalInstallments": 0,      "reason": "insufficient_funds",      "declineCode": "string",      "amountMinor": 0,      "currency": "string",      "attempts": 0,      "lastFailedAtMs": 0,      "invoiceStatus": "string",      "attemptCount": 0,      "nextPaymentAttempt": 0,      "hostedInvoiceUrl": "string",      "retriable": true    }  ],  "stripeConnected": true}
{  "error": "string",  "message": "string"}

Retry a failed subscription payment

POST/subscriptions/failed-payments/{invoiceId}/retry

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Path Parameters

invoiceId*string

Response Body

application/json

application/json

curl -X POST "https://example.com/subscriptions/failed-payments/string/retry"
{  "status": "paid",  "message": "string",  "reason": "subscription_ended",  "hostedInvoiceUrl": "string"}
{  "error": "string",  "message": "string"}

Upcoming manual renewals

GET/subscriptions/upcoming-renewals

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Response Body

application/json

application/json

curl -X GET "https://example.com/subscriptions/upcoming-renewals"
{  "items": [    {      "clientId": "string",      "clientEmail": "string",      "customerName": "string",      "productId": "string",      "productName": "string",      "currentPeriodEnd": 0,      "daysLeft": 0,      "renewalLink": "string",      "lastReminderAtMs": 0    }  ]}
{  "error": "string",  "message": "string"}

Subscriptions ending at period end

GET/subscriptions/ending

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Response Body

application/json

application/json

curl -X GET "https://example.com/subscriptions/ending"
{  "items": [    {      "subscriptionId": "string",      "clientId": "string",      "clientEmail": "string",      "customerName": "string",      "productId": "string",      "productName": "string",      "amountMinor": 0,      "currency": "string",      "recurring": {        "interval_count": 0,        "trial_period_days": 0,        "interval": "day",        "endAccessStrategy": "cancel"      },      "currentPeriodEnd": 0,      "daysLeft": 0    }  ]}
{  "error": "string",  "message": "string"}

What happens when a buyer stops paying instalments

GET/settings/installment-non-payment

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Response Body

application/json

application/json

curl -X GET "https://example.com/settings/installment-non-payment"
{  "action": "revoke",  "explicit": true}
{  "error": "string",  "message": "string"}

Change what happens when a buyer stops paying instalments

PATCH/settings/installment-non-payment

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X PATCH "https://example.com/settings/installment-non-payment" \  -H "Content-Type: application/json" \  -d '{    "action": "revoke"  }'
{  "action": "revoke",  "explicit": true}
{  "error": "string",  "message": "string"}

List buyers behind on instalments („Zaległości”)

GET/installment-arrears

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Query Parameters

productId?string

One product (prod_… from list-products); omitted = every product.

Length1 <= length
includeKept?boolean

Also list the buyers the creator already chose „Zostaw” for. Default false.

Response Body

application/json

application/json

curl -X GET "https://example.com/installment-arrears"
{  "items": [    {      "productId": "string",      "productName": "string",      "clientEmail": "string",      "firstName": "string",      "lastName": "string",      "subscriptionId": "string",      "subscriptionStatus": "active",      "stripeStillCollecting": true,      "installmentsPaid": 0,      "installmentsTotal": 0,      "currency": "string",      "overdueAmountMinor": 0,      "overdueInstallments": 0,      "notYetDueAmountMinor": 0,      "notYetDueInstallments": 0,      "notYetDueBasis": "last-installment-invoice",      "overdueSince": 0,      "endedAt": 0,      "rule": "started-before-setting",      "keptAt": 0,      "proformaCheckNeeded": true    }  ],  "stripeConnected": true,  "setting": "revoke",  "paidOutsideStripeCount": 0,  "keptCount": 0,  "unverifiedCount": 0}
{  "error": "string",  "message": "string"}

Keep a behind-on-instalments buyer's access („Zostaw”)

POST/installment-arrears/keep

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

curl -X POST "https://example.com/installment-arrears/keep" \  -H "Content-Type: application/json" \  -d '{    "productId": "string",    "clientEmail": "string"  }'
{  "kept": true,  "keptAt": 0}
{  "error": "string",  "message": "string"}

E-mail sending balance and packs

GET/email-packs

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Query Parameters

neededEmails?integer

E-mails you are short of (a campaign audience minus balance.total); fills upgradeHint.

Range1 <= value
currency?string

Used only without a Stripe plan: pln (default) or usd. A Stripe plan always pays in its own currency, which the answer returns as currency.

Value in

  • "pln"
  • "usd"

Response Body

application/json

application/json

curl -X GET "https://example.com/email-packs"
{  "balance": {    "plan": {      "total": 0,      "used": 0,      "remaining": 0,      "resetsAt": "string"    },    "packs": {      "remaining": 0,      "nextExpiry": "string"    },    "total": 0,    "unlimited": true  },  "planTier": "string",  "availableOnPlan": true,  "unavailableReason": "no-email-marketing",  "availableFromTier": "string",  "currency": "pln",  "packs": [    {      "id": "string",      "emails": 0,      "prices": {        "pln": {          "amount": 0        },        "usd": {          "amount": 0        }      }    }  ],  "maxQuantity": 0,  "maxPacksPerPeriod": 0,  "packsBoughtThisPeriod": 0,  "packsLeftThisPeriod": 0,  "packsHeld": 0,  "heldUntil": "string",  "purchases": [    {      "id": "string",      "packId": "string",      "quantity": 0,      "emails": 0,      "emailsRemaining": 0,      "amount": 0,      "currency": "string",      "tier": "string",      "unitAmount": 0,      "status": "active",      "purchasedAt": "string",      "expiresAt": "string",      "invoiceUrl": "string"    }  ],  "upgradeHint": {    "tier": "string",    "monthlyEmails": 0,    "monthlyPriceDifference": 0,    "packsCost": 0,    "upgradePacksCost": 0,    "upgradeCost": 0,    "currency": "pln"  }}
{  "error": "string",  "message": "string"}
POST/email-packs/checkout

Authorization

bearerAuth
AuthorizationBearer <token>

API key from Dashboard → Integrations → API, MCP and CLI.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Starts the one-time Checkout of 1-10 e-mail packs. The amount is the catalog's, server-side.

Response Body

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/email-packs/checkout" \  -H "Content-Type: application/json" \  -d '{    "packId": "string",    "quantity": 0,    "currency": "pln"  }'
{  "url": "string",  "quantity": 0,  "emails": 0,  "priceTier": "string",  "unitAmount": 0,  "currency": "pln"}
{  "unavailableReason": "no-email-marketing",  "availableFromTier": "string",  "freesUpAt": "string",  "retryWhen": "tomorrow",  "packsLeftThisPeriod": 0,  "packsHeld": 0,  "error": "string",  "message": "string"}
{  "unavailableReason": "no-email-marketing",  "availableFromTier": "string",  "freesUpAt": "string",  "retryWhen": "tomorrow",  "packsLeftThisPeriod": 0,  "packsHeld": 0,  "error": "string",  "message": "string"}
{  "error": "string",  "message": "string"}

Was this article helpful?

Related articles

Spotted something off? Tell us at support@zanfia.com.