Przejdź do głównej zawartości

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.

Okno terminala
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:

  • tierstarter, team, business lub enterprise.
  • subscriptionStatus — status Stripe dosłownie. W praktyce zobaczysz wartości trialing, active, past_due, unpaid, canceled lub pusty (free / przed rozliczeniem).
  • currentPeriodEnd — kiedy kończy się bieżący okres rozliczeniowy. Odnowienie następuje wtedy, jeśli aktywne.
  • trialEndsAt — ustawione tylko gdy subscriptionStatus = trialing.
  • billedFeaturesActivetrue, 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.

Okno terminala
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.

Okno terminala
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:

// pseudokod
const 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);
}