API guide
The Vipps MobilePay Recurring API delivers recurring payment functionality for a merchant to create a payment agreement with a customer for fixed interval payments. When the agreement is accepted by the end user, the merchant can send charges that will be automatically processed on the due date.
Important: The Recurring v2 API will be phased out and will not be available from 1 November 2023. See the migration guide for an overview of what has changed from v2 to v3.
Requirements
Important: The Recurring API requires additional compliance checks (more than what is required for the ePayment API), as required by Finanstilsynet (the financial authorities).
To get access to the Recurring API in production, please order Billing and Recurring Payments. It is the same order form as Payment Integration (ePayment API). You will then get a new sales unit (MSN) that can be used for recurring payments.
If you need to use an existing sales unit that already has access to the eCom/ePayment API for the Recurring API too, please contact your KAM or customer service. Please have this information ready:
- Estimated total annual turnover for the sales unit. Example: 100 MNOK.
- Percentage of the payment volume that will be through recurring payments. Example: 50 MNOK.
- The length of the agreements. Example: Annual and monthly.
- The distribution (in %) of the lengths. Example: 80 % annual, 20 % monthly
Please note: You can check if you have access to the Recurring API:
- As a merchant: Check your sales unit(s) on portal.vippsmobilepay.com, in the Developer section.
- As a partner: Check the sales unit(s) with the Management API.
API version: 3.0.0.
Terminology
Term | Description |
---|---|
Agreement | A payment subscription with a set of parameters that a customer agrees to. |
Charge | A single payment within an agreement. |
Idempotency | The property of endpoints to be called multiple times without changing the result after the initial request. |
Flow
The overall flow is:
- The merchant creates a draft agreement and proposes it to the customer via Vipps MobilePay.
- The customer approves the agreement in Vipps MobilePay.
- The customer can find a full overview of the agreement in Vipps MobilePay, including a link to the merchant's website.
- The merchant sends a charge request to Vipps MobilePay at least two days before due date
- If the agreement is active, Vipps MobilePay authorizes the charge.
- Charge will be processed on due date.
This diagram shows a simplified flow:
See the How it works guides for details.
Call by call guide
There are two happy-flows based on how the sales unit is set up:
One for "direct capture" and one for "reserve capture".
This is specified with the transactionType
, and for "direct capture"
the sales unit must be configured for this by Vipps MobilePay.
For more details, see Knowledge base: Reserve and capture.
Please note: Vipps MobilePay will only perform a payment transaction on an agreement that
the merchant has created a charge for with the POST:/recurring/v3/agreements/{agreementId}/charges
endpoint.
You can also manage charges and agreements.
Direct capture
For a "transactionType": "DIRECT_CAPTURE"
setup, the normal flow would be:
- Create a (draft) agreement using the
POST:/recurring/v3/agreements
endpoint. The user can now confirm the agreement in Vipps MobilePay (the app). See Create a new agreement. - The user approves the agreement in Vipps MobilePay: This will result in a capture(or reserve) of the initial charge (if one was defined in the first step). See Initial charge.
- Retrieve the agreement by calling the
GET:/recurring/v3/agreements/{agreementId}
endpoint. See Retrieve an agreement. Please note: At this point the agreement will beACTIVE
if the user completed step 2. - All future charges can be created by using the
POST:/recurring/v3/agreements/{agreementId}/charges
endpoint. For direct capture you must set"transactionType": "DIRECT_CAPTURE"
. See Create a charge. Based on thedue
set in the request, we will try to process the charge on that day. If for some reason, a charge fails to be processed, we will retry for the number of days specified by theretryDays
value. We strongly recommend at least two days retry:retryDays: 2
.
Reserve capture
Please note: Reserve capture on recurring charges is available in the Recurring API v3. In the API V2, reserve capture is only available on initial charges.
For a "transactionType": "RESERVE_CAPTURE"
setup, the normal flow would be:
- Create a (draft) agreement using the
POST:/recurring/v3/agreements
endpoint. The user can now confirm the agreement in the Vipps or MobilePay app. See Create a new agreement. - The user approves the agreement in Vipps MobilePay: This will result in a capture(or reserve) of the initial charge (if one was defined in the first step). See Initial charge.
- Retrieve the agreement by calling the
GET:/recurring/v3/agreements/{agreementId}
endpoint. See Retrieve an agreement. Please note: At this point the agreement will beACTIVE
if the user completed step 2. - All future charges can be created by using the
POST:/recurring/v3/agreements/{agreementId}/charges
endpoint. For reserve capture you must set"transactionType": "RESERVE_CAPTURE"
. See Create a charge. Based on thedue
set in the request, we will try to process the charge on that day. If the charge is processed successfully, the status will beRESERVED
. If for some reason, a charge fails to be processed, we will retry for the number of days specified by theretryDays
value. We recommend at least 2 days retry. - If there is a product that is shipped to the customer, the charge should be captured at this point.
Capture the charge by calling the
POST:/recurring/v3/agreements/{agreementId}/charges/{chargeId}/capture
endpoint.
API endpoints
See Authentication and authorization.
See the Quick start guide for en easy way to test the API.
Authentication and authorization
All API calls are authenticated with an access token and an API subscription key. See Get an access token, for details.
Use the standard HTTP headers for all requests.
Idempotency Key header
V3 API only
The Idempotency-Key
header must be set in any request that creates or modifies a resource (POST
, PUT
, PATCH
or DELETE
).
This way, if a request fails for any technical reason, or there is a networking issue, it can be retried with the same Idempotency-Key
. The idempotency key should prevent operations and side effects from being performed more than once, and you should receive the same response as if you only sent one request.
Important: If the response is a client-error (4xx), you will continue to get the same error as long as you use the same idempotency key, as the requested operation is not retried.
Important: If you reuse an idempotency key on a different request, you will get a 409 CONFLICT.
See the Idempotency header for more details.
Continuation-Token header
V3 API only
The Continuation-Token
header is introduced on endpoints that returns multiple items to allow pagination. When returned from the API, it indicates that there are more items to be received. In order to receive the next page, repeat the request adding the received token in the Continuation-Token
-header.
orderId recommendations
An optional and recommended orderId
field can be set in the POST:/recurring/v3/agreements/{agreementId}/charges
request.
{
"amount": 49900,
"description": "Premier League subscription",
"due": "2030-12-31",
"transactionType": "DIRECT_CAPTURE",
"retryDays": 5,
"orderId": "acmeshop123order123abc"
}
Important: If the orderId
is provided:
- The value of the
orderId
is used for all instances ofchargeId
- The
orderId
(andchargeId
) is used for all subsequent identification of the charge. - The
orderId
is used in the settlement files if noexternalId
is specified. - This
orderId
must be unique across all Recurring and eCom transactions for the givenmerchantSerialNumber
.
If the field is not provided, we will automatically create a unique ID
prefixed with chr-
: chr-xxxxxxx
(where each x is an alphanumeric character).
👉 Please read orderId / reference in the Knowledge base for detailed recommendations.
Agreements
An agreement is between the Vipps MobilePay user and the merchant. This payment agreement allows you to routinely charge the customer without requiring them to manually approve every time. See charges for more details.
Create an agreement
This is an example of a request body for the POST:/recurring/v3/agreements
call:
{
"phoneNumber":"4712345678",
"interval": {
"unit" : "MONTH",
"count": 1
},
"merchantRedirectUrl": "https://example.com/confirmation",
"merchantAgreementUrl": "https://example.com/my-customer-agreement",
"pricing": {
"amount": 49900,
"currency": "NOK"
},
"productDescription": "Access to all games of English top football",
"productName": "Premier League subscription"
}
Agreement fields and their usage in the Vipps or MobilePay app
pricing
: Price of the subscription.interval
: Describes how often the user will be charged.productName
: A short description of the subscription. Will be displayed as the agreement name in the Vipps or MobilePay app.productDescription
: More details about the subscription. Optional field.merchantAgreementUrl
: URL where you will send the customer to view/manage their subscription. See Merchant agreement URL for more details.
Please note: To create agreements with support for variable amounts on charges, see Recurring agreements with variable amount.
Agreements may be initiated with or without an initial charge.
The agreement price and the amount for the initial charge, is given in øre for NOK and DKK, and in cent for EUR.
The minimum amount in NOK and DKK is 100 øre. The minimum amount in EUR is 1 cent.
# | Agreement | Description |
---|---|---|
1 | Agreement starting now | Agreement with an initialcharge that uses DIRECT_CAPTURE will only be active if the initial charge is processed successfully |
2 | Agreement starting in future | Agreement without an initialcharge , or with initialcharge that uses RESERVE_CAPTURE , can be approved, but no payment will happen until the first charge is provided |
The response contains an agreementResource
, a vippsConfirmationUrl
and an agreementId
.
This agreementResource
is a complete URL for performing a
GET:/recurring/v3/agreements/{agreementId}
request.
The vippsConfirmationUrl
should be used to redirect the
user to the Vipps MobilePay landing page in a desktop flow (with https://
),
or to Vipps MobilePay in a mobile flow (with vipps://
), where the
user can then approve the agreement.
See landing page from Knowledge base, for more details.
Please note: If payment should be required to activate an agreement, you need to specify an initial charge. If you are dealing with physical goods, this should be a RESERVE_CAPTURE, but for digital goods where the customer instantly gains access, DIRECT_CAPTURE might be easier to manage. See Initial charge.
Accept an agreement
The POST:/recurring/v3/agreements
endpoint will return the following JSON structure.
{
"vippsConfirmationUrl": "https://api.vipps.no/dwo-api-application/v1/deeplink/vippsgateway?v=2/token=eyJraWQiOiJqd3RrZXkiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJmMDE0MmIxYy02YjI",
"agreementId": "agr_TGSuPyV"
}
The vippsConfirmationUrl
should be used to redirect the user to the Vipps MobilePay landing
page. The user can then confirm their identity and receive a prompt to accept the
agreement within Vipps MobilePay.
If the payment is initiated in a native app, it is possible to explicitly force
a vipps://
URL by sending the isApp
parameter in the initiate call:
"isApp": false
: The URL ishttps://
, which handles everything automatically for you. The phone's operating system will know, through "universal linking", that thehttps://api.vipps.no
URL should open the Vipps or MobilePay app, and not the default web browser. Please note: In some cases, this requires the user to approve that Vipps MobilePay is opened, but this is usually only the first time."isApp": true
: The URL is for a deeplink, for forced app-switch to Vipps, withvipps://
. Please note: In our test environment (MT), the scheme isvippsMT://
If the user does not have Vipps MobilePay installed:
"isApp":false
: The Vipps MobilePay landing page will be shown, and the user can enter a phone number and pay on a device with Vipps MobilePay installed."isApp": true
: The user will get an error message saying that the link can not be opened.
For more details, see Knowledge base: Deep link flow.
Agreement activation or rejection
If the user accepts or rejects the agreement the user will be redirected back to themerchantRedirectUrl
.
Activation of the agreement is not guaranteed to be finished by the time the user is redirected back to the merchantRedirectUrl
.
The agreement could still have the status PENDING
. Also, if the user closes the Vipps or MobilePay app before the redirect is done, the merchantRedirectUrl
will not be used.
Therefore, it is important to actively check the agreement's status with the
GET:/recurring/v3/agreements/{agreementId}
endpoint instead of relying on the redirect to the merchantRedirectUrl
.
See current rate limits for more details about polling.
Once a final status (ACTIVE
, EXPIRED
or STOPPED
) is returned by the API, the agreement can be updated in your system.
Merchant agreement URL
The merchantAgreementUrl
is a link to the customer's account page on your website, where they
can manage the agreement (e.g., change, pause, cancel the agreement).
The URL is opened in the standard web browser.
Please note: Vipps MobilePay does not offer any form of agreement management, as this may include quite complex operations (e.g., changing subscription types, temporary address change, pausing the agreement, etc.).
Important: The integrator must implement such functionality for the
customer to manage the agreement in their system.
It is the integrator's responsibility to make sure the merchantAgreementUrl
in the agreement works for the user.
We don't have any specific requirements for the security of the page, other than using HTTPS, but strongly recommend using Login, so the user does not need a username or password, but is logged in automatically through Vipps MobilePay. See the Login API for more details.
Intervals
There are two types of interval : "RECURRING" and "FLEXIBLE".
When an interval has type "RECURRING", it is defined with an interval unit YEAR
, MONTH
, WEEK
, or DAY
and frequency as a count. The count can be any number between 1 and 31.
The interval defines how often the user will be charged.
When an interval has type "FLEXIBLE", it means that it has no periodicity. For example, a user can subscribe to an agreement for e-scooter rental, where the user is charged every time they rent a scooter, without any interval involved. To create an agreement with a flexible interval, the interval field has to be omitted.
Example for a bi-weekly subscription:
{
"interval": {
"unit": "WEEK",
"count": 2
}
}
Users can be charged the full amount every two weeks, regardless of the day in the week. (E.g. First charge can be due on Wednesday of week 1 and the second charge can be due on Monday of week 3).
Example for a quarterly subscription
{
"interval": {
"unit": "MONTH",
"count": 3
}
}
Users can be charged the full amount every third month, regardless of the day in the month. (E.g. First charge can be due on 05.01.2023 and second on 02.04.2023)
Examples for a yearly subscription
{
"interval": {
"unit": "YEAR",
"count": 1
}
}
OR
{
"interval": {
"unit": "MONTH",
"count": 12
}
}
Users can be charged the full amount once every year, regardless of the day in the year. (E.g. First charge can be due on 02.06.2022 and second charge on any day in 2023, for example on 01.01.2023)
Example for a subscription every 30th day:
{
"interval": {
"unit": "DAY",
"count": 30
}
}
Users can be charged the full amount once every 30 days, regardless of the day in the month. (E.g. First charge can be due on 12.06.2022 and second charge on 04.07.2022)
Pricing representation
Legacy pricing
Available for Vipps and MobilePay.
LEGACY
is the default type.
pricing.amount
should represent the price that the user will pay every period.
The amount
of a charge is flexible and does not have to match the price
of the agreement.
A limit is in place however, which is 5 times the agreement price
.
For example, the agreement below has price
of 1000 NOK
. The maximum allowed charge would be 5000 NOK
. If this limit becomes a
hindrance the agreement price
can be updated.
Please note: Although it is technically possible to increase the price 10 times, we strongly recommend that you are as user-friendly as possible. Make sure the user understands any changes and are provided with updated information.
Here is a truncated example of request body for the POST:/recurring/v3/agreements
endpoint:
{
"pricing": {
"type": "LEGACY",
"amount": 100000,
"currency": "NOK"
},
"interval": {
"unit" : "MONTH",
"count": 1
},
"...": "..."
}
Variable amount pricing
Available for Vipps and MobilePay.
Recurring with variable amounts offer merchants a way to charge users a different amount each payment, as long as the amount is lower than the user's specified max amount.
This provides clarity for the customer and ensures that they know the maximum price they will have to pay for the product or service.
To create a variable amount agreement, use the VARIABLE
type in Pricing
.
With VARIABLE
pricing, you no longer specify a price, but a suggestedMaxAmount
for the user.
This field should be set to what the maximum price could be each payment.
This suggestedMaxAmount
is presented to the user together with a list of auto generated amount suggestions that is created by Vipps MobilePay.
The suggestedMaxAmount
is however pre-selected for the user.
The user chooses a max amount themselves when accepting the agreement, but we
recommended the user to choose the same amount as suggestedMaxAmount
. The max
amount can at any time be changed by the user. What the user has picked as their
max amount will be available in the GET agreement
response. Its recommended
that when you set the suggestedMaxAmount
, that you set a realistic amount -
as setting it to unrealistic amounts might scare off the user when they accept
the agreement.
See the How Recurring works with variable amount for details.
Here is a truncated example of request body for the POST:/recurring/v3/agreements
endpoint:
{
"pricing": {
"suggestedMaxAmount": 200000,
"currency": "NOK",
"type": "VARIABLE"
},
"interval": {
"unit" : "MONTH",
"count": 1
},
"...": "..."
}
Restrictions when using variable amount
-
There are limits for each currency for the
suggestedMaxAmount
:- NOK: 20 000 kr
- DKK: 300 000 kr
- EUR: 2 000 Euro
-
Campaign
can not be used when the agreement hasvariableAmount
.
The user will be presented with the variable agreement in the Vipps, where they can change the max amount they allow to be charged each interval. See the How Recurring works with variable amount for details.
Please note: The auto generated list is based on the suggestedMaxAmount
and can not be changed by the merchant individually.
It will however change if suggestedMaxAmount
changes, which can be done in the PATCH agreement
endpoint.
Retrieving the agreement shows the maxAmount
picked by the user
GET:/recurring/v3/agreements/{agreementId}
response:
{
"id": "agr_Yv2zYk3",
"start": "2021-06-18T19:56:22Z",
"stop": null,
"status": "ACTIVE",
"productName": "Power company A",
"pricing": {
"type": "VARIABLE",
"suggestedMaxAmount": 500000,
"maxAmount": 1800000,
"currency": "NOK"
},
"productDescription": "Access to subscription",
"interval": {
"unit": "MONTH",
"count": 1,
"text": "hver måned"
},
"campaign": null,
"sub": null,
"userinfoUrl": null
}
Change suggestedMaxAmount
It's possible to change the suggestedMaxAmount
on the agreement by calling the update agreement endpoint with the PATCH:/recurring/v3/agreements/{agreementId}
request below.
{
"suggestedMaxAmount": 300000
}
Please note: The user will not be alerted by this change.