DocsAPI ReferencePortal Sessions
Portal Sessions
Generate secure, expiring links your customers can open to view their payment history with your store — everything, a single order, or a single subscription. Stripe-style: create a session server-side, send the returned URL to your customer.
How it works
A portal session is a short-lived, read-only view over sensitive payment data. Its URL contains a high-entropy bearer token: anyone with the link can open the portal until it expires or you revoke it. The token is stored hashed and the full URL is returned exactly once, at creation — retrieving a session later never returns the URL again.
| Scope | Created with | The customer sees |
|---|---|---|
customer_id / customer_email | A customer of your store | Full payment history: all orders and subscriptions, totals, statuses, refunds |
order_id | A single order | That order only: amounts, tax, payment status, refunds |
subscription_id | A single subscription | That subscription only: plan, status, next billing, payment attempts |
Also available in the dashboard
Create a portal session
/api/v1/portal/sessionsSecret key (sk_)| Field | Type | Required | Description |
|---|---|---|---|
| customer_id | string | One of four | Customer id. Creates a customer-scope portal (full history). |
| customer_email | string | One of four | Alternative to customer_id — resolved against your store's customers. |
| order_id | string | One of four | Order id (the public order_id from webhooks or the dashboard). |
| subscription_id | string | One of four | Subscription id. Creates a subscription-scope portal. |
| expires_at | integer | No | Epoch seconds. Clamped to [now + 5 minutes, now + 30 days]. Defaults to 24 hours. |
| metadata | object | No | Up to 20 string key/value pairs, returned on reads. |
Provide exactly one of customer_id, customer_email, order_id or subscription_id. The Idempotency-Key header makes retries safe: a repeated key replays the original session (the URL is replayed only while the link is still active).
curl -X POST https://saleonix.com/api/v1/portal/sessions \
-H "Authorization: Bearer sk_test_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: portal-cus-812" \
-d '{
"customer_email": "buyer@example.com",
"expires_at": 1751713200
}'Response
json
{
"id": "ps_test_9fJk3W2v1XyZ8Qw7Tt6Rr5Ee4Uu3Ii2",
"object": "portal.session",
"status": "active",
"scope": "customer",
"livemode": false,
"customer_id": "clcus1abc...",
"order_id": null,
"subscription_id": null,
"url": "https://saleonix.com/portal/vN3qX...43-char-token...Qp",
"metadata": {},
"access_count": 0,
"last_accessed_at": null,
"created": 1751529600,
"expires_at": 1751616000
}The URL is a credential
url like a password: deliver it directly to the customer it belongs to (email, SMS, support chat) and never log it or embed it in public pages. Prefer short expiries — you can always mint a new link.Order and subscription scopes
ts
// Order-only portal: the customer sees this one order (amount, tax,
// payment status, refunds) and nothing else.
await fetch("https://saleonix.com/api/v1/portal/sessions", {
method: "POST",
headers: { Authorization: `Bearer ${SECRET_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ order_id: "clorder123..." }),
});
// Subscription-only portal: plan, status, next billing date and payment history.
await fetch("https://saleonix.com/api/v1/portal/sessions", {
method: "POST",
headers: { Authorization: `Bearer ${SECRET_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ subscription_id: "clsub456..." }),
});Retrieve a portal session
/api/v1/portal/sessions/{id}Secret key (sk_)Returns the state of a session — status (active, expired or revoked), access_count and last_accessed_at — but never the URL. If a link was lost, create a new session instead.
Revoke a portal session
/api/v1/portal/sessions/{id}Secret key (sk_)Kill switch for a leaked or mis-sent link: the portal stops resolving on the next request. Revocation is permanent; returns the session with status: "revoked".
bash
curl -X DELETE https://saleonix.com/api/v1/portal/sessions/ps_live_xxx \
-H "Authorization: Bearer sk_live_xxx"Security model
| Property | Behaviour |
|---|---|
| Token | 256-bit random, stored as a SHA-256 hash; shown once at creation |
| Expiry | Mandatory on every link — 5 minutes to 30 days, default 24 hours |
| Revocation | Immediate, via DELETE or by deleting the customer |
| Tenant isolation | A key can only create/read sessions for its own store |
| Rate limiting | Portal page lookups are per-IP rate limited |
| Data scope | Read-only; no card data, no merchant fees, no other customers' data |
| Indexing | Portal pages are served with noindex/noarchive robots directives |