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.

RequestPurpose
GET /v2/customer-portal/customerVerify the session's customer identity.
GET /v2/customer-portal/invoicesList that customer's invoices.
GET /v2/customer-portal/subscriptionsList that customer's subscriptions.
POST /v2/customer-portal/subscriptions/{id}/cancelCancel an eligible subscription using the documented body.
GET /v2/customer-portal/mandatesList that customer's Direct Debit authorities.
POST /v2/customer-portal/mandates/{id}/cancelCancel 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

  1. Send POST /v2/customer-portal/mandates/{id}/re-authorize/send-otp with the customer bearer session.
  2. Submit the received code to POST /v2/customer-portal/mandates/{id}/re-authorize/verify-otp using the operation's request schema.
  3. Pass its verification_token with the re-authorisation request to POST /v2/customer-portal/mandates/{id}/re-authorize.
  4. 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.

On this page