Integrate the Portal API
Create customer-scoped sessions and use the correct identity for self-service requests.
Create a customer session on your server
First authenticate the customer in your own application and resolve their RevKeen customer UUID from your server-side mapping. Never accept an arbitrary customer ID from the browser and mint a session for it.
const apiKey = process.env.REVKEEN_API_KEY;
const customerId = process.env.REVKEEN_CUSTOMER_ID;
if (!apiKey || !customerId) throw new Error("Set staging key and authorised customer UUID");
const response = await fetch("https://staging-api.revkeen.com/v2/customer-portal/sessions", {
method: "POST",
headers: { "x-api-key": apiKey, "Content-Type": "application/json" },
body: JSON.stringify({ customer_id: customerId, ttl_minutes: 15 }),
});
if (!response.ok) throw new Error(`Session creation failed (${response.status})`);
const { data: session } = await response.json();
// Use session.token through a controlled session handoff; never log it.The response contains id, token, customer_id, expires_at, and created_at inside data. TTL is 5–240 minutes, default 60. There is no return_url request field or hosted URL in this response. Handle application navigation yourself; the hosted portal has its own login flow.
Use the customer identity
Call /v2/customer-portal/* with Authorization: Bearer <session.token>. The token identifies one customer under one merchant. Keep it out of URLs, logs, analytics, and persistent browser-accessible storage. Do not substitute the merchant API key for customer authentication on these routes.
| Request | Purpose |
|---|---|
GET /v2/customer-portal/customer | Verify the session's customer identity. |
GET /v2/customer-portal/invoices | List that customer's invoices. |
GET /v2/customer-portal/subscriptions | List that customer's subscriptions. |
POST /v2/customer-portal/subscriptions/{id}/cancel | Cancel an eligible subscription using the documented body. |
GET /v2/customer-portal/mandates | List that customer's Direct Debit authorities. |
POST /v2/customer-portal/mandates/{id}/cancel | Cancel an authority; does not refund or start collection. |
Follow the list's cursor parameters and request bounded pages. Treat an expired/revoked session as a sign-in problem. A denied action is not a reason to retry with merchant credentials in the customer browser.
Change of bank with step-up
- Send
POST /v2/customer-portal/mandates/{id}/re-authorize/send-otpwith the customer bearer session. - Submit the received code to
POST /v2/customer-portal/mandates/{id}/re-authorize/verify-otpusing the operation's request schema. - Pass its
verification_tokenwith the re-authorisation request toPOST /v2/customer-portal/mandates/{id}/re-authorize. - Complete the replacement mandate journey and wait for activation before collection.
The step-up token is bound to the customer, action, and mandate. A code for another mandate must fail. Do not collect on a submitted, cancelled, or replaced authority.
Integration checks
Verify customer identity, bounded pagination, expiry, wrong-customer access, cancelled authority behavior, and OTP mismatch/expiry in staging. An HTTP 200 on the public sign-in page does not establish that authenticated self-service works. See authentication for credential and permission boundaries.