Skip to main content

Creating A Session (Server-To-Server)

This is the default way to open the widget. Your backend authenticates with the Pagamio API key, creates a session for one customer, and gives the returned widgetUrl to your app.

If your integration uses signed redirects instead, see Partner-Initiated Launch.


Path: POST {WIDGET_BASE_URL}/partner/v1/sessions

Authorization: ApiKey <YOUR_API_KEY>

Required scope: sessions:create

Content-Type: application/json

Call this from your backend only. Never put the API key in your app or web page.


Request Body​

Unknown fields are rejected with 400 BAD_REQUEST.

FieldTypeRequiredDescription
customerIdstring (1-128, printable ASCII)YesYour identifier for the customer. Returned to you unchanged in transactions and statements.
walletIdstring (max 128, printable ASCII)NoYour identifier for the wallet Pagamio should hold funds in. Sent to your wallet API on every hold.
customer.displayNamestring (max 60)NoShown in the widget.
customer.firstNamestring (max 60)NoPrefill only. See below.
customer.surnamestring (max 60)NoPrefill only.
customer.mobileNumberstring (max 20; digits, +, spaces, brackets, dashes)NoPrefill only.
localestring (max 20)NoReserved for the customer's language.
preselect, returnUrlanyNoAccepted but ignored in this release. Do not rely on them.

Identity numbers, dates of birth and bank details are not accepted anywhere in this API.

Prefill Attributes​

customer.firstName, customer.surname and customer.mobileNumber are optional. Some products need the customer's name or mobile number at the point of sale; when you send them, the widget fills those fields in and the customer can still edit them. When you do not send them, the customer types the values at each sale.

  • They are stored on the session only, not on transactions, receipts or statements.
  • A mobile number in +27..., 0027... or 27... form is converted to the local 0... form. Any other value is passed through (trimmed, with spaces, dashes and brackets removed) and validated by the widget.
  • They reach the widget as a prefill map keyed by firstname, surname and mobileNumber.

Example Request​

curl -X POST "$WIDGET_BASE_URL/partner/v1/sessions" \
-H "Authorization: ApiKey $PAGAMIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customerId": "customer-123",
"walletId": "wallet-456",
"customer": {
"displayName": "Thabo",
"firstName": "Thabo",
"surname": "Mokoena",
"mobileNumber": "+27821234567"
}
}'

Response 201 Created​

{
"sessionId": "0b7e6a0e-6f2c-4d0b-9c61-3f0f8f6f2a11",
"widgetUrl": "https://vas-widget-sandbox.pagamio.tech/w/acme/#session=<opaque-token>",
"expiresAt": "2026-09-30T10:15:00Z"
}
FieldDescription
sessionIdIdentifier you can use to revoke the session.
widgetUrlLoad this URL in the web-view, iframe or browser. The session token sits in the URL fragment (#session=), so it is never sent to a server or in a Referer header. The widget reads it and removes it from the address bar.
expiresAtWhen the session will expire if the customer is idle.

Loading The Widget​

  • Android web-view: webView.loadUrl(widgetUrl). Enable JavaScript and DOM storage.
  • iOS WKWebView: webView.load(URLRequest(url: URL(string: widgetUrl)!)).
  • iframe: <iframe src="{widgetUrl}">. Your page's origin must be on the allowed origins list, or the browser will refuse to frame the widget.

Treat widgetUrl as a credential: do not log it, and do not reuse it for another customer.

Session Lifetime​

A session expires after an idle period (default 15 minutes, extended by each widget request) or an absolute lifetime (default 60 minutes), whichever comes first. An expired session shows "Your session has expired" and the customer must be sent back through your app to open a new one. Create a fresh session each time the customer opens the widget.

Revoking A Session​

Path: DELETE {WIDGET_BASE_URL}/partner/v1/sessions/{sessionId}

Required scope: sessions:create

Returns 204 No Content. Use it when the customer signs out of your app. An unknown session, or one that belongs to another partner, returns 404 SESSION_NOT_FOUND.

Errors​

StatuscodeMeaning
400BAD_REQUESTMalformed JSON, or a field this API does not accept.
401UNAUTHORIZEDMissing, malformed or unknown API key.
403FORBIDDENThe key lacks the sessions:create scope.
422VALIDATIONA field failed validation; see fieldErrors.
429RATE_LIMITEDOver your per-key limit. Wait for Retry-After seconds.

The full list is in the Error Reference.


Last updated: September 2026