> **Description:** Step-by-step guide to implementing your first recurring payment, from initial setup to processing recurring charges.

> **AI agent:** Read [https://developer.vippsmobilepay.com/docs/knowledge-base/ai-tools.md](https://developer.vippsmobilepay.com/docs/knowledge-base/ai-tools.md) first. It covers keeping API keys and secrets out of generated code.

> **Full site overview:** For an overview of the entire site, read [https://developer.vippsmobilepay.com/llms.txt](https://developer.vippsmobilepay.com/llms.txt).

# Quick start

This guide takes you through all the Recurring API requests.

## Before you begin

Sign up as an organization with Vipps MobilePay and get your API keys.

#### Merchants

You will need the [sales unit API keys](https://developer.vippsmobilepay.com/docs/knowledge-base/api-keys.md) for a *test* sales unit:

* `client_id` - Client ID for the sales unit.
* `client_secret` - Client secret for the sales unit.
* `Ocp-Apim-Subscription-Key` - The subscription key for making API requests.
* `merchantSerialNumber` - The unique ID (MSN) for the sales unit.

#### Partners

[Partner keys](https://developer.vippsmobilepay.com/docs/partner/partner-keys.md#partner-keys) only work in the production environment.
To follow this guide in the test environment, use the test sales unit API keys provided in your welcome email.

In production, partner keys are used exactly like sales unit API keys, with one difference:
the `Merchant-Serial-Number` header is *required*, not just recommended.

If you're new to the platform, see
[Integration quick start guide](https://developer.vippsmobilepay.com/docs/getting-started.md)
for information about API keys, product activation, and the test environment.

The example values in this guide must be replaced with the values for your sales unit and user.
This applies to API keys, HTTP headers, references, phone numbers, and similar values.

## Your first agreement

### Step 1 - Setup

#### API client

Download the following files. They are in the
[Postman collection format](https://developer.vippsmobilepay.com/docs/knowledge-base/api-collections.md), so you can use them in Postman or import them
into another API client.

Update the environment with your own values for the API keys and mobile number. *Don't store production keys in the cloud.*

* [Download Recurring API collection](https://developer.vippsmobilepay.com/tools/recurring-v3-api-postman-collection.json)
* [Download global environment](https://developer.vippsmobilepay.com/tools/global-postman-environment.json)

**TIP**

If you are using Bruno with multiple environments together, you may see conflicts and strange behavior. To avoid this,
import your environment file into each collection, instead of using it as a global environment.

#### curl

No setup is needed. Continue to [Step 2](#step-2---get-an-access-token).

### Step 2 - Get an access token

For all the following, you will need an `access_token` from the
[Access Token API](https://developer.vippsmobilepay.com/docs/APIs/access-token-api/README.md):
[`POST:/accesstoken/get`][access-token-endpoint].
This provides you with access to the API.

#### API client

```text
Send request "Get Access Token"
```

#### curl

```bash
curl -X POST 'https://apitest.vipps.no/accesstoken/get' \
-H "Content-Type: application/json" \
-H 'client_id: YOUR-CLIENT-ID' \
-H 'client_secret: YOUR-CLIENT-SECRET' \
-H 'Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY' \
-H 'Merchant-Serial-Number: YOUR-MSN' \
--data ''
```

In production, include all `Vipps-System` headers to aid debugging.
See [HTTP headers](https://developer.vippsmobilepay.com/docs/knowledge-base/http-headers.md) for details.

The property `access_token` should be used as the Bearer token in the `Authorization` header of all the following API requests.

### Step 3 - Create a minimal agreement

Create an agreement with: [`POST:/recurring/v3/agreements`][draft-agreement-endpoint].
When your test mobile number is provided in `phoneNumber`, it will be prefilled in the form.

Note that `orderId` must be unique for each payment you create.

#### API client

Set the `Idempotency-Key-Draft` value in your active environment.

```text
Send request "Draft Agreement - Legacy pricing"
```

#### curl

```bash
curl -X POST https://apitest.vipps.no/recurring/v3/agreements/ \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H 'Idempotency-Key: YOUR-IDEMPOTENCY-KEY' \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-H "Vipps-System-Plugin-Name: acme-webshop" \
-H "Vipps-System-Plugin-Version: 4.5.6" \
-d '{
   "interval": {
      "unit" : "WEEK",
      "count": 2
   },
   "pricing": {
      "amount": 1000,
      "currency": "NOK"
   },
   "merchantRedirectUrl": "https://example.com/redirect-url",
   "merchantAgreementUrl": "https://example.com/agreement-url",
   "phoneNumber": "12345678",
   "productName": "Test product"
}'
```

### Step 4 - Authorize the agreement

Open the `vippsConfirmationUrl` link that is returned in the previous step. It will take you to the
[landing page](https://developer.vippsmobilepay.com/docs/knowledge-base/landing-page.md).
The phone number of your test user should already be filled in, so you only have to click *Next*.

You will be presented with the agreement in the app, where you can authorize and be directed to the specified `merchantRedirectUrl` under a "best effort" policy.

**NOTE**

We cannot guarantee the user will be redirected back to the same browser or session, or that they will at all be redirected back. User interaction can be unpredictable, and the user may choose to fully close the app or browser.

You should now have an active agreement.
Take note of the value included in `agreementId`, as you will need this to access the agreement later.

### Step 5 - Fetch the agreement

To receive the result of the user action, you may poll the status of the agreement with:
[`GET:/recurring/v3/agreements/{agreementId}`][fetch-agreement-endpoint].

#### API client

```text
Send request "Get Agreement"
```

#### curl

```bash
curl -X GET https://apitest.vipps.no/recurring/v3/agreements/UNIQUE-AGREEMENT-ID \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-H "Vipps-System-Plugin-Name: acme-webshop" \
-H "Vipps-System-Plugin-Version: 4.5.6" \
```

If you confirmed the agreement, the status should be ACTIVE in the response.

### Step 6 - Create a charge for the agreement

Create a charge with:
[`POST:/recurring/v3/agreements/{agreementId}/charges`][create-charge-endpoint].

Set a unique `orderId` that can be used to access the charge later.
Also, set a unique `Idempotency-Key` value to ensure the charge is not created more than once.

#### API client

Ensure that `agreementId` is set to the ID of an ACTIVE agreement.

Set `Idempotency-Key-Create` value.

```text
Send request "Create Charge - Direct capture"
```

#### curl

```bash
curl -X POST https://apitest.vipps.no/recurring/v3/agreements/UNIQUE-AGREEMENT-ID/charges \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H 'Idempotency-Key: YOUR-IDEMPOTENCY-KEY' \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-H "Vipps-System-Plugin-Name: acme-webshop" \
-H "Vipps-System-Plugin-Version: 4.5.6" \
-d '{
  "amount": 1000,
  "description": "This payment was charged with an API client.",
  "due": "2023-08-08",
  "retryDays": 0,
  "transactionType": "DIRECT_CAPTURE",
  "orderId": "UNIQUE-ORDERID"
}'
```

The status will be `PENDING` until the payment is processed.

A charge must be scheduled a minimum of one day before the payment will occur (it is a minimum one day in the test environment).
See [direct capture](https://developer.vippsmobilepay.com/docs/APIs/recurring-api/recurring-api-guide.md#direct-capture) for more details about timing.

### Step 7 - Fetch the charge

To get the status of the charge, use:
[`GET:/recurring/v3/agreements/{agreementId}/charges/{chargeId}`][fetch-charge-endpoint].

The value for `chargeId` must match what you provided for `orderId`.

#### API client

```text
Send request "Get Charge"
```

#### curl

```bash
curl -X GET https://apitest.vipps.no/recurring/v3/agreements/UNIQUE-AGREEMENT-ID/charges/UNIQUE-ORDERID \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-H "Vipps-System-Plugin-Name: acme-webshop" \
-H "Vipps-System-Plugin-Version: 4.5.6" \
```

### (Optional) Step 8 - Cancel the charge

To cancel an unpaid charge, use:
[`DELETE:/recurring/v3/agreements/{agreementId}/charges/{chargeId}`][cancel-charge-endpoint].

#### API client

```text
Send request "Cancel Charge"
```

#### curl

```bash
curl -X DELETE https://apitest.vipps.no/recurring/v3/agreements/UNIQUE-AGREEMENT-ID/charges/UNIQUE-CHARGE-ID \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H 'Idempotency-Key: YOUR-IDEMPOTENCY-KEY' \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-H "Vipps-System-Plugin-Name: acme-webshop" \
-H "Vipps-System-Plugin-Version: 4.5.6" \
```

### (Optional) Step 9 - Refund a charge

To refund a charge, use:
[`POST:/recurring/v3/agreements/{agreementId}/charges/{chargeId}/refund`][refund-charge-endpoint].

#### API client

Update the `chargeId` to a charge that has been processed.

```text
Send request "Refund Charge"
```

#### curl

```bash
curl -X POST https://apitest.vipps.no/recurring/v3/agreements/UNIQUE-AGREEMENT-ID/charges/UNIQUE-CHARGE-ID/refund \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H 'Idempotency-Key: YOUR-IDEMPOTENCY-KEY' \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-H "Vipps-System-Plugin-Name: acme-webshop" \
-H "Vipps-System-Plugin-Version: 4.5.6" \
-d '{
  "amount": 1000,
  "description":"This charge was refunded with an API client"
}'
```

### (Optional) Step 10 - Stop an agreement

To stop an agreement,
send [`PATCH:/recurring/v3/agreements/{agreementId}`][update-agreement-patch-endpoint]
with `"status": "STOPPED"`.

#### API client

Set `agreementId` to the ID of an ACTIVE agreement.

```text
Send request "Stop agreement"
```

#### curl

```bash
curl -X PATCH https://apitest.vipps.no/recurring/v3/agreements/UNIQUE-AGREEMENT-ID  \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR-ACCESS-TOKEN" \
-H "Ocp-Apim-Subscription-Key: YOUR-SUBSCRIPTION-KEY" \
-H "Merchant-Serial-Number: YOUR-MSN" \
-H 'Idempotency-Key: YOUR-IDEMPOTENCY-KEY' \
-H "Vipps-System-Name: acme" \
-H "Vipps-System-Version: 3.1.2" \
-H "Vipps-System-Plugin-Name: acme-webshop" \
-H "Vipps-System-Plugin-Version: 4.5.6" \
-d '{
  "status": "STOPPED"
}'
```

## Next steps

Complete the required [Recurring checklist](https://developer.vippsmobilepay.com/docs/APIs/recurring-api/recurring-api-checklist.md) to integrate the API into your software.

[access-token-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/access-token-swagger-id.yaml
[draft-agreement-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/recurring-swagger-id.yaml
[agreement-endpoints]: https://developer.vippsmobilepay.com/redocusaurus/recurring-swagger-id.yaml
[fetch-agreement-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/recurring-swagger-id.yaml
[update-agreement-patch-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/recurring-swagger-id.yaml
[create-charge-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/recurring-swagger-id.yaml
[fetch-charge-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/recurring-swagger-id.yaml
[cancel-charge-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/recurring-swagger-id.yaml
[refund-charge-endpoint]: https://developer.vippsmobilepay.com/redocusaurus/recurring-swagger-id.yaml
