API rozliczeń
Trzy endpointy pozwalają agentom i integracjom pracować ze stanem rozliczeń, którym zarządza Twój dashboard.
Wszystkie endpointy wymagają klucza API typu Bearer (zobacz Uwierzytelnianie).
GET /me/billing/state
Zwraca migawkę subskrypcji Twojego tenanta.
curl https://api.saiku.bi/me/billing/state \ -H "Authorization: Bearer $SAIKU_API_KEY"Odpowiedź:
{ "tenantId": "81e301f2-…", "tier": "team", "stripeCustomerId": "cus_…", "subscriptionStatus": "active", "currentPeriodEnd": "2026-06-23T00:00:00Z", "trialEndsAt": null, "billedFeaturesActive": true}Pola:
tier—starter,team,businesslubenterprise.subscriptionStatus— status Stripe dosłownie. W praktyce zobaczysz wartościtrialing,active,past_due,unpaid,canceledlub pusty (free / przed rozliczeniem).currentPeriodEnd— kiedy kończy się bieżący okres rozliczeniowy. Odnowienie następuje wtedy, jeśli aktywne.trialEndsAt— ustawione tylko gdysubscriptionStatus = trialing.billedFeaturesActive—true, dopóki masz dostęp do płatnych funkcji. W przeciwnym razie false. Używaj tego do bramkowania własnego UI.
POST /me/billing/checkout-session
Generuje jednorazowy URL do hostowanego Checkout Stripe na rozpoczęcie okresu próbnego lub wykupienie planu.
curl -X POST https://api.saiku.bi/me/billing/checkout-session \ -H "Authorization: Bearer $SAIKU_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "tier": "team", "email": "alice@acme.com", "name": "Acme Corp", "successUrl": "https://app.acme.com/billing/success", "cancelUrl": "https://app.acme.com/billing/cancel" }'Odpowiedź:
{ "url": "https://checkout.stripe.com/c/pay/cs_test_a1…", "sessionId": "cs_test_a1…"}Wyślij przeglądarkę użytkownika na url przekierowaniem 303. URL jest
jednorazowy i wygasa po kilku minutach — nie buforuj.
successUrl i cancelUrl to absolutne URL-e, na które Stripe odsyła
użytkownika po zakończeniu lub porzuceniu Checkout. Oba muszą być
HTTPS.
POST /me/billing/portal-session
Generuje jednorazowy URL do Portalu klienta Stripe. Portal to hostowana przez Stripe strona do zarządzania subskrypcją: aktualizacja karty, zmiana planu, pobranie faktur, anulowanie.
curl -X POST https://api.saiku.bi/me/billing/portal-session \ -H "Authorization: Bearer $SAIKU_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "returnUrl": "https://app.acme.com/billing" }'Odpowiedź:
{ "url": "https://billing.stripe.com/p/session/test_…" }Zwraca 409 no_customer, jeśli tenant nigdy nie ukończył Checkout —
nie ma klienta Stripe do zarządzania. Najpierw uruchom
POST /me/billing/checkout-session.
Działający przykład — osadzony stan subskrypcji
Jeśli budujesz UI admina obudowujący Saiku Cloud i chcesz pokazywać użytkownikom ich bieżący plan inline:
// pseudokodconst state = await fetch('https://api.saiku.bi/me/billing/state', { headers: { Authorization: `Bearer ${saikuApiKey}` }}).then(r => r.json());
if (!state.billedFeaturesActive) { // użytkownik nie ma aktywnej subskrypcji ani okresu próbnego — pokaż CTA "upgrade" const session = await fetch( 'https://api.saiku.bi/me/billing/checkout-session', { method: 'POST', headers: { Authorization: `Bearer ${saikuApiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ tier: 'team', email: user.email, name: org.name, successUrl: `${window.location.origin}/billing/success`, cancelUrl: `${window.location.origin}/billing/cancel` }) } ).then(r => r.json()); window.location.href = session.url;} else { // użytkownik ma dostęp — pokaż bieżący plan + przycisk zarządzania renderPlan(state.tier, state.currentPeriodEnd); const portal = await fetch( 'https://api.saiku.bi/me/billing/portal-session', { method: 'POST', headers: { Authorization: `Bearer ${saikuApiKey}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ returnUrl: `${window.location.origin}/billing` }) } ).then(r => r.json()); renderManageButton(portal.url);}