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 November 1, 2023. See the migration guide for an overview of what has changed from v2 to v3.
Requirements
Important: The Vipps MobilePay Recurring API requires additional compliance checks (more than what is required for the Vipps eCom API), as required by Finanstilsynet (the financial authorities).
To get access to the Recurring API in production, please order "Vipps MobilePay Faste Betalinger/Recurring" (recurring payments) on portal.vipps.no. It is the same order form as "Vipps på Nett" (Vipps eCom 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 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.vipps.no.
- As a partner: Check the sales unit(s) with the Partner 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 or MobilePay.
- The customer approves the agreement in Vipps or MobilePay.
- The customer can find a full overview of the agreement in Vipps or MobilePay, including a link to the merchant's website.
- The merchant sends a charge request to Vipps or MobilePay at least two days before due date
- If the agreement is active, Vipps or 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 Common topics: 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:/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:/agreements
endpoint. The user can now confirm the agreement in Vipps or MobilePay (the app). See Create a new agreement. - The user approves the agreement in Vipps or 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:/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:/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 recommend at least two days retry.
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:/agreements
endpoint. The user can now confirm the agreement in Vipps (the app). See Create a new agreement. - The user approves the agreement in Vipps or 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:/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:/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:/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 Vipps API calls are authenticated with an access token and an API subscription key. See Get an access token, for details.
Vipps HTTP headers
We recommend using the standard Vipps MobilePay HTTP headers for all requests.
See Vipps MobilePay HTTP headers in the Getting started guide, for details.
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:/agreements/{agreementId}/charges
request.
{
"amount": 49900,
"description": "Premier League subscription",
"due": "2030-12-31",
"transactionType": "DIRECT_CAPTURE",
"retryDays": 5,
"orderId": "acmeshop123order123abc"
}
The orderId
replaces the chargeId
.
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.
This orderId
must be unique across all Recurring and eCom
transactions for the given merchantSerialNumber
.
If the field is not provided, Vipps will automatically create a unique ID
prefixed with chr-
: chr-xxxxxxx
(where each x is an alphanumeric character).
If you ever have a problem that requires us to search in our logs, we will need
orderId
values that are "unique enough" to actually find them. An orderId
that
is just a number may not be possible to find.
While the minimum length for orderId
technically is just one character,
we strongly recommend using at least 6 characters, and a combination of numbers
and characters.
The maximum length of an orderId
is 50, and can contain alphanumeric characters and dashes:
a-z, A-Z, 0-9, -. Example: 2c2a838c-5a88-4b3a-ab9f-e884b92b9bec
.
We strongly recommend to use orderId
format that makes it easy to
search for them in logs. This means that abc123def456
is a better
format than 123456
.
Leading zeros should be avoided, as some applications (like Excel) tend to remove them, and this may cause misunderstandings.
With multiple sales units, prefixing the orderId
with the MSN
for each sales unit is recommended: If the MSN is 654321
, the
orderId
values could start at 654321000000000001
and increment by 1
for each order, or some similar, unique and readable pattern.
Agreements
An agreement is between the Vipps or 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.
Create an agreement
This is an example of a request body for the POST:/agreements
call:
{
"phoneNumber":"90000000",
"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 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 MobilePay app.productDescription
: More details about the subscription. Optional field.merchantAgreementUrl
: URL where Vipps can send the customer to view/manage their subscription. See Merchant agreement URL.
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, the centesimal subdivision of the Norwegian kroner (NOK). There are 100 øre in 1 krone.
# | 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:/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 or MobilePay in a mobile flow (with vipps://
), where the
user can then approve the agreement.
See landing page from Common topics, for more details about the landing page.
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.
Pricing representation
There are two different types of pricing available:
The first one is LEGACY
, this is the default type. See Amount limits for the limit rules.
Here is a truncated example of request body for the POST:/agreements
endpoint:
{
"pricing": {
"type": "LEGACY",
"amount": 100000,
"currency": "NOK"
},
"productName": "MyNews Digital",
"phoneNumber": "45678272",
"...": "..."
}
The second one is VARIABLE
. See variable amount.
Here is a truncated example of request body for the POST:/agreements
endpoint:
{
"pricing": {
"type": "VARIABLE",
"suggestedMaxAmount": 3000,
"currency": "NOK"
},
"productName": "MyNews Digital",
"phoneNumber": "45678272",
"...": "..."
}
Accept an agreement
The POST:/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 or 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 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 or 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 or MobilePay installed."isApp": true
: The user will get an error message saying that the link can not be opened.
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 Vipps 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:/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.
Vipps does not have any specific requirements for the security of the page, other than using HTTPS, but strongly recommend using Vipps MobilePay Login, so the user does not need a username or password, but is logged in automatically through Vipps MobilePay. See the Login API documentation for more details.
Intervals
Intervals are defined with an interval type 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.
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)
Please note: It is not possible to change intervals. See Can I change the charge interval?
Initial charge
Please note: If the subscription is cheaper in the beginning than the normal price later, use
campaigns in combination with initial charge.
If you use initialcharge
alone for campaigns, users will be confused by how it appears in Vipps,
as it looks like the full price period starts immediately.
Initial charge will be performed if the initialcharge
is provided when
creating an agreement. If there is no initial charge, don't send initialcharge
when creating the new agreement.
Unlike regular (or RECURRING
) charges, there is no price limit on an initialCharge
.
This allows for products to be bundled with agreements as one transaction
(for example, a phone). The user will be clearly informed when an initialCharge
is included in the agreement they are accepting.
See Charge Titles for explanation of how the charge description is shown to the user.
The initial charge has two forms of transaction, DIRECT_CAPTURE
and RESERVE_CAPTURE
.
DIRECT_CAPTURE
processes the payment immediately, while RESERVE_CAPTURE
reserves the payment for capturing at a later date. See:
What is the difference between "Reserve Capture" and "Direct Capture"
in the FAQ.
RESERVE_CAPTURE
must be
used when selling physical goods bundled with an agreement - such as a phone
when subscribing to an agreement.
This example shows the same agreement as above, with an initialCharge
of 499 NOK:
{
"phoneNumber": "90000000",
"initialCharge": {
"amount": 49900,
"description": "Premier League subscription",
"transactionType": "DIRECT_CAPTURE"
},
"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"
}
Change the transactionType
field to RESERVE_CAPTURE
to reserve the initial charge.
{
"initialCharge": {
"transactionType": "RESERVE_CAPTURE",
"amount": 19900,
"description": "Phone"
}
}
A reserved charge can be captured with the
POST:/agreements/{agreementId}/charges/{chargeId}/capture
endpoint
when the product is shipped.
Retrieve an agreement
A newly created agreement will be in status PENDING
for 10 minutes before it expires.
If the customer approves the agreement, and the initialCharge
(if provided) is successfully
processed, the agreement status will change to ACTIVE
.
The approved agreement is retrieved from the
GET:/agreements/{agreementId}
endpoint
with "status":"ACTIVE"
when the customer has approved the agreement. It is important to keep retrieving the agreement until the status is ACTIVE
, STOPPED
or EXPIRED
.
See Agreement states.
This is an example response from a call to the
GET:/agreements/{agreementId}
endpoint:
{
"id": "agr_ADbq4JK",
"created": "2018-08-22T12:59:56Z",
"start": "2018-08-22T13:00:00Z",
"stop": null,
"status": "ACTIVE",
"productName": "Premier League subscription",
"productDescription": "Access to all games of English top football",
"pricing": {
"type": "LEGACY",
"amount": 49900,
"currency": "NOK"
},
"interval": {
"unit" : "MONTH",
"count": 2,
"text": "every 2 months"
},
"campaign": null,
"merchantAgreementUrl": "https://www.merchant.no/subscriptions/1234/",
"uuid": "6080c099-d7f2-43ef-a82b-2991ccc3a239",
"countryCode": "NO"
}
Campaigns
A campaign in Recurring is a period where the price is lower than usual, and this is communicated to the customer with the original price shown for comparison. Campaigns cannot be used in combination with variable amount.
Campaigns in V2 API
In order to start a campaign, the campaign field must be added either to the
POST:/agreements
request
for a campaign in the start of an agreement, or to the
PATCH:/agreements/{agreementId}
request
for an ongoing agreement. When adding a campaign
while drafting a new agreement, the start date is ignored and the current
date-time is used. All dates must be in date-time format as according to
RFC-3339.
{
"campaign": {
"start": "2019-05-01T00:00:00Z",
"end": "2019-06-01T00:00:00Z",
"campaignPrice": 49900
}
}
Field | Description |
---|---|
start | Start date of campaign offer, if you are creating an agreement this is set to default now, and not an available variable |
end | End date of campaign offer, can not be in the past |
campaignPrice | The price that will be shown for comparison |
Campaigns in V3 API
In V3, we introduce 4 different campaign types: price campaign, period campaign, event campaign, and full flex campaign. See more about the different campaign types in the table below.
Campaign types | Description | Example |
---|---|---|
price campaign | Different interval price until specified date. Same interval as agreement. | 1kr every week until 2022-12-25T00:00:00Z and then 50kr every week |
period campaign | A set price for a given duration. A duration is defined by a number of periods (DAY, WEEK, MONTH, YEAR) | 10 weeks for 1kr and then 349kr every month |
event campaign | A set price until a given event date with a text describing the event | 1kr until Christmas and then 349kr every month |
full flex campaign | Different price and interval until a given date | 100kr every month until 2023-01-01T00:00:00Z and then 1000kr every year |
In order to start a campaign, the campaign
field has to be added to the agreement draft body in the
POST:/agreements
call.
Product description guidelines for agreements with campaigns
We do not recommend you to use Product Description
for agreements with a campaign.
We see that the user experience is not optimal when a lot of text is "squeezed" in the purple bubble displaying an agreement.
Price campaign
{
"campaign": {
"type": "PRICE_CAMPAIGN",
"end": "2022-12-25T00:00:00Z",
"price": 100
}
}
Field | Description |
---|---|
type | The type of the campaign |
price | The price that the customer will pay for each interval during the campaign |
end | The end date of the campaign |
Period campaign
{
"campaign": {
"type": "PERIOD_CAMPAIGN",
"price": 100,
"period": {
"unit": "WEEK",
"count": 10
}
}
}
Field | Description |
---|---|
type | The type of the campaign |
price | The price that the customer will pay for the period of the campaign |
period | The period where the campaign price is applied. Consist of a Unit and a Count, example; { "unit": "MONTH", "count": 1 } |
Event campaign
{
"campaign": {
"type": "EVENT_CAMPAIGN",
"price": 100,
"eventDate": "2022-09-01T00:00:00Z",
"eventText": "To the end of august"
}
}
Field | Description |
---|---|
type | The type of the campaign |
price | The price that the customer will pay until the event date |
eventDate | The date of the event marking the end of the campaign |
eventText | The event text to display to the end user |
Please note: We recommend starting the event text with lowercase for better user experience. See example below.
Full flex campaign
Please note: Contact Vipps before creating a draft agreement with a full flex campaign. See contact us.
{
"campaign": {
"type": "FULL_FLEX_CAMPAIGN",
"price": 10000,
"end": "2023-01-01T00:00:00Z",
"interval": {
"unit": "MONTH",
"count": 1
}
}
}
Field | Description |
---|---|
type | The type of the campaign |
price | The price that the customer will pay for each interval during the campaign |
end | The end date of the campaign |
interval | The payment interval where the campaign price is applied. Consist of a Unit and a Count, example; { "unit": "MONTH", "count": 1 } |
Charges
An agreement has payments, called charges.
Create a charge
Each specific charge on an agreement must be scheduled by the merchant.
To create a charge use the POST:/agreements/{agreementId}/charges
endpoint.
Also see check Recommendations for reference
and orderId
before creating charges.
For agreements of type variable
, also see Recurring agreements with variable amount.
Due date
due
will define for which date the charge will be performed.
This date has to be minimum two days (one day in the test environment) in the future and maximum two years in advance.
The minimum is set to two days because the user should be able to see the upcoming charge in the Vipps app. All charges due
in 35 days or less are visible under the "Payments tab" in the Vipps app.
Example: If the charge is created on the 25th, the earliest the charge can be due is the 27th (25+2). This is so that the user can be informed about the upcoming charge. The user is only shown one charge per agreement, in order to not overwhelm the user when doing daily or weekly charges.
Please note: You can request to be put on a "one day minimum" allow list if
you have a need to be able to create charges that are DUE
1 day after being
created. This means that a charge can be created to be DUE
the next day.
Example: If the charge is created at any time on the 25th, the charge can be
due and processed at the 26th.
Amount
Charge type
A recurring charge has two forms of transaction, DIRECT_CAPTURE
and RESERVE_CAPTURE
.
Please note: RESERVE_CAPTURE
transaction type is only available in the V3 API.
DIRECT_CAPTURE
processes the payment immediately, while RESERVE_CAPTURE
reserves the payment for capturing at a later date. See:
What is the difference between "Reserve Capture" and "Direct Capture"?
in the Vipps FAQ for more details.
RESERVE_CAPTURE
must be used when selling physical goods or a need to provide access at a later point.
The advantage to using reserve capture is that you can release the reservation immediately:
- For a reserved payment, the merchant can make a /cancel call to immediately release the reservation and make it available in the customer's account.
- For a captured payment, the merchant must make a /refund call. It then takes a few days before the amount is available in the customer's account.
Capture a charge
Capture payment allows the merchant to capture the reserved amount of a charge. The API allows for both a full amount capture and a partial amount capture (V3 API only)
The amount to capture cannot be higher than the reserved amount.
According to Norwegian regulations, capture cannot be done before the goods have been shipped.
The description
text is mandatory and is displayed to the end user in the Vipps app.
Capture is done with the POST:/agreements/{agreementId}/charges/{chargeId}/capture
endpoint.
Please note: It is important to check the response of the /capture
call.
The capture is only successful when the response is HTTP 204 No Content
.
Capture can be made up to 180 days after reservation. Attempting to capture an older payment will result in HTTP 400 Bad Request
.
Partial capture
V3 API only: Partial capture may be used in cases where a partial order is shipped or for other reasons. Partial capture can be called as many times as required while remaining reserved amount is available.
If one or more partial capture have been made, any remaining reserved amount will be automatically released after a few days. See For how long is a payment reserved in the Vipps FAQ for more details.
If you cancel a charge that is PARTIALLY_CAPTURED
, the remaining funds on the charge will be released back to the customer.
Amount limits
LEGACY
pricing (default)
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, in the agreement
above
a limit of 2495 NOK (499 x 5) would be in place. 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.
VARIABLE
pricing
The user chooses a max amount themselves when accepting the agreement based on the recommended suggestedMaxAmount
. There is currently a limit of 20 000 NOK for the suggestedMaxAmount
.
The max amount can at any time be changed by the user.
Charge descriptions
When charges are shown to users in the app, they will have a title, and a
description. The title of a charge is derived directly from
{agreement.productName}
whereas the description is set per charge, i.e.
{charge.description}
. For example, a charge on an agreement with product
name "Premier League subscription" with description "October" would look like
the following screenshot:
When the charge is completed (the money has been moved), the payment will
show up in the users' payment history. In the payment history a charge from
Vipps recurring payment will have a description with follow format
{agreement.ProductName} - {charge.description}
.
This is an example of a request body for the POST:/agreements/{agreementId}/charges
call:
{
"amount": 49900,
"transactionType": "DIRECT_CAPTURE",
"description": "October",
"due": "2018-09-01",
"retryDays": 5
}
Please note: description
cannot be longer than 45 characters.
Cancel a charge
You can cancel charges that are in the PENDING
, DUE
or RESERVED
state.
If you cancel a charge that is PARTIALLY_CAPTURED
, the remaining funds on the charge will be released back to the customer.
Please note: If you cancel an agreement, there is no need to cancel the charges that belong to the agreement. This will be done automatically by Vipps.
A charge can be cancelled with the
POST:/agreements/{agreementId}/charges/{chargeId}
endpoint.
Refund a charge
A charge can be refunded with the `POST:/agreements/{agreementId}/charges/{chargeId}/refund endpoint.
Charge times
Charge attempts are primarily made two times during the day: 07:00 and 15:00 UTC.
Vipps may do extra attempts and/or change this without notice.
The processing of charges typically takes around one hour, however this varies, and we do not guarantee any time.
This is the same both for our production and test environment.
Subsequent attempts are made according to the retryDays
specified.
When a charge has reached its due
date, the status of the charge will be
DUE
until the charge is successful, for as long as the merchant has
specified with retryDays
. On other words: There are no status updates
while Vipps is attempting to charge.
Important: Vipps does not "leak" the customers' information about insufficient funds, blocked cards, etc. Users are informed about all such problems in Vipps, which is the only place they can be corrected. The merchant's customer service should always ask the user to check in Vipps if a charge has failed.
Please note: Payments might get processed any time during the day (07:00 UTC - 23:59 UTC) due to special circumstances requiring it.
Please note: Since payments can be processed any time (07:00UTC - 23:59 UTC) it is advisable to fetch the charge at/after 00:00 UTC the day after the last retry day to be sure you get the last status.
Charge retries
Vipps will retry the charge for the number of days specified in retryDays
.
The maximum number of retryDays
is 14.
This means that if the user's card has insufficient funds, the card has expired, the card is invalid, etc.: The user is notified and can correct the problem. Vipps will make sure the user is able to pay.
IMPORTANT: Vipps does not provide details about each charge attempt to the merchant, but helps the user to correct any problems in Vipps. This results in a very high success rate for charges.
The retryDays
are not tied to the agreement’s interval. This means that a charge
can be retried for a maximum of 14 days even though the next interval has started.
For example, an agreement with daily interval can have a charge retried for
multiple days, and it is possible to create new daily charges while others are
still retrying.
The status of a charge will be DUE
while Vipps is taking care of business,
from the due
date until the charge has succeeded, or until the
retryDays
have passed without a successful charge.
The final status will be CHARGED
or FAILED
.
See: Charge states.
Retrieve a charge
To retrieve a charge, we recommend using the GET:/agreements/{agreementId}/charges/{chargeId}
endpoint.
Please note: The endpoint GET:/charges/{chargeId}
is not intended for automation.
There is a stricter rate limiting (See Rate limiting) on this endpoint because it is more expensive to fetch a charge without the agreementId.
Its purpose is to simplify investigations when the merchant lost track of which charge belongs to which agreement.
It should not be used as a substitute for the GET:/agreements/{agreementId}/charges/{chargeId}
endpoint.
Details on charges
The response from the GET:/agreements/{agreementId}/charges/{chargeId}
endpoint
contains the history of the charge and not just the current status.
It also contains a summary of the total of amounts captured, refunded and cancelled.
Truncated example of the response from the GET:/agreements/{agreementId}/charges/{chargeId}
endpoint:
{
"id": "chr_WCVbcA",
"status": "REFUNDED",
"amount": 1000,
"type": "RECURRING",
"transactionType": "RESERVE_CAPTURE",
"...": "...",
"summary": {
"captured": 1000,
"refunded": 600,
"cancelled": 0
},
"history": [
{
"occurred": "2022-09-14T10:31:15Z",
"event": "CREATE",
"amount": 1000,
"idempotencyKey": "e80bd8c6-3b83-4583-a49c-847021fcd839",
"success": true
},
{
"occurred": "2022-09-16T06:01:00Z",
"event": "RESERVE",
"amount": 1000,
"idempotencyKey": "chr-4assY8f-agr_FJw2Anb-ProcessPayment",
"success": true
},
{
"occurred": "2022-09-18T06:01:00Z",
"event": "CAPTURE",
"amount": 1000,
"idempotencyKey": "096b1415-2c77-4001-9576-531a856bbaf4",
"success": true
},
{
"occurred": "2022-09-20T06:01:00Z",
"event": "REFUND",
"amount": 600,
"idempotencyKey": "0bc7cc3b-fdef-4d24-b4fe-49b7da40d22f",
"success": true
}
]
}
Please note: failureReason
and failureDescription
are experimental, and
will be replaced by an event log. Subscribe to the technical newsletter
to get updates: Technical newsletter for developers.
See more about charge failure reason.
See: Charge states.
List charges
All charges, including the optional initial charge, for an agreement can be retrieved with the
GET:/agreements/{agreementId}/charges
endpoint.
Manage charges and agreements
It is the merchant's responsibility to manage and update charges and agreements, and to use the API to make sure everything is in sync.
Agreement states
# | State | Description |
---|---|---|
1 | PENDING | Agreement has been created, but not approved by the user in Vipps yet |
2 | ACTIVE | The agreement has been confirmed by the end user in Vipps and can receive charges |
3 | STOPPED | Agreement has been stopped, either by the merchant by the PATCH:/agreements/{agreementId} endpoint, or by the user by cancelling or rejecting the agreement. |
4 | EXPIRED | The user did not accept, or failed to accept (due to processing an initialCharge ), the agreement in Vipps |
Update an agreement
A merchant can update an agreement by calling the
PATCH:/agreements/{agreementId}
endpoint.
The following properties are available for updating:
{
"productName": "A new name",
"productDescription": "A new description",
"merchantAgreementUrl": "https://example.com/vipps-subscriptions/1234/",
"pricing": {
"amount": 25000,
"suggestedMaxAmount": 300000
}
}
Updating amount
is only possible for agreements with pricing.type:LEGACY
Updating suggestedMaxAmount
is only possible for agreements with pricing.type:VARIABLE
Please note: As a PATCH
operation all parameters are optional. However,
when setting an agreement status to STOPPED
no other changes are allowed.
Attempts at changing other properties while stopping an agreement will result
in a 400 Bad Request
response.
Pause an agreement
Today unfortunately we do not have a pause/freeze status. This is something we are looking into. If there should be a pause in an agreement, like a temporary stop of a subscription: Simply do not create any charges during the pause. We recommend to use Agreement Description to communicate to the user that the agreement is paused/frozen.
We recommended not to set the agreement status to STOPPED
. STOPPED
agreements cannot be reactivated.
Stop an agreement
When a user notifies the merchant that they want to cancel a subscription or
service, the merchant must ensure that the status of the recurring agreement is
set to STOPPED
at a suitable time.
A merchant can stopped an agreement by calling the PATCH:/agreements/{agreementId}
endpoint.
Request body for stopping an agreement:
{
"status": "STOPPED"
}
Stopping an agreement results in cancellation of any charges that are DUE/PENDING/RESERVED at the time of stopping it, and it will not be possible to create new charges for a stopped agreement.
We recommend that the recurring agreement remains ACTIVE
for as long as the
user has access to the service.
For example; if the user cancels their subscription, but they are still able to
use the service until the end of the billing cycle, the agreement should only be
set to STOPPED
at the end of the billing cycle.
Since STOPPED
agreements cannot be reactivated, a benefit of waiting until
the "end of service" before setting the agreement status to STOPPED
is that
the merchant will be able to reactivate the user's subscription without having
to set up a new agreement.
Charge states
This table has all the details for the charge states returned by the
GET:/agreements/{agreementId}/charges/{chargeId}
endpoint:
State | Description |
---|---|
PENDING | The charge has been created, but is not yet be visible in Vipps. |
DUE | The charge is visible in Vipps and will be processed on the due date. |
PROCESSING | The charge is being processed right now. |
UNKNOWN | The charge status is unknown. This is usually very transient and will be resolved shortly. |
CHARGED | The charge has been successfully processed, and the available amount has been captured. |
FAILED | The charge has failed because of insufficient funds, no valid cards, etc. Vipps gives the user all possible opportunities to pay, including adding a new card, but does not provide the details to the merchant. |
REFUNDED | The charge has been refunded. Refunds are allowed up to 365 days after the capture date. |
PARTIALLY_REFUNDED | A part of the captured amount has been refunded. |
RESERVED | The charge amount has been reserved, and can now be captured POST:/agreements/{agreementId}/charges/{chargeId}/capture |
PARTIALLY_CAPTURED | Part of the reserved amount has been captured. If you do not plan on capturing the rest, you should cancel the remaining amount to release the funds to the customer. |
CANCELLED | The charge has been cancelled. |
IMPORTANT: Vipps does not provide details about each charge attempt to the merchant, but helps the user to correct any problems in Vipps. This results in a very high success rate for charges.
Example charge flows
Scenario: Everything goes as it should: The user has money, and the charge is successful on the due
date:
PENDING
->DUE
(just for the one due day)->CHARGED
Scenario: The user does not have funds and retryDays = 0
:
PENDING
->DUE
->FAILED
Scenario: The user does not have funds on the due
date, retryDays = 10
, and has funds on the fifth day:
PENDING
->DUE
(for five days) ->CHARGED
Please note: Since charges are polled by the merchant, it is possible that
the charge status appears to "skip" a transition, e.g. moving directly from
PENDING
to CHARGED
, or even from PENDING
to REFUNDED
depending on your systems.
Charge failure reasons
Please note: failureReason
and failureDescription
are experimental, and
will be replaced by an event log. Subscribe to the technical newsletter
to get updates: Technical newsletter for developers.
When fetching a charge through the API, you can find two fields in the response
body to identify why the charge failed failureReason
and failureDescription
.
An example from a response:
{
"status": "FAILED",
"type": "RECURRING",
"failureReason": "user_action_required",
"failureDescription": "User action required"
}
Here is a list of possible values for failureReason
, their respective descriptions and possible actions that the user/merchant could take.
Reason | Description | Action |
---|---|---|
user_action_required | Payment failed. Could be lack of funds, card is blocked for ecommerce, card is expired. If you want to send an email or similar to the user, you should encourage them to open Vipps and check the payment there to see why it is not paid. | User will get notified in Vipps and need to take action. This could be to add funds to the card or change the card on the agreement. |
charge_amount_too_high | Amount is higher than the user's specified max amount. | The user has a lower maxAmount on the variableAmount agreement than the amount of the charge. The user must update their maxAmount on the agreement for the charge to be processed. |
non_technical_error | Payment failed. Could be that the user has deleted their Vipps profile. | The user needs to take action in Vipps. |
technical_error | Payment failed due to a technical error in Recurring or a downstream service. | As long as the charge is not in the status FAILED , we are retrying the payment. Contact Vipps for more information if this failure shows up on a FAILED charge. |
App
The user will be able to see these failures in Vipps and take the necessary action.
Example if a user has an expired card:
Deprecated failureReasons
The following failureReasons
are no longer exposed on charges:
Reason | Description | Action |
---|---|---|
insufficient_funds | Payment was declined by the payer bank due to lack of funds. | User must either add funds to the card to cover the difference between the amount to be paid. Alternatively they can change to another, or add a new, payment source that is adequately funded to complete the transaction. |
invalid_card | The user tried to pay using a card that has either expired or is disabled by the issuer. | User must change, or add a new, payment source on the agreement in Vipps. |
verification_required | Payment declined because the issuing bank requires verification. | Ask the user to change, or add a new, payment source on their agreement in Vipps. Alternatively removing and then adding the card might solve the issue. |
invalid_payment_source | The provided payment source is disabled or does not exist. | User must change payment source for the agreement. |
internal_error | Internal Error / Something went wrong | The error could not be identified as one of the above. Try to create the charge again, changing or adding payment sources on the agreement, or contact Vipps for more information. |
The user gets more information in Vipps regarding why the charge did not get processed. If they contact you about failing charges, you should refer them to Vipps. As long as the charge has retryDays
left, we will continue to try and process the charge and notify the user.
Userinfo
Vipps offers the possibility for merchants to ask for the user's profile information as part of the payment flow. This is also called "Profile Sharing".
To enable the possibility to fetch profile information for a user the merchant can add a
scope
parameter to the POST:/agreements
call.
See the Userinfo API guide for details.
Userinfo call by call guide
Scenario: You want to complete a payment and get the name and phone number of a customer.
- Retrieve the access token by calling the
POST:/accesstoken/get
endpoint. - Add the scope field to the draft agreement request body and include the scope you wish to get
access to (valid scope) before calling the
POST:/agreements
endpoint. - The user consents to the information sharing and accepts the agreement in Vipps.
- Retrieve the
sub
by calling theGET:/agreements/{agreementId}
endpoint. - Using the sub from step 4, call the
GET:/vipps-userinfo-api/userinfo/{sub}
endpoint to retrieve the user's information.
Important note: The API call to the GET:/vipps-userinfo-api/userinfo/{sub}
endpoint
must not include the subscription key (the Ocp-Apim-Subscription-Key
header) used for the Recurring API.
This is because userinfo is part of Vipps Login and is therefore not under the same subscription,
and will result in a HTTP Unauthorized 401
error.
Example calls
To request this scope, add the scope to the initial POST:/agreements
call
Example of request with scope:
{
"phoneNumber":"90000000",
"interval": {
"unit": "MONTH",
"count": 1
},
"merchantRedirectUrl": "https://example.com/confirmation",
"merchantAgreementUrl": "https://example.com/my-customer-agreement",
"pricing": {
"type": "LEGACY",
"amount": 49900,
"currency": "NOK"
},
"productDescription": "Access to all games of English top football",
"productName": "Premier League subscription",
"scope": "address name email birthDate phoneNumber"
}
The user then consents and pays in Vipps.
Please note: This operation has an all or nothing approach, a user must complete a valid agreement and consent to all values in order to complete the session. If a user chooses to reject the terms the agreement will not be processed. Unless the whole flow is completed, this will be handled as a regular failed agreement by the recurring APIs.
Once the user completes the session a unique identifier sub
can be retrieved with the
GET:/agreements/{agreementId}
endpoint, alongside the full URL to Userinfo.
Example sub
and userinfoUrl
format:
{
"sub": "c06c4afe-d9e1-4c5d-939a-177d752a0944",
"userinfoUrl": "https://api.vipps.no/vipps-userinfo-api/userinfo/c06c4afe-d9e1-4c5d-939a-177d752a0944"
}
This sub
is a link between the merchant and the user and can be used to retrieve
the user's details from the Vipps GET:/vipps-userinfo-api/userinfo/{sub}
endpoint.
The sub
is based on the user's national identity number ("fødselsnummer"
in Norway), and does not change (except in very special cases).
Please note: It is recommended to get the user's information directly after
completing the transaction. There is however a time limit of 168 hours
(one week) to retrieve the consented profile data from the /userinfo
endpoint to
better support merchants that depend on manual steps/checks in their process of
fetching the profile data. The merchant will get the information that is in the
user profile at the time when they actually fetch the information. This means
that the information might have changed from the time the user completed the
transaction and the fetching of the profile data.
Userinfo call
This endpoint returns the payload with the information that the user has consented to share.
Call the Vipps GET:/vipps-userinfo-api/userinfo/{sub}
endpoint with the sub
that was retrieved earlier.
See the Userinfo call for details.
Recurring agreements with variable amount
Recurring with variable amounts offer merchants a way to charge users a different amount each interval, as long as the amount is lower than the user's specified max amount.
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 interval.
This suggestedMaxAmount
is presented to the user together with a list of auto generated amount suggestions that is created by Vipps.
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.
Create agreement
Create an agreement and specify that it's with variableAmount
and set a
suggestedMaxAmount
(in øre).
Create agreement request:
{
"pricing": {
"suggestedMaxAmount": 200000,
"currency": "NOK",
"type": "VARIABLE"
},
"interval": {
"unit" : "MONTH",
"count": 1
},
"merchantRedirectUrl": "https://example.com/confirmation",
"merchantAgreementUrl": "https://example.com/my-customer-agreement",
"phoneNumber": "90000000",
"productDescription": "Access to subscription",
"productName": "Power company A"
}
Restrictions when using variable amount:
- There is currently a limit of 20 000 NOK for the
suggestedMaxAmount
. Campaign
can not be used when the agreement hasvariableAmount
.
The user will be presented with the variable agreement in Vipps, where they can change the max amount they allow to be charged each interval.
In this example the suggestedMaxAmount
is 5 000 kr, this amount gets pre-selected in Vipps.
The user clicks on "maksbeløp" (max amount) and opens the list of auto generated suggestions together with the suggestedMaxAmount
.
The text above the list explains that the merchant recommends the user to set their max amount to 5 000 kr.
The user proceeds with 5 000 kr and accepts the agreement.
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.
Accepting agreement in Vipps:
Variable amount and initial charge can be combined:
Get agreement
Retrieving the agreement shows the maxAmount
picked by the user.
GET:/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:/agreements/{agreementId}
request below.
{
"suggestedMaxAmount": 300000
}
Please note: The user will not be alerted by this change by Vipps.
Create charge
The amount of the charge/charges in the interval can not be higher than the suggestedMaxAmount
or maxAmount
field, depending on which is highest.
Examples:
- If
suggestedMaxAmount
is set to 5 000 kr andmaxAmount
chosen by the user is 2 000 kr then the charge amount can not be higher than 5 000 kr - If
suggestedMaxAmount
is set to 5 000 kr andmaxAmount
chosen by the user is 7 000 kr then the charge amount can not be higher than 7 000 kr
Charge amount higher than the user's max amount
If the amount of a charge is below (or equal) the suggestMaxAmount
but above the user's maxAmount
, the charge will be set
to DUE
and the user will be notified and encouraged to alter the max amount to a higher amount.
If the user does not update their maxAmount
to the same or a higher amount than the charge, it will fail when due
+ retryDays
is reached, and
the status will be FAILED
.
The user will also see a failure description on the charge in the Vipps app.
Display of charge failure due to a charge being higher than the maxAmount
in Vipps:
Skip landing page
This functionality is only available for special cases.
See: Landing page
If the skipLandingPage
property is set to true
in the
POST:/agreements
call, it will cause a push notification to be sent to the given phone number
immediately, without loading the landing page.
If the sales unit is not whitelisted, the request will fail and an error message will be returned.
HTTP responses
This API returns the following HTTP statuses in the responses:
HTTP status | Description |
---|---|
200 OK | Request successful |
204 No content | Request successful |
202 Accepted | Request accepted, indicates that the request has been accepted for processing, but the processing has not been completed yet. |
400 Bad Request | Invalid request, see the error for details |
401 Unauthorized | Invalid credentials |
403 Forbidden | Authentication ok, but credentials lacks authorization |
404 Not Found | The resource was not found |
409 Conflict | Unsuccessful due to conflicting resource |
422 Unprocessable Entity | Vipps could not process |
429 Too Many Requests | Look at table below to view current rate limits |
500 Server Error | An internal Vipps problem. |
Please note: Responses might include a Retry-After
-header that will indicate the earliest time you should
retry the request or poll the resource to see if an operation has been performed.
This will follow the spec as defined here,
and will either be a http-date or a number indicating a delay in seconds.
This will mostly apply to 429 responses, but may also appear in certain other circumstances where it would be natural
to retry the request at a later point in time.
Error responses
HTTP responses for errors follow the RFC 7807 standard.
See: Errors.
Rate limiting
We have added rate-limiting to our API (HTTP 429 Too Many Requests
) to prevent
fraudulent and wrongful behavior, and increase the stability and security of
our API. The limits should not affect normal behavior, but please
contact us
if you notice any unexpected behavior.
The "Key" column specifies what we consider to be the unique identifier, and what we "use to count". The limits are of course not total limits.
API | Limit | Key used | Explanation |
---|---|---|---|
CreateCharge | 2 per minute | agreementId + chargeId (based on idempotency key) | Two calls per minute per unique agreementId and chargeId |
CancelCharge | 5 per minute | agreementId + chargeId | Five calls per minute per unique agreementId and chargeId |
CaptureCharge | 5 per minute | agreementId + chargeId | Five calls per minute per unique agreementId and chargeId |
RefundCharge | 5 per minute | agreementId + chargeId | Five calls per minute per unique agreementId and chargeId |
ListAgreements | 5 per minute | (per merchant) | Five calls per minute per merchant |
UpdateAgreement | 5 per minute | agreementId | Five calls per minute per unique agreementId |
FetchCharge | 10 per minute | agreementId + chargeId | Ten calls per minute per unique agreementId and chargeId |
FetchChargeById | 100 per minute | chargeId | Hundred calls per minutes per merchant |
ListCharges | 10 per minute | agreementId | Ten calls per minute per unique agreementId |
FetchAgreement | 120 per minute | agreementId | 120 calls per minute per unique agreementId |
DraftAgreement | 300 per minute | (per merchant) | 300 calls per minute per merchant |
Please note: The "Key" column is important. The above means that we allow two CreateCharge calls per minute per unique agreementId and chargeId. This is to prevent too many CreateCharge calls for the same charge. The overall limit for number of different payments is far higher than 2.
Please note: Responses might include a Retry-After
-header that will indicate the earliest time you should
retry the request or poll the resource to see if an operation has been performed.
This will follow the spec as defined here,
and will either be a http-date or a number indicating a delay in seconds.
This will mostly apply to 429 responses, but may also appear in certain other circumstances where it would be natural
to retry the request at a later point in time.
Partner keys
In addition to the normal Authentication we offer partner keys, which let a partner make API calls on behalf of a merchant.
If you are a Vipps partner managing agreements on behalf of Vipps merchants you
can use your own API credentials to authenticate, and then send
the Merchant-Serial-Number
header to identify which of your merchants you
are acting on behalf of. The Merchant-Serial-Number
must be sent in the header
of all API requests.
By including the Vipps HTTP Headers you will make
it easier to investigate problems, if anything unexpected happens. Partners may
re-use the values of the Vipps-System-Name
and Vipps-System-Plugin-Name
in
the plugins headers if having different values do not make sense.
Here's an example of headers (please refer to the OpenAPI specification for all the details):
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1Ni <snip>
Ocp-Apim-Subscription-Key: 0f14ebcab0ec4b29ae0cb90d91b4a84a
Merchant-Serial-Number: 123456
Vipps-System-Name: acme
Vipps-System-Version: 3.1.2
Vipps-System-Plugin-Name: acme-pos
Vipps-System-Plugin-Version: 4.5.6
Content-Type: application/json
Please note: The Merchant Serial Number (MSN) is a unique ID for the sale unit. This is a required parameter if you are a Vipps partner making API requests on behalf of a merchant. The partner must use the merchant's MSN, not the partner's MSN. This parameter is also recommended for regular Vipps merchants making API calls for themselves.
See: Vipps Partners.
Polling guidelines
General guidelines for polling with the
GET:/agreements/{agreementId}
endpoint can be found at:
See Polling guidelines in Common topics, for details.
Notifications to users for failed charges
We notify the user in two ways, through push notifications and failure texts on the charge. When a charge fails to be processed, we send the user a push notification letting them know the charge failed to process. This push message is sent every time we try to process the charge, see charge times for when the processing of charges happen. More information about how and when we send push notifications can be found in the FAQ.
Please note: We send push notification for failed payments regardless if Notification upon payment
is toggled on or off on the agreement.
This toggle only determine if the user will get notified when a charge is successfully charged.
In addition to sending push notifications, a failure texts is also set on the charge.
By letting the customer know why the charge failed we enable them to fix the underlying issue before the retryDays
are over.
For more information about what the failure texts are, see the FAQ.
Please note: These exact reasons why the charge fails is not shown in the recurring API, only to the customers (users). See charge failure reason for an overview of what is available in the merchant API.
Timeouts
Testing
To facilitate automated testing in the
Vipps Test Environment (MT),
the Vipps Recurring API provides a force accept agreement
endpoint to avoid manual
agreement acceptance in the Vipps app:
The "force approve" endpoint allows developers to approve a payment through the Vipps Recurring API without the use of Vipps. This is useful for automated testing. The endpoint is only available in our test environment.
Recommendations regarding handling redirects
See Recommendations regarding handling redirects in Common topics for details.
Different agreement types and when to use them
Vipps recurring payments is a fairly flexible service, that allows you as a merchant to tailor the user experience in Vipps to your needs by utilizing the normal agreements, initial charges, campaigns, or a combination of those.
This can be a bit confusing when deciding on which implementation to go for. In short our advice is to implement support for all our flows, and also implement features in your own systems for moving between the flows depending on the use case.
Normal agreement
This is the preferred flow whenever there is no campaign or no required payment on the start of an agreement.
In the normal agreement, the user gets presented with the agreement, agrees to it, and gets sent to a confirmation screen.
On the agreement we present the start date, the price of the agreements, the productName
and the product description
which are all defined by the merchant.
We also present an agreement explanation which is used to describe the agreement interval to the user.
For example, for an agreement with interval.unit=YEAR
and interval.count=1
, the agreement explanation will be hvert år til du sier opp
or every year until cancelled
Agreement with initial charge
If you require a payment to be completed at the same time that the agreement is created, you must use initial charge.
When an initial charge is present and the amount is different from the agreement price (or campaign price), the flow in Vipps will change. First the user gets presented with an overview over both the agreement and the initial charge. Then, when the user proceeds to confirm the agreement, the payment of the initial charge will be processed.
Here we also show productName
and the agreement explanation on the agreement, as well as description
on the initial charge. productName
and initial charge description
are defined by the merchant. The agreement explanation is created by Vipps based on the interval and the campaign if specified.
Initial charges are designed to be used whenever there is an additional cost in setting up the agreement. This could be bundling of a mobile phone together with a mobile subscription, or a TV setup-box when becoming a customer at a cable company. We do not recommend this flow to be used purely for campaigns, as it could be confusing to the user.
As an example: If you have a campaign of 10 NOK for a digital media subscription for 3 months, and the normal price is 299,- monthly, the user would see both the charge of 10 NOK, and have to confirm the agreement for 299,- monthly, which can lead the user to believe that both will be paid upon entering the agreement.
Agreement with campaign
This is the preferred flow whenever you have a type of campaign where the subscription has a certain price for a certain interval or time, before it switches over to ordinary price.
See Campaigns and How it works: Campaigns for details about campaigns.
When setting a campaign, this follows the normal agreement flow - with some changes. Instead of showing the ordinary price of the agreement, the campaign price will override this, and the ordinary price will be shown below together with information about when the change from the campaign price to the ordinary price will happen.
Please note: Campaign is not supported for variableAmount
agreements.
Agreement with initial charge and campaign
Ideally, this flow is intended for when you have a combination of an additional cost when setting up the agreement, presented as the initial charge, as well as having a limited time offer on the actual subscription.
In addition to campaigns and initial charges being available as individual flows, they can also be combined. In this case, the user would see first a summary of both the agreement, including the campaign as described in the sections on campaigns, as well as the initial charge. Again, all fields described in previous flows are available for the merchant to display information to the user.
Agreement screens with initial and campaign v2
Agreement screens with initial and campaign v3